diff --git a/beacon-chain/rpc/beaconv1/BUILD.bazel b/beacon-chain/rpc/beaconv1/BUILD.bazel index 28aff268e643..13d83d710496 100644 --- a/beacon-chain/rpc/beaconv1/BUILD.bazel +++ b/beacon-chain/rpc/beaconv1/BUILD.bazel @@ -51,6 +51,7 @@ go_test( "blocks_test.go", "config_test.go", "server_test.go", + "state_test.go", ], embed = [":go_default_library"], deps = [ diff --git a/beacon-chain/rpc/beaconv1/state.go b/beacon-chain/rpc/beaconv1/state.go index ea61c00ebfb7..e632ef3846b6 100644 --- a/beacon-chain/rpc/beaconv1/state.go +++ b/beacon-chain/rpc/beaconv1/state.go @@ -1,16 +1,41 @@ package beaconv1 import ( + "bytes" "context" "errors" ptypes "github.com/gogo/protobuf/types" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1" + "github.com/prysmaticlabs/prysm/shared/params" + "go.opencensus.io/trace" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) // GetGenesis retrieves details of the chain's genesis which can be used to identify chain. func (bs *Server) GetGenesis(ctx context.Context, _ *ptypes.Empty) (*ethpb.GenesisResponse, error) { - return nil, errors.New("unimplemented") + ctx, span := trace.StartSpan(ctx, "beaconv1.GetGenesis") + defer span.End() + + genesisTime := bs.GenesisTimeFetcher.GenesisTime() + if genesisTime.IsZero() { + return nil, status.Errorf(codes.NotFound, "Chain genesis info is not yet known") + } + validatorRoot := bs.ChainInfoFetcher.GenesisValidatorRoot() + if bytes.Equal(validatorRoot[:], params.BeaconConfig().ZeroHash[:]) { + return nil, status.Errorf(codes.NotFound, "Chain genesis info is not yet known") + } + forkVersion := params.BeaconConfig().GenesisForkVersion + + return ðpb.GenesisResponse{ + GenesisTime: &ptypes.Timestamp{ + Seconds: genesisTime.Unix(), + Nanos: 0, + }, + GenesisValidatorsRoot: validatorRoot[:], + GenesisForkVersion: forkVersion, + }, nil } // GetStateRoot calculates HashTreeRoot for state with given 'stateId'. If stateId is root, same value will be returned. diff --git a/beacon-chain/rpc/beaconv1/state_test.go b/beacon-chain/rpc/beaconv1/state_test.go new file mode 100644 index 000000000000..f7e895ec3c0e --- /dev/null +++ b/beacon-chain/rpc/beaconv1/state_test.go @@ -0,0 +1,65 @@ +package beaconv1 + +import ( + "context" + "testing" + "time" + + ptypes "github.com/gogo/protobuf/types" + chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" + "github.com/prysmaticlabs/prysm/shared/params" + "github.com/prysmaticlabs/prysm/shared/testutil/assert" + "github.com/prysmaticlabs/prysm/shared/testutil/require" +) + +func TestGetGenesis(t *testing.T) { + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.GenesisForkVersion = []byte("genesis") + params.OverrideBeaconConfig(config) + genesis := time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC) + validatorsRoot := [32]byte{1, 2, 3, 4, 5, 6} + + t.Run("OK", func(t *testing.T) { + chainService := &chainMock.ChainService{ + Genesis: genesis, + ValidatorsRoot: validatorsRoot, + } + s := Server{ + GenesisTimeFetcher: chainService, + ChainInfoFetcher: chainService, + } + resp, err := s.GetGenesis(context.Background(), &ptypes.Empty{}) + require.NoError(t, err) + assert.Equal(t, genesis.Unix(), resp.GenesisTime.Seconds) + assert.Equal(t, int32(0), resp.GenesisTime.Nanos) + assert.DeepEqual(t, validatorsRoot[:], resp.GenesisValidatorsRoot) + assert.DeepEqual(t, []byte("genesis"), resp.GenesisForkVersion) + }) + + t.Run("No genesis time", func(t *testing.T) { + chainService := &chainMock.ChainService{ + Genesis: time.Time{}, + ValidatorsRoot: validatorsRoot, + } + s := Server{ + GenesisTimeFetcher: chainService, + ChainInfoFetcher: chainService, + } + _, err := s.GetGenesis(context.Background(), &ptypes.Empty{}) + assert.ErrorContains(t, "Chain genesis info is not yet known", err) + }) + + t.Run("No genesis validator root", func(t *testing.T) { + chainService := &chainMock.ChainService{ + Genesis: genesis, + ValidatorsRoot: [32]byte{}, + } + s := Server{ + GenesisTimeFetcher: chainService, + ChainInfoFetcher: chainService, + } + _, err := s.GetGenesis(context.Background(), &ptypes.Empty{}) + assert.ErrorContains(t, "Chain genesis info is not yet known", err) + }) +}