github.com/adoriasoft/tendermint@v0.34.0-dev1.0.20200722151356-96d84601a75a/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(ctx *rpctypes.Context, query string, prove bool, pagePtr, perPagePtr *int, orderBy string) ( 58 *ctypes.ResultTxSearch, error) { 59 // if index is disabled, return error 60 if _, ok := env.TxIndexer.(*null.TxIndex); ok { 61 return nil, errors.New("transaction indexing is disabled") 62 } 63 64 q, err := tmquery.New(query) 65 if err != nil { 66 return nil, err 67 } 68 69 results, err := env.TxIndexer.Search(ctx.Context(), q) 70 if err != nil { 71 return nil, err 72 } 73 74 // sort results (must be done before pagination) 75 switch orderBy { 76 case "desc": 77 sort.Slice(results, func(i, j int) bool { 78 if results[i].Height == results[j].Height { 79 return results[i].Index > results[j].Index 80 } 81 return results[i].Height > results[j].Height 82 }) 83 case "asc", "": 84 sort.Slice(results, func(i, j int) bool { 85 if results[i].Height == results[j].Height { 86 return results[i].Index < results[j].Index 87 } 88 return results[i].Height < results[j].Height 89 }) 90 default: 91 return nil, errors.New("expected order_by to be either `asc` or `desc` or empty") 92 } 93 94 // paginate results 95 totalCount := len(results) 96 perPage := validatePerPage(perPagePtr) 97 page, err := validatePage(pagePtr, perPage, totalCount) 98 if err != nil { 99 return nil, err 100 } 101 skipCount := validateSkipCount(page, perPage) 102 pageSize := tmmath.MinInt(perPage, totalCount-skipCount) 103 104 apiResults := make([]*ctypes.ResultTx, 0, pageSize) 105 for i := skipCount; i < skipCount+pageSize; i++ { 106 r := results[i] 107 108 var proof types.TxProof 109 if prove { 110 block := env.BlockStore.LoadBlock(r.Height) 111 proof = block.Data.Txs.Proof(int(r.Index)) // XXX: overflow on 32-bit machines 112 } 113 114 apiResults = append(apiResults, &ctypes.ResultTx{ 115 Hash: types.Tx(r.Tx).Hash(), 116 Height: r.Height, 117 Index: r.Index, 118 TxResult: r.Result, 119 Tx: r.Tx, 120 Proof: proof, 121 }) 122 } 123 124 return &ctypes.ResultTxSearch{Txs: apiResults, TotalCount: totalCount}, nil 125 }