From 49d712a4dadd00e2cb4f2bba920a675caa2d53ae Mon Sep 17 00:00:00 2001 From: ptrus Date: Mon, 23 Aug 2021 14:26:56 +0200 Subject: [PATCH] go/runtime: fix round in runtime query --- go/roothash/api/history.go | 3 +++ go/runtime/client/client.go | 31 +++++++++++++++--------------- go/runtime/client/tests/tester.go | 19 +++++++++++++++--- go/runtime/history/history.go | 11 +++++++++++ go/runtime/history/history_test.go | 13 +++++++++++++ go/runtime/host/mock/mock.go | 2 +- 6 files changed, 60 insertions(+), 19 deletions(-) diff --git a/go/roothash/api/history.go b/go/roothash/api/history.go index d8eee4476c2..3609d7bc0c7 100644 --- a/go/roothash/api/history.go +++ b/go/roothash/api/history.go @@ -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) diff --git a/go/runtime/client/client.go b/go/runtime/client/client.go index 96343d5f7c0..e582ce139aa 100644 --- a/go/runtime/client/client.go +++ b/go/runtime/client/client.go @@ -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 } diff --git a/go/runtime/client/tests/tester.go b/go/runtime/client/tests/tester.go index 81a6646975b..2d0c289d855 100644 --- a/go/runtime/client/tests/tester.go +++ b/go/runtime/client/tests/tester.go @@ -233,10 +233,23 @@ 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()") - 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()") + 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)") // Execute CheckTx using the mock runtime host. err = c.CheckTx(ctx, &api.CheckTxRequest{ diff --git a/go/runtime/history/history.go b/go/runtime/history/history.go index ec8e30c6499..70017a210ed 100644 --- a/go/runtime/history/history.go +++ b/go/runtime/history/history.go @@ -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 } @@ -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() diff --git a/go/runtime/history/history_test.go b/go/runtime/history/history_test.go index 57e81b6c07f..8b7b3875ef9 100644 --- a/go/runtime/history/history_test.go +++ b/go/runtime/history/history_test.go @@ -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) @@ -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") @@ -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") @@ -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") diff --git a/go/runtime/host/mock/mock.go b/go/runtime/host/mock/mock.go index f893d1d0668..e8630e681b7 100644 --- a/go/runtime/host/mock/mock.go +++ b/go/runtime/host/mock/mock.go @@ -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: