github.com/okex/exchain@v1.8.0/libs/tendermint/rpc/core/tx.go (about)

     1  package core
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  
     7  	"github.com/pkg/errors"
     8  
     9  	tmmath "github.com/okex/exchain/libs/tendermint/libs/math"
    10  	tmquery "github.com/okex/exchain/libs/tendermint/libs/pubsub/query"
    11  	ctypes "github.com/okex/exchain/libs/tendermint/rpc/core/types"
    12  	rpctypes "github.com/okex/exchain/libs/tendermint/rpc/jsonrpc/types"
    13  	"github.com/okex/exchain/libs/tendermint/state/txindex/null"
    14  	"github.com/okex/exchain/libs/tendermint/types"
    15  )
    16  
    17  // Tx allows you to query the transaction results. `nil` could mean the
    18  // transaction is in the mempool, invalidated, or was not sent in the first
    19  // place.
    20  // More: https://docs.tendermint.com/master/rpc/#/Info/tx
    21  func Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
    22  	// if index is disabled, return error
    23  	if _, ok := env.TxIndexer.(*null.TxIndex); ok {
    24  		return nil, fmt.Errorf("transaction indexing is disabled")
    25  	}
    26  
    27  	r, err := env.TxIndexer.Get(hash)
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  
    32  	if r == nil {
    33  		return nil, fmt.Errorf("tx (%X) not found", hash)
    34  	}
    35  
    36  	height := r.Height
    37  	index := r.Index
    38  
    39  	var proof types.TxProof
    40  	if prove {
    41  		block := env.BlockStore.LoadBlock(height)
    42  		proof = block.Data.Txs.Proof(int(index), block.Height) // XXX: overflow on 32-bit machines
    43  	}
    44  
    45  	return &ctypes.ResultTx{
    46  		Hash:     hash,
    47  		Height:   height,
    48  		Index:    index,
    49  		TxResult: r.Result,
    50  		Tx:       r.Tx,
    51  		Proof:    proof,
    52  	}, nil
    53  }
    54  
    55  // TxSearch allows you to query for multiple transactions results. It returns a
    56  // list of transactions (maximum ?per_page entries) and the total count.
    57  // More: https://docs.tendermint.com/master/rpc/#/Info/tx_search
    58  func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int, orderBy string) (
    59  	*ctypes.ResultTxSearch, error) {
    60  	// if index is disabled, return error
    61  	if _, ok := env.TxIndexer.(*null.TxIndex); ok {
    62  		return nil, errors.New("transaction indexing is disabled")
    63  	}
    64  
    65  	q, err := tmquery.New(query)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	results, err := env.TxIndexer.Search(ctx.Context(), q)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	// sort results (must be done before pagination)
    76  	switch orderBy {
    77  	case "desc":
    78  		sort.Slice(results, func(i, j int) bool {
    79  			if results[i].Height == results[j].Height {
    80  				return results[i].Index > results[j].Index
    81  			}
    82  			return results[i].Height > results[j].Height
    83  		})
    84  	case "asc", "":
    85  		sort.Slice(results, func(i, j int) bool {
    86  			if results[i].Height == results[j].Height {
    87  				return results[i].Index < results[j].Index
    88  			}
    89  			return results[i].Height < results[j].Height
    90  		})
    91  	default:
    92  		return nil, errors.New("expected order_by to be either `asc` or `desc` or empty")
    93  	}
    94  
    95  	// paginate results
    96  	totalCount := len(results)
    97  	perPage = validatePerPage(perPage)
    98  	page, err = validatePage(page, perPage, totalCount)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	skipCount := validateSkipCount(page, perPage)
   103  	pageSize := tmmath.MinInt(perPage, totalCount-skipCount)
   104  
   105  	apiResults := make([]*ctypes.ResultTx, 0, pageSize)
   106  	for i := skipCount; i < skipCount+pageSize; i++ {
   107  		r := results[i]
   108  
   109  		var proof types.TxProof
   110  		if prove {
   111  			block := env.BlockStore.LoadBlock(r.Height)
   112  			proof = block.Data.Txs.Proof(int(r.Index), block.Height) // XXX: overflow on 32-bit machines
   113  		}
   114  
   115  		apiResults = append(apiResults, &ctypes.ResultTx{
   116  			Hash:     r.Tx.Hash(r.Height),
   117  			Height:   r.Height,
   118  			Index:    r.Index,
   119  			TxResult: r.Result,
   120  			Tx:       r.Tx,
   121  			Proof:    proof,
   122  		})
   123  	}
   124  
   125  	return &ctypes.ResultTxSearch{Txs: apiResults, TotalCount: totalCount}, nil
   126  }