github.com/number571/tendermint@v0.34.11-gost/rpc/core/tx.go (about)

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