Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use begin end/block instead of query in data commitments #838

10 changes: 6 additions & 4 deletions light/proxy/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func RPCRoutes(c *lrpc.Client) map[string]*rpcserver.RPCFunc {
"block_by_hash": rpcserver.NewRPCFunc(makeBlockByHashFunc(c), "hash"),
"block_results": rpcserver.NewRPCFunc(makeBlockResultsFunc(c), "height"),
"commit": rpcserver.NewRPCFunc(makeCommitFunc(c), "height"),
"data_commitment": rpcserver.NewRPCFunc(makeDataCommitmentFunc(c), "query"),
"data_commitment": rpcserver.NewRPCFunc(makeDataCommitmentFunc(c), "beginBlock,endBlock"),
"tx": rpcserver.NewRPCFunc(makeTxFunc(c), "hash,prove"),
"tx_search": rpcserver.NewRPCFunc(makeTxSearchFunc(c), "query,prove,page,per_page,order_by"),
"block_search": rpcserver.NewRPCFunc(makeBlockSearchFunc(c), "query,page,per_page,order_by"),
Expand Down Expand Up @@ -136,15 +136,17 @@ func makeCommitFunc(c *lrpc.Client) rpcCommitFunc {

type rpcDataCommitmentFunc func(
ctx *rpctypes.Context,
query string,
beginBlock uint64,
endBlock uint64,
) (*ctypes.ResultDataCommitment, error)

func makeDataCommitmentFunc(c *lrpc.Client) rpcDataCommitmentFunc {
return func(
ctx *rpctypes.Context,
query string,
beginBlock uint64,
endBlock uint64,
) (*ctypes.ResultDataCommitment, error) {
return c.DataCommitment(ctx.Context(), query)
return c.DataCommitment(ctx.Context(), beginBlock, endBlock)
}
}

Expand Down
8 changes: 6 additions & 2 deletions light/rpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,12 @@ func (c *Client) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommi
}, nil
}

func (c *Client) DataCommitment(ctx context.Context, query string) (*ctypes.ResultDataCommitment, error) {
return c.next.DataCommitment(ctx, query)
func (c *Client) DataCommitment(
ctx context.Context,
beginBlock uint64,
endBlock uint64,
) (*ctypes.ResultDataCommitment, error) {
return c.next.DataCommitment(ctx, beginBlock, endBlock)
}

// Tx calls rpcclient#Tx method and then verifies the proof if such was
Expand Down
9 changes: 7 additions & 2 deletions rpc/client/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -457,10 +457,15 @@ func (c *baseRPCClient) Commit(ctx context.Context, height *int64) (*ctypes.Resu
return result, nil
}

func (c *baseRPCClient) DataCommitment(ctx context.Context, query string) (*ctypes.ResultDataCommitment, error) {
func (c *baseRPCClient) DataCommitment(
ctx context.Context,
beginBlock uint64,
endBlock uint64,
) (*ctypes.ResultDataCommitment, error) {
result := new(ctypes.ResultDataCommitment)
params := map[string]interface{}{
"query": query,
"beginBlock": beginBlock,
"endBlock": endBlock,
}

_, err := c.caller.Call(ctx, "data_commitment", params, result)
Expand Down
2 changes: 1 addition & 1 deletion rpc/client/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ type SignClient interface {
BlockResults(ctx context.Context, height *int64) (*ctypes.ResultBlockResults, error)
Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error)

DataCommitment(ctx context.Context, query string) (*ctypes.ResultDataCommitment, error)
DataCommitment(ctx context.Context, beginBlock uint64, endBlock uint64) (*ctypes.ResultDataCommitment, error)

Validators(ctx context.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error)
Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.ResultTx, error)
Expand Down
8 changes: 6 additions & 2 deletions rpc/client/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,12 @@ func (c *Local) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit
return core.Commit(c.ctx, height)
}

func (c *Local) DataCommitment(_ context.Context, query string) (*ctypes.ResultDataCommitment, error) {
return core.DataCommitment(c.ctx, query)
func (c *Local) DataCommitment(
_ context.Context,
beginBlock uint64,
endBlock uint64,
) (*ctypes.ResultDataCommitment, error) {
return core.DataCommitment(c.ctx, beginBlock, endBlock)
}

func (c *Local) Validators(ctx context.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error) {
Expand Down
9 changes: 6 additions & 3 deletions rpc/client/mock/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ var _ client.Client = Client{}

// Call is used by recorders to save a call and response.
// It can also be used to configure mock responses.
//
type Call struct {
Name string
Args interface{}
Expand Down Expand Up @@ -170,8 +169,12 @@ func (c Client) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit
return core.Commit(&rpctypes.Context{}, height)
}

func (c Client) DataCommitment(ctx context.Context, query string) (*ctypes.ResultDataCommitment, error) {
return core.DataCommitment(&rpctypes.Context{}, query)
func (c Client) DataCommitment(
ctx context.Context,
beginBlock uint64,
endBlock uint64,
) (*ctypes.ResultDataCommitment, error) {
return core.DataCommitment(&rpctypes.Context{}, beginBlock, endBlock)
}

func (c Client) Validators(ctx context.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error) {
Expand Down
2 changes: 1 addition & 1 deletion rpc/client/rpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ func TestDataCommitment(t *testing.T) {

// check if data commitment is not nil.
// Checking if the commitment is correct is done in `core/blocks_test.go`.
dataCommitment, err := c.DataCommitment(ctx, fmt.Sprintf("block.height <= %d", expectedHeight))
dataCommitment, err := c.DataCommitment(ctx, 0, uint64(expectedHeight))
require.NotNil(t, dataCommitment, "data commitment shouldn't be nul.")
require.Nil(t, err, "%+v when creating data commitment.", err)
}
Expand Down
59 changes: 45 additions & 14 deletions rpc/core/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,28 +136,59 @@ func Commit(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultCommit, erro

// DataCommitment collects the data roots over a provided ordered range of blocks,
// and then creates a new Merkle root of those data roots.
func DataCommitment(ctx *rpctypes.Context, query string) (*ctypes.ResultDataCommitment, error) {
heights, err := heightsByQuery(ctx, query)
func DataCommitment(ctx *rpctypes.Context, beginBlock uint64, endBlock uint64) (*ctypes.ResultDataCommitment, error) {
err := validateDataCommitmentRange(beginBlock, endBlock)
if err != nil {
return nil, err
}
heights := generateHeightsList(beginBlock, endBlock)
blockResults := fetchBlocks(heights, len(heights), 0)
root := hashDataRoots(blockResults)
// Create data commitment
return &ctypes.ResultDataCommitment{DataCommitment: root}, nil
}

if len(heights) > consts.DataCommitmentBlocksLimit {
return nil, fmt.Errorf("the query exceeds the limit of allowed blocks %d", consts.DataCommitmentBlocksLimit)
} else if len(heights) == 0 {
return nil, fmt.Errorf("cannot create the data commitments for an empty set of blocks")
// generateHeightsList takes a begin and end block, then generates a list of heights
// containing the elements of the range [beginBlock, endBlock].
func generateHeightsList(beginBlock uint64, endBlock uint64) []int64 {
heights := make([]int64, endBlock-beginBlock+1)
for i := beginBlock; i <= endBlock; i++ {
heights[i-beginBlock] = int64(i)
}
return heights
}

err = sortBlocks(heights, "asc")
// validateDataCommitmentRange runs basic checks on the asc sorted list of heights
// that will be used subsequently in generating data commitments over the defined set of heights.
func validateDataCommitmentRange(beginBlock uint64, endBlock uint64) error {
heightsRange := endBlock - beginBlock + 1
if heightsRange > uint64(consts.DataCommitmentBlocksLimit) {
return fmt.Errorf("the query exceeds the limit of allowed blocks %d", consts.DataCommitmentBlocksLimit)
}
if heightsRange == 0 {
return fmt.Errorf("cannot create the data commitments for an empty set of blocks")
}
if beginBlock > endBlock {
return fmt.Errorf("end block is smaller than begin block")
}
if endBlock > uint64(env.BlockStore.Height()) {
return fmt.Errorf(
"end block %d is higher than current chain height %d",
endBlock,
env.BlockStore.Height(),
)
}
has, err := env.BlockIndexer.Has(int64(endBlock))
if err != nil {
return nil, err
return err
}

blockResults := fetchBlocks(heights, len(heights), 0)
root := hashDataRoots(blockResults)

// Create data commitment
return &ctypes.ResultDataCommitment{DataCommitment: root}, nil
if !has {
return fmt.Errorf(
"end block %d is still not indexed",
endBlock,
)
}
return nil
}

// hashDataRoots hashes a list of blocks data hashes and returns their merkle root.
Expand Down
7 changes: 4 additions & 3 deletions rpc/core/blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func TestBlockResults(t *testing.T) {

func TestDataCommitmentResults(t *testing.T) {
env = &Environment{}
height := int64(100)
height := int64(2826)

blocks := randomBlocks(height)
blockStore := mockBlockStore{
Expand All @@ -137,19 +137,20 @@ func TestDataCommitmentResults(t *testing.T) {
expectPass bool
}{
{10, 15, true},
{2727, 2828, false},
{10, 9, false},
{0, 1000, false},
{10, 8, false},
}

for _, tc := range testCases {
mockedQuery := fmt.Sprintf("block.height >= %d AND block.height <= %d", tc.beginQuery, tc.endQuery)
env.BlockIndexer = mockBlockIndexer{
height: height,
beginQueryBlock: tc.beginQuery,
endQueryBlock: tc.endQuery,
}

actualCommitment, err := DataCommitment(&rpctypes.Context{}, mockedQuery)
actualCommitment, err := DataCommitment(&rpctypes.Context{}, uint64(tc.beginQuery), uint64(tc.endQuery))
if tc.expectPass {
require.Nil(t, err, "should generate the needed data commitment.")

Expand Down
2 changes: 1 addition & 1 deletion rpc/core/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ var Routes = map[string]*rpc.RPCFunc{
"block_by_hash": rpc.NewRPCFunc(BlockByHash, "hash"),
"block_results": rpc.NewRPCFunc(BlockResults, "height"),
"commit": rpc.NewRPCFunc(Commit, "height"),
"data_commitment": rpc.NewRPCFunc(DataCommitment, "query"),
"data_commitment": rpc.NewRPCFunc(DataCommitment, "beginBlock,endBlock"),
"check_tx": rpc.NewRPCFunc(CheckTx, "tx"),
"tx": rpc.NewRPCFunc(Tx, "hash,prove"),
"tx_search": rpc.NewRPCFunc(TxSearch, "query,prove,page,per_page,order_by"),
Expand Down