mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 07:58:22 -05:00
Add REST API endpoint for node client's GetGenesis (#12168)
* Add REST API endpoint for node client's GetGenesis * Remove unused parameter * Fix test name --------- Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
@@ -56,6 +56,7 @@ go_library(
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@io_bazel_rules_go//proto/wkt:empty_go_proto",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -66,6 +67,7 @@ go_test(
|
||||
"activation_test.go",
|
||||
"attestation_data_test.go",
|
||||
"beacon_api_helpers_test.go",
|
||||
"beacon_api_node_client_test.go",
|
||||
"beacon_api_validator_client_test.go",
|
||||
"beacon_block_converter_test.go",
|
||||
"beacon_block_json_helpers_test.go",
|
||||
@@ -118,5 +120,6 @@ go_test(
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@io_bazel_rules_go//proto/wkt:empty_go_proto",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -3,16 +3,22 @@ package beacon_api
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
type beaconApiNodeClient struct {
|
||||
fallbackClient iface.NodeClient
|
||||
jsonRestHandler jsonRestHandler
|
||||
genesisProvider genesisProvider
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) GetSyncStatus(ctx context.Context, in *empty.Empty) (*ethpb.SyncStatus, error) {
|
||||
@@ -24,13 +30,43 @@ func (c *beaconApiNodeClient) GetSyncStatus(ctx context.Context, in *empty.Empty
|
||||
panic("beaconApiNodeClient.GetSyncStatus is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiNodeClientWithFallback.")
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) GetGenesis(ctx context.Context, in *empty.Empty) (*ethpb.Genesis, error) {
|
||||
if c.fallbackClient != nil {
|
||||
return c.fallbackClient.GetGenesis(ctx, in)
|
||||
func (c *beaconApiNodeClient) GetGenesis(ctx context.Context, _ *empty.Empty) (*ethpb.Genesis, error) {
|
||||
genesisJson, _, err := c.genesisProvider.GetGenesis(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get genesis")
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
panic("beaconApiNodeClient.GetGenesis is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiNodeClientWithFallback.")
|
||||
genesisValidatorRoot, err := hexutil.Decode(genesisJson.GenesisValidatorsRoot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to decode genesis validator root `%s`", genesisJson.GenesisValidatorsRoot)
|
||||
}
|
||||
|
||||
genesisTime, err := strconv.ParseInt(genesisJson.GenesisTime, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse genesis time `%s`", genesisJson.GenesisTime)
|
||||
}
|
||||
|
||||
depositContractJson := apimiddleware.DepositContractResponseJson{}
|
||||
if _, err = c.jsonRestHandler.GetRestJsonResponse(ctx, "/eth/v1/config/deposit_contract", &depositContractJson); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to query deposit contract information")
|
||||
}
|
||||
|
||||
if depositContractJson.Data == nil {
|
||||
return nil, errors.New("deposit contract data is nil")
|
||||
}
|
||||
|
||||
depositContactAddress, err := hexutil.Decode(depositContractJson.Data.Address)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to decode deposit contract address `%s`", depositContractJson.Data.Address)
|
||||
}
|
||||
|
||||
return ðpb.Genesis{
|
||||
GenesisTime: ×tamppb.Timestamp{
|
||||
Seconds: genesisTime,
|
||||
},
|
||||
DepositContractAddress: depositContactAddress,
|
||||
GenesisValidatorsRoot: genesisValidatorRoot,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) GetVersion(ctx context.Context, in *empty.Empty) (*ethpb.Version, error) {
|
||||
@@ -60,5 +96,6 @@ func NewNodeClientWithFallback(host string, timeout time.Duration, fallbackClien
|
||||
return &beaconApiNodeClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
fallbackClient: fallbackClient,
|
||||
genesisProvider: beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler},
|
||||
}
|
||||
}
|
||||
|
||||
153
validator/client/beacon-api/beacon_api_node_client_test.go
Normal file
153
validator/client/beacon-api/beacon_api_node_client_test.go
Normal file
@@ -0,0 +1,153 @@
|
||||
package beacon_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/beacon-api/mock"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
func TestGetGenesis(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
genesisResponse *apimiddleware.GenesisResponse_GenesisJson
|
||||
genesisError error
|
||||
depositContractResponse apimiddleware.DepositContractResponseJson
|
||||
depositContractError error
|
||||
queriesDepositContract bool
|
||||
expectedResponse *ethpb.Genesis
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "fails to get genesis",
|
||||
genesisError: errors.New("foo error"),
|
||||
expectedError: "failed to get genesis: foo error",
|
||||
},
|
||||
{
|
||||
name: "fails to decode genesis validator root",
|
||||
genesisResponse: &apimiddleware.GenesisResponse_GenesisJson{
|
||||
GenesisTime: "1",
|
||||
GenesisValidatorsRoot: "foo",
|
||||
},
|
||||
expectedError: "failed to decode genesis validator root `foo`",
|
||||
},
|
||||
{
|
||||
name: "fails to parse genesis time",
|
||||
genesisResponse: &apimiddleware.GenesisResponse_GenesisJson{
|
||||
GenesisTime: "foo",
|
||||
GenesisValidatorsRoot: hexutil.Encode([]byte{1}),
|
||||
},
|
||||
expectedError: "failed to parse genesis time `foo`",
|
||||
},
|
||||
{
|
||||
name: "fails to query contract information",
|
||||
genesisResponse: &apimiddleware.GenesisResponse_GenesisJson{
|
||||
GenesisTime: "1",
|
||||
GenesisValidatorsRoot: hexutil.Encode([]byte{2}),
|
||||
},
|
||||
depositContractError: errors.New("foo error"),
|
||||
queriesDepositContract: true,
|
||||
expectedError: "failed to query deposit contract information: foo error",
|
||||
},
|
||||
{
|
||||
name: "fails to read nil deposit contract data",
|
||||
genesisResponse: &apimiddleware.GenesisResponse_GenesisJson{
|
||||
GenesisTime: "1",
|
||||
GenesisValidatorsRoot: hexutil.Encode([]byte{2}),
|
||||
},
|
||||
queriesDepositContract: true,
|
||||
depositContractResponse: apimiddleware.DepositContractResponseJson{
|
||||
Data: nil,
|
||||
},
|
||||
expectedError: "deposit contract data is nil",
|
||||
},
|
||||
{
|
||||
name: "fails to decode deposit contract address",
|
||||
genesisResponse: &apimiddleware.GenesisResponse_GenesisJson{
|
||||
GenesisTime: "1",
|
||||
GenesisValidatorsRoot: hexutil.Encode([]byte{2}),
|
||||
},
|
||||
queriesDepositContract: true,
|
||||
depositContractResponse: apimiddleware.DepositContractResponseJson{
|
||||
Data: &apimiddleware.DepositContractJson{
|
||||
Address: "foo",
|
||||
},
|
||||
},
|
||||
expectedError: "failed to decode deposit contract address `foo`",
|
||||
},
|
||||
{
|
||||
name: "successfully retrieves genesis info",
|
||||
genesisResponse: &apimiddleware.GenesisResponse_GenesisJson{
|
||||
GenesisTime: "654812",
|
||||
GenesisValidatorsRoot: hexutil.Encode([]byte{2}),
|
||||
},
|
||||
queriesDepositContract: true,
|
||||
depositContractResponse: apimiddleware.DepositContractResponseJson{
|
||||
Data: &apimiddleware.DepositContractJson{
|
||||
Address: hexutil.Encode([]byte{3}),
|
||||
},
|
||||
},
|
||||
expectedResponse: ðpb.Genesis{
|
||||
GenesisTime: ×tamppb.Timestamp{
|
||||
Seconds: 654812,
|
||||
},
|
||||
DepositContractAddress: []byte{3},
|
||||
GenesisValidatorsRoot: []byte{2},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
ctx := context.Background()
|
||||
|
||||
genesisProvider := mock.NewMockgenesisProvider(ctrl)
|
||||
genesisProvider.EXPECT().GetGenesis(
|
||||
ctx,
|
||||
).Return(
|
||||
testCase.genesisResponse,
|
||||
nil,
|
||||
testCase.genesisError,
|
||||
)
|
||||
|
||||
depositContractJson := apimiddleware.DepositContractResponseJson{}
|
||||
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||
|
||||
if testCase.queriesDepositContract {
|
||||
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||
ctx,
|
||||
"/eth/v1/config/deposit_contract",
|
||||
&depositContractJson,
|
||||
).Return(
|
||||
nil,
|
||||
testCase.depositContractError,
|
||||
).SetArg(
|
||||
2,
|
||||
testCase.depositContractResponse,
|
||||
)
|
||||
}
|
||||
|
||||
nodeClient := &beaconApiNodeClient{
|
||||
genesisProvider: genesisProvider,
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
response, err := nodeClient.GetGenesis(ctx, &emptypb.Empty{})
|
||||
|
||||
if testCase.expectedResponse == nil {
|
||||
assert.ErrorContains(t, testCase.expectedError, err)
|
||||
} else {
|
||||
assert.DeepEqual(t, testCase.expectedResponse, response)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user