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

go/runtime: fix round in runtime query #4210

Merged
merged 1 commit into from
Aug 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changelog/4210.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/runtime: fix ignored round in runtime Query
3 changes: 3 additions & 0 deletions go/roothash/api/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ type BlockHistory interface {
// GetBlock returns the block at a specific round.
GetBlock(ctx context.Context, round uint64) (*block.Block, error)

// GetAnnotatedBlock returns the annotated block at a specific round.
GetAnnotatedBlock(ctx context.Context, round uint64) (*AnnotatedBlock, error)

// GetLatestBlock returns the block at latest round.
GetLatestBlock(ctx context.Context) (*block.Block, error)

Expand Down
31 changes: 16 additions & 15 deletions go/runtime/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,33 +419,34 @@ func (c *runtimeClient) GetBlockByHash(ctx context.Context, request *api.GetBloc

// Implements api.RuntimeClient.
func (c *runtimeClient) Query(ctx context.Context, request *api.QueryRequest) (*api.QueryResponse, error) {
hrt, ok := c.hosts[request.RuntimeID]
clientHost, ok := c.hosts[request.RuntimeID]
if !ok {
return nil, api.ErrNoHostedRuntime
}
rt := hrt.GetHostedRuntime()
if rt == nil {
hrt := clientHost.GetHostedRuntime()
if hrt == nil {
return nil, api.ErrNoHostedRuntime
}

// Get current blocks.
rs, err := c.common.consensus.RootHash().GetRuntimeState(ctx, &roothash.RuntimeRequest{
RuntimeID: request.RuntimeID,
Height: consensus.HeightLatest,
})
rt, err := c.common.runtimeRegistry.GetRuntime(request.RuntimeID)
if err != nil {
return nil, fmt.Errorf("client: failed to get runtime %s state: %w", request.RuntimeID, err)
return nil, err
}
lb, err := c.common.consensus.GetLightBlock(ctx, rs.CurrentBlockHeight)
annBlk, err := rt.History().GetAnnotatedBlock(ctx, request.Round)
if err != nil {
return nil, fmt.Errorf("client: failed to get light block at height %d: %w", rs.CurrentBlockHeight, err)
return nil, fmt.Errorf("client: failed to fetch annotated block from history: %w", err)
}

// Get consensus state at queried round.
lb, err := c.common.consensus.GetLightBlock(ctx, annBlk.Height)
if err != nil {
return nil, fmt.Errorf("client: failed to get light block at height %d: %w", annBlk.Height, err)
}
epoch, err := c.common.consensus.Beacon().GetEpoch(ctx, rs.CurrentBlockHeight)
epoch, err := c.common.consensus.Beacon().GetEpoch(ctx, annBlk.Height)
if err != nil {
return nil, fmt.Errorf("client: failed to get epoch at height %d: %w", rs.CurrentBlockHeight, err)
return nil, fmt.Errorf("client: failed to get epoch at height %d: %w", annBlk.Height, err)
}

data, err := rt.Query(ctx, rs.CurrentBlock, lb, epoch, request.Method, request.Args)
data, err := hrt.Query(ctx, annBlk.Block, lb, epoch, request.Method, request.Args)
if err != nil {
return nil, err
}
Expand Down
30 changes: 27 additions & 3 deletions go/runtime/client/tests/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,34 @@ func testQuery(
Method: "hello",
})
require.NoError(t, err, "Query")
var decMethod string
err = cbor.Unmarshal(rsp.Data, &decMethod)
var decResp string
err = cbor.Unmarshal(rsp.Data, &decResp)
require.NoError(t, err, "cbor.Unmarshal(<QueryResponse.Data>)")
require.EqualValues(t, "hello world", decMethod, "Query response should be correct")
require.True(t, strings.HasPrefix(decResp, "hello world"), "Query response should be correct")

rsp, err = c.Query(ctx, &api.QueryRequest{
RuntimeID: runtimeID,
Round: 1,
Method: "hello",
})
require.NoError(t, err, "Query")
var decResp2 string
err = cbor.Unmarshal(rsp.Data, &decResp2)
require.NoError(t, err, "cbor.Unmarshal(<QueryResponse.Data>)")
require.True(t, strings.HasPrefix(decResp2, "hello world"), "Query response at round 1 should be correct")
require.NotEqualValues(t, decResp, decResp2, "Query responses for different rounds should not be equal (round consensus height should be included in response)")

rsp, err = c.Query(ctx, &api.QueryRequest{
RuntimeID: runtimeID,
Round: 1,
Method: "hello",
})
require.NoError(t, err, "Query")
var decResp3 string
err = cbor.Unmarshal(rsp.Data, &decResp3)
require.NoError(t, err, "cbor.Unmarshal(<QueryResponse.Data>)")
require.True(t, strings.HasPrefix(decResp3, "hello world"), "Query response at round 1 should be correct")
require.EqualValues(t, decResp2, decResp3, "Query responses for same round should be equal (round consensus height should be included in response)")

// Execute CheckTx using the mock runtime host.
err = c.CheckTx(ctx, &api.CheckTxRequest{
Expand Down
11 changes: 11 additions & 0 deletions go/runtime/history/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ func (h *nopHistory) GetBlock(ctx context.Context, round uint64) (*block.Block,
return nil, errNopHistory
}

func (h *nopHistory) GetAnnotatedBlock(ctx context.Context, round uint64) (*roothash.AnnotatedBlock, error) {
return nil, errNopHistory
}

func (h *nopHistory) GetLatestBlock(ctx context.Context) (*block.Block, error) {
return nil, errNopHistory
}
Expand Down Expand Up @@ -155,6 +159,13 @@ func (h *runtimeHistory) GetBlock(ctx context.Context, round uint64) (*block.Blo
return annBlk.Block, nil
}

func (h *runtimeHistory) GetAnnotatedBlock(ctx context.Context, round uint64) (*roothash.AnnotatedBlock, error) {
if ctx.Err() != nil {
return nil, ctx.Err()
}
return h.db.getBlock(round)
}

func (h *runtimeHistory) GetLatestBlock(ctx context.Context) (*block.Block, error) {
if ctx.Err() != nil {
return nil, ctx.Err()
Expand Down
13 changes: 13 additions & 0 deletions go/runtime/history/history_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ func TestHistory(t *testing.T) {
require.Error(err, "GetBlock should fail for non-indexed block")
require.Equal(roothash.ErrNotFound, err)

_, err = history.GetAnnotatedBlock(context.Background(), 10)
require.Error(err, "GetAnnotatedBlock should fail for non-indexed block")
require.Equal(roothash.ErrNotFound, err)

_, err = history.GetLatestBlock(context.Background())
require.Error(err, "GetLatestBlock should fail for no indexed block")
require.Equal(roothash.ErrNotFound, err)
Expand Down Expand Up @@ -84,6 +88,7 @@ func TestHistory(t *testing.T) {
blk.Block.Header.Round = 5
err = history.Commit(&blk, roundResults)
require.Error(err, "Commit should fail for a lower round")
blk.Block.Header.Round = 10

lastHeight, err = history.LastConsensusHeight()
require.NoError(err, "LastConsensusHeight")
Expand All @@ -93,6 +98,10 @@ func TestHistory(t *testing.T) {
require.NoError(err, "GetBlock")
require.Equal(&putBlk, gotBlk, "GetBlock should return the correct block")

gotAnnBlk, err := history.GetAnnotatedBlock(context.Background(), 10)
require.NoError(err, "GetAnnotatedBlock")
require.Equal(&blk, gotAnnBlk, "GetAnnotatedBlock should return the correct block")

gotLatestBlk, err := history.GetLatestBlock(context.Background())
require.NoError(err, "GetLatestBlock")
require.Equal(&putBlk, gotLatestBlk, "GetLatestBlock should return the correct block")
Expand Down Expand Up @@ -122,6 +131,10 @@ func TestHistory(t *testing.T) {
require.NoError(err, "GetBlock")
require.Equal(&putBlk, gotBlk, "GetBlock should return the correct block")

gotAnnBlk, err = history.GetAnnotatedBlock(context.Background(), 10)
require.NoError(err, "GetAnnotatedBlock")
require.Equal(&blk, gotAnnBlk, "GetAnnotatedBlock should return the correct block")

gotLatestBlk, err = history.GetLatestBlock(context.Background())
require.NoError(err, "GetLatestBlock")
require.Equal(&putBlk, gotLatestBlk, "GetLatestBlock should return the correct block")
Expand Down
2 changes: 1 addition & 1 deletion go/runtime/host/mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (r *runtime) Call(ctx context.Context, body *protocol.Body) (*protocol.Body
}}, nil
default:
return &protocol.Body{RuntimeQueryResponse: &protocol.RuntimeQueryResponse{
Data: cbor.Marshal(rq.Method + " world"),
Data: cbor.Marshal(rq.Method + " world at:" + fmt.Sprintf("%d", rq.ConsensusBlock.Height)),
}}, nil
}
default:
Expand Down