You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

128 lines
3.4 KiB

package core
import (
"fmt"
"sort"
"github.com/pkg/errors"
tmmath "github.com/tendermint/tendermint/libs/math"
tmquery "github.com/tendermint/tendermint/libs/pubsub/query"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
rpctypes "github.com/tendermint/tendermint/rpc/lib/types"
"github.com/tendermint/tendermint/state/txindex/null"
"github.com/tendermint/tendermint/types"
)
// Tx allows you to query the transaction results. `nil` could mean the
// transaction is in the mempool, invalidated, or was not sent in the first
// place.
// More: https://docs.tendermint.com/master/rpc/#/Info/tx
func Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
// if index is disabled, return error
if _, ok := txIndexer.(*null.TxIndex); ok {
return nil, fmt.Errorf("transaction indexing is disabled")
}
r, err := txIndexer.Get(hash)
if err != nil {
return nil, err
}
if r == nil {
return nil, fmt.Errorf("tx (%X) not found", hash)
}
height := r.Height
index := r.Index
var proof types.TxProof
if prove {
block := blockStore.LoadBlock(height)
proof = block.Data.Txs.Proof(int(index)) // XXX: overflow on 32-bit machines
}
return &ctypes.ResultTx{
Hash: hash,
Height: height,
Index: index,
TxResult: r.Result,
Tx: r.Tx,
Proof: proof,
}, nil
}
// TxSearch allows you to query for multiple transactions results. It returns a
// list of transactions (maximum ?per_page entries) and the total count.
// More: https://docs.tendermint.com/master/rpc/#/Info/tx_search
func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int, orderBy string) (
*ctypes.ResultTxSearch, error) {
// if index is disabled, return error
if _, ok := txIndexer.(*null.TxIndex); ok {
return nil, errors.New("transaction indexing is disabled")
}
q, err := tmquery.New(query)
if err != nil {
return nil, err
}
results, err := txIndexer.Search(q)
if err != nil {
return nil, err
}
totalCount := len(results)
perPage = validatePerPage(perPage)
page, err = validatePage(page, perPage, totalCount)
if err != nil {
return nil, err
}
skipCount := validateSkipCount(page, perPage)
apiResults := make([]*ctypes.ResultTx, tmmath.MinInt(perPage, totalCount-skipCount))
var proof types.TxProof
// if there's no tx in the results array, we don't need to loop through the apiResults array
for i := 0; i < len(apiResults); i++ {
r := results[skipCount+i]
height := r.Height
index := r.Index
if prove {
block := blockStore.LoadBlock(height)
proof = block.Data.Txs.Proof(int(index)) // XXX: overflow on 32-bit machines
}
apiResults[i] = &ctypes.ResultTx{
Hash: r.Tx.Hash(),
Height: height,
Index: index,
TxResult: r.Result,
Tx: r.Tx,
Proof: proof,
}
}
if len(apiResults) > 1 {
switch orderBy {
case "desc":
sort.Slice(apiResults, func(i, j int) bool {
if apiResults[i].Height == apiResults[j].Height {
return apiResults[i].Index > apiResults[j].Index
}
return apiResults[i].Height > apiResults[j].Height
})
case "asc", "":
sort.Slice(apiResults, func(i, j int) bool {
if apiResults[i].Height == apiResults[j].Height {
return apiResults[i].Index < apiResults[j].Index
}
return apiResults[i].Height < apiResults[j].Height
})
default:
return nil, errors.New("expected order_by to be either `asc` or `desc` or empty")
}
}
return &ctypes.ResultTxSearch{Txs: apiResults, TotalCount: totalCount}, nil
}