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