Skip to content

Commit

Permalink
Implement Commit and BlockSearch methods cosmos#258)
Browse files Browse the repository at this point in the history
Co-authored-by: Tomasz Zdybał <tomek@zdybal.lap.pl>
  • Loading branch information
Raneet10 and tzdybal authored Feb 7, 2022
1 parent ec78aa3 commit 566d728
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG-PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Month, DD, YYYY
- [store,indexer] [Replace tm-db dependency with store package #268](https://github.com/celestiaorg/optimint/pull/268) [@tzdybal](https://github.com/tzdybal/)
- [rpc] [Implement ConsensusState/DumpConsensusState #273](https://github.com/celestiaorg/optimint/pull/273) [@tzdybal](https://github.com/tzdybal/)
- [rpc] [Implement Tx Method #272](https://github.com/celestiaorg/optimint/pull/272) [@mauriceLC92](https://github.com/mauriceLC92)
- [rpc] [Implement Commit and BlockSearch method #258](https://github.com/celestiaorg/optimint/pull/258) [@raneet10](https://github.com/Raneet10/)

### BUG FIXES

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ require (
github.com/golang/protobuf v1.5.2
github.com/google/orderedcode v0.0.1
github.com/gorilla/rpc v1.2.0
github.com/gorilla/websocket v1.4.2
github.com/ipfs/go-log v1.0.5
github.com/libp2p/go-libp2p v0.15.1
github.com/libp2p/go-libp2p-core v0.9.0
Expand Down Expand Up @@ -55,6 +54,7 @@ require (
github.com/google/gopacket v1.1.19 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/gtank/merlin v0.1.1 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
Expand Down
100 changes: 89 additions & 11 deletions rpc/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,14 +313,8 @@ func (c *Client) Health(ctx context.Context) (*ctypes.ResultHealth, error) {

func (c *Client) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, error) {
// needs block store
var h uint64
if height == nil {
h = c.node.Store.Height()
} else {
h = uint64(*height)
}

block, err := c.node.Store.LoadBlock(h)
heightValue := c.normalizeHeight(height)
block, err := c.node.Store.LoadBlock(heightValue)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -389,8 +383,22 @@ func (c *Client) BlockResults(ctx context.Context, height *int64) (*ctypes.Resul
}

func (c *Client) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error) {
// needs block store
panic("Commit - not implemented!")
heightValue := c.normalizeHeight(height)
com, err := c.node.Store.LoadCommit(heightValue)
if err != nil {
return nil, err
}
b, err := c.node.Store.LoadBlock(heightValue)
if err != nil {
return nil, err
}
commit := abciconv.ToABCICommit(com)
block, err := abciconv.ToABCIBlock(b)
if err != nil {
return nil, err
}

return ctypes.NewResultCommit(&block.Header, commit, true), nil
}

func (c *Client) Validators(ctx context.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error) {
Expand Down Expand Up @@ -500,7 +508,66 @@ func (c *Client) TxSearch(ctx context.Context, query string, prove bool, pagePtr
// BlockSearch defines a method to search for a paginated set of blocks by
// BeginBlock and EndBlock event search criteria.
func (c *Client) BlockSearch(ctx context.Context, query string, page, perPage *int, orderBy string) (*ctypes.ResultBlockSearch, error) {
panic("BlockSearch - not implemented!")
q, err := tmquery.New(query)
if err != nil {
return nil, err
}

results, err := c.node.BlockIndexer.Search(ctx, q)
if err != nil {
return nil, err
}

// Sort the results
switch orderBy {
case "desc":
sort.Slice(results, func(i, j int) bool {
return results[i] > results[j]
})

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

// Paginate
totalCount := len(results)
perPageVal := validatePerPage(perPage)

pageVal, err := validatePage(page, perPageVal, totalCount)
if err != nil {
return nil, err
}

skipCount := validateSkipCount(pageVal, perPageVal)
pageSize := tmmath.MinInt(perPageVal, totalCount-skipCount)

pageResults := make([]int64, pageSize)
copy(pageResults, results[skipCount:skipCount+pageSize])

// Fetch the blocks
blocks := make([]*ctypes.ResultBlock, 0, len(pageResults))
for _, h := range pageResults {
b, err := c.node.Store.LoadBlock(uint64(h))
if err != nil {
return nil, err
}
block, err := abciconv.ToABCIBlock(b)
if err != nil {
return nil, err
}
blocks = append(blocks, &ctypes.ResultBlock{
Block: block,
BlockID: types.BlockID{
Hash: block.Hash(),
},
})
}

return &ctypes.ResultBlockSearch{Blocks: blocks, TotalCount: totalCount}, nil
}

func (c *Client) Status(ctx context.Context) (*ctypes.ResultStatus, error) {
Expand Down Expand Up @@ -631,6 +698,17 @@ func (c *Client) snapshot() proxy.AppConnSnapshot {
return c.node.ProxyApp().Snapshot()
}

func (c *Client) normalizeHeight(height *int64) uint64 {
var heightValue uint64
if height == nil {
heightValue = c.node.Store.Height()
} else {
heightValue = uint64(*height)
}

return heightValue
}

func validatePerPage(perPagePtr *int) int {
if perPagePtr == nil { // no per_page parameter
return defaultPerPage
Expand Down
137 changes: 137 additions & 0 deletions rpc/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package client
import (
"context"
crand "crypto/rand"
"fmt"
"math/rand"
"testing"
"time"
Expand Down Expand Up @@ -214,6 +215,103 @@ func TestGetBlock(t *testing.T) {
require.NoError(err)
}

func TestGetCommit(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
mockApp, rpc := getRPC(t)
mockApp.On("BeginBlock", mock.Anything).Return(abci.ResponseBeginBlock{})
mockApp.On("Commit", mock.Anything).Return(abci.ResponseCommit{})

blocks := []*types.Block{getRandomBlock(1, 5), getRandomBlock(2, 6), getRandomBlock(3, 8), getRandomBlock(4, 10)}

err := rpc.node.Start()
require.NoError(err)

for _, b := range blocks {
err = rpc.node.Store.SaveBlock(b, &types.Commit{Height: b.Header.Height})
require.NoError(err)
}
t.Run("Fetch all commits", func(t *testing.T) {
for _, b := range blocks {
h := int64(b.Header.Height)
commit, err := rpc.Commit(context.Background(), &h)
require.NoError(err)
require.NotNil(commit)
assert.Equal(b.Header.Height, uint64(commit.Height))
}
})

t.Run("Fetch commit for nil height", func(t *testing.T) {
commit, err := rpc.Commit(context.Background(), nil)
require.NoError(err)
require.NotNil(commit)
assert.Equal(blocks[3].Header.Height, uint64(commit.Height))
})

err = rpc.node.Stop()
require.NoError(err)
}

func TestBlockSearch(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
mockApp, rpc := getRPC(t)
mockApp.On("BeginBlock", mock.Anything).Return(abci.ResponseBeginBlock{})
mockApp.On("Commit", mock.Anything).Return(abci.ResponseCommit{})

heights := []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
for _, h := range heights {
block := getRandomBlock(uint64(h), 5)
err := rpc.node.Store.SaveBlock(block, &types.Commit{
Height: uint64(h),
HeaderHash: block.Header.Hash(),
})
require.NoError(err)
}
indexBlocks(t, rpc, heights)

tests := []struct {
query string
page int
perPage int
totalCount int
orderBy string
}{
{
query: "block.height >= 1 AND end_event.foo <= 5",
page: 1,
perPage: 5,
totalCount: 5,
orderBy: "asc",
},
{
query: "block.height >= 2 AND end_event.foo <= 10",
page: 1,
perPage: 3,
totalCount: 9,
orderBy: "desc",
},
{
query: "begin_event.proposer = 'FCAA001' AND end_event.foo <= 5",
page: 1,
perPage: 5,
totalCount: 5,
orderBy: "asc",
},
}

for _, test := range tests {
test := test
t.Run(test.query, func(t *testing.T) {
result, err := rpc.BlockSearch(context.Background(), test.query, &test.page, &test.perPage, test.orderBy)
require.NoError(err)
assert.Equal(test.totalCount, result.TotalCount)
assert.Len(result.Blocks, test.perPage)
})

}
}

func TestGetBlockByHash(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
Expand Down Expand Up @@ -464,6 +562,45 @@ func getRPC(t *testing.T) (*mocks.Application, *Client) {
return app, rpc
}

// From state/indexer/block/kv/kv_test
func indexBlocks(t *testing.T, rpc *Client, heights []int64) {
t.Helper()

for _, h := range heights {
require.NoError(t, rpc.node.BlockIndexer.Index(tmtypes.EventDataNewBlockHeader{
Header: tmtypes.Header{Height: h},
ResultBeginBlock: abci.ResponseBeginBlock{
Events: []abci.Event{
{
Type: "begin_event",
Attributes: []abci.EventAttribute{
{
Key: []byte("proposer"),
Value: []byte("FCAA001"),
Index: true,
},
},
},
},
},
ResultEndBlock: abci.ResponseEndBlock{
Events: []abci.Event{
{
Type: "end_event",
Attributes: []abci.EventAttribute{
{
Key: []byte("foo"),
Value: []byte(fmt.Sprintf("%d", h)),
Index: true,
},
},
},
},
},
}))
}

}
func TestMempool2Nodes(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
Expand Down

0 comments on commit 566d728

Please sign in to comment.