adding ssz for get block endpoint (#15390)

* adding get ssz

* adding some tests

* gaz

* adding ssz to e2e

* wip ssz

* adding in additional check on header type

* remove unused

* renaming json rest handler, and adding in usage of use ssz debug flag

* fixing unit tests

* fixing tests

* gaz

* radek feedback

* Update config/features/config.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/features/flags.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/features/flags.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update validator/client/beacon-api/get_beacon_block.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update validator/client/beacon-api/get_beacon_block.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update validator/client/beacon-api/get_beacon_block.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* addressing feedback

* missing import

* another missing import

* fixing tests

* gaz

* removing unused

* gaz

* more radek feedback

* fixing context

* adding in check for non accepted conent type

* reverting to not create more edgecases

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
james-prysm
2025-06-20 09:27:09 -05:00
committed by GitHub
parent b9fd32dfff
commit d63ae69920
26 changed files with 1200 additions and 284 deletions

View File

@@ -0,0 +1,7 @@
### Added
- New ssz-only flag for validator client to enable calling rest apis in SSZ, starting with get block endpoint.
### Changed
- when REST api is enabled the get Block api defaults to requesting and receiving SSZ instead of JSON, JSON is the fallback.

View File

@@ -52,6 +52,7 @@ type Flags struct {
EnableExperimentalAttestationPool bool // EnableExperimentalAttestationPool enables an experimental attestation pool design. EnableExperimentalAttestationPool bool // EnableExperimentalAttestationPool enables an experimental attestation pool design.
EnableDutiesV2 bool // EnableDutiesV2 sets validator client to use the get Duties V2 endpoint EnableDutiesV2 bool // EnableDutiesV2 sets validator client to use the get Duties V2 endpoint
EnableWeb bool // EnableWeb enables the webui on the validator client EnableWeb bool // EnableWeb enables the webui on the validator client
SSZOnly bool // SSZOnly forces the validator client to use SSZ for communication with the beacon node when REST mode is enabled (useful for debugging)
// Logging related toggles. // Logging related toggles.
DisableGRPCConnectionLogs bool // Disables logging when a new grpc client has connected. DisableGRPCConnectionLogs bool // Disables logging when a new grpc client has connected.
EnableFullSSZDataLogging bool // Enables logging for full ssz data on rejected gossip messages EnableFullSSZDataLogging bool // Enables logging for full ssz data on rejected gossip messages
@@ -344,6 +345,11 @@ func ConfigureValidator(ctx *cli.Context) error {
logEnabled(EnableWebFlag) logEnabled(EnableWebFlag)
cfg.EnableWeb = true cfg.EnableWeb = true
} }
if ctx.Bool(SSZOnly.Name) {
logEnabled(SSZOnly)
cfg.SSZOnly = true
}
cfg.KeystoreImportDebounceInterval = ctx.Duration(dynamicKeyReloadDebounceInterval.Name) cfg.KeystoreImportDebounceInterval = ctx.Duration(dynamicKeyReloadDebounceInterval.Name)
Init(cfg) Init(cfg)
return nil return nil

View File

@@ -201,6 +201,12 @@ var (
Usage: "(Work in progress): Enables the web portal for the validator client.", Usage: "(Work in progress): Enables the web portal for the validator client.",
Value: false, Value: false,
} }
// SSZOnly forces the validator client to use SSZ for communication with the beacon node when REST mode is enabled
SSZOnly = &cli.BoolFlag{
Name: "ssz-only",
Usage: "(debug): Forces the validator client to use SSZ for communication with the beacon node when REST mode is enabled",
}
) )
// devModeFlags holds list of flags that are set when development mode is on. // devModeFlags holds list of flags that are set when development mode is on.
@@ -223,6 +229,7 @@ var ValidatorFlags = append(deprecatedFlags, []cli.Flag{
EnableBeaconRESTApi, EnableBeaconRESTApi,
EnableDutiesV2, EnableDutiesV2,
EnableWebFlag, EnableWebFlag,
SSZOnly,
}...) }...)
// E2EValidatorFlags contains a list of the validator feature flags to be tested in E2E. // E2EValidatorFlags contains a list of the validator feature flags to be tested in E2E.

View File

@@ -5,6 +5,12 @@ import (
enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1" enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1"
) )
// GenericConverter defines any struct that can be converted to a generic beacon block.
// We assume all your versioned block structs implement this method.
type GenericConverter interface {
ToGeneric() (*GenericBeaconBlock, error)
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Phase 0 // Phase 0
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -248,6 +248,9 @@ func (v *ValidatorNode) Start(ctx context.Context) error {
args = append(args, args = append(args,
fmt.Sprintf("--%s=http://localhost:%d", flags.BeaconRESTApiProviderFlag.Name, beaconRestApiPort), fmt.Sprintf("--%s=http://localhost:%d", flags.BeaconRESTApiProviderFlag.Name, beaconRestApiPort),
fmt.Sprintf("--%s", features.EnableBeaconRESTApi.Name)) fmt.Sprintf("--%s", features.EnableBeaconRESTApi.Name))
if v.config.UseSSZOnly {
args = append(args, fmt.Sprintf("--%s", features.SSZOnly.Name))
}
} }
// Only apply e2e flags to the current branch. New flags may not exist in previous release. // Only apply e2e flags to the current branch. New flags may not exist in previous release.

View File

@@ -29,6 +29,10 @@ func TestEndToEnd_MinimalConfig_ValidatorRESTApi(t *testing.T) {
e2eMinimal(t, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2ETestConfig()), types.WithCheckpointSync(), types.WithValidatorRESTApi()).run() e2eMinimal(t, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2ETestConfig()), types.WithCheckpointSync(), types.WithValidatorRESTApi()).run()
} }
func TestEndToEnd_MinimalConfig_ValidatorRESTApi_SSZ(t *testing.T) {
e2eMinimal(t, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2ETestConfig()), types.WithCheckpointSync(), types.WithValidatorRESTApi(), types.WithSSZOnly()).run()
}
func TestEndToEnd_ScenarioRun_EEOffline(t *testing.T) { func TestEndToEnd_ScenarioRun_EEOffline(t *testing.T) {
t.Skip("TODO(#10242) Prysm is current unable to handle an offline e2e") t.Skip("TODO(#10242) Prysm is current unable to handle an offline e2e")
cfg := types.InitForkCfg(version.Bellatrix, version.Deneb, params.E2ETestConfig()) cfg := types.InitForkCfg(version.Bellatrix, version.Deneb, params.E2ETestConfig())

View File

@@ -51,6 +51,12 @@ func WithValidatorRESTApi() E2EConfigOpt {
} }
} }
func WithSSZOnly() E2EConfigOpt {
return func(cfg *E2EConfig) {
cfg.UseSSZOnly = true
}
}
func WithBuilder() E2EConfigOpt { func WithBuilder() E2EConfigOpt {
return func(cfg *E2EConfig) { return func(cfg *E2EConfig) {
cfg.UseBuilder = true cfg.UseBuilder = true
@@ -70,6 +76,7 @@ type E2EConfig struct {
UseFixedPeerIDs bool UseFixedPeerIDs bool
UseValidatorCrossClient bool UseValidatorCrossClient bool
UseBeaconRestApi bool UseBeaconRestApi bool
UseSSZOnly bool
UseBuilder bool UseBuilder bool
EpochsToRun uint64 EpochsToRun uint64
Seed int64 Seed int64

View File

@@ -87,7 +87,7 @@ func (acm *CLIManager) prepareBeaconClients(ctx context.Context) (*iface.Validat
acm.beaconApiTimeout, acm.beaconApiTimeout,
) )
restHandler := beaconApi.NewBeaconApiJsonRestHandler( restHandler := beaconApi.NewBeaconApiRestHandler(
http.Client{Timeout: acm.beaconApiTimeout}, http.Client{Timeout: acm.beaconApiTimeout},
acm.beaconApiEndpoint, acm.beaconApiEndpoint,
) )

View File

@@ -18,7 +18,6 @@ go_library(
"genesis.go", "genesis.go",
"get_beacon_block.go", "get_beacon_block.go",
"index.go", "index.go",
"json_rest_handler.go",
"log.go", "log.go",
"metrics.go", "metrics.go",
"prepare_beacon_proposer.go", "prepare_beacon_proposer.go",
@@ -27,6 +26,7 @@ go_library(
"propose_exit.go", "propose_exit.go",
"prysm_beacon_chain_client.go", "prysm_beacon_chain_client.go",
"registration.go", "registration.go",
"rest_handler_client.go",
"state_validators.go", "state_validators.go",
"status.go", "status.go",
"stream_blocks.go", "stream_blocks.go",
@@ -47,6 +47,7 @@ go_library(
"//api/server/structs:go_default_library", "//api/server/structs:go_default_library",
"//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/signing:go_default_library",
"//config/features:go_default_library",
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
@@ -91,7 +92,6 @@ go_test(
"genesis_test.go", "genesis_test.go",
"get_beacon_block_test.go", "get_beacon_block_test.go",
"index_test.go", "index_test.go",
"json_rest_handler_test.go",
"prepare_beacon_proposer_test.go", "prepare_beacon_proposer_test.go",
"propose_attestation_test.go", "propose_attestation_test.go",
"propose_beacon_block_altair_test.go", "propose_beacon_block_altair_test.go",
@@ -110,6 +110,7 @@ go_test(
"propose_exit_test.go", "propose_exit_test.go",
"prysm_beacon_chain_client_test.go", "prysm_beacon_chain_client_test.go",
"registration_test.go", "registration_test.go",
"rest_handler_client_test.go",
"state_validators_test.go", "state_validators_test.go",
"status_test.go", "status_test.go",
"stream_blocks_test.go", "stream_blocks_test.go",
@@ -128,6 +129,7 @@ go_test(
"//api/server/structs:go_default_library", "//api/server/structs:go_default_library",
"//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/rpc/eth/shared/testing:go_default_library", "//beacon-chain/rpc/eth/shared/testing:go_default_library",
"//config/features:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//consensus-types/validator:go_default_library", "//consensus-types/validator:go_default_library",
@@ -145,6 +147,8 @@ go_test(
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_golang_protobuf//ptypes/empty", "@com_github_golang_protobuf//ptypes/empty",
"@com_github_pkg_errors//:go_default_library", "@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library", "@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
"@org_uber_go_mock//gomock:go_default_library", "@org_uber_go_mock//gomock:go_default_library",

View File

@@ -17,7 +17,7 @@ import (
type beaconApiChainClient struct { type beaconApiChainClient struct {
fallbackClient iface.ChainClient fallbackClient iface.ChainClient
jsonRestHandler JsonRestHandler jsonRestHandler RestHandler
stateValidatorsProvider StateValidatorsProvider stateValidatorsProvider StateValidatorsProvider
} }
@@ -333,7 +333,7 @@ func (c beaconApiChainClient) ValidatorParticipation(ctx context.Context, in *et
return nil, errors.New("beaconApiChainClient.ValidatorParticipation is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.") return nil, errors.New("beaconApiChainClient.ValidatorParticipation is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
} }
func NewBeaconApiChainClientWithFallback(jsonRestHandler JsonRestHandler, fallbackClient iface.ChainClient) iface.ChainClient { func NewBeaconApiChainClientWithFallback(jsonRestHandler RestHandler, fallbackClient iface.ChainClient) iface.ChainClient {
return &beaconApiChainClient{ return &beaconApiChainClient{
jsonRestHandler: jsonRestHandler, jsonRestHandler: jsonRestHandler,
fallbackClient: fallbackClient, fallbackClient: fallbackClient,

View File

@@ -20,7 +20,7 @@ var (
type beaconApiNodeClient struct { type beaconApiNodeClient struct {
fallbackClient iface.NodeClient fallbackClient iface.NodeClient
jsonRestHandler JsonRestHandler jsonRestHandler RestHandler
genesisProvider GenesisProvider genesisProvider GenesisProvider
healthTracker health.Tracker healthTracker health.Tracker
} }
@@ -111,7 +111,7 @@ func (c *beaconApiNodeClient) HealthTracker() health.Tracker {
return c.healthTracker return c.healthTracker
} }
func NewNodeClientWithFallback(jsonRestHandler JsonRestHandler, fallbackClient iface.NodeClient) iface.NodeClient { func NewNodeClientWithFallback(jsonRestHandler RestHandler, fallbackClient iface.NodeClient) iface.NodeClient {
b := &beaconApiNodeClient{ b := &beaconApiNodeClient{
jsonRestHandler: jsonRestHandler, jsonRestHandler: jsonRestHandler,
fallbackClient: fallbackClient, fallbackClient: fallbackClient,

View File

@@ -22,13 +22,13 @@ type beaconApiValidatorClient struct {
genesisProvider GenesisProvider genesisProvider GenesisProvider
dutiesProvider dutiesProvider dutiesProvider dutiesProvider
stateValidatorsProvider StateValidatorsProvider stateValidatorsProvider StateValidatorsProvider
jsonRestHandler JsonRestHandler jsonRestHandler RestHandler
beaconBlockConverter BeaconBlockConverter beaconBlockConverter BeaconBlockConverter
prysmChainClient iface.PrysmChainClient prysmChainClient iface.PrysmChainClient
isEventStreamRunning bool isEventStreamRunning bool
} }
func NewBeaconApiValidatorClient(jsonRestHandler JsonRestHandler, opts ...ValidatorClientOpt) iface.ValidatorClient { func NewBeaconApiValidatorClient(jsonRestHandler RestHandler, opts ...ValidatorClientOpt) iface.ValidatorClient {
c := &beaconApiValidatorClient{ c := &beaconApiValidatorClient{
genesisProvider: &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler}, genesisProvider: &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler},
dutiesProvider: beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}, dutiesProvider: beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler},

View File

@@ -27,7 +27,7 @@ type dutiesProvider interface {
} }
type beaconApiDutiesProvider struct { type beaconApiDutiesProvider struct {
jsonRestHandler JsonRestHandler jsonRestHandler RestHandler
} }
type attesterDuty struct { type attesterDuty struct {

View File

@@ -20,7 +20,7 @@ type GenesisProvider interface {
} }
type beaconApiGenesisProvider struct { type beaconApiGenesisProvider struct {
jsonRestHandler JsonRestHandler jsonRestHandler RestHandler
genesis *structs.Genesis genesis *structs.Genesis
once sync.Once once sync.Once
} }

View File

@@ -6,7 +6,10 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
neturl "net/url" neturl "net/url"
"strconv"
"strings"
"github.com/OffchainLabs/prysm/v6/api"
"github.com/OffchainLabs/prysm/v6/api/apiutil" "github.com/OffchainLabs/prysm/v6/api/apiutil"
"github.com/OffchainLabs/prysm/v6/api/server/structs" "github.com/OffchainLabs/prysm/v6/api/server/structs"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
@@ -22,160 +25,224 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti
if len(graffiti) > 0 { if len(graffiti) > 0 {
queryParams.Add("graffiti", hexutil.Encode(graffiti)) queryParams.Add("graffiti", hexutil.Encode(graffiti))
} }
queryUrl := apiutil.BuildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), queryParams) queryUrl := apiutil.BuildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), queryParams)
produceBlockV3ResponseJson := structs.ProduceBlockV3Response{} data, header, err := c.jsonRestHandler.GetSSZ(ctx, queryUrl)
err := c.jsonRestHandler.Get(ctx, queryUrl, &produceBlockV3ResponseJson)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if strings.Contains(header.Get("Content-Type"), api.OctetStreamMediaType) {
return processBlockResponse( ver, err := version.FromString(header.Get(api.VersionHeader))
produceBlockV3ResponseJson.Version, if err != nil {
produceBlockV3ResponseJson.ExecutionPayloadBlinded, return nil, errors.Wrap(err, fmt.Sprintf("unsupported header version %s", header.Get(api.VersionHeader)))
json.NewDecoder(bytes.NewReader(produceBlockV3ResponseJson.Data)), }
) isBlindedRaw := header.Get(api.ExecutionPayloadBlindedHeader)
isBlinded, err := strconv.ParseBool(isBlindedRaw)
if err != nil {
return nil, err
}
return processBlockSSZResponse(ver, data, isBlinded)
} else {
decoder := json.NewDecoder(bytes.NewBuffer(data))
produceBlockV3ResponseJson := structs.ProduceBlockV3Response{}
if err = decoder.Decode(&produceBlockV3ResponseJson); err != nil {
return nil, errors.Wrapf(err, "failed to decode response body into json for %s", queryUrl)
}
return processBlockJSONResponse(
produceBlockV3ResponseJson.Version,
produceBlockV3ResponseJson.ExecutionPayloadBlinded,
json.NewDecoder(bytes.NewReader(produceBlockV3ResponseJson.Data)),
)
}
} }
// nolint: gocognit func processBlockSSZResponse(ver int, data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
func processBlockResponse(ver string, isBlinded bool, decoder *json.Decoder) (*ethpb.GenericBeaconBlock, error) { if ver >= version.Fulu {
var response *ethpb.GenericBeaconBlock return processBlockSSZResponseFulu(data, isBlinded)
}
if ver >= version.Electra {
return processBlockSSZResponseElectra(data, isBlinded)
}
if ver >= version.Deneb {
return processBlockSSZResponseDeneb(data, isBlinded)
}
if ver >= version.Capella {
return processBlockSSZResponseCapella(data, isBlinded)
}
if ver >= version.Bellatrix {
return processBlockSSZResponseBellatrix(data, isBlinded)
}
if ver >= version.Altair {
block := &ethpb.BeaconBlockAltair{}
if err := block.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Altair{Altair: block}}, nil
}
if ver >= version.Phase0 {
block := &ethpb.BeaconBlock{}
if err := block.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Phase0{Phase0: block}}, nil
}
return nil, fmt.Errorf("unsupported block version %s", version.String(ver))
}
func processBlockSSZResponseFulu(data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
if isBlinded {
blindedBlock := &ethpb.BlindedBeaconBlockFulu{}
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedFulu{BlindedFulu: blindedBlock}, IsBlinded: true}, nil
}
block := &ethpb.BeaconBlockContentsFulu{}
if err := block.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Fulu{Fulu: block}}, nil
}
func processBlockSSZResponseElectra(data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
if isBlinded {
blindedBlock := &ethpb.BlindedBeaconBlockElectra{}
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedElectra{BlindedElectra: blindedBlock}, IsBlinded: true}, nil
}
block := &ethpb.BeaconBlockContentsElectra{}
if err := block.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Electra{Electra: block}}, nil
}
func processBlockSSZResponseDeneb(data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
if isBlinded {
blindedBlock := &ethpb.BlindedBeaconBlockDeneb{}
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedDeneb{BlindedDeneb: blindedBlock}, IsBlinded: true}, nil
}
block := &ethpb.BeaconBlockContentsDeneb{}
if err := block.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Deneb{Deneb: block}}, nil
}
func processBlockSSZResponseCapella(data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
if isBlinded {
blindedBlock := &ethpb.BlindedBeaconBlockCapella{}
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedCapella{BlindedCapella: blindedBlock}, IsBlinded: true}, nil
}
block := &ethpb.BeaconBlockCapella{}
if err := block.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Capella{Capella: block}}, nil
}
func processBlockSSZResponseBellatrix(data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
if isBlinded {
blindedBlock := &ethpb.BlindedBeaconBlockBellatrix{}
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: blindedBlock}, IsBlinded: true}, nil
}
block := &ethpb.BeaconBlockBellatrix{}
if err := block.UnmarshalSSZ(data); err != nil {
return nil, err
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Bellatrix{Bellatrix: block}}, nil
}
func convertBlockToGeneric(decoder *json.Decoder, dest ethpb.GenericConverter, version string, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
typeName := version
if isBlinded {
typeName = "blinded " + typeName
}
if err := decoder.Decode(dest); err != nil {
return nil, errors.Wrapf(err, "failed to decode %s block response json", typeName)
}
genericBlock, err := dest.ToGeneric()
if err != nil {
return nil, errors.Wrapf(err, "failed to convert %s block", typeName)
}
return genericBlock, nil
}
func processBlockJSONResponse(ver string, isBlinded bool, decoder *json.Decoder) (*ethpb.GenericBeaconBlock, error) {
if decoder == nil { if decoder == nil {
return nil, errors.New("no produce block json decoder found") return nil, errors.New("no produce block json decoder found")
} }
switch ver { switch ver {
case version.String(version.Phase0): case version.String(version.Phase0):
jsonPhase0Block := structs.BeaconBlock{} return convertBlockToGeneric(decoder, &structs.BeaconBlock{}, version.String(version.Phase0), false)
if err := decoder.Decode(&jsonPhase0Block); err != nil {
return nil, errors.Wrap(err, "failed to decode phase0 block response json")
}
genericBlock, err := jsonPhase0Block.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get phase0 block")
}
response = genericBlock
case version.String(version.Altair): case version.String(version.Altair):
jsonAltairBlock := structs.BeaconBlockAltair{} return convertBlockToGeneric(decoder, &structs.BeaconBlockAltair{}, "altair", false)
if err := decoder.Decode(&jsonAltairBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode altair block response json")
}
genericBlock, err := jsonAltairBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get altair block")
}
response = genericBlock
case version.String(version.Bellatrix): case version.String(version.Bellatrix):
if isBlinded { return processBellatrixBlock(decoder, isBlinded)
jsonBellatrixBlock := structs.BlindedBeaconBlockBellatrix{}
if err := decoder.Decode(&jsonBellatrixBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode blinded bellatrix block response json")
}
genericBlock, err := jsonBellatrixBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get blinded bellatrix block")
}
response = genericBlock
} else {
jsonBellatrixBlock := structs.BeaconBlockBellatrix{}
if err := decoder.Decode(&jsonBellatrixBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode bellatrix block response json")
}
genericBlock, err := jsonBellatrixBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get bellatrix block")
}
response = genericBlock
}
case version.String(version.Capella): case version.String(version.Capella):
if isBlinded { return processCapellaBlock(decoder, isBlinded)
jsonCapellaBlock := structs.BlindedBeaconBlockCapella{}
if err := decoder.Decode(&jsonCapellaBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode blinded capella block response json")
}
genericBlock, err := jsonCapellaBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get blinded capella block")
}
response = genericBlock
} else {
jsonCapellaBlock := structs.BeaconBlockCapella{}
if err := decoder.Decode(&jsonCapellaBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode capella block response json")
}
genericBlock, err := jsonCapellaBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get capella block")
}
response = genericBlock
}
case version.String(version.Deneb): case version.String(version.Deneb):
if isBlinded { return processDenebBlock(decoder, isBlinded)
jsonDenebBlock := structs.BlindedBeaconBlockDeneb{}
if err := decoder.Decode(&jsonDenebBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode blinded deneb block response json")
}
genericBlock, err := jsonDenebBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get blinded deneb block")
}
response = genericBlock
} else {
jsonDenebBlockContents := structs.BeaconBlockContentsDeneb{}
if err := decoder.Decode(&jsonDenebBlockContents); err != nil {
return nil, errors.Wrap(err, "failed to decode deneb block response json")
}
genericBlock, err := jsonDenebBlockContents.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get deneb block")
}
response = genericBlock
}
case version.String(version.Electra): case version.String(version.Electra):
if isBlinded { return processElectraBlock(decoder, isBlinded)
jsonElectraBlock := structs.BlindedBeaconBlockElectra{}
if err := decoder.Decode(&jsonElectraBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode blinded electra block response json")
}
genericBlock, err := jsonElectraBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get blinded electra block")
}
response = genericBlock
} else {
jsonElectraBlockContents := structs.BeaconBlockContentsElectra{}
if err := decoder.Decode(&jsonElectraBlockContents); err != nil {
return nil, errors.Wrap(err, "failed to decode electra block response json")
}
genericBlock, err := jsonElectraBlockContents.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get electra block")
}
response = genericBlock
}
case version.String(version.Fulu): case version.String(version.Fulu):
if isBlinded { return processFuluBlock(decoder, isBlinded)
jsonFuluBlock := structs.BlindedBeaconBlockFulu{}
if err := decoder.Decode(&jsonFuluBlock); err != nil {
return nil, errors.Wrap(err, "failed to decode blinded fulu block response json")
}
genericBlock, err := jsonFuluBlock.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get blinded fulu block")
}
response = genericBlock
} else {
jsonFuluBlockContents := structs.BeaconBlockContentsFulu{}
if err := decoder.Decode(&jsonFuluBlockContents); err != nil {
return nil, errors.Wrap(err, "failed to decode fulu block response json")
}
genericBlock, err := jsonFuluBlockContents.ToGeneric()
if err != nil {
return nil, errors.Wrap(err, "failed to get fulu block")
}
response = genericBlock
}
default: default:
return nil, errors.Errorf("unsupported consensus version `%s`", ver) return nil, errors.Errorf("unsupported consensus version `%s`", ver)
} }
return response, nil }
func processBellatrixBlock(decoder *json.Decoder, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
if isBlinded {
return convertBlockToGeneric(decoder, &structs.BlindedBeaconBlockBellatrix{}, "bellatrix", true)
}
return convertBlockToGeneric(decoder, &structs.BeaconBlockBellatrix{}, "bellatrix", false)
}
func processCapellaBlock(decoder *json.Decoder, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
if isBlinded {
return convertBlockToGeneric(decoder, &structs.BlindedBeaconBlockCapella{}, "capella", true)
}
return convertBlockToGeneric(decoder, &structs.BeaconBlockCapella{}, "capella", false)
}
func processDenebBlock(decoder *json.Decoder, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
if isBlinded {
return convertBlockToGeneric(decoder, &structs.BlindedBeaconBlockDeneb{}, "deneb", true)
}
return convertBlockToGeneric(decoder, &structs.BeaconBlockContentsDeneb{}, "deneb", false)
}
func processElectraBlock(decoder *json.Decoder, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
if isBlinded {
return convertBlockToGeneric(decoder, &structs.BlindedBeaconBlockElectra{}, "electra", true)
}
return convertBlockToGeneric(decoder, &structs.BeaconBlockContentsElectra{}, "electra", false)
}
func processFuluBlock(decoder *json.Decoder, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
if isBlinded {
return convertBlockToGeneric(decoder, &structs.BlindedBeaconBlockFulu{}, "fulu", true)
}
return convertBlockToGeneric(decoder, &structs.BeaconBlockContentsFulu{}, "fulu", false)
} }

File diff suppressed because it is too large Load Diff

View File

@@ -56,6 +56,23 @@ func (mr *MockJsonRestHandlerMockRecorder) Get(ctx, endpoint, resp any) *gomock.
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockJsonRestHandler)(nil).Get), ctx, endpoint, resp) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockJsonRestHandler)(nil).Get), ctx, endpoint, resp)
} }
// GetSSZ mocks base method.
func (m *MockJsonRestHandler) GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSSZ", ctx, endpoint)
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(http.Header)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
// GetSSZ indicates an expected call of GetSSZ.
func (mr *MockJsonRestHandlerMockRecorder) GetSSZ(ctx, endpoint any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSSZ", reflect.TypeOf((*MockJsonRestHandler)(nil).GetSSZ), ctx, endpoint)
}
// Host mocks base method. // Host mocks base method.
func (m *MockJsonRestHandler) Host() string { func (m *MockJsonRestHandler) Host() string {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View File

@@ -18,7 +18,7 @@ import (
) )
// NewPrysmChainClient returns implementation of iface.PrysmChainClient. // NewPrysmChainClient returns implementation of iface.PrysmChainClient.
func NewPrysmChainClient(jsonRestHandler JsonRestHandler, nodeClient iface.NodeClient) iface.PrysmChainClient { func NewPrysmChainClient(jsonRestHandler RestHandler, nodeClient iface.NodeClient) iface.PrysmChainClient {
return prysmChainClient{ return prysmChainClient{
jsonRestHandler: jsonRestHandler, jsonRestHandler: jsonRestHandler,
nodeClient: nodeClient, nodeClient: nodeClient,
@@ -26,7 +26,7 @@ func NewPrysmChainClient(jsonRestHandler JsonRestHandler, nodeClient iface.NodeC
} }
type prysmChainClient struct { type prysmChainClient struct {
jsonRestHandler JsonRestHandler jsonRestHandler RestHandler
nodeClient iface.NodeClient nodeClient iface.NodeClient
} }

View File

@@ -4,49 +4,53 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"net/http" "net/http"
"strings" "strings"
"github.com/OffchainLabs/prysm/v6/api" "github.com/OffchainLabs/prysm/v6/api"
"github.com/OffchainLabs/prysm/v6/config/features"
"github.com/OffchainLabs/prysm/v6/network/httputil" "github.com/OffchainLabs/prysm/v6/network/httputil"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus"
) )
type JsonRestHandler interface { type RestHandler interface {
Get(ctx context.Context, endpoint string, resp interface{}) error Get(ctx context.Context, endpoint string, resp interface{}) error
GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error)
Post(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer, resp interface{}) error Post(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer, resp interface{}) error
HttpClient() *http.Client HttpClient() *http.Client
Host() string Host() string
SetHost(host string) SetHost(host string)
} }
type BeaconApiJsonRestHandler struct { type BeaconApiRestHandler struct {
client http.Client client http.Client
host string host string
} }
// NewBeaconApiJsonRestHandler returns a JsonRestHandler // NewBeaconApiRestHandler returns a RestHandler
func NewBeaconApiJsonRestHandler(client http.Client, host string) JsonRestHandler { func NewBeaconApiRestHandler(client http.Client, host string) RestHandler {
return &BeaconApiJsonRestHandler{ return &BeaconApiRestHandler{
client: client, client: client,
host: host, host: host,
} }
} }
// HttpClient returns the underlying HTTP client of the handler // HttpClient returns the underlying HTTP client of the handler
func (c *BeaconApiJsonRestHandler) HttpClient() *http.Client { func (c *BeaconApiRestHandler) HttpClient() *http.Client {
return &c.client return &c.client
} }
// Host returns the underlying HTTP host // Host returns the underlying HTTP host
func (c *BeaconApiJsonRestHandler) Host() string { func (c *BeaconApiRestHandler) Host() string {
return c.host return c.host
} }
// Get sends a GET request and decodes the response body as a JSON object into the passed in object. // Get sends a GET request and decodes the response body as a JSON object into the passed in object.
// If an HTTP error is returned, the body is decoded as a DefaultJsonError JSON object and returned as the first return value. // If an HTTP error is returned, the body is decoded as a DefaultJsonError JSON object and returned as the first return value.
func (c *BeaconApiJsonRestHandler) Get(ctx context.Context, endpoint string, resp interface{}) error { func (c *BeaconApiRestHandler) Get(ctx context.Context, endpoint string, resp interface{}) error {
url := c.host + endpoint url := c.host + endpoint
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil { if err != nil {
@@ -66,9 +70,61 @@ func (c *BeaconApiJsonRestHandler) Get(ctx context.Context, endpoint string, res
return decodeResp(httpResp, resp) return decodeResp(httpResp, resp)
} }
func (c *BeaconApiRestHandler) GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error) {
url := c.host + endpoint
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed to create request for endpoint %s", url)
}
primaryAcceptType := fmt.Sprintf("%s;q=%s", api.OctetStreamMediaType, "0.95")
secondaryAcceptType := fmt.Sprintf("%s;q=%s", api.JsonMediaType, "0.9")
acceptHeaderString := fmt.Sprintf("%s,%s", primaryAcceptType, secondaryAcceptType)
if features.Get().SSZOnly {
acceptHeaderString = api.OctetStreamMediaType
}
req.Header.Set("Accept", acceptHeaderString)
httpResp, err := c.client.Do(req)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed to perform request for endpoint %s", url)
}
defer func() {
if err := httpResp.Body.Close(); err != nil {
return
}
}()
contentType := httpResp.Header.Get("Content-Type")
body, err := io.ReadAll(httpResp.Body)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed to read response body for %s", httpResp.Request.URL)
}
if !strings.Contains(primaryAcceptType, contentType) {
log.WithFields(logrus.Fields{
"primaryAcceptType": primaryAcceptType,
"secondaryAcceptType": secondaryAcceptType,
"receivedAcceptType": contentType,
}).Debug("Server responded with non primary accept type")
}
// non-2XX codes are a failure
if !strings.HasPrefix(httpResp.Status, "2") {
decoder := json.NewDecoder(bytes.NewBuffer(body))
errorJson := &httputil.DefaultJsonError{}
if err = decoder.Decode(errorJson); err != nil {
return nil, nil, errors.Wrapf(err, "failed to decode response body into error json for %s", httpResp.Request.URL)
}
return nil, nil, errorJson
}
if features.Get().SSZOnly && contentType != api.OctetStreamMediaType {
return nil, nil, errors.Errorf("server responded with non primary accept type %s", contentType)
}
return body, httpResp.Header, nil
}
// Post sends a POST request and decodes the response body as a JSON object into the passed in object. // Post sends a POST request and decodes the response body as a JSON object into the passed in object.
// If an HTTP error is returned, the body is decoded as a DefaultJsonError JSON object and returned as the first return value. // If an HTTP error is returned, the body is decoded as a DefaultJsonError JSON object and returned as the first return value.
func (c *BeaconApiJsonRestHandler) Post( func (c *BeaconApiRestHandler) Post(
ctx context.Context, ctx context.Context,
apiEndpoint string, apiEndpoint string,
headers map[string]string, headers map[string]string,
@@ -136,6 +192,6 @@ func decodeResp(httpResp *http.Response, resp interface{}) error {
return nil return nil
} }
func (c *BeaconApiJsonRestHandler) SetHost(host string) { func (c *BeaconApiRestHandler) SetHost(host string) {
c.host = host c.host = host
} }

View File

@@ -2,6 +2,7 @@ package beacon_api
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"io" "io"
"net/http" "net/http"
@@ -15,6 +16,8 @@ import (
"github.com/OffchainLabs/prysm/v6/testing/assert" "github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/require" "github.com/OffchainLabs/prysm/v6/testing/require"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
) )
func TestGet(t *testing.T) { func TestGet(t *testing.T) {
@@ -39,7 +42,7 @@ func TestGet(t *testing.T) {
server := httptest.NewServer(mux) server := httptest.NewServer(mux)
defer server.Close() defer server.Close()
jsonRestHandler := BeaconApiJsonRestHandler{ jsonRestHandler := BeaconApiRestHandler{
client: http.Client{Timeout: time.Second * 5}, client: http.Client{Timeout: time.Second * 5},
host: server.URL, host: server.URL,
} }
@@ -48,6 +51,98 @@ func TestGet(t *testing.T) {
assert.DeepEqual(t, genesisJson, resp) assert.DeepEqual(t, genesisJson, resp)
} }
func TestGetSSZ(t *testing.T) {
ctx := context.Background()
const endpoint = "/example/rest/api/ssz"
genesisJson := &structs.GetGenesisResponse{
Data: &structs.Genesis{
GenesisTime: "123",
GenesisValidatorsRoot: "0x456",
GenesisForkVersion: "0x789",
},
}
t.Run("Successful SSZ response", func(t *testing.T) {
expectedBody := []byte{10, 20, 30, 40}
mux := http.NewServeMux()
mux.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) {
assert.StringContains(t, api.OctetStreamMediaType, r.Header.Get("Accept"))
w.Header().Set("Content-Type", api.OctetStreamMediaType)
_, err := w.Write(expectedBody)
require.NoError(t, err)
})
server := httptest.NewServer(mux)
defer server.Close()
jsonRestHandler := BeaconApiRestHandler{
client: http.Client{Timeout: time.Second * 5},
host: server.URL,
}
body, header, err := jsonRestHandler.GetSSZ(ctx, endpoint)
require.NoError(t, err)
assert.DeepEqual(t, expectedBody, body)
require.StringContains(t, api.OctetStreamMediaType, header.Get("Content-Type"))
})
t.Run("Json Content-Type response", func(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel)
defer logrus.SetLevel(logrus.InfoLevel) // reset it afterwards
logHook := test.NewGlobal()
mux := http.NewServeMux()
mux.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) {
assert.StringContains(t, api.OctetStreamMediaType, r.Header.Get("Accept"))
w.Header().Set("Content-Type", api.JsonMediaType)
marshalledJson, err := json.Marshal(genesisJson)
require.NoError(t, err)
_, err = w.Write(marshalledJson)
require.NoError(t, err)
})
server := httptest.NewServer(mux)
defer server.Close()
jsonRestHandler := BeaconApiRestHandler{
client: http.Client{Timeout: time.Second * 5},
host: server.URL,
}
body, header, err := jsonRestHandler.GetSSZ(ctx, endpoint)
require.NoError(t, err)
assert.LogsContain(t, logHook, "Server responded with non primary accept type")
require.Equal(t, api.JsonMediaType, header.Get("Content-Type"))
resp := &structs.GetGenesisResponse{}
require.NoError(t, json.Unmarshal(body, resp))
require.Equal(t, "123", resp.Data.GenesisTime)
})
t.Run("Wrong Content-Type response, doesn't error out and instead handled downstream", func(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel)
defer logrus.SetLevel(logrus.InfoLevel) // reset it afterwards
logHook := test.NewGlobal()
mux := http.NewServeMux()
mux.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) {
assert.StringContains(t, api.OctetStreamMediaType, r.Header.Get("Accept"))
w.Header().Set("Content-Type", "text/plain") // Invalid content type
_, err := w.Write([]byte("some text"))
require.NoError(t, err)
})
server := httptest.NewServer(mux)
defer server.Close()
jsonRestHandler := BeaconApiRestHandler{
client: http.Client{Timeout: time.Second * 5},
host: server.URL,
}
_, _, err := jsonRestHandler.GetSSZ(ctx, endpoint)
require.NoError(t, err)
assert.LogsContain(t, logHook, "Server responded with non primary accept type")
})
}
func TestPost(t *testing.T) { func TestPost(t *testing.T) {
ctx := t.Context() ctx := t.Context()
const endpoint = "/example/rest/api/endpoint" const endpoint = "/example/rest/api/endpoint"
@@ -85,7 +180,7 @@ func TestPost(t *testing.T) {
server := httptest.NewServer(mux) server := httptest.NewServer(mux)
defer server.Close() defer server.Close()
jsonRestHandler := BeaconApiJsonRestHandler{ jsonRestHandler := BeaconApiRestHandler{
client: http.Client{Timeout: time.Second * 5}, client: http.Client{Timeout: time.Second * 5},
host: server.URL, host: server.URL,
} }

View File

@@ -21,7 +21,7 @@ type StateValidatorsProvider interface {
} }
type beaconApiStateValidatorsProvider struct { type beaconApiStateValidatorsProvider struct {
jsonRestHandler JsonRestHandler jsonRestHandler RestHandler
} }
func (c beaconApiStateValidatorsProvider) StateValidators( func (c beaconApiStateValidatorsProvider) StateValidators(

View File

@@ -9,7 +9,7 @@ import (
validatorHelpers "github.com/OffchainLabs/prysm/v6/validator/helpers" validatorHelpers "github.com/OffchainLabs/prysm/v6/validator/helpers"
) )
func NewChainClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler beaconApi.JsonRestHandler) iface.ChainClient { func NewChainClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler beaconApi.RestHandler) iface.ChainClient {
grpcClient := grpcApi.NewGrpcChainClient(validatorConn.GetGrpcClientConn()) grpcClient := grpcApi.NewGrpcChainClient(validatorConn.GetGrpcClientConn())
if features.Get().EnableBeaconRESTApi { if features.Get().EnableBeaconRESTApi {
return beaconApi.NewBeaconApiChainClientWithFallback(jsonRestHandler, grpcClient) return beaconApi.NewBeaconApiChainClientWithFallback(jsonRestHandler, grpcClient)
@@ -18,7 +18,7 @@ func NewChainClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandl
} }
} }
func NewPrysmChainClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler beaconApi.JsonRestHandler) iface.PrysmChainClient { func NewPrysmChainClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler beaconApi.RestHandler) iface.PrysmChainClient {
if features.Get().EnableBeaconRESTApi { if features.Get().EnableBeaconRESTApi {
return beaconApi.NewPrysmChainClient(jsonRestHandler, nodeClientFactory.NewNodeClient(validatorConn, jsonRestHandler)) return beaconApi.NewPrysmChainClient(jsonRestHandler, nodeClientFactory.NewNodeClient(validatorConn, jsonRestHandler))
} else { } else {

View File

@@ -8,7 +8,7 @@ import (
validatorHelpers "github.com/OffchainLabs/prysm/v6/validator/helpers" validatorHelpers "github.com/OffchainLabs/prysm/v6/validator/helpers"
) )
func NewNodeClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler beaconApi.JsonRestHandler) iface.NodeClient { func NewNodeClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler beaconApi.RestHandler) iface.NodeClient {
grpcClient := grpcApi.NewNodeClient(validatorConn.GetGrpcClientConn()) grpcClient := grpcApi.NewNodeClient(validatorConn.GetGrpcClientConn())
if features.Get().EnableBeaconRESTApi { if features.Get().EnableBeaconRESTApi {
return beaconApi.NewNodeClientWithFallback(jsonRestHandler, grpcClient) return beaconApi.NewNodeClientWithFallback(jsonRestHandler, grpcClient)

View File

@@ -179,7 +179,7 @@ func (v *ValidatorService) Start() {
return return
} }
restHandler := beaconApi.NewBeaconApiJsonRestHandler( restHandler := beaconApi.NewBeaconApiRestHandler(
http.Client{Timeout: v.conn.GetBeaconApiTimeout(), Transport: otelhttp.NewTransport(http.DefaultTransport)}, http.Client{Timeout: v.conn.GetBeaconApiTimeout(), Transport: otelhttp.NewTransport(http.DefaultTransport)},
hosts[0], hosts[0],
) )

View File

@@ -10,7 +10,7 @@ import (
func NewValidatorClient( func NewValidatorClient(
validatorConn validatorHelpers.NodeConnection, validatorConn validatorHelpers.NodeConnection,
jsonRestHandler beaconApi.JsonRestHandler, jsonRestHandler beaconApi.RestHandler,
opt ...beaconApi.ValidatorClientOpt, opt ...beaconApi.ValidatorClientOpt,
) iface.ValidatorClient { ) iface.ValidatorClient {
if features.Get().EnableBeaconRESTApi { if features.Get().EnableBeaconRESTApi {

View File

@@ -55,7 +55,7 @@ func (s *Server) registerBeaconClient() error {
s.beaconApiTimeout, s.beaconApiTimeout,
) )
restHandler := beaconApi.NewBeaconApiJsonRestHandler( restHandler := beaconApi.NewBeaconApiRestHandler(
http.Client{Timeout: s.beaconApiTimeout, Transport: otelhttp.NewTransport(http.DefaultTransport)}, http.Client{Timeout: s.beaconApiTimeout, Transport: otelhttp.NewTransport(http.DefaultTransport)},
s.beaconApiEndpoint, s.beaconApiEndpoint,
) )