diff --git a/client/client.go b/client/client.go index b28af84fa..504e181f4 100644 --- a/client/client.go +++ b/client/client.go @@ -544,3 +544,15 @@ func getEventsResult(res *access.EventsResponse) ([]BlockEvents, error) { return results, nil } + +// GetLatestProtocolStateSnapshot retrieves the latest snapshot of the protocol +// state in serialized form. This is used to generate a root snapshot file +// used by Flow nodes to bootstrap their local protocol state database. +func (c *Client) GetLatestProtocolStateSnapshot(ctx context.Context, opts ...grpc.CallOption) ([]byte, error) { + res, err := c.rpcClient.GetLatestProtocolStateSnapshot(ctx, &access.GetLatestProtocolStateSnapshotRequest{}, opts...) + if err != nil { + return nil, newRPCError(err) + } + + return res.GetSerializedSnapshot(), nil +} diff --git a/client/client_test.go b/client/client_test.go index 2f9ac7f97..4dec759a5 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -20,6 +20,7 @@ package client_test import ( "context" + "math/rand" "testing" "github.com/golang/protobuf/ptypes" @@ -812,3 +813,28 @@ func TestClient_GetEventsForBlockIDs(t *testing.T) { assert.Empty(t, blocks) })) } + +func TestClient_GetLatestProtocolStateSnapshot(t *testing.T) { + t.Run("Success", clientTest(func(t *testing.T, ctx context.Context, rpc *MockRPCClient, c *client.Client) { + expected := &access.ProtocolStateSnapshotResponse{ + SerializedSnapshot: make([]byte, 128), + } + _, err := rand.Read(expected.SerializedSnapshot) + assert.NoError(t, err) + + rpc.On("GetLatestProtocolStateSnapshot", ctx, mock.Anything).Return(expected, nil) + + res, err := c.GetLatestProtocolStateSnapshot(ctx) + assert.NoError(t, err) + assert.Equal(t, expected.SerializedSnapshot, res) + })) + + t.Run("Internal error", clientTest(func(t *testing.T, ctx context.Context, rpc *MockRPCClient, c *client.Client) { + rpc.On("GetLatestProtocolStateSnapshot", ctx, mock.Anything). + Return(nil, errInternal) + + _, err := c.GetLatestProtocolStateSnapshot(ctx) + assert.Error(t, err) + assert.Equal(t, codes.Internal, status.Code(err)) + })) +} diff --git a/client/mock_client_test.go b/client/mock_client_test.go index cab8436ba..00b5762c9 100644 --- a/client/mock_client_test.go +++ b/client/mock_client_test.go @@ -467,6 +467,36 @@ func (_m *MockRPCClient) GetLatestBlockHeader(ctx context.Context, in *access.Ge return r0, r1 } +// GetLatestProtocolStateSnapshot provides a mock function with given fields: ctx, in, opts +func (_m *MockRPCClient) GetLatestProtocolStateSnapshot(ctx context.Context, in *access.GetLatestProtocolStateSnapshotRequest, opts ...grpc.CallOption) (*access.ProtocolStateSnapshotResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *access.ProtocolStateSnapshotResponse + if rf, ok := ret.Get(0).(func(context.Context, *access.GetLatestProtocolStateSnapshotRequest, ...grpc.CallOption) *access.ProtocolStateSnapshotResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*access.ProtocolStateSnapshotResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *access.GetLatestProtocolStateSnapshotRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetNetworkParameters provides a mock function with given fields: ctx, in, opts func (_m *MockRPCClient) GetNetworkParameters(ctx context.Context, in *access.GetNetworkParametersRequest, opts ...grpc.CallOption) (*access.GetNetworkParametersResponse, error) { _va := make([]interface{}, len(opts)) diff --git a/go.mod b/go.mod index f07c0760a..25917228c 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/ethereum/go-ethereum v1.9.9 github.com/golang/protobuf v1.4.2 github.com/onflow/cadence v0.12.6 - github.com/onflow/flow/protobuf/go/flow v0.1.8 + github.com/onflow/flow/protobuf/go/flow v0.1.9 github.com/pkg/errors v0.8.1 github.com/stretchr/objx v0.1.1 // indirect github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 9a5dfdca6..eb7b7936e 100644 --- a/go.sum +++ b/go.sum @@ -225,8 +225,8 @@ github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXW github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onflow/cadence v0.12.6 h1:IvKSx5C84B4DGBf4DUAtLE2WtC24KAZR4z5XZyGGPYM= github.com/onflow/cadence v0.12.6/go.mod h1:CHQIgovf2fks/6kwrpBaatNarHxX5qJggynAbjEnSvQ= -github.com/onflow/flow/protobuf/go/flow v0.1.8 h1:jBR8aXEL0MOh3gVJmCr0KYXmtG3JUBhzADonKkYE6oI= -github.com/onflow/flow/protobuf/go/flow v0.1.8/go.mod h1:kRugbzZjwQqvevJhrnnCFMJZNmoSJmxlKt6hTGXZojM= +github.com/onflow/flow/protobuf/go/flow v0.1.9 h1:ugK6/9K4AkMxqPbCvQzbbV24AH50Ozze43nqpukQoOM= +github.com/onflow/flow/protobuf/go/flow v0.1.9/go.mod h1:kRugbzZjwQqvevJhrnnCFMJZNmoSJmxlKt6hTGXZojM= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=