Skip to content

Commit

Permalink
feat: implement TxByHeight (#138)
Browse files Browse the repository at this point in the history
* feat: implement `TxByHeight`

* chore: revise sort
  • Loading branch information
jinsan-line authored Nov 10, 2020
1 parent 7c28c3e commit 7e1ec17
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 0 deletions.
5 changes: 5 additions & 0 deletions lite2/rpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,11 @@ func (c *Client) TxSearch(query string, prove bool, page, perPage int, orderBy s
return c.next.TxSearch(query, prove, page, perPage, orderBy)
}

func (c *Client) TxByHeight(height int64, prove bool, orderBy string) (
*ctypes.ResultTxSearch, error) {
return c.next.TxByHeight(height, prove, orderBy)
}

// Validators fetches and verifies validators.
//
// WARNING: only full validator sets are verified (when length of validators is
Expand Down
15 changes: 15 additions & 0 deletions rpc/client/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,21 @@ func (c *baseRPCClient) TxSearch(query string, prove bool, page, perPage int, or
return result, nil
}

func (c *baseRPCClient) TxByHeight(height int64, prove bool, orderBy string) (
*ctypes.ResultTxSearch, error) {
result := new(ctypes.ResultTxSearch)
params := map[string]interface{}{
"height": height,
"prove": prove,
"order_by": orderBy,
}
_, err := c.caller.Call("tx_by_height", params, result)
if err != nil {
return nil, errors.Wrap(err, "TxByHeight")
}
return result, nil
}

func (c *baseRPCClient) Validators(height *int64, page, perPage int) (*ctypes.ResultValidators, error) {
result := new(ctypes.ResultValidators)
_, err := c.caller.Call("validators", map[string]interface{}{
Expand Down
2 changes: 2 additions & 0 deletions rpc/client/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ type SignClient interface {
Validators(height *int64, page, perPage int) (*ctypes.ResultValidators, error)
Tx(hash []byte, prove bool) (*ctypes.ResultTx, error)
TxSearch(query string, prove bool, page, perPage int, orderBy string) (*ctypes.ResultTxSearch, error)
// NOTE It could affect on the performance and it must be used only for `blocks_with_tx_results`
TxByHeight(height int64, prove bool, orderBy string) (*ctypes.ResultTxSearch, error)
}

// HistoryClient provides access to data from genesis to now in large chunks.
Expand Down
1 change: 1 addition & 0 deletions rpc/core/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var Routes = map[string]*rpc.RPCFunc{
"commit": rpc.NewRPCFunc(Commit, "height"),
"tx": rpc.NewRPCFunc(Tx, "hash,prove"),
"tx_search": rpc.NewRPCFunc(TxSearch, "query,prove,page,per_page,order_by"),
"tx_by_height": rpc.NewRPCFunc(TxByHeight, "height,prove,order_by"),
"validators": rpc.NewRPCFunc(Validators, "height,page,per_page"),
"dump_consensus_state": rpc.NewRPCFunc(DumpConsensusState, ""),
"consensus_state": rpc.NewRPCFunc(ConsensusState, ""),
Expand Down
61 changes: 61 additions & 0 deletions rpc/core/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,64 @@ func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int

return &ctypes.ResultTxSearch{Txs: apiResults, TotalCount: totalCount}, nil
}

func TxByHeight(ctx *rpctypes.Context, height int64, prove bool, 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(fmt.Sprintf("tx.height=%d", height))
if err != nil {
return nil, err
}

results, err := txIndexer.Search(ctx.Context(), q)
if err != nil {
return nil, err
}

// sort results
switch orderBy {
case "desc":
sort.Slice(results, func(i, j int) bool {
return results[i].Index > results[j].Index
})
case "asc", "":
sort.Slice(results, func(i, j int) bool {
return results[i].Index < results[j].Index
})
default:
return nil, errors.New("expected order_by to be either `asc` or `desc` or empty")
}

totalCount := len(results)

var block *types.Block
if prove {
block = blockStore.LoadBlock(height)
}

apiResults := make([]*ctypes.ResultTx, 0, totalCount)
for _, r := range results {

var proof types.TxProof
if prove {
if block == nil {
panic("block must not be nil")
}
proof = block.Data.Txs.Proof(int(r.Index)) // XXX: overflow on 32-bit machines
}

apiResults = append(apiResults, &ctypes.ResultTx{
Hash: r.Tx.Hash(),
Height: r.Height,
Index: r.Index,
TxResult: r.Result,
Tx: r.Tx,
Proof: proof,
})
}

return &ctypes.ResultTxSearch{Txs: apiResults, TotalCount: totalCount}, nil
}

0 comments on commit 7e1ec17

Please sign in to comment.