github.com/Oyster-zx/tendermint@v0.34.24-fork/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/v0.34/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/v0.34/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 } else if len(query) > maxQueryLength { 69 return nil, errors.New("maximum query length exceeded") 70 } 71 72 q, err := tmquery.New(query) 73 if err != nil { 74 return nil, err 75 } 76 77 results, err := env.TxIndexer.Search(ctx.Context(), q) 78 if err != nil { 79 return nil, err 80 } 81 82 // sort results (must be done before pagination) 83 switch orderBy { 84 case "desc": 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 case "asc", "": 92 sort.Slice(results, func(i, j int) bool { 93 if results[i].Height == results[j].Height { 94 return results[i].Index < results[j].Index 95 } 96 return results[i].Height < results[j].Height 97 }) 98 default: 99 return nil, errors.New("expected order_by to be either `asc` or `desc` or empty") 100 } 101 102 // paginate results 103 totalCount := len(results) 104 perPage := validatePerPage(perPagePtr) 105 106 page, err := validatePage(pagePtr, perPage, totalCount) 107 if err != nil { 108 return nil, err 109 } 110 111 skipCount := validateSkipCount(page, perPage) 112 pageSize := tmmath.MinInt(perPage, totalCount-skipCount) 113 114 apiResults := make([]*ctypes.ResultTx, 0, pageSize) 115 for i := skipCount; i < skipCount+pageSize; i++ { 116 r := results[i] 117 118 var proof types.TxProof 119 if prove { 120 block := env.BlockStore.LoadBlock(r.Height) 121 proof = block.Data.Txs.Proof(int(r.Index)) // XXX: overflow on 32-bit machines 122 } 123 124 apiResults = append(apiResults, &ctypes.ResultTx{ 125 Hash: types.Tx(r.Tx).Hash(), 126 Height: r.Height, 127 Index: r.Index, 128 TxResult: r.Result, 129 Tx: r.Tx, 130 Proof: proof, 131 }) 132 } 133 134 return &ctypes.ResultTxSearch{Txs: apiResults, TotalCount: totalCount}, nil 135 }