From 4632e2107d337cb2f229830a07940c04a16927d3 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar <43061995+xenowits@users.noreply.github.com> Date: Mon, 30 Oct 2023 15:50:51 +0530 Subject: [PATCH] *: fix compatibility with latest go-eth2-client (#2650) Fix charon's compatibility with latest release of `go-eth2-client` which contains breaking changes, notably the ETH2 client interface methods. This PR also enables easy integration of deneb fork as the data structures for deneb are included in the new release. An example of the API change is as follows: Earlier ``` validatorsProvider.Validators(ctx, "head", nil) ``` Now ``` validatorsProvider.Validators(ctx, &api.ValidatorsOpts{ State: "head", }) ``` Also fix corresponding tests. category: feature ticket: #2646 --- app/app.go | 4 +- app/eth2wrap/eth2wrap.go | 11 +- app/eth2wrap/eth2wrap_gen.go | 278 ++++----- app/eth2wrap/eth2wrap_test.go | 14 +- app/eth2wrap/genwrap/genwrap.go | 8 +- app/eth2wrap/success.go | 11 +- app/eth2wrap/synthproposer.go | 280 +++++---- app/eth2wrap/synthproposer_test.go | 56 +- app/eth2wrap/valcache.go | 8 +- app/eth2wrap/valcache_test.go | 7 +- app/monitoringapi.go | 7 +- core/bcast/bcast.go | 12 +- core/bcast/bcast_test.go | 28 +- core/dutydb/memory.go | 49 +- core/dutydb/memory_internal_test.go | 4 +- core/dutydb/memory_test.go | 84 +-- core/eth2signeddata.go | 59 +- core/eth2signeddata_test.go | 6 +- core/fetcher/fetcher.go | 90 ++- core/fetcher/fetcher_test.go | 12 +- core/interfaces.go | 169 +++-- core/parsigex/parsigex_test.go | 41 +- core/proto.go | 8 +- core/proto_test.go | 14 +- core/scheduler/scheduler.go | 32 +- core/serialise_test.go | 8 +- core/sigagg/sigagg_test.go | 22 +- core/signeddata.go | 434 +++++++------ core/signeddata_test.go | 18 +- core/ssz.go | 247 ++++---- core/ssz_test.go | 16 +- ...ation_VersionedBlindedProposal.json.golden | 577 ++++++++++++++++++ ...erialisation_VersionedProposal.json.golden | 390 ++++++++++++ ...VersionedSignedBlindedProposal.json.golden | 467 ++++++++++++++ ...sation_VersionedSignedProposal.json.golden | 434 +++++++++++++ ...sation_VersionedBlindedProposal.ssz.golden | Bin 0 -> 10017 bytes ...Serialisation_VersionedProposal.ssz.golden | Bin 0 -> 5659 bytes ..._VersionedSignedBlindedProposal.ssz.golden | Bin 0 -> 8402 bytes ...isation_VersionedSignedProposal.ssz.golden | Bin 0 -> 6862 bytes core/tracker/inclusion.go | 8 +- core/tracker/inclusion_internal_test.go | 6 +- core/tracker/tracker.go | 4 +- core/tracker/tracker_internal_test.go | 8 +- core/unsigneddata.go | 145 ++--- core/unsigneddata_test.go | 8 +- core/validatorapi/eth2types.go | 9 +- core/validatorapi/router.go | 146 +++-- core/validatorapi/router_internal_test.go | 402 +++++++----- core/validatorapi/validatorapi.go | 218 ++++--- core/validatorapi/validatorapi_test.go | 150 +++-- eth2util/eth2exp/attagg_old.go | 6 +- eth2util/signing/signing.go | 4 +- go.mod | 3 +- go.sum | 6 +- testutil/beaconmock/beaconmock.go | 179 ++++-- testutil/beaconmock/beaconmock_fuzz.go | 11 +- testutil/beaconmock/beaconmock_test.go | 49 +- testutil/beaconmock/options.go | 67 +- testutil/beaconmock/server_test.go | 47 +- testutil/fuzz.go | 40 +- testutil/random.go | 67 +- testutil/validatormock/attest.go | 26 +- testutil/validatormock/propose.go | 108 +++- testutil/validatormock/synccomm.go | 27 +- 64 files changed, 4106 insertions(+), 1543 deletions(-) create mode 100644 core/testdata/TestJSONSerialisation_VersionedBlindedProposal.json.golden create mode 100644 core/testdata/TestJSONSerialisation_VersionedProposal.json.golden create mode 100644 core/testdata/TestJSONSerialisation_VersionedSignedBlindedProposal.json.golden create mode 100644 core/testdata/TestJSONSerialisation_VersionedSignedProposal.json.golden create mode 100644 core/testdata/TestSSZSerialisation_VersionedBlindedProposal.ssz.golden create mode 100644 core/testdata/TestSSZSerialisation_VersionedProposal.ssz.golden create mode 100644 core/testdata/TestSSZSerialisation_VersionedSignedBlindedProposal.ssz.golden create mode 100644 core/testdata/TestSSZSerialisation_VersionedSignedProposal.ssz.golden diff --git a/app/app.go b/app/app.go index 42ea7f1ee..d02388459 100644 --- a/app/app.go +++ b/app/app.go @@ -809,10 +809,12 @@ func newETH2Client(ctx context.Context, conf Config, life *lifecycle.Manager, } // Check BN chain/network. - schedule, err := eth2Cl.ForkSchedule(ctx) + eth2Resp, err := eth2Cl.ForkSchedule(ctx) if err != nil { return nil, errors.Wrap(err, "fetch fork schedule") } + schedule := eth2Resp.Data + var ok bool for _, fork := range schedule { if bytes.Equal(fork.CurrentVersion[:], forkVersion) { diff --git a/app/eth2wrap/eth2wrap.go b/app/eth2wrap/eth2wrap.go index 4e2dfe8b3..23bcdb221 100644 --- a/app/eth2wrap/eth2wrap.go +++ b/app/eth2wrap/eth2wrap.go @@ -10,6 +10,7 @@ import ( "sync" "time" + eth2api "github.com/attestantio/go-eth2-client/api" eth2http "github.com/attestantio/go-eth2-client/http" "github.com/attestantio/go-eth2-client/spec/bellatrix" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" @@ -329,12 +330,12 @@ func incError(endpoint string) { // wrapError returns the error as a wrapped structured error. func wrapError(ctx context.Context, err error, label string, fields ...z.Field) error { // Decompose go-eth2-client http errors - if e2err := new(eth2http.Error); errors.As(err, e2err) { + if apiErr := new(eth2api.Error); errors.As(err, apiErr) { err = errors.New("nok http response", - z.Int("status_code", e2err.StatusCode), - z.Str("endpoint", e2err.Endpoint), - z.Str("method", e2err.Method), - z.Str("data", string(e2err.Data)), + z.Int("status_code", apiErr.StatusCode), + z.Str("endpoint", apiErr.Endpoint), + z.Str("method", apiErr.Method), + z.Str("data", string(apiErr.Data)), ) } diff --git a/app/eth2wrap/eth2wrap_gen.go b/app/eth2wrap/eth2wrap_gen.go index 8a9750480..df706bd3b 100644 --- a/app/eth2wrap/eth2wrap_gen.go +++ b/app/eth2wrap/eth2wrap_gen.go @@ -34,12 +34,10 @@ type Client interface { eth2client.AttestationDataProvider eth2client.AttestationsSubmitter eth2client.AttesterDutiesProvider - eth2client.BeaconBlockProposalProvider eth2client.BeaconBlockRootProvider - eth2client.BeaconBlockSubmitter eth2client.BeaconCommitteeSubscriptionsSubmitter - eth2client.BlindedBeaconBlockProposalProvider - eth2client.BlindedBeaconBlockSubmitter + eth2client.BlindedProposalProvider + eth2client.BlindedProposalSubmitter eth2client.DepositContractProvider eth2client.DomainProvider eth2client.ForkProvider @@ -49,6 +47,8 @@ type Client interface { eth2client.NodeSyncingProvider eth2client.NodeVersionProvider eth2client.ProposalPreparationsSubmitter + eth2client.ProposalProvider + eth2client.ProposalSubmitter eth2client.ProposerDutiesProvider eth2client.SignedBeaconBlockProvider eth2client.SlotDurationProvider @@ -66,11 +66,11 @@ type Client interface { // NodeVersion returns a free-text string with the node version. // Note this endpoint is cached in go-eth2-client. -func (m multi) NodeVersion(ctx context.Context) (string, error) { +func (m multi) NodeVersion(ctx context.Context) (*api.Response[string], error) { const label = "node_version" res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (string, error) { + func(ctx context.Context, cl Client) (*api.Response[string], error) { return cl.NodeVersion(ctx) }, nil, m.bestIdx, @@ -124,13 +124,13 @@ func (m multi) SlotsPerEpoch(ctx context.Context) (uint64, error) { return res0, err } -// DepositContract provides details of the Ethereum 1 deposit contract for the chain. +// DepositContract provides details of the execution deposit contract for the chain. // Note this endpoint is cached in go-eth2-client. -func (m multi) DepositContract(ctx context.Context) (*apiv1.DepositContract, error) { +func (m multi) DepositContract(ctx context.Context) (*api.Response[*apiv1.DepositContract], error) { const label = "deposit_contract" res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*apiv1.DepositContract, error) { + func(ctx context.Context, cl Client) (*api.Response[*apiv1.DepositContract], error) { return cl.DepositContract(ctx) }, nil, m.bestIdx, @@ -145,13 +145,13 @@ func (m multi) DepositContract(ctx context.Context) (*apiv1.DepositContract, err } // SignedBeaconBlock fetches a signed beacon block given a block ID. -func (m multi) SignedBeaconBlock(ctx context.Context, blockID string) (*spec.VersionedSignedBeaconBlock, error) { +func (m multi) SignedBeaconBlock(ctx context.Context, opts *api.SignedBeaconBlockOpts) (*api.Response[*spec.VersionedSignedBeaconBlock], error) { const label = "signed_beacon_block" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*spec.VersionedSignedBeaconBlock, error) { - return cl.SignedBeaconBlock(ctx, blockID) + func(ctx context.Context, cl Client) (*api.Response[*spec.VersionedSignedBeaconBlock], error) { + return cl.SignedBeaconBlock(ctx, opts) }, nil, m.bestIdx, ) @@ -164,14 +164,14 @@ func (m multi) SignedBeaconBlock(ctx context.Context, blockID string) (*spec.Ver return res0, err } -// AggregateAttestation fetches the aggregate attestation given an attestation. -func (m multi) AggregateAttestation(ctx context.Context, slot phase0.Slot, attestationDataRoot phase0.Root) (*phase0.Attestation, error) { +// AggregateAttestation fetches the aggregate attestation for the given options. +func (m multi) AggregateAttestation(ctx context.Context, opts *api.AggregateAttestationOpts) (*api.Response[*phase0.Attestation], error) { const label = "aggregate_attestation" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*phase0.Attestation, error) { - return cl.AggregateAttestation(ctx, slot, attestationDataRoot) + func(ctx context.Context, cl Client) (*api.Response[*phase0.Attestation], error) { + return cl.AggregateAttestation(ctx, opts) }, isAggregateAttestationOk, m.bestIdx, ) @@ -204,14 +204,14 @@ func (m multi) SubmitAggregateAttestations(ctx context.Context, aggregateAndProo return err } -// AttestationData fetches the attestation data for the given slot and committee index. -func (m multi) AttestationData(ctx context.Context, slot phase0.Slot, committeeIndex phase0.CommitteeIndex) (*phase0.AttestationData, error) { +// AttestationData fetches the attestation data for the given options. +func (m multi) AttestationData(ctx context.Context, opts *api.AttestationDataOpts) (*api.Response[*phase0.AttestationData], error) { const label = "attestation_data" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*phase0.AttestationData, error) { - return cl.AttestationData(ctx, slot, committeeIndex) + func(ctx context.Context, cl Client) (*api.Response[*phase0.AttestationData], error) { + return cl.AttestationData(ctx, opts) }, nil, m.bestIdx, ) @@ -245,14 +245,13 @@ func (m multi) SubmitAttestations(ctx context.Context, attestations []*phase0.At } // AttesterDuties obtains attester duties. -// If validatorIndicess is nil it will return all duties for the given epoch. -func (m multi) AttesterDuties(ctx context.Context, epoch phase0.Epoch, validatorIndices []phase0.ValidatorIndex) ([]*apiv1.AttesterDuty, error) { +func (m multi) AttesterDuties(ctx context.Context, opts *api.AttesterDutiesOpts) (*api.Response[[]*apiv1.AttesterDuty], error) { const label = "attester_duties" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) ([]*apiv1.AttesterDuty, error) { - return cl.AttesterDuties(ctx, epoch, validatorIndices) + func(ctx context.Context, cl Client) (*api.Response[[]*apiv1.AttesterDuty], error) { + return cl.AttesterDuties(ctx, opts) }, nil, m.bestIdx, ) @@ -267,13 +266,13 @@ func (m multi) AttesterDuties(ctx context.Context, epoch phase0.Epoch, validator // SyncCommitteeDuties obtains sync committee duties. // If validatorIndicess is nil it will return all duties for the given epoch. -func (m multi) SyncCommitteeDuties(ctx context.Context, epoch phase0.Epoch, validatorIndices []phase0.ValidatorIndex) ([]*apiv1.SyncCommitteeDuty, error) { +func (m multi) SyncCommitteeDuties(ctx context.Context, opts *api.SyncCommitteeDutiesOpts) (*api.Response[[]*apiv1.SyncCommitteeDuty], error) { const label = "sync_committee_duties" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) ([]*apiv1.SyncCommitteeDuty, error) { - return cl.SyncCommitteeDuties(ctx, epoch, validatorIndices) + func(ctx context.Context, cl Client) (*api.Response[[]*apiv1.SyncCommitteeDuty], error) { + return cl.SyncCommitteeDuties(ctx, opts) }, nil, m.bestIdx, ) @@ -327,13 +326,13 @@ func (m multi) SubmitSyncCommitteeSubscriptions(ctx context.Context, subscriptio } // SyncCommitteeContribution provides a sync committee contribution. -func (m multi) SyncCommitteeContribution(ctx context.Context, slot phase0.Slot, subcommitteeIndex uint64, beaconBlockRoot phase0.Root) (*altair.SyncCommitteeContribution, error) { +func (m multi) SyncCommitteeContribution(ctx context.Context, opts *api.SyncCommitteeContributionOpts) (*api.Response[*altair.SyncCommitteeContribution], error) { const label = "sync_committee_contribution" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*altair.SyncCommitteeContribution, error) { - return cl.SyncCommitteeContribution(ctx, slot, subcommitteeIndex, beaconBlockRoot) + func(ctx context.Context, cl Client) (*api.Response[*altair.SyncCommitteeContribution], error) { + return cl.SyncCommitteeContribution(ctx, opts) }, nil, m.bestIdx, ) @@ -366,14 +365,14 @@ func (m multi) SubmitSyncCommitteeContributions(ctx context.Context, contributio return err } -// BeaconBlockProposal fetches a proposed beacon block for signing. -func (m multi) BeaconBlockProposal(ctx context.Context, slot phase0.Slot, randaoReveal phase0.BLSSignature, graffiti []byte) (*spec.VersionedBeaconBlock, error) { - const label = "beacon_block_proposal" +// Proposal fetches a proposal for signing. +func (m multi) Proposal(ctx context.Context, opts *api.ProposalOpts) (*api.Response[*api.VersionedProposal], error) { + const label = "proposal" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*spec.VersionedBeaconBlock, error) { - return cl.BeaconBlockProposal(ctx, slot, randaoReveal, graffiti) + func(ctx context.Context, cl Client) (*api.Response[*api.VersionedProposal], error) { + return cl.Proposal(ctx, opts) }, nil, m.bestIdx, ) @@ -386,14 +385,14 @@ func (m multi) BeaconBlockProposal(ctx context.Context, slot phase0.Slot, randao return res0, err } -// BeaconBlockRoot fetches a block's root given a block ID. +// BeaconBlockRoot fetches a block's root given a set of options. // Note this endpoint is cached in go-eth2-client. -func (m multi) BeaconBlockRoot(ctx context.Context, blockID string) (*phase0.Root, error) { +func (m multi) BeaconBlockRoot(ctx context.Context, opts *api.BeaconBlockRootOpts) (*api.Response[*phase0.Root], error) { const label = "beacon_block_root" res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*phase0.Root, error) { - return cl.BeaconBlockRoot(ctx, blockID) + func(ctx context.Context, cl Client) (*api.Response[*phase0.Root], error) { + return cl.BeaconBlockRoot(ctx, opts) }, nil, m.bestIdx, ) @@ -406,14 +405,14 @@ func (m multi) BeaconBlockRoot(ctx context.Context, blockID string) (*phase0.Roo return res0, err } -// SubmitBeaconBlock submits a beacon block. -func (m multi) SubmitBeaconBlock(ctx context.Context, block *spec.VersionedSignedBeaconBlock) error { - const label = "submit_beacon_block" +// SubmitProposal submits a proposal. +func (m multi) SubmitProposal(ctx context.Context, block *api.VersionedSignedProposal) error { + const label = "submit_proposal" defer latency(label)() err := submit(ctx, m.clients, func(ctx context.Context, cl Client) error { - return cl.SubmitBeaconBlock(ctx, block) + return cl.SubmitProposal(ctx, block) }, m.bestIdx, ) @@ -446,14 +445,14 @@ func (m multi) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscript return err } -// BlindedBeaconBlockProposal fetches a blinded proposed beacon block for signing. -func (m multi) BlindedBeaconBlockProposal(ctx context.Context, slot phase0.Slot, randaoReveal phase0.BLSSignature, graffiti []byte) (*api.VersionedBlindedBeaconBlock, error) { - const label = "blinded_beacon_block_proposal" +// BlindedProposal fetches a blinded proposed beacon block for signing. +func (m multi) BlindedProposal(ctx context.Context, opts *api.BlindedProposalOpts) (*api.Response[*api.VersionedBlindedProposal], error) { + const label = "blinded_proposal" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*api.VersionedBlindedBeaconBlock, error) { - return cl.BlindedBeaconBlockProposal(ctx, slot, randaoReveal, graffiti) + func(ctx context.Context, cl Client) (*api.Response[*api.VersionedBlindedProposal], error) { + return cl.BlindedProposal(ctx, opts) }, nil, m.bestIdx, ) @@ -466,14 +465,14 @@ func (m multi) BlindedBeaconBlockProposal(ctx context.Context, slot phase0.Slot, return res0, err } -// SubmitBlindedBeaconBlock submits a beacon block. -func (m multi) SubmitBlindedBeaconBlock(ctx context.Context, block *api.VersionedSignedBlindedBeaconBlock) error { - const label = "submit_blinded_beacon_block" +// SubmitBlindedProposal submits a beacon block. +func (m multi) SubmitBlindedProposal(ctx context.Context, block *api.VersionedSignedBlindedProposal) error { + const label = "submit_blinded_proposal" defer latency(label)() err := submit(ctx, m.clients, func(ctx context.Context, cl Client) error { - return cl.SubmitBlindedBeaconBlock(ctx, block) + return cl.SubmitBlindedProposal(ctx, block) }, m.bestIdx, ) @@ -507,13 +506,13 @@ func (m multi) SubmitValidatorRegistrations(ctx context.Context, registrations [ } // Fork fetches fork information for the given state. -func (m multi) Fork(ctx context.Context, stateID string) (*phase0.Fork, error) { +func (m multi) Fork(ctx context.Context, opts *api.ForkOpts) (*api.Response[*phase0.Fork], error) { const label = "fork" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*phase0.Fork, error) { - return cl.Fork(ctx, stateID) + func(ctx context.Context, cl Client) (*api.Response[*phase0.Fork], error) { + return cl.Fork(ctx, opts) }, nil, m.bestIdx, ) @@ -527,12 +526,12 @@ func (m multi) Fork(ctx context.Context, stateID string) (*phase0.Fork, error) { } // ForkSchedule provides details of past and future changes in the chain's fork version. -func (m multi) ForkSchedule(ctx context.Context) ([]*phase0.Fork, error) { +func (m multi) ForkSchedule(ctx context.Context) (*api.Response[[]*phase0.Fork], error) { const label = "fork_schedule" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) ([]*phase0.Fork, error) { + func(ctx context.Context, cl Client) (*api.Response[[]*phase0.Fork], error) { return cl.ForkSchedule(ctx) }, nil, m.bestIdx, @@ -548,11 +547,11 @@ func (m multi) ForkSchedule(ctx context.Context) ([]*phase0.Fork, error) { // Genesis fetches genesis information for the chain. // Note this endpoint is cached in go-eth2-client. -func (m multi) Genesis(ctx context.Context) (*apiv1.Genesis, error) { +func (m multi) Genesis(ctx context.Context) (*api.Response[*apiv1.Genesis], error) { const label = "genesis" res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*apiv1.Genesis, error) { + func(ctx context.Context, cl Client) (*api.Response[*apiv1.Genesis], error) { return cl.Genesis(ctx) }, nil, m.bestIdx, @@ -567,12 +566,12 @@ func (m multi) Genesis(ctx context.Context) (*apiv1.Genesis, error) { } // NodeSyncing provides the state of the node's synchronization with the chain. -func (m multi) NodeSyncing(ctx context.Context) (*apiv1.SyncState, error) { +func (m multi) NodeSyncing(ctx context.Context) (*api.Response[*apiv1.SyncState], error) { const label = "node_syncing" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*apiv1.SyncState, error) { + func(ctx context.Context, cl Client) (*api.Response[*apiv1.SyncState], error) { return cl.NodeSyncing(ctx) }, isSyncStateOk, m.bestIdx, @@ -607,15 +606,14 @@ func (m multi) SubmitProposalPreparations(ctx context.Context, preparations []*a return err } -// ProposerDuties obtains proposer duties for the given epoch. -// If validatorIndices is empty all duties are returned, otherwise only matching duties are returned. -func (m multi) ProposerDuties(ctx context.Context, epoch phase0.Epoch, validatorIndices []phase0.ValidatorIndex) ([]*apiv1.ProposerDuty, error) { +// ProposerDuties obtains proposer duties for the given options. +func (m multi) ProposerDuties(ctx context.Context, opts *api.ProposerDutiesOpts) (*api.Response[[]*apiv1.ProposerDuty], error) { const label = "proposer_duties" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) ([]*apiv1.ProposerDuty, error) { - return cl.ProposerDuties(ctx, epoch, validatorIndices) + func(ctx context.Context, cl Client) (*api.Response[[]*apiv1.ProposerDuty], error) { + return cl.ProposerDuties(ctx, opts) }, nil, m.bestIdx, ) @@ -630,11 +628,11 @@ func (m multi) ProposerDuties(ctx context.Context, epoch phase0.Epoch, validator // Spec provides the spec information of the chain. // Note this endpoint is cached in go-eth2-client. -func (m multi) Spec(ctx context.Context) (map[string]interface{}, error) { +func (m multi) Spec(ctx context.Context) (*api.Response[map[string]any], error) { const label = "spec" res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (map[string]interface{}, error) { + func(ctx context.Context, cl Client) (*api.Response[map[string]any], error) { return cl.Spec(ctx) }, nil, m.bestIdx, @@ -648,40 +646,14 @@ func (m multi) Spec(ctx context.Context) (map[string]interface{}, error) { return res0, err } -// Validators provides the validators, with their balance and status, for a given state. -// stateID can be a slot number or state root, or one of the special values "genesis", "head", "justified" or "finalized". -// validatorIndices is a list of validator indices to restrict the returned values. If no validators IDs are supplied no filter -// will be applied. -func (m multi) Validators(ctx context.Context, stateID string, validatorIndices []phase0.ValidatorIndex) (map[phase0.ValidatorIndex]*apiv1.Validator, error) { +// Validators provides the validators, with their balance and status, for the given options. +func (m multi) Validators(ctx context.Context, opts *api.ValidatorsOpts) (*api.Response[map[phase0.ValidatorIndex]*apiv1.Validator], error) { const label = "validators" defer latency(label)() res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (map[phase0.ValidatorIndex]*apiv1.Validator, error) { - return cl.Validators(ctx, stateID, validatorIndices) - }, - nil, m.bestIdx, - ) - - if err != nil { - incError(label) - err = wrapError(ctx, err, label) - } - - return res0, err -} - -// ValidatorsByPubKey provides the validators, with their balance and status, for a given state. -// stateID can be a slot number or state root, or one of the special values "genesis", "head", "justified" or "finalized". -// validatorPubKeys is a list of validator public keys to restrict the returned values. If no validators public keys are -// supplied no filter will be applied. -func (m multi) ValidatorsByPubKey(ctx context.Context, stateID string, validatorPubKeys []phase0.BLSPubKey) (map[phase0.ValidatorIndex]*apiv1.Validator, error) { - const label = "validators_by_pub_key" - defer latency(label)() - - res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (map[phase0.ValidatorIndex]*apiv1.Validator, error) { - return cl.ValidatorsByPubKey(ctx, stateID, validatorPubKeys) + func(ctx context.Context, cl Client) (*api.Response[map[phase0.ValidatorIndex]*apiv1.Validator], error) { + return cl.Validators(ctx, opts) }, nil, m.bestIdx, ) @@ -735,7 +707,7 @@ func (m multi) Domain(ctx context.Context, domainType phase0.DomainType, epoch p } // GenesisDomain returns the domain for the given domain type at genesis. -// N.B. this is not always the same as the the domain at epoch 0. It is possible +// N.B. this is not always the same as the domain at epoch 0. It is possible // for a chain's fork schedule to have multiple forks at genesis. In this situation, // GenesisDomain() will return the first, and Domain() will return the last. // Note this endpoint is cached in go-eth2-client. @@ -778,7 +750,7 @@ func (m multi) GenesisTime(ctx context.Context) (time.Time, error) { } // NodeVersion returns a free-text string with the node version. -func (l *lazy) NodeVersion(ctx context.Context) (res0 string, err error) { +func (l *lazy) NodeVersion(ctx context.Context) (res0 *api.Response[string], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err @@ -807,8 +779,8 @@ func (l *lazy) SlotsPerEpoch(ctx context.Context) (res0 uint64, err error) { return cl.SlotsPerEpoch(ctx) } -// DepositContract provides details of the Ethereum 1 deposit contract for the chain. -func (l *lazy) DepositContract(ctx context.Context) (res0 *apiv1.DepositContract, err error) { +// DepositContract provides details of the execution deposit contract for the chain. +func (l *lazy) DepositContract(ctx context.Context) (res0 *api.Response[*apiv1.DepositContract], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err @@ -818,23 +790,23 @@ func (l *lazy) DepositContract(ctx context.Context) (res0 *apiv1.DepositContract } // SignedBeaconBlock fetches a signed beacon block given a block ID. -func (l *lazy) SignedBeaconBlock(ctx context.Context, blockID string) (res0 *spec.VersionedSignedBeaconBlock, err error) { +func (l *lazy) SignedBeaconBlock(ctx context.Context, opts *api.SignedBeaconBlockOpts) (res0 *api.Response[*spec.VersionedSignedBeaconBlock], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.SignedBeaconBlock(ctx, blockID) + return cl.SignedBeaconBlock(ctx, opts) } -// AggregateAttestation fetches the aggregate attestation given an attestation. -func (l *lazy) AggregateAttestation(ctx context.Context, slot phase0.Slot, attestationDataRoot phase0.Root) (res0 *phase0.Attestation, err error) { +// AggregateAttestation fetches the aggregate attestation for the given options. +func (l *lazy) AggregateAttestation(ctx context.Context, opts *api.AggregateAttestationOpts) (res0 *api.Response[*phase0.Attestation], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.AggregateAttestation(ctx, slot, attestationDataRoot) + return cl.AggregateAttestation(ctx, opts) } // SubmitAggregateAttestations submits aggregate attestations. @@ -847,14 +819,14 @@ func (l *lazy) SubmitAggregateAttestations(ctx context.Context, aggregateAndProo return cl.SubmitAggregateAttestations(ctx, aggregateAndProofs) } -// AttestationData fetches the attestation data for the given slot and committee index. -func (l *lazy) AttestationData(ctx context.Context, slot phase0.Slot, committeeIndex phase0.CommitteeIndex) (res0 *phase0.AttestationData, err error) { +// AttestationData fetches the attestation data for the given options. +func (l *lazy) AttestationData(ctx context.Context, opts *api.AttestationDataOpts) (res0 *api.Response[*phase0.AttestationData], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.AttestationData(ctx, slot, committeeIndex) + return cl.AttestationData(ctx, opts) } // SubmitAttestations submits attestations. @@ -868,25 +840,24 @@ func (l *lazy) SubmitAttestations(ctx context.Context, attestations []*phase0.At } // AttesterDuties obtains attester duties. -// If validatorIndicess is nil it will return all duties for the given epoch. -func (l *lazy) AttesterDuties(ctx context.Context, epoch phase0.Epoch, validatorIndices []phase0.ValidatorIndex) (res0 []*apiv1.AttesterDuty, err error) { +func (l *lazy) AttesterDuties(ctx context.Context, opts *api.AttesterDutiesOpts) (res0 *api.Response[[]*apiv1.AttesterDuty], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.AttesterDuties(ctx, epoch, validatorIndices) + return cl.AttesterDuties(ctx, opts) } // SyncCommitteeDuties obtains sync committee duties. // If validatorIndicess is nil it will return all duties for the given epoch. -func (l *lazy) SyncCommitteeDuties(ctx context.Context, epoch phase0.Epoch, validatorIndices []phase0.ValidatorIndex) (res0 []*apiv1.SyncCommitteeDuty, err error) { +func (l *lazy) SyncCommitteeDuties(ctx context.Context, opts *api.SyncCommitteeDutiesOpts) (res0 *api.Response[[]*apiv1.SyncCommitteeDuty], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.SyncCommitteeDuties(ctx, epoch, validatorIndices) + return cl.SyncCommitteeDuties(ctx, opts) } // SubmitSyncCommitteeMessages submits sync committee messages. @@ -910,13 +881,13 @@ func (l *lazy) SubmitSyncCommitteeSubscriptions(ctx context.Context, subscriptio } // SyncCommitteeContribution provides a sync committee contribution. -func (l *lazy) SyncCommitteeContribution(ctx context.Context, slot phase0.Slot, subcommitteeIndex uint64, beaconBlockRoot phase0.Root) (res0 *altair.SyncCommitteeContribution, err error) { +func (l *lazy) SyncCommitteeContribution(ctx context.Context, opts *api.SyncCommitteeContributionOpts) (res0 *api.Response[*altair.SyncCommitteeContribution], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.SyncCommitteeContribution(ctx, slot, subcommitteeIndex, beaconBlockRoot) + return cl.SyncCommitteeContribution(ctx, opts) } // SubmitSyncCommitteeContributions submits sync committee contributions. @@ -929,34 +900,34 @@ func (l *lazy) SubmitSyncCommitteeContributions(ctx context.Context, contributio return cl.SubmitSyncCommitteeContributions(ctx, contributionAndProofs) } -// BeaconBlockProposal fetches a proposed beacon block for signing. -func (l *lazy) BeaconBlockProposal(ctx context.Context, slot phase0.Slot, randaoReveal phase0.BLSSignature, graffiti []byte) (res0 *spec.VersionedBeaconBlock, err error) { +// Proposal fetches a proposal for signing. +func (l *lazy) Proposal(ctx context.Context, opts *api.ProposalOpts) (res0 *api.Response[*api.VersionedProposal], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.BeaconBlockProposal(ctx, slot, randaoReveal, graffiti) + return cl.Proposal(ctx, opts) } -// BeaconBlockRoot fetches a block's root given a block ID. -func (l *lazy) BeaconBlockRoot(ctx context.Context, blockID string) (res0 *phase0.Root, err error) { +// BeaconBlockRoot fetches a block's root given a set of options. +func (l *lazy) BeaconBlockRoot(ctx context.Context, opts *api.BeaconBlockRootOpts) (res0 *api.Response[*phase0.Root], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.BeaconBlockRoot(ctx, blockID) + return cl.BeaconBlockRoot(ctx, opts) } -// SubmitBeaconBlock submits a beacon block. -func (l *lazy) SubmitBeaconBlock(ctx context.Context, block *spec.VersionedSignedBeaconBlock) (err error) { +// SubmitProposal submits a proposal. +func (l *lazy) SubmitProposal(ctx context.Context, block *api.VersionedSignedProposal) (err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return err } - return cl.SubmitBeaconBlock(ctx, block) + return cl.SubmitProposal(ctx, block) } // SubmitBeaconCommitteeSubscriptions subscribes to beacon committees. @@ -969,24 +940,24 @@ func (l *lazy) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscript return cl.SubmitBeaconCommitteeSubscriptions(ctx, subscriptions) } -// BlindedBeaconBlockProposal fetches a blinded proposed beacon block for signing. -func (l *lazy) BlindedBeaconBlockProposal(ctx context.Context, slot phase0.Slot, randaoReveal phase0.BLSSignature, graffiti []byte) (res0 *api.VersionedBlindedBeaconBlock, err error) { +// BlindedProposal fetches a blinded proposed beacon block for signing. +func (l *lazy) BlindedProposal(ctx context.Context, opts *api.BlindedProposalOpts) (res0 *api.Response[*api.VersionedBlindedProposal], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.BlindedBeaconBlockProposal(ctx, slot, randaoReveal, graffiti) + return cl.BlindedProposal(ctx, opts) } -// SubmitBlindedBeaconBlock submits a beacon block. -func (l *lazy) SubmitBlindedBeaconBlock(ctx context.Context, block *api.VersionedSignedBlindedBeaconBlock) (err error) { +// SubmitBlindedProposal submits a beacon block. +func (l *lazy) SubmitBlindedProposal(ctx context.Context, block *api.VersionedSignedBlindedProposal) (err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return err } - return cl.SubmitBlindedBeaconBlock(ctx, block) + return cl.SubmitBlindedProposal(ctx, block) } // SubmitValidatorRegistrations submits a validator registration. @@ -1000,17 +971,17 @@ func (l *lazy) SubmitValidatorRegistrations(ctx context.Context, registrations [ } // Fork fetches fork information for the given state. -func (l *lazy) Fork(ctx context.Context, stateID string) (res0 *phase0.Fork, err error) { +func (l *lazy) Fork(ctx context.Context, opts *api.ForkOpts) (res0 *api.Response[*phase0.Fork], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.Fork(ctx, stateID) + return cl.Fork(ctx, opts) } // ForkSchedule provides details of past and future changes in the chain's fork version. -func (l *lazy) ForkSchedule(ctx context.Context) (res0 []*phase0.Fork, err error) { +func (l *lazy) ForkSchedule(ctx context.Context) (res0 *api.Response[[]*phase0.Fork], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err @@ -1020,7 +991,7 @@ func (l *lazy) ForkSchedule(ctx context.Context) (res0 []*phase0.Fork, err error } // Genesis fetches genesis information for the chain. -func (l *lazy) Genesis(ctx context.Context) (res0 *apiv1.Genesis, err error) { +func (l *lazy) Genesis(ctx context.Context) (res0 *api.Response[*apiv1.Genesis], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err @@ -1030,7 +1001,7 @@ func (l *lazy) Genesis(ctx context.Context) (res0 *apiv1.Genesis, err error) { } // NodeSyncing provides the state of the node's synchronization with the chain. -func (l *lazy) NodeSyncing(ctx context.Context) (res0 *apiv1.SyncState, err error) { +func (l *lazy) NodeSyncing(ctx context.Context) (res0 *api.Response[*apiv1.SyncState], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err @@ -1050,19 +1021,18 @@ func (l *lazy) SubmitProposalPreparations(ctx context.Context, preparations []*a return cl.SubmitProposalPreparations(ctx, preparations) } -// ProposerDuties obtains proposer duties for the given epoch. -// If validatorIndices is empty all duties are returned, otherwise only matching duties are returned. -func (l *lazy) ProposerDuties(ctx context.Context, epoch phase0.Epoch, validatorIndices []phase0.ValidatorIndex) (res0 []*apiv1.ProposerDuty, err error) { +// ProposerDuties obtains proposer duties for the given options. +func (l *lazy) ProposerDuties(ctx context.Context, opts *api.ProposerDutiesOpts) (res0 *api.Response[[]*apiv1.ProposerDuty], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.ProposerDuties(ctx, epoch, validatorIndices) + return cl.ProposerDuties(ctx, opts) } // Spec provides the spec information of the chain. -func (l *lazy) Spec(ctx context.Context) (res0 map[string]interface{}, err error) { +func (l *lazy) Spec(ctx context.Context) (res0 *api.Response[map[string]any], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err @@ -1071,30 +1041,14 @@ func (l *lazy) Spec(ctx context.Context) (res0 map[string]interface{}, err error return cl.Spec(ctx) } -// Validators provides the validators, with their balance and status, for a given state. -// stateID can be a slot number or state root, or one of the special values "genesis", "head", "justified" or "finalized". -// validatorIndices is a list of validator indices to restrict the returned values. If no validators IDs are supplied no filter -// will be applied. -func (l *lazy) Validators(ctx context.Context, stateID string, validatorIndices []phase0.ValidatorIndex) (res0 map[phase0.ValidatorIndex]*apiv1.Validator, err error) { - cl, err := l.getOrCreateClient(ctx) - if err != nil { - return res0, err - } - - return cl.Validators(ctx, stateID, validatorIndices) -} - -// ValidatorsByPubKey provides the validators, with their balance and status, for a given state. -// stateID can be a slot number or state root, or one of the special values "genesis", "head", "justified" or "finalized". -// validatorPubKeys is a list of validator public keys to restrict the returned values. If no validators public keys are -// supplied no filter will be applied. -func (l *lazy) ValidatorsByPubKey(ctx context.Context, stateID string, validatorPubKeys []phase0.BLSPubKey) (res0 map[phase0.ValidatorIndex]*apiv1.Validator, err error) { +// Validators provides the validators, with their balance and status, for the given options. +func (l *lazy) Validators(ctx context.Context, opts *api.ValidatorsOpts) (res0 *api.Response[map[phase0.ValidatorIndex]*apiv1.Validator], err error) { cl, err := l.getOrCreateClient(ctx) if err != nil { return res0, err } - return cl.ValidatorsByPubKey(ctx, stateID, validatorPubKeys) + return cl.Validators(ctx, opts) } // SubmitVoluntaryExit submits a voluntary exit. @@ -1118,7 +1072,7 @@ func (l *lazy) Domain(ctx context.Context, domainType phase0.DomainType, epoch p } // GenesisDomain returns the domain for the given domain type at genesis. -// N.B. this is not always the same as the the domain at epoch 0. It is possible +// N.B. this is not always the same as the domain at epoch 0. It is possible // for a chain's fork schedule to have multiple forks at genesis. In this situation, // GenesisDomain() will return the first, and Domain() will return the last. func (l *lazy) GenesisDomain(ctx context.Context, domainType phase0.DomainType) (res0 phase0.Domain, err error) { diff --git a/app/eth2wrap/eth2wrap_test.go b/app/eth2wrap/eth2wrap_test.go index 33d33cb7e..6687613f2 100644 --- a/app/eth2wrap/eth2wrap_test.go +++ b/app/eth2wrap/eth2wrap_test.go @@ -160,7 +160,7 @@ func TestSyncState(t *testing.T) { resp, err := eth2Cl.NodeSyncing(context.Background()) require.NoError(t, err) - require.False(t, resp.IsSyncing) + require.False(t, resp.Data.IsSyncing) } func TestErrors(t *testing.T) { @@ -203,18 +203,6 @@ func TestErrors(t *testing.T) { require.ErrorContains(t, err, "beacon api slots_per_epoch: context canceled") }) - t.Run("go-eth2-client http error", func(t *testing.T) { - bmock, err := beaconmock.New() - require.NoError(t, err) - eth2Cl, err := eth2wrap.NewMultiHTTP(time.Second, bmock.Address()) - require.NoError(t, err) - - _, err = eth2Cl.AggregateAttestation(ctx, 0, eth2p0.Root{}) - log.Error(ctx, "See this error log for fields", err) - require.Error(t, err) - require.ErrorContains(t, err, "beacon api aggregate_attestation: nok http response") - }) - t.Run("zero net op error", func(t *testing.T) { bmock, err := beaconmock.New() require.NoError(t, err) diff --git a/app/eth2wrap/genwrap/genwrap.go b/app/eth2wrap/genwrap/genwrap.go index 0786b1dde..a6ef58e0b 100644 --- a/app/eth2wrap/genwrap/genwrap.go +++ b/app/eth2wrap/genwrap/genwrap.go @@ -100,12 +100,12 @@ type Client interface { "AttestationDataProvider": true, "AttestationsSubmitter": true, "AttesterDutiesProvider": true, - "BeaconBlockProposalProvider": true, + "ProposalProvider": true, "BeaconBlockRootProvider": false, - "BeaconBlockSubmitter": true, + "ProposalSubmitter": true, "BeaconCommitteeSubscriptionsSubmitter": true, - "BlindedBeaconBlockProposalProvider": true, - "BlindedBeaconBlockSubmitter": true, + "BlindedProposalProvider": true, + "BlindedProposalSubmitter": true, "DepositContractProvider": false, "DomainProvider": false, "ForkProvider": true, diff --git a/app/eth2wrap/success.go b/app/eth2wrap/success.go index 9073f3e28..5ac63e494 100644 --- a/app/eth2wrap/success.go +++ b/app/eth2wrap/success.go @@ -3,16 +3,17 @@ package eth2wrap import ( + "github.com/attestantio/go-eth2-client/api" apiv1 "github.com/attestantio/go-eth2-client/api/v1" "github.com/attestantio/go-eth2-client/spec/phase0" ) -// isSyncStateOk returns tue if the sync state is not syncing. -func isSyncStateOk(s *apiv1.SyncState) bool { - return !s.IsSyncing +// isSyncStateOk returns true if the sync state is not syncing. +func isSyncStateOk(resp *api.Response[*apiv1.SyncState]) bool { + return !resp.Data.IsSyncing } // isAggregateAttestationOk returns true if the aggregate attestation is not nil (which can happen if the subscription wasn't successful). -func isAggregateAttestationOk(att *phase0.Attestation) bool { - return att != nil +func isAggregateAttestationOk(resp *api.Response[*phase0.Attestation]) bool { + return resp.Data != nil } diff --git a/app/eth2wrap/synthproposer.go b/app/eth2wrap/synthproposer.go index 933bad6ae..0c2788576 100644 --- a/app/eth2wrap/synthproposer.go +++ b/app/eth2wrap/synthproposer.go @@ -10,7 +10,7 @@ import ( "sync" eth2client "github.com/attestantio/go-eth2-client" - "github.com/attestantio/go-eth2-client/api" + eth2api "github.com/attestantio/go-eth2-client/api" eth2v1 "github.com/attestantio/go-eth2-client/api/v1" eth2bellatrix "github.com/attestantio/go-eth2-client/api/v1/bellatrix" eth2capella "github.com/attestantio/go-eth2-client/api/v1/capella" @@ -72,9 +72,14 @@ func (h *synthWrapper) getFeeRecipient(vIdx eth2p0.ValidatorIndex) bellatrix.Exe // ProposerDuties returns upstream proposer duties for the provided validator indexes or // upstream proposer duties and synthetic duties for all cluster validators if enabled. -func (h *synthWrapper) ProposerDuties(ctx context.Context, epoch eth2p0.Epoch, _ []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) { +func (h *synthWrapper) ProposerDuties(ctx context.Context, opts *eth2api.ProposerDutiesOpts) (*eth2api.Response[[]*eth2v1.ProposerDuty], error) { // TODO(corver): Should we support fetching duties for other validators not in the cluster? - return h.synthProposerCache.Duties(ctx, h.Client, epoch) + duties, err := h.synthProposerCache.Duties(ctx, h.Client, opts.Epoch) + if err != nil { + return nil, err + } + + return wrapResponse(duties), nil } func (h *synthWrapper) SubmitProposalPreparations(ctx context.Context, preparations []*eth2v1.ProposalPreparation) error { @@ -83,93 +88,115 @@ func (h *synthWrapper) SubmitProposalPreparations(ctx context.Context, preparati return h.Client.SubmitProposalPreparations(ctx, preparations) } -// BeaconBlockProposal returns an unsigned beacon block, possibly marked as synthetic. -func (h *synthWrapper) BeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, randao eth2p0.BLSSignature, graffiti []byte) (*spec.VersionedBeaconBlock, error) { - vIdx, ok, err := h.synthProposerCache.SyntheticVIdx(ctx, h.Client, slot) +// Proposal returns an unsigned beacon block proposal, possibly marked as synthetic. +func (h *synthWrapper) Proposal(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.Response[*eth2api.VersionedProposal], error) { + vIdx, ok, err := h.synthProposerCache.SyntheticVIdx(ctx, h.Client, opts.Slot) if err != nil { return nil, err } else if !ok { - return h.Client.BeaconBlockProposal(ctx, slot, randao, graffiti) + resp, err := h.Client.Proposal(ctx, opts) + if err != nil { + return nil, errors.Wrap(err, "propose beacon proposal") + } + + return resp, nil } - return h.syntheticBlock(ctx, slot, vIdx) + proposal, err := h.syntheticProposal(ctx, opts.Slot, vIdx) + if err != nil { + return nil, err + } + + return wrapResponse(proposal), nil } -// BlindedBeaconBlockProposal returns an unsigned blinded beacon block, possibly marked as synthetic. -func (h *synthWrapper) BlindedBeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, randao eth2p0.BLSSignature, graffiti []byte) (*api.VersionedBlindedBeaconBlock, error) { - vIdx, ok, err := h.synthProposerCache.SyntheticVIdx(ctx, h.Client, slot) +// BlindedProposal returns an unsigned blinded beacon block proposal, possibly marked as synthetic. +func (h *synthWrapper) BlindedProposal(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.Response[*eth2api.VersionedBlindedProposal], error) { + vIdx, ok, err := h.synthProposerCache.SyntheticVIdx(ctx, h.Client, opts.Slot) if err != nil { return nil, err } else if !ok { - return h.Client.BlindedBeaconBlockProposal(ctx, slot, randao, graffiti) + resp, err := h.Client.BlindedProposal(ctx, opts) + if err != nil { + return nil, errors.Wrap(err, "propose blinded beacon block") + } + + return resp, nil } - block, err := h.syntheticBlock(ctx, slot, vIdx) + proposal, err := h.syntheticProposal(ctx, opts.Slot, vIdx) if err != nil { return nil, err } - return blindedBlock(block) + synthBlindedProposal, err := blindedProposal(proposal) + if err != nil { + return nil, err + } + + return wrapResponse(synthBlindedProposal), nil } -// syntheticBlock returns a synthetic beacon block to propose. -func (h *synthWrapper) syntheticBlock(ctx context.Context, slot eth2p0.Slot, vIdx eth2p0.ValidatorIndex) (*spec.VersionedBeaconBlock, error) { +// syntheticProposal returns a synthetic unsigned beacon block to propose. +func (h *synthWrapper) syntheticProposal(ctx context.Context, slot eth2p0.Slot, vIdx eth2p0.ValidatorIndex) (*eth2api.VersionedProposal, error) { var signedBlock *spec.VersionedSignedBeaconBlock - // Work our way back from previous slot to find a block to base the synthetic block on. + // Work our way back from previous slot to find a proposal to base the synthetic proposal on. for prev := slot - 1; prev > 0; prev-- { - signed, err := h.Client.SignedBeaconBlock(ctx, fmt.Sprint(prev)) + opts := ð2api.SignedBeaconBlockOpts{ + Block: fmt.Sprint(prev), + } + signed, err := h.Client.SignedBeaconBlock(ctx, opts) if err != nil { return nil, err - } else if signed == nil { // go-eth2-client returns nil if block is not found. + } else if signed == nil { // go-eth2-client returns nil if proposal is not found. continue } - signedBlock = signed + signedBlock = signed.Data break } if signedBlock == nil { - return nil, errors.New("no block found to base synthetic block on") + return nil, errors.New("no proposal found to base synthetic proposal on") } - // Convert signed block into unsigned block with synthetic graffiti and correct slot. + // Convert signed proposal into unsigned proposal with synthetic graffiti and correct slot. feeRecipient := h.getFeeRecipient(vIdx) - block := &spec.VersionedBeaconBlock{Version: signedBlock.Version} - + proposal := ð2api.VersionedProposal{Version: signedBlock.Version} switch signedBlock.Version { case spec.DataVersionPhase0: - block.Phase0 = signedBlock.Phase0.Message - block.Phase0.Body.Graffiti = GetSyntheticGraffiti() - block.Phase0.Slot = slot - block.Phase0.ProposerIndex = vIdx + proposal.Phase0 = signedBlock.Phase0.Message + proposal.Phase0.Body.Graffiti = GetSyntheticGraffiti() + proposal.Phase0.Slot = slot + proposal.Phase0.ProposerIndex = vIdx case spec.DataVersionAltair: - block.Altair = signedBlock.Altair.Message - block.Altair.Body.Graffiti = GetSyntheticGraffiti() - block.Altair.Slot = slot - block.Altair.ProposerIndex = vIdx + proposal.Altair = signedBlock.Altair.Message + proposal.Altair.Body.Graffiti = GetSyntheticGraffiti() + proposal.Altair.Slot = slot + proposal.Altair.ProposerIndex = vIdx case spec.DataVersionBellatrix: - block.Bellatrix = signedBlock.Bellatrix.Message - block.Bellatrix.Body.Graffiti = GetSyntheticGraffiti() - block.Bellatrix.Slot = slot - block.Bellatrix.ProposerIndex = vIdx - block.Bellatrix.Body.ExecutionPayload.FeeRecipient = feeRecipient - block.Bellatrix.Body.ExecutionPayload.Transactions = fraction(block.Bellatrix.Body.ExecutionPayload.Transactions) + proposal.Bellatrix = signedBlock.Bellatrix.Message + proposal.Bellatrix.Body.Graffiti = GetSyntheticGraffiti() + proposal.Bellatrix.Slot = slot + proposal.Bellatrix.ProposerIndex = vIdx + proposal.Bellatrix.Body.ExecutionPayload.FeeRecipient = feeRecipient + proposal.Bellatrix.Body.ExecutionPayload.Transactions = fraction(proposal.Bellatrix.Body.ExecutionPayload.Transactions) case spec.DataVersionCapella: - block.Capella = signedBlock.Capella.Message - block.Capella.Body.Graffiti = GetSyntheticGraffiti() - block.Capella.Slot = slot - block.Capella.ProposerIndex = vIdx - block.Capella.Body.ExecutionPayload.FeeRecipient = feeRecipient - block.Capella.Body.ExecutionPayload.Transactions = fraction(block.Capella.Body.ExecutionPayload.Transactions) + proposal.Capella = signedBlock.Capella.Message + proposal.Capella.Body.Graffiti = GetSyntheticGraffiti() + proposal.Capella.Slot = slot + proposal.Capella.ProposerIndex = vIdx + proposal.Capella.Body.ExecutionPayload.FeeRecipient = feeRecipient + proposal.Capella.Body.ExecutionPayload.Transactions = fraction(proposal.Capella.Body.ExecutionPayload.Transactions) default: - return nil, errors.New("unsupported block version") + return nil, errors.New("unsupported proposal version") } - return block, nil + return proposal, nil } // fraction returns a fraction of the transactions in the block. @@ -178,24 +205,24 @@ func fraction(transactions []bellatrix.Transaction) []bellatrix.Transaction { return transactions[:len(transactions)/syntheticBlockFraction] } -// SubmitBlindedBeaconBlock submits a blinded beacon block or swallows it if marked as synthetic. -func (h *synthWrapper) SubmitBlindedBeaconBlock(ctx context.Context, block *api.VersionedSignedBlindedBeaconBlock) error { - if IsSyntheticBlindedBlock(block) { - log.Debug(ctx, "Synthetic blinded beacon block swallowed") +// SubmitBlindedProposal submits a blinded beacon block proposal or swallows it if marked as synthetic. +func (h *synthWrapper) SubmitBlindedProposal(ctx context.Context, proposal *eth2api.VersionedSignedBlindedProposal) error { + if IsSyntheticBlindedBlock(proposal) { + log.Debug(ctx, "Synthetic blinded beacon proposal swallowed") return nil } - return h.Client.SubmitBlindedBeaconBlock(ctx, block) + return h.Client.SubmitBlindedProposal(ctx, proposal) } -// SubmitBeaconBlock submits a beacon block or swallows it if marked as synthetic. -func (h *synthWrapper) SubmitBeaconBlock(ctx context.Context, block *spec.VersionedSignedBeaconBlock) error { - if IsSyntheticBlock(block) { +// SubmitProposal submits a beacon block or swallows it if marked as synthetic. +func (h *synthWrapper) SubmitProposal(ctx context.Context, proposal *eth2api.VersionedSignedProposal) error { + if IsSyntheticProposal(proposal) { log.Debug(ctx, "Synthetic beacon block swallowed") return nil } - return h.Client.SubmitBeaconBlock(ctx, block) + return h.Client.SubmitProposal(ctx, proposal) } // GetSyntheticGraffiti returns the graffiti used to mark synthetic blocks. @@ -207,7 +234,7 @@ func GetSyntheticGraffiti() [32]byte { } // IsSyntheticBlindedBlock returns true if the blinded block is a synthetic block. -func IsSyntheticBlindedBlock(block *api.VersionedSignedBlindedBeaconBlock) bool { +func IsSyntheticBlindedBlock(block *eth2api.VersionedSignedBlindedProposal) bool { var graffiti [32]byte switch block.Version { case spec.DataVersionBellatrix: @@ -221,8 +248,8 @@ func IsSyntheticBlindedBlock(block *api.VersionedSignedBlindedBeaconBlock) bool return graffiti == GetSyntheticGraffiti() } -// IsSyntheticBlock returns true if the block is a synthetic block. -func IsSyntheticBlock(block *spec.VersionedSignedBeaconBlock) bool { +// IsSyntheticProposal returns true if the block is a synthetic block proposal. +func IsSyntheticProposal(block *eth2api.VersionedSignedProposal) bool { var graffiti [32]byte switch block.Version { case spec.DataVersionPhase0: @@ -279,11 +306,17 @@ func (c *synthProposerCache) Duties(ctx context.Context, eth2Cl synthProposerEth } // Get actual duties for all validators for the epoch. - duties, err = eth2Cl.ProposerDuties(ctx, epoch, vals.Indices()) + opts := ð2api.ProposerDutiesOpts{ + Epoch: epoch, + Indices: vals.Indices(), + } + resp, err := eth2Cl.ProposerDuties(ctx, opts) if err != nil { return nil, err } + duties = resp.Data + // Get slotsPerEpoch and the starting slot of the epoch. slotsPerEpoch, err := eth2Cl.SlotsPerEpoch(ctx) if err != nil { @@ -398,88 +431,93 @@ func getStandardHashFn() shuffle.HashFn { return hashFn } -// blindedBlock converts a normal block into a blinded block. -func blindedBlock(block *spec.VersionedBeaconBlock) (*api.VersionedBlindedBeaconBlock, error) { - var resp *api.VersionedBlindedBeaconBlock +// blindedProposal converts a normal block into a blinded block proposal. +func blindedProposal(proposal *eth2api.VersionedProposal) (*eth2api.VersionedBlindedProposal, error) { + var resp *eth2api.VersionedBlindedProposal // Blinded blocks are only available from bellatrix. - switch block.Version { + switch proposal.Version { case spec.DataVersionBellatrix: - resp = &api.VersionedBlindedBeaconBlock{ - Version: block.Version, + resp = ð2api.VersionedBlindedProposal{ + Version: proposal.Version, Bellatrix: ð2bellatrix.BlindedBeaconBlock{ - Slot: block.Bellatrix.Slot, - ProposerIndex: block.Bellatrix.ProposerIndex, - ParentRoot: block.Bellatrix.ParentRoot, - StateRoot: block.Bellatrix.StateRoot, + Slot: proposal.Bellatrix.Slot, + ProposerIndex: proposal.Bellatrix.ProposerIndex, + ParentRoot: proposal.Bellatrix.ParentRoot, + StateRoot: proposal.Bellatrix.StateRoot, Body: ð2bellatrix.BlindedBeaconBlockBody{ - RANDAOReveal: block.Bellatrix.Body.RANDAOReveal, - ETH1Data: block.Bellatrix.Body.ETH1Data, - Graffiti: block.Bellatrix.Body.Graffiti, - ProposerSlashings: block.Bellatrix.Body.ProposerSlashings, - AttesterSlashings: block.Bellatrix.Body.AttesterSlashings, - Attestations: block.Bellatrix.Body.Attestations, - Deposits: block.Bellatrix.Body.Deposits, - VoluntaryExits: block.Bellatrix.Body.VoluntaryExits, - SyncAggregate: block.Bellatrix.Body.SyncAggregate, + RANDAOReveal: proposal.Bellatrix.Body.RANDAOReveal, + ETH1Data: proposal.Bellatrix.Body.ETH1Data, + Graffiti: proposal.Bellatrix.Body.Graffiti, + ProposerSlashings: proposal.Bellatrix.Body.ProposerSlashings, + AttesterSlashings: proposal.Bellatrix.Body.AttesterSlashings, + Attestations: proposal.Bellatrix.Body.Attestations, + Deposits: proposal.Bellatrix.Body.Deposits, + VoluntaryExits: proposal.Bellatrix.Body.VoluntaryExits, + SyncAggregate: proposal.Bellatrix.Body.SyncAggregate, ExecutionPayloadHeader: &bellatrix.ExecutionPayloadHeader{ - ParentHash: block.Bellatrix.Body.ExecutionPayload.ParentHash, - FeeRecipient: block.Bellatrix.Body.ExecutionPayload.FeeRecipient, - StateRoot: block.Bellatrix.Body.ExecutionPayload.StateRoot, - ReceiptsRoot: block.Bellatrix.Body.ExecutionPayload.ReceiptsRoot, - LogsBloom: block.Bellatrix.Body.ExecutionPayload.LogsBloom, - PrevRandao: block.Bellatrix.Body.ExecutionPayload.PrevRandao, - BlockNumber: block.Bellatrix.Body.ExecutionPayload.BlockNumber, - GasLimit: block.Bellatrix.Body.ExecutionPayload.GasLimit, - GasUsed: block.Bellatrix.Body.ExecutionPayload.GasUsed, - Timestamp: block.Bellatrix.Body.ExecutionPayload.Timestamp, - ExtraData: block.Bellatrix.Body.ExecutionPayload.ExtraData, - BaseFeePerGas: block.Bellatrix.Body.ExecutionPayload.BaseFeePerGas, - BlockHash: block.Bellatrix.Body.ExecutionPayload.BlockHash, + ParentHash: proposal.Bellatrix.Body.ExecutionPayload.ParentHash, + FeeRecipient: proposal.Bellatrix.Body.ExecutionPayload.FeeRecipient, + StateRoot: proposal.Bellatrix.Body.ExecutionPayload.StateRoot, + ReceiptsRoot: proposal.Bellatrix.Body.ExecutionPayload.ReceiptsRoot, + LogsBloom: proposal.Bellatrix.Body.ExecutionPayload.LogsBloom, + PrevRandao: proposal.Bellatrix.Body.ExecutionPayload.PrevRandao, + BlockNumber: proposal.Bellatrix.Body.ExecutionPayload.BlockNumber, + GasLimit: proposal.Bellatrix.Body.ExecutionPayload.GasLimit, + GasUsed: proposal.Bellatrix.Body.ExecutionPayload.GasUsed, + Timestamp: proposal.Bellatrix.Body.ExecutionPayload.Timestamp, + ExtraData: proposal.Bellatrix.Body.ExecutionPayload.ExtraData, + BaseFeePerGas: proposal.Bellatrix.Body.ExecutionPayload.BaseFeePerGas, + BlockHash: proposal.Bellatrix.Body.ExecutionPayload.BlockHash, TransactionsRoot: eth2p0.Root{}, // Use empty root. }, }, }, } case spec.DataVersionCapella: - resp = &api.VersionedBlindedBeaconBlock{ - Version: block.Version, + resp = ð2api.VersionedBlindedProposal{ + Version: proposal.Version, Capella: ð2capella.BlindedBeaconBlock{ - Slot: block.Capella.Slot, - ProposerIndex: block.Capella.ProposerIndex, - ParentRoot: block.Capella.ParentRoot, - StateRoot: block.Capella.StateRoot, + Slot: proposal.Capella.Slot, + ProposerIndex: proposal.Capella.ProposerIndex, + ParentRoot: proposal.Capella.ParentRoot, + StateRoot: proposal.Capella.StateRoot, Body: ð2capella.BlindedBeaconBlockBody{ - RANDAOReveal: block.Capella.Body.RANDAOReveal, - ETH1Data: block.Capella.Body.ETH1Data, - Graffiti: block.Capella.Body.Graffiti, - ProposerSlashings: block.Capella.Body.ProposerSlashings, - AttesterSlashings: block.Capella.Body.AttesterSlashings, - Attestations: block.Capella.Body.Attestations, - Deposits: block.Capella.Body.Deposits, - VoluntaryExits: block.Capella.Body.VoluntaryExits, - SyncAggregate: block.Capella.Body.SyncAggregate, + RANDAOReveal: proposal.Capella.Body.RANDAOReveal, + ETH1Data: proposal.Capella.Body.ETH1Data, + Graffiti: proposal.Capella.Body.Graffiti, + ProposerSlashings: proposal.Capella.Body.ProposerSlashings, + AttesterSlashings: proposal.Capella.Body.AttesterSlashings, + Attestations: proposal.Capella.Body.Attestations, + Deposits: proposal.Capella.Body.Deposits, + VoluntaryExits: proposal.Capella.Body.VoluntaryExits, + SyncAggregate: proposal.Capella.Body.SyncAggregate, ExecutionPayloadHeader: &capella.ExecutionPayloadHeader{ - ParentHash: block.Capella.Body.ExecutionPayload.ParentHash, - FeeRecipient: block.Capella.Body.ExecutionPayload.FeeRecipient, - StateRoot: block.Capella.Body.ExecutionPayload.StateRoot, - ReceiptsRoot: block.Capella.Body.ExecutionPayload.ReceiptsRoot, - LogsBloom: block.Capella.Body.ExecutionPayload.LogsBloom, - PrevRandao: block.Capella.Body.ExecutionPayload.PrevRandao, - BlockNumber: block.Capella.Body.ExecutionPayload.BlockNumber, - GasLimit: block.Capella.Body.ExecutionPayload.GasLimit, - GasUsed: block.Capella.Body.ExecutionPayload.GasUsed, - Timestamp: block.Capella.Body.ExecutionPayload.Timestamp, - ExtraData: block.Capella.Body.ExecutionPayload.ExtraData, - BaseFeePerGas: block.Capella.Body.ExecutionPayload.BaseFeePerGas, - BlockHash: block.Capella.Body.ExecutionPayload.BlockHash, + ParentHash: proposal.Capella.Body.ExecutionPayload.ParentHash, + FeeRecipient: proposal.Capella.Body.ExecutionPayload.FeeRecipient, + StateRoot: proposal.Capella.Body.ExecutionPayload.StateRoot, + ReceiptsRoot: proposal.Capella.Body.ExecutionPayload.ReceiptsRoot, + LogsBloom: proposal.Capella.Body.ExecutionPayload.LogsBloom, + PrevRandao: proposal.Capella.Body.ExecutionPayload.PrevRandao, + BlockNumber: proposal.Capella.Body.ExecutionPayload.BlockNumber, + GasLimit: proposal.Capella.Body.ExecutionPayload.GasLimit, + GasUsed: proposal.Capella.Body.ExecutionPayload.GasUsed, + Timestamp: proposal.Capella.Body.ExecutionPayload.Timestamp, + ExtraData: proposal.Capella.Body.ExecutionPayload.ExtraData, + BaseFeePerGas: proposal.Capella.Body.ExecutionPayload.BaseFeePerGas, + BlockHash: proposal.Capella.Body.ExecutionPayload.BlockHash, TransactionsRoot: eth2p0.Root{}, // Use empty root. }, }, }, } - default: - return nil, errors.New("unsupported blinded block version") + default: // TODO(xenowits): Add a case for deneb blinded block + return nil, errors.New("unsupported blinded proposal version") } return resp, nil } + +// wrapResponse wraps the provided data into an API Response and returns the response. +func wrapResponse[T any](data T) *eth2api.Response[T] { + return ð2api.Response[T]{Data: data} +} diff --git a/app/eth2wrap/synthproposer_test.go b/app/eth2wrap/synthproposer_test.go index b83a64636..63b75f7f0 100644 --- a/app/eth2wrap/synthproposer_test.go +++ b/app/eth2wrap/synthproposer_test.go @@ -4,7 +4,6 @@ package eth2wrap_test import ( "context" - "math/rand" "testing" eth2api "github.com/attestantio/go-eth2-client/api" @@ -32,15 +31,17 @@ func TestSynthProposer(t *testing.T) { done = make(chan struct{}) activeVals = 0 ) + bmock, err := beaconmock.New(beaconmock.WithValidatorSet(set), beaconmock.WithSlotsPerEpoch(slotsPerEpoch)) require.NoError(t, err) - bmock.SubmitBeaconBlockFunc = func(ctx context.Context, block *spec.VersionedSignedBeaconBlock) error { - require.Equal(t, realBlockSlot, block.Capella.Message.Slot) + bmock.SubmitProposalFunc = func(ctx context.Context, proposal *eth2api.VersionedSignedProposal) error { + require.Equal(t, realBlockSlot, proposal.Capella.Message.Slot) close(done) return nil } + bmock.ProposerDutiesFunc = func(ctx context.Context, e eth2p0.Epoch, indices []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) { require.Equal(t, int(epoch), int(e)) @@ -59,11 +60,13 @@ func TestSynthProposer(t *testing.T) { } signedBeaconBlock := bmock.SignedBeaconBlock bmock.SignedBeaconBlockFunc = func(ctx context.Context, blockID string) (*spec.VersionedSignedBeaconBlock, error) { - if rand.Float32() < 0.3 { // Fail to find 2/3 of blocks. - return nil, nil //nolint:nilnil // go-eth2-client returns nilnil if block not found. + opts := ð2api.SignedBeaconBlockOpts{Block: blockID} + resp, err := signedBeaconBlock(ctx, opts) + if err != nil { + return nil, err } - return signedBeaconBlock(ctx, blockID) + return resp.Data, nil } eth2Cl := eth2wrap.WithSyntheticDuties(bmock) @@ -78,40 +81,65 @@ func TestSynthProposer(t *testing.T) { require.NoError(t, eth2Cl.SubmitProposalPreparations(ctx, preps)) // Get synthetic duties - duties, err := eth2Cl.ProposerDuties(ctx, epoch, nil) + opts := ð2api.ProposerDutiesOpts{ + Epoch: epoch, + Indices: nil, + } + resp1, err := eth2Cl.ProposerDuties(ctx, opts) require.NoError(t, err) + duties := resp1.Data require.Len(t, duties, len(set)) require.Equal(t, 1, activeVals) // Get synthetic duties again - duties2, err := eth2Cl.ProposerDuties(ctx, epoch, nil) + resp2, err := eth2Cl.ProposerDuties(ctx, opts) require.NoError(t, err) + duties2 := resp2.Data require.Equal(t, duties, duties2) // Identical require.Equal(t, 1, activeVals) // Cached // Submit blocks for _, duty := range duties { - block, err := eth2Cl.BeaconBlockProposal(ctx, duty.Slot, testutil.RandomEth2Signature(), []byte("test")) + var graff [32]byte + copy(graff[:], "test") + opts1 := ð2api.ProposalOpts{ + Slot: duty.Slot, + RandaoReveal: testutil.RandomEth2Signature(), + Graffiti: graff, + } + resp, err := eth2Cl.Proposal(ctx, opts1) require.NoError(t, err) + block := resp.Data + if duty.Slot == realBlockSlot { require.NotContains(t, string(block.Capella.Body.Graffiti[:]), "DO NOT SUBMIT") require.NotEqual(t, feeRecipient, block.Capella.Body.ExecutionPayload.FeeRecipient) } else { require.Contains(t, string(block.Capella.Body.Graffiti[:]), "DO NOT SUBMIT") require.Equal(t, feeRecipient, block.Capella.Body.ExecutionPayload.FeeRecipient) + + continue } require.Equal(t, spec.DataVersionCapella, block.Version) - signed := testutil.RandomCapellaVersionedSignedBeaconBlock() + signed := testutil.RandomVersionedSignedProposal() signed.Capella.Message = block.Capella - err = eth2Cl.SubmitBeaconBlock(ctx, signed) + err = eth2Cl.SubmitProposal(ctx, signed) require.NoError(t, err) } // Submit blinded blocks for _, duty := range duties { - block, err := eth2Cl.BlindedBeaconBlockProposal(ctx, duty.Slot, testutil.RandomEth2Signature(), []byte("test")) + var graff [32]byte + copy(graff[:], "test") + opts := ð2api.BlindedProposalOpts{ + Slot: duty.Slot, + RandaoReveal: testutil.RandomEth2Signature(), + Graffiti: graff, + } + resp, err := eth2Cl.BlindedProposal(ctx, opts) require.NoError(t, err) + block := resp.Data if duty.Slot == realBlockSlot { require.NotContains(t, string(block.Capella.Body.Graffiti[:]), "DO NOT SUBMIT") require.NotEqual(t, feeRecipient, block.Capella.Body.ExecutionPayloadHeader.FeeRecipient) @@ -120,14 +148,14 @@ func TestSynthProposer(t *testing.T) { } require.Equal(t, spec.DataVersionCapella, block.Version) - signed := ð2api.VersionedSignedBlindedBeaconBlock{ + signed := ð2api.VersionedSignedBlindedProposal{ Version: spec.DataVersionCapella, Capella: ð2capella.SignedBlindedBeaconBlock{ Message: block.Capella, Signature: testutil.RandomEth2Signature(), }, } - err = eth2Cl.SubmitBlindedBeaconBlock(ctx, signed) + err = eth2Cl.SubmitBlindedProposal(ctx, signed) require.NoError(t, err) } diff --git a/app/eth2wrap/valcache.go b/app/eth2wrap/valcache.go index 9e1f2f535..b68e38d3c 100644 --- a/app/eth2wrap/valcache.go +++ b/app/eth2wrap/valcache.go @@ -6,6 +6,7 @@ import ( "context" "sync" + eth2api "github.com/attestantio/go-eth2-client/api" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/obolnetwork/charon/app/errors" @@ -88,10 +89,15 @@ func (c *ValidatorCache) Get(ctx context.Context) (ActiveValidators, error) { return c.active, nil } - vals, err := c.eth2Cl.ValidatorsByPubKey(ctx, "head", c.pubkeys) + opts := ð2api.ValidatorsOpts{ + State: "head", + PubKeys: c.pubkeys, + } + eth2Resp, err := c.eth2Cl.Validators(ctx, opts) if err != nil { return nil, err } + vals := eth2Resp.Data resp := make(ActiveValidators) for _, val := range vals { diff --git a/app/eth2wrap/valcache_test.go b/app/eth2wrap/valcache_test.go index 09efca2d2..609887dc4 100644 --- a/app/eth2wrap/valcache_test.go +++ b/app/eth2wrap/valcache_test.go @@ -7,6 +7,7 @@ import ( "math/rand" "testing" + eth2api "github.com/attestantio/go-eth2-client/api" eth2v1 "github.com/attestantio/go-eth2-client/api/v1" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/stretchr/testify/require" @@ -42,10 +43,10 @@ func TestValidatorCache(t *testing.T) { // Configure it to return the set of validators if queried. var queried int - eth2Cl.ValidatorsByPubKeyFunc = func(ctx context.Context, stateID string, keys []eth2p0.BLSPubKey) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { + eth2Cl.ValidatorsFunc = func(ctx context.Context, opts *eth2api.ValidatorsOpts) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { queried++ - require.Equal(t, "head", stateID) - require.Equal(t, pubkeys, keys) + require.Equal(t, "head", opts.State) + require.Equal(t, pubkeys, opts.PubKeys) return set, nil } diff --git a/app/monitoringapi.go b/app/monitoringapi.go index 5e4fb89c2..59bcfb5b6 100644 --- a/app/monitoringapi.go +++ b/app/monitoringapi.go @@ -205,12 +205,12 @@ func startReadyChecker(ctx context.Context, tcpNode host.Host, eth2Cl eth2wrap.C // beaconNodeSyncing returns true if the beacon node is still syncing. It also returns the sync distance, ie, the distance // between the node's highest synced slot and the head slot. func beaconNodeSyncing(ctx context.Context, eth2Cl eth2client.NodeSyncingProvider) (bool, eth2p0.Slot, error) { - state, err := eth2Cl.NodeSyncing(ctx) + eth2Resp, err := eth2Cl.NodeSyncing(ctx) if err != nil { return false, 0, err } - return state.IsSyncing, state.SyncDistance, nil + return eth2Resp.Data.IsSyncing, eth2Resp.Data.SyncDistance, nil } // beaconNodeVersionMetric sets the beacon node version gauge. @@ -218,11 +218,12 @@ func beaconNodeVersionMetric(ctx context.Context, eth2Cl eth2wrap.Client, clock nodeVersionTicker := clock.NewTicker(10 * time.Minute) setNodeVersion := func() { - version, err := eth2Cl.NodeVersion(ctx) + eth2Resp, err := eth2Cl.NodeVersion(ctx) if err != nil { log.Error(ctx, "Failed to get beacon node version", err) return } + version := eth2Resp.Data beaconNodeVersionGauge.Reset() beaconNodeVersionGauge.WithLabelValues(version).Set(1) diff --git a/core/bcast/bcast.go b/core/bcast/bcast.go index 2a855ba54..cee83554e 100644 --- a/core/bcast/bcast.go +++ b/core/bcast/bcast.go @@ -73,12 +73,12 @@ func (b Broadcaster) Broadcast(ctx context.Context, duty core.Duty, set core.Sig return err } - block, ok := aggData.(core.VersionedSignedBeaconBlock) + block, ok := aggData.(core.VersionedSignedProposal) if !ok { - return errors.New("invalid block") + return errors.New("invalid proposal") } - err = b.eth2Cl.SubmitBeaconBlock(ctx, &block.VersionedSignedBeaconBlock) + err = b.eth2Cl.SubmitProposal(ctx, &block.VersionedSignedProposal) if err == nil { log.Info(ctx, "Successfully submitted block proposal to beacon node", z.Any("delay", b.delayFunc(duty.Slot)), @@ -94,12 +94,12 @@ func (b Broadcaster) Broadcast(ctx context.Context, duty core.Duty, set core.Sig return err } - block, ok := aggData.(core.VersionedSignedBlindedBeaconBlock) + block, ok := aggData.(core.VersionedSignedBlindedProposal) if !ok { - return errors.New("invalid block") + return errors.New("invalid blinded proposal") } - err = b.eth2Cl.SubmitBlindedBeaconBlock(ctx, &block.VersionedSignedBlindedBeaconBlock) + err = b.eth2Cl.SubmitBlindedProposal(ctx, &block.VersionedSignedBlindedProposal) if err == nil { log.Info(ctx, "Successfully submitted blinded block proposal to beacon node", z.Any("delay", b.delayFunc(duty.Slot)), diff --git a/core/bcast/bcast_test.go b/core/bcast/bcast_test.go index e5e57c162..c6dd5dfb8 100644 --- a/core/bcast/bcast_test.go +++ b/core/bcast/bcast_test.go @@ -31,8 +31,8 @@ type test struct { func TestBroadcast(t *testing.T) { testFuncs := []func(*testing.T, *beaconmock.Mock) test{ attData, // Attestation - beaconBlockData, // BeaconBlock - blindedBeaconBlockData, // BlindedBeaconBlock + proposalData, // BeaconBlock + blindedProposalData, // BlindedBeaconBlock validatorRegistrationData, // ValidatorRegistration validatorExitData, // ValidatorExit aggregateAttestationData, // AggregateAttestation @@ -102,12 +102,12 @@ func attData(t *testing.T, mock *beaconmock.Mock) test { } } -func beaconBlockData(t *testing.T, mock *beaconmock.Mock) test { +func proposalData(t *testing.T, mock *beaconmock.Mock) test { t.Helper() asserted := make(chan struct{}) - block1 := eth2spec.VersionedSignedBeaconBlock{ + proposal1 := eth2api.VersionedSignedProposal{ Version: eth2spec.DataVersionPhase0, Phase0: ð2p0.SignedBeaconBlock{ Message: testutil.RandomPhase0BeaconBlock(), @@ -115,17 +115,17 @@ func beaconBlockData(t *testing.T, mock *beaconmock.Mock) test { }, } - aggData := core.VersionedSignedBeaconBlock{VersionedSignedBeaconBlock: block1} + aggData := core.VersionedSignedProposal{VersionedSignedProposal: proposal1} - mock.SubmitBeaconBlockFunc = func(ctx context.Context, block2 *eth2spec.VersionedSignedBeaconBlock) error { - require.Equal(t, block1, *block2) + mock.SubmitProposalFunc = func(ctx context.Context, proposal2 *eth2api.VersionedSignedProposal) error { + require.Equal(t, proposal1, *proposal2) close(asserted) return nil } return test{ - name: "Broadcast Beacon Block", + name: "Broadcast Beacon Block Proposal", aggData: aggData, duty: core.DutyProposer, bcastCnt: 1, @@ -133,12 +133,12 @@ func beaconBlockData(t *testing.T, mock *beaconmock.Mock) test { } } -func blindedBeaconBlockData(t *testing.T, mock *beaconmock.Mock) test { +func blindedProposalData(t *testing.T, mock *beaconmock.Mock) test { t.Helper() asserted := make(chan struct{}) - block1 := eth2api.VersionedSignedBlindedBeaconBlock{ + proposal1 := eth2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Capella: ð2capella.SignedBlindedBeaconBlock{ Message: testutil.RandomCapellaBlindedBeaconBlock(), @@ -146,17 +146,17 @@ func blindedBeaconBlockData(t *testing.T, mock *beaconmock.Mock) test { }, } - aggData := core.VersionedSignedBlindedBeaconBlock{VersionedSignedBlindedBeaconBlock: block1} + aggData := core.VersionedSignedBlindedProposal{VersionedSignedBlindedProposal: proposal1} - mock.SubmitBlindedBeaconBlockFunc = func(ctx context.Context, block2 *eth2api.VersionedSignedBlindedBeaconBlock) error { - require.Equal(t, block1, *block2) + mock.SubmitBlindedProposalFunc = func(ctx context.Context, proposal2 *eth2api.VersionedSignedBlindedProposal) error { + require.Equal(t, proposal1, *proposal2) close(asserted) return nil } return test{ - name: "Broadcast Blinded Beacon Block", + name: "Broadcast Blinded Beacon Block Proposal", aggData: aggData, duty: core.DutyBuilderProposer, bcastCnt: 1, diff --git a/core/dutydb/memory.go b/core/dutydb/memory.go index 742a33f94..e6e1ac283 100644 --- a/core/dutydb/memory.go +++ b/core/dutydb/memory.go @@ -7,7 +7,6 @@ import ( "sync" eth2api "github.com/attestantio/go-eth2-client/api" - eth2spec "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/altair" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" @@ -22,8 +21,8 @@ func NewMemDB(deadliner core.Deadliner) *MemDB { attDuties: make(map[attKey]*eth2p0.AttestationData), attPubKeys: make(map[pkKey]core.PubKey), attKeysBySlot: make(map[int64][]pkKey), - builderProDuties: make(map[int64]*eth2api.VersionedBlindedBeaconBlock), - proDuties: make(map[int64]*eth2spec.VersionedBeaconBlock), + builderProDuties: make(map[int64]*eth2api.VersionedBlindedProposal), + proDuties: make(map[int64]*eth2api.VersionedProposal), aggDuties: make(map[aggKey]core.AggregatedAttestation), aggKeysBySlot: make(map[int64][]aggKey), contribDuties: make(map[contribKey]*altair.SyncCommitteeContribution), @@ -45,11 +44,11 @@ type MemDB struct { attQueries []attQuery // DutyBuilderProposer - builderProDuties map[int64]*eth2api.VersionedBlindedBeaconBlock + builderProDuties map[int64]*eth2api.VersionedBlindedProposal builderProQueries []builderProQuery // DutyProposer - proDuties map[int64]*eth2spec.VersionedBeaconBlock + proDuties map[int64]*eth2api.VersionedProposal proQueries []proQuery // DutyAggregator @@ -88,7 +87,7 @@ func (db *MemDB) Store(_ context.Context, duty core.Duty, unsignedSet core.Unsig return errors.New("unexpected proposer data set length", z.Int("n", len(unsignedSet))) } for _, unsignedData := range unsignedSet { - err := db.storeBeaconBlockUnsafe(unsignedData) + err := db.storeProposalUnsafe(unsignedData) if err != nil { return err } @@ -155,11 +154,11 @@ func (db *MemDB) Store(_ context.Context, duty core.Duty, unsignedSet core.Unsig return nil } -// AwaitBeaconBlock implements core.DutyDB, see its godoc. -func (db *MemDB) AwaitBeaconBlock(ctx context.Context, slot int64) (*eth2spec.VersionedBeaconBlock, error) { +// AwaitProposal implements core.DutyDB, see its godoc. +func (db *MemDB) AwaitProposal(ctx context.Context, slot int64) (*eth2api.VersionedProposal, error) { cancel := make(chan struct{}) defer close(cancel) - response := make(chan *eth2spec.VersionedBeaconBlock, 1) + response := make(chan *eth2api.VersionedProposal, 1) db.mu.Lock() db.proQueries = append(db.proQueries, proQuery{ @@ -180,11 +179,11 @@ func (db *MemDB) AwaitBeaconBlock(ctx context.Context, slot int64) (*eth2spec.Ve } } -// AwaitBlindedBeaconBlock implements core.DutyDB, see its godoc. -func (db *MemDB) AwaitBlindedBeaconBlock(ctx context.Context, slot int64) (*eth2api.VersionedBlindedBeaconBlock, error) { +// AwaitBlindedProposal implements core.DutyDB, see its godoc. +func (db *MemDB) AwaitBlindedProposal(ctx context.Context, slot int64) (*eth2api.VersionedBlindedProposal, error) { cancel := make(chan struct{}) defer close(cancel) - response := make(chan *eth2api.VersionedBlindedBeaconBlock, 1) + response := make(chan *eth2api.VersionedBlindedProposal, 1) db.mu.Lock() db.builderProQueries = append(db.builderProQueries, builderProQuery{ @@ -452,19 +451,19 @@ func (db *MemDB) storeSyncContributionUnsafe(unsignedData core.UnsignedData) err return nil } -// storeBeaconBlockUnsafe stores the unsigned BeaconBlock. It is unsafe since it assumes the lock is held. -func (db *MemDB) storeBeaconBlockUnsafe(unsignedData core.UnsignedData) error { +// storeProposalUnsafe stores the unsigned Proposal. It is unsafe since it assumes the lock is held. +func (db *MemDB) storeProposalUnsafe(unsignedData core.UnsignedData) error { cloned, err := unsignedData.Clone() // Clone before storing. if err != nil { return err } - block, ok := cloned.(core.VersionedBeaconBlock) + proposal, ok := cloned.(core.VersionedProposal) if !ok { - return errors.New("invalid unsigned block") + return errors.New("invalid versioned proposal") } - slot, err := block.Slot() + slot, err := proposal.Slot() if err != nil { return err } @@ -472,19 +471,19 @@ func (db *MemDB) storeBeaconBlockUnsafe(unsignedData core.UnsignedData) error { if existing, ok := db.proDuties[int64(slot)]; ok { existingRoot, err := existing.Root() if err != nil { - return errors.Wrap(err, "block root") + return errors.Wrap(err, "proposal root") } - providedRoot, err := block.Root() + providedRoot, err := proposal.Root() if err != nil { - return errors.Wrap(err, "block root") + return errors.Wrap(err, "proposal root") } if existingRoot != providedRoot { return errors.New("clashing blocks") } } else { - db.proDuties[int64(slot)] = &block.VersionedBeaconBlock + db.proDuties[int64(slot)] = &proposal.VersionedProposal } return nil @@ -497,7 +496,7 @@ func (db *MemDB) storeBlindedBeaconBlockUnsafe(unsignedData core.UnsignedData) e return err } - block, ok := cloned.(core.VersionedBlindedBeaconBlock) + block, ok := cloned.(core.VersionedBlindedProposal) if !ok { return errors.New("invalid unsigned blinded block") } @@ -522,7 +521,7 @@ func (db *MemDB) storeBlindedBeaconBlockUnsafe(unsignedData core.UnsignedData) e return errors.New("clashing blinded blocks") } } else { - db.builderProDuties[int64(slot)] = &block.VersionedBlindedBeaconBlock + db.builderProDuties[int64(slot)] = &block.VersionedBlindedProposal } return nil @@ -699,7 +698,7 @@ type attQuery struct { // proQuery is a waiting proQuery with a response channel. type proQuery struct { Key int64 - Response chan<- *eth2spec.VersionedBeaconBlock + Response chan<- *eth2api.VersionedProposal Cancel <-chan struct{} } @@ -713,7 +712,7 @@ type aggQuery struct { // builderProQuery is a waiting builderProQuery with a response channel. type builderProQuery struct { Key int64 - Response chan<- *eth2api.VersionedBlindedBeaconBlock + Response chan<- *eth2api.VersionedBlindedProposal Cancel <-chan struct{} } diff --git a/core/dutydb/memory_internal_test.go b/core/dutydb/memory_internal_test.go index 0a364535a..401216d0d 100644 --- a/core/dutydb/memory_internal_test.go +++ b/core/dutydb/memory_internal_test.go @@ -27,10 +27,10 @@ func TestCancelledQueries(t *testing.T) { _, err = db.AwaitAggAttestation(ctx, slot, eth2p0.Root{}) require.ErrorContains(t, err, "shutdown") - _, err = db.AwaitBeaconBlock(ctx, slot) + _, err = db.AwaitProposal(ctx, slot) require.ErrorContains(t, err, "shutdown") - _, err = db.AwaitBlindedBeaconBlock(ctx, slot) + _, err = db.AwaitBlindedProposal(ctx, slot) require.ErrorContains(t, err, "shutdown") _, err = db.AwaitSyncContribution(ctx, slot, 0, eth2p0.Root{}) diff --git a/core/dutydb/memory_test.go b/core/dutydb/memory_test.go index 5c0ea18c7..8ce6c22bb 100644 --- a/core/dutydb/memory_test.go +++ b/core/dutydb/memory_test.go @@ -24,7 +24,7 @@ func TestShutdown(t *testing.T) { errChan := make(chan error, 1) go func() { - _, err := db.AwaitBeaconBlock(context.Background(), 999) + _, err := db.AwaitProposal(context.Background(), 999) errChan <- err }() @@ -133,33 +133,33 @@ func TestMemDBProposer(t *testing.T) { slots := [queries]int64{123, 456, 789} type response struct { - block *eth2spec.VersionedBeaconBlock + block *eth2api.VersionedProposal } var awaitResponse [queries]chan response for i := 0; i < queries; i++ { awaitResponse[i] = make(chan response) go func(slot int) { - block, err := db.AwaitBeaconBlock(ctx, slots[slot]) + block, err := db.AwaitProposal(ctx, slots[slot]) require.NoError(t, err) awaitResponse[slot] <- response{block: block} }(i) } - blocks := make([]*eth2spec.VersionedBeaconBlock, queries) + proposals := make([]*eth2api.VersionedProposal, queries) pubkeysByIdx := make(map[eth2p0.ValidatorIndex]core.PubKey) for i := 0; i < queries; i++ { - blocks[i] = ð2spec.VersionedBeaconBlock{ - Version: eth2spec.DataVersionPhase0, - Phase0: testutil.RandomPhase0BeaconBlock(), + proposals[i] = ð2api.VersionedProposal{ + Version: eth2spec.DataVersionBellatrix, + Bellatrix: testutil.RandomBellatrixBeaconBlock(), } - blocks[i].Phase0.Slot = eth2p0.Slot(slots[i]) - blocks[i].Phase0.ProposerIndex = eth2p0.ValidatorIndex(i) + proposals[i].Bellatrix.Slot = eth2p0.Slot(slots[i]) + proposals[i].Bellatrix.ProposerIndex = eth2p0.ValidatorIndex(i) pubkeysByIdx[eth2p0.ValidatorIndex(i)] = testutil.RandomCorePubKey(t) } // Store the Blocks for i := 0; i < queries; i++ { - unsigned, err := core.NewVersionedBeaconBlock(blocks[i]) + unsigned, err := core.NewVersionedProposal(proposals[i]) require.NoError(t, err) duty := core.Duty{Slot: slots[i], Type: core.DutyProposer} @@ -172,7 +172,7 @@ func TestMemDBProposer(t *testing.T) { // Get and assert the proQuery responses for i := 0; i < queries; i++ { actualData := <-awaitResponse[i] - require.Equal(t, blocks[i], actualData.block) + require.Equal(t, proposals[i], actualData.block) } } @@ -301,23 +301,23 @@ func TestMemDBClashingBlocks(t *testing.T) { db := dutydb.NewMemDB(new(testDeadliner)) const slot = 123 - block1 := ð2spec.VersionedBeaconBlock{ - Version: eth2spec.DataVersionPhase0, - Phase0: testutil.RandomPhase0BeaconBlock(), + block1 := ð2api.VersionedProposal{ + Version: eth2spec.DataVersionBellatrix, + Bellatrix: testutil.RandomBellatrixBeaconBlock(), } - block1.Phase0.Slot = eth2p0.Slot(slot) - block2 := ð2spec.VersionedBeaconBlock{ - Version: eth2spec.DataVersionPhase0, - Phase0: testutil.RandomPhase0BeaconBlock(), + block1.Bellatrix.Slot = eth2p0.Slot(slot) + block2 := ð2api.VersionedProposal{ + Version: eth2spec.DataVersionBellatrix, + Bellatrix: testutil.RandomBellatrixBeaconBlock(), } - block2.Phase0.Slot = eth2p0.Slot(slot) + block2.Bellatrix.Slot = eth2p0.Slot(slot) pubkey := testutil.RandomCorePubKey(t) // Encode the Blocks - unsigned1, err := core.NewVersionedBeaconBlock(block1) + unsigned1, err := core.NewVersionedProposal(block1) require.NoError(t, err) - unsigned2, err := core.NewVersionedBeaconBlock(block2) + unsigned2, err := core.NewVersionedProposal(block2) require.NoError(t, err) // Store the Blocks @@ -339,15 +339,15 @@ func TestMemDBClashProposer(t *testing.T) { const slot = 123 - block := ð2spec.VersionedBeaconBlock{ - Version: eth2spec.DataVersionPhase0, - Phase0: testutil.RandomPhase0BeaconBlock(), + block := ð2api.VersionedProposal{ + Version: eth2spec.DataVersionBellatrix, + Bellatrix: testutil.RandomBellatrixBeaconBlock(), } - block.Phase0.Slot = eth2p0.Slot(slot) + block.Bellatrix.Slot = eth2p0.Slot(slot) pubkey := testutil.RandomCorePubKey(t) // Encode the block - unsigned, err := core.NewVersionedBeaconBlock(block) + unsigned, err := core.NewVersionedProposal(block) require.NoError(t, err) // Store the Blocks @@ -364,8 +364,8 @@ func TestMemDBClashProposer(t *testing.T) { require.NoError(t, err) // Store a different block for the same slot - block.Phase0.ProposerIndex++ - unsignedB, err := core.NewVersionedBeaconBlock(block) + block.Bellatrix.ProposerIndex++ + unsignedB, err := core.NewVersionedProposal(block) require.NoError(t, err) err = db.Store(ctx, duty, core.UnsignedDataSet{ pubkey: unsignedB, @@ -381,22 +381,22 @@ func TestMemDBBuilderProposer(t *testing.T) { slots := [queries]int64{123, 456, 789} type response struct { - block *eth2api.VersionedBlindedBeaconBlock + block *eth2api.VersionedBlindedProposal } var awaitResponse [queries]chan response for i := 0; i < queries; i++ { awaitResponse[i] = make(chan response) go func(slot int) { - block, err := db.AwaitBlindedBeaconBlock(ctx, slots[slot]) + block, err := db.AwaitBlindedProposal(ctx, slots[slot]) require.NoError(t, err) awaitResponse[slot] <- response{block: block} }(i) } - blocks := make([]*eth2api.VersionedBlindedBeaconBlock, queries) + blocks := make([]*eth2api.VersionedBlindedProposal, queries) pubkeysByIdx := make(map[eth2p0.ValidatorIndex]core.PubKey) for i := 0; i < queries; i++ { - blocks[i] = ð2api.VersionedBlindedBeaconBlock{ + blocks[i] = ð2api.VersionedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: testutil.RandomBellatrixBlindedBeaconBlock(), } @@ -407,7 +407,7 @@ func TestMemDBBuilderProposer(t *testing.T) { // Store the Blocks for i := 0; i < queries; i++ { - unsigned, err := core.NewVersionedBlindedBeaconBlock(blocks[i]) + unsigned, err := core.NewVersionedBlindedProposal(blocks[i]) require.NoError(t, err) duty := core.Duty{Slot: slots[i], Type: core.DutyBuilderProposer} @@ -429,12 +429,12 @@ func TestMemDBClashingBlindedBlocks(t *testing.T) { db := dutydb.NewMemDB(new(testDeadliner)) const slot = 123 - block1 := ð2api.VersionedBlindedBeaconBlock{ + block1 := ð2api.VersionedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: testutil.RandomBellatrixBlindedBeaconBlock(), } block1.Bellatrix.Slot = eth2p0.Slot(slot) - block2 := ð2api.VersionedBlindedBeaconBlock{ + block2 := ð2api.VersionedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: testutil.RandomBellatrixBlindedBeaconBlock(), } @@ -442,10 +442,10 @@ func TestMemDBClashingBlindedBlocks(t *testing.T) { pubkey := testutil.RandomCorePubKey(t) // Encode the Blocks - unsigned1, err := core.NewVersionedBlindedBeaconBlock(block1) + unsigned1, err := core.NewVersionedBlindedProposal(block1) require.NoError(t, err) - unsigned2, err := core.NewVersionedBlindedBeaconBlock(block2) + unsigned2, err := core.NewVersionedBlindedProposal(block2) require.NoError(t, err) // Store the Blocks @@ -467,7 +467,7 @@ func TestMemDBClashBuilderProposer(t *testing.T) { const slot = 123 - block := ð2api.VersionedBlindedBeaconBlock{ + block := ð2api.VersionedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: testutil.RandomBellatrixBlindedBeaconBlock(), } @@ -475,7 +475,7 @@ func TestMemDBClashBuilderProposer(t *testing.T) { pubkey := testutil.RandomCorePubKey(t) // Encode the block - unsigned, err := core.NewVersionedBlindedBeaconBlock(block) + unsigned, err := core.NewVersionedBlindedProposal(block) require.NoError(t, err) // Store the Blocks @@ -493,7 +493,7 @@ func TestMemDBClashBuilderProposer(t *testing.T) { // Store a different block for the same slot block.Bellatrix.ProposerIndex++ - unsignedB, err := core.NewVersionedBlindedBeaconBlock(block) + unsignedB, err := core.NewVersionedBlindedProposal(block) require.NoError(t, err) err = db.Store(ctx, duty, core.UnsignedDataSet{ pubkey: unsignedB, @@ -523,9 +523,11 @@ func TestDutyExpiry(t *testing.T) { // Expire attestation deadliner.expire() + versionedProposal := core.VersionedProposal{VersionedProposal: *testutil.RandomVersionedProposal()} + // Store another duty which deletes expired duties err = db.Store(ctx, core.NewProposerDuty(slot+1), core.UnsignedDataSet{ - testutil.RandomCorePubKey(t): testutil.RandomBellatrixCoreVersionedBeaconBlock(), + testutil.RandomCorePubKey(t): versionedProposal, }) require.NoError(t, err) diff --git a/core/eth2signeddata.go b/core/eth2signeddata.go index 3535c7820..e1f216b52 100644 --- a/core/eth2signeddata.go +++ b/core/eth2signeddata.go @@ -5,6 +5,7 @@ package core import ( "context" + eth2spec "github.com/attestantio/go-eth2-client/spec" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/obolnetwork/charon/app/errors" @@ -16,10 +17,10 @@ import ( ) var ( - _ Eth2SignedData = VersionedSignedBeaconBlock{} + _ Eth2SignedData = VersionedSignedProposal{} _ Eth2SignedData = Attestation{} _ Eth2SignedData = SignedVoluntaryExit{} - _ Eth2SignedData = VersionedSignedBlindedBeaconBlock{} + _ Eth2SignedData = VersionedSignedBlindedProposal{} _ Eth2SignedData = VersionedSignedValidatorRegistration{} _ Eth2SignedData = SignedRandao{} _ Eth2SignedData = BeaconCommitteeSelection{} @@ -60,14 +61,33 @@ func VerifyEth2SignedData(ctx context.Context, eth2Cl eth2wrap.Client, data Eth2 return nil } -// Implement Eth2SignedData for VersionedSignedBeaconBlock. +// Implement Eth2SignedData for VersionedSignedProposal. + +func (p VersionedSignedProposal) DomainNames() []signing.DomainName { + switch p.Version { + case eth2spec.DataVersionPhase0: + return []signing.DomainName{signing.DomainBeaconProposer} + case eth2spec.DataVersionAltair: + return []signing.DomainName{signing.DomainBeaconProposer} + case eth2spec.DataVersionBellatrix: + return []signing.DomainName{signing.DomainBeaconProposer} + case eth2spec.DataVersionCapella: + return []signing.DomainName{signing.DomainBeaconProposer} + case eth2spec.DataVersionDeneb: + var domains []signing.DomainName + domains = append(domains, signing.DomainBeaconProposer) // Deneb beacon block + for range p.Deneb.SignedBlobSidecars { + domains = append(domains, signing.DomainBlobSidecar) // Deneb blob sidecar + } -func (VersionedSignedBeaconBlock) DomainNames() []signing.DomainName { - return []signing.DomainName{signing.DomainBeaconProposer} + return domains + default: + return []signing.DomainName{signing.DomainBeaconProposer} + } } -func (b VersionedSignedBeaconBlock) Epoch(ctx context.Context, eth2Cl eth2wrap.Client) (eth2p0.Epoch, error) { - slot, err := b.VersionedSignedBeaconBlock.Slot() +func (p VersionedSignedProposal) Epoch(ctx context.Context, eth2Cl eth2wrap.Client) (eth2p0.Epoch, error) { + slot, err := p.Slot() if err != nil { return 0, err } @@ -75,14 +95,29 @@ func (b VersionedSignedBeaconBlock) Epoch(ctx context.Context, eth2Cl eth2wrap.C return eth2util.EpochFromSlot(ctx, eth2Cl, slot) } -// Implement Eth2SignedData for VersionedSignedBlindedBeaconBlock. +// Implement Eth2SignedData for VersionedSignedBlindedProposal. -func (VersionedSignedBlindedBeaconBlock) DomainNames() []signing.DomainName { - return []signing.DomainName{signing.DomainBeaconProposer} +func (p VersionedSignedBlindedProposal) DomainNames() []signing.DomainName { + switch p.Version { + case eth2spec.DataVersionBellatrix: + return []signing.DomainName{signing.DomainBeaconProposer} + case eth2spec.DataVersionCapella: + return []signing.DomainName{signing.DomainBeaconProposer} + case eth2spec.DataVersionDeneb: + var domains []signing.DomainName + domains = append(domains, signing.DomainBeaconProposer) // Deneb beacon block + for range p.Deneb.SignedBlindedBlobSidecars { + domains = append(domains, signing.DomainBlobSidecar) // Deneb blob sidecar + } + + return domains + default: + return []signing.DomainName{signing.DomainBeaconProposer} + } } -func (b VersionedSignedBlindedBeaconBlock) Epoch(ctx context.Context, eth2Cl eth2wrap.Client) (eth2p0.Epoch, error) { - slot, err := b.VersionedSignedBlindedBeaconBlock.Slot() +func (p VersionedSignedBlindedProposal) Epoch(ctx context.Context, eth2Cl eth2wrap.Client) (eth2p0.Epoch, error) { + slot, err := p.VersionedSignedBlindedProposal.Slot() if err != nil { return 0, err } diff --git a/core/eth2signeddata_test.go b/core/eth2signeddata_test.go index 86d5ea442..05dc83d3d 100644 --- a/core/eth2signeddata_test.go +++ b/core/eth2signeddata_test.go @@ -28,15 +28,15 @@ func TestVerifyEth2SignedData(t *testing.T) { }, { name: "verify beacon block", - data: testutil.RandomBellatrixCoreVersionedSignedBeaconBlock(), + data: testutil.RandomBellatrixCoreVersionedSignedProposal(), }, { name: "verify blinded beacon block bellatrix", - data: testutil.RandomBellatrixVersionedSignedBlindedBeaconBlock(), + data: testutil.RandomBellatrixVersionedSignedBlindedProposal(), }, { name: "verify blinded beacon block capella", - data: testutil.RandomCapellaVersionedSignedBlindedBeaconBlock(), + data: testutil.RandomCapellaVersionedSignedBlindedProposal(), }, { name: "verify randao", diff --git a/core/fetcher/fetcher.go b/core/fetcher/fetcher.go index 9501f4213..7c1fe264c 100644 --- a/core/fetcher/fetcher.go +++ b/core/fetcher/fetcher.go @@ -128,10 +128,17 @@ func (f *Fetcher) fetchAttesterData(ctx context.Context, slot int64, defSet core eth2AttData, ok := dataByCommIdx[commIdx] if !ok { var err error - eth2AttData, err = f.eth2Cl.AttestationData(ctx, eth2p0.Slot(uint64(slot)), commIdx) + opts := ð2api.AttestationDataOpts{ + Slot: eth2p0.Slot(uint64(slot)), + CommitteeIndex: commIdx, + } + eth2Resp, err := f.eth2Cl.AttestationData(ctx, opts) if err != nil { return nil, err - } else if eth2AttData == nil { + } + + eth2AttData = eth2Resp.Data + if eth2AttData == nil { return nil, errors.New("attestation data cannot be nil") } @@ -201,10 +208,17 @@ func (f *Fetcher) fetchAggregatorData(ctx context.Context, slot int64, defSet co } // Query BN for aggregate attestation. - aggAtt, err = f.eth2Cl.AggregateAttestation(ctx, eth2p0.Slot(slot), dataRoot) + opts := ð2api.AggregateAttestationOpts{ + Slot: eth2p0.Slot(slot), + AttestationDataRoot: dataRoot, + } + eth2Resp, err := f.eth2Cl.AggregateAttestation(ctx, opts) if err != nil { return core.UnsignedDataSet{}, err - } else if aggAtt == nil { + } + + aggAtt = eth2Resp.Data + if aggAtt == nil { // Some beacon nodes return nil if the root is not found, return retryable error. // This could happen if the beacon node didn't subscribe to the correct subnet. return core.UnsignedDataSet{}, errors.New("aggregate attestation not found by root (retryable)", z.Hex("root", dataRoot[:])) @@ -236,20 +250,27 @@ func (f *Fetcher) fetchProposerData(ctx context.Context, slot int64, defSet core var graffiti [32]byte commitSHA, _ := version.GitCommit() copy(graffiti[:], fmt.Sprintf("charon/%v-%s", version.Version, commitSHA)) - block, err := f.eth2Cl.BeaconBlockProposal(ctx, eth2p0.Slot(uint64(slot)), randao, graffiti[:]) + + opts := ð2api.ProposalOpts{ + Slot: eth2p0.Slot(uint64(slot)), + RandaoReveal: randao, + Graffiti: graffiti, + } + eth2Resp, err := f.eth2Cl.Proposal(ctx, opts) if err != nil { return nil, err } + proposal := eth2Resp.Data - // Ensure fee recipient is correctly populated in block. - verifyFeeRecipient(ctx, block, f.feeRecipientFunc(pubkey)) + // Ensure fee recipient is correctly populated in proposal. + verifyFeeRecipient(ctx, proposal, f.feeRecipientFunc(pubkey)) - coreBlock, err := core.NewVersionedBeaconBlock(block) + coreProposal, err := core.NewVersionedProposal(proposal) if err != nil { - return nil, errors.Wrap(err, "new block") + return nil, errors.Wrap(err, "new proposal") } - resp[pubkey] = coreBlock + resp[pubkey] = coreProposal } return resp, nil @@ -274,19 +295,26 @@ func (f *Fetcher) fetchBuilderProposerData(ctx context.Context, slot int64, defS var graffiti [32]byte commitSHA, _ := version.GitCommit() copy(graffiti[:], fmt.Sprintf("charon/%v-%s", version.Version, commitSHA)) - block, err := f.eth2Cl.BlindedBeaconBlockProposal(ctx, eth2p0.Slot(uint64(slot)), randao, graffiti[:]) + + opts := ð2api.BlindedProposalOpts{ + Slot: eth2p0.Slot(uint64(slot)), + RandaoReveal: randao, + Graffiti: graffiti, + } + eth2Resp, err := f.eth2Cl.BlindedProposal(ctx, opts) if err != nil { return nil, err } + blindedProposal := eth2Resp.Data - verifyFeeRecipientBlindedBlock(ctx, block, f.feeRecipientFunc(pubkey)) + verifyFeeRecipientBlinded(ctx, blindedProposal, f.feeRecipientFunc(pubkey)) - coreBlock, err := core.NewVersionedBlindedBeaconBlock(block) + coreProposal, err := core.NewVersionedBlindedProposal(blindedProposal) if err != nil { return nil, errors.Wrap(err, "new block") } - resp[pubkey] = coreBlock + resp[pubkey] = coreProposal } return resp, nil @@ -332,10 +360,18 @@ func (f *Fetcher) fetchContributionData(ctx context.Context, slot int64, defSet blockRoot := msg.BeaconBlockRoot // Query BN for sync committee contribution. - contribution, err := f.eth2Cl.SyncCommitteeContribution(ctx, eth2p0.Slot(slot), subcommIdx, blockRoot) + opts := ð2api.SyncCommitteeContributionOpts{ + Slot: eth2p0.Slot(slot), + SubcommitteeIndex: subcommIdx, + BeaconBlockRoot: blockRoot, + } + eth2Resp, err := f.eth2Cl.SyncCommitteeContribution(ctx, opts) if err != nil { return core.UnsignedDataSet{}, err - } else if contribution == nil { + } + + contribution := eth2Resp.Data + if contribution == nil { // Some beacon nodes return nil if the beacon block root is not found for the subcommittee, return retryable error. // This could happen if the beacon node didn't subscribe to the correct subnet. return core.UnsignedDataSet{}, errors.New("sync committee contribution not found by root (retryable)", z.U64("subcommidx", subcommIdx), z.Hex("root", blockRoot[:])) @@ -351,41 +387,41 @@ func (f *Fetcher) fetchContributionData(ctx context.Context, slot int64, defSet } // verifyFeeRecipient logs a warning when fee recipient is not correctly populated in the block. -func verifyFeeRecipient(ctx context.Context, block *eth2spec.VersionedBeaconBlock, feeRecipientAddress string) { +func verifyFeeRecipient(ctx context.Context, proposal *eth2api.VersionedProposal, feeRecipientAddress string) { // Note that fee-recipient is not available in forks earlier than bellatrix. var actualAddr string - switch block.Version { + switch proposal.Version { case eth2spec.DataVersionBellatrix: - actualAddr = fmt.Sprintf("%#x", block.Bellatrix.Body.ExecutionPayload.FeeRecipient) + actualAddr = fmt.Sprintf("%#x", proposal.Bellatrix.Body.ExecutionPayload.FeeRecipient) case eth2spec.DataVersionCapella: - actualAddr = fmt.Sprintf("%#x", block.Capella.Body.ExecutionPayload.FeeRecipient) + actualAddr = fmt.Sprintf("%#x", proposal.Capella.Body.ExecutionPayload.FeeRecipient) default: return } if actualAddr != "" && !strings.EqualFold(actualAddr, feeRecipientAddress) { - log.Warn(ctx, "Proposing block with unexpected fee recipient address", nil, + log.Warn(ctx, "Proposal with unexpected fee recipient address", nil, z.Str("expected", feeRecipientAddress), z.Str("actual", actualAddr)) } } -// verifyFeeRecipientBlindedBlock logs a warning when fee recipient is not correctly populated in the provided blinded beacon block. -func verifyFeeRecipientBlindedBlock(ctx context.Context, block *eth2api.VersionedBlindedBeaconBlock, feeRecipientAddress string) { +// verifyFeeRecipientBlinded logs a warning when fee recipient is not correctly populated in the provided blinded beacon block. +func verifyFeeRecipientBlinded(ctx context.Context, proposal *eth2api.VersionedBlindedProposal, feeRecipientAddress string) { // Note that fee-recipient is not available in forks earlier than bellatrix. var actualAddr string - switch block.Version { + switch proposal.Version { case eth2spec.DataVersionBellatrix: - actualAddr = fmt.Sprintf("%#x", block.Bellatrix.Body.ExecutionPayloadHeader.FeeRecipient) + actualAddr = fmt.Sprintf("%#x", proposal.Bellatrix.Body.ExecutionPayloadHeader.FeeRecipient) case eth2spec.DataVersionCapella: - actualAddr = fmt.Sprintf("%#x", block.Capella.Body.ExecutionPayloadHeader.FeeRecipient) + actualAddr = fmt.Sprintf("%#x", proposal.Capella.Body.ExecutionPayloadHeader.FeeRecipient) default: return } if actualAddr != "" && !strings.EqualFold(actualAddr, feeRecipientAddress) { - log.Warn(ctx, "Proposing block with unexpected fee recipient address", nil, + log.Warn(ctx, "Proposal with unexpected fee recipient address", nil, z.Str("expected", feeRecipientAddress), z.Str("actual", actualAddr)) } } diff --git a/core/fetcher/fetcher_test.go b/core/fetcher/fetcher_test.go index 7111143f8..4a07edffc 100644 --- a/core/fetcher/fetcher_test.go +++ b/core/fetcher/fetcher_test.go @@ -289,14 +289,14 @@ func TestFetchBlocks(t *testing.T) { require.Equal(t, duty, resDuty) require.Len(t, resDataSet, 2) - dutyDataA := resDataSet[pubkeysByIdx[vIdxA]].(core.VersionedBeaconBlock) + dutyDataA := resDataSet[pubkeysByIdx[vIdxA]].(core.VersionedProposal) slotA, err := dutyDataA.Slot() require.NoError(t, err) require.EqualValues(t, slot, slotA) require.Equal(t, feeRecipientAddr, fmt.Sprintf("%#x", dutyDataA.Capella.Body.ExecutionPayload.FeeRecipient)) assertRandao(t, randaoByPubKey[pubkeysByIdx[vIdxA]].Signatures()[0].ToETH2(), dutyDataA) - dutyDataB := resDataSet[pubkeysByIdx[vIdxB]].(core.VersionedBeaconBlock) + dutyDataB := resDataSet[pubkeysByIdx[vIdxB]].(core.VersionedProposal) slotB, err := dutyDataB.Slot() require.NoError(t, err) require.EqualValues(t, slot, slotB) @@ -325,14 +325,14 @@ func TestFetchBlocks(t *testing.T) { require.Equal(t, duty, resDuty) require.Len(t, resDataSet, 2) - dutyDataA := resDataSet[pubkeysByIdx[vIdxA]].(core.VersionedBlindedBeaconBlock) + dutyDataA := resDataSet[pubkeysByIdx[vIdxA]].(core.VersionedBlindedProposal) slotA, err := dutyDataA.Slot() require.NoError(t, err) require.EqualValues(t, slot, slotA) require.Equal(t, feeRecipientAddr, fmt.Sprintf("%#x", dutyDataA.Capella.Body.ExecutionPayloadHeader.FeeRecipient)) assertRandaoBlindedBlock(t, randaoByPubKey[pubkeysByIdx[vIdxA]].Signatures()[0].ToETH2(), dutyDataA) - dutyDataB := resDataSet[pubkeysByIdx[vIdxB]].(core.VersionedBlindedBeaconBlock) + dutyDataB := resDataSet[pubkeysByIdx[vIdxB]].(core.VersionedBlindedProposal) slotB, err := dutyDataB.Slot() require.NoError(t, err) require.EqualValues(t, slot, slotB) @@ -554,7 +554,7 @@ func TestFetchSyncContribution(t *testing.T) { }) } -func assertRandao(t *testing.T, randao eth2p0.BLSSignature, block core.VersionedBeaconBlock) { +func assertRandao(t *testing.T, randao eth2p0.BLSSignature, block core.VersionedProposal) { t.Helper() switch block.Version { @@ -571,7 +571,7 @@ func assertRandao(t *testing.T, randao eth2p0.BLSSignature, block core.Versioned } } -func assertRandaoBlindedBlock(t *testing.T, randao eth2p0.BLSSignature, block core.VersionedBlindedBeaconBlock) { +func assertRandaoBlindedBlock(t *testing.T, randao eth2p0.BLSSignature, block core.VersionedBlindedProposal) { t.Helper() switch block.Version { diff --git a/core/interfaces.go b/core/interfaces.go index 4d32cac6c..23655233f 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -6,7 +6,6 @@ import ( "context" eth2api "github.com/attestantio/go-eth2-client/api" - eth2spec "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/altair" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" ) @@ -44,13 +43,13 @@ type DutyDB interface { // Store stores the unsigned duty data set. Store(context.Context, Duty, UnsignedDataSet) error - // AwaitBeaconBlock blocks and returns the proposed beacon block + // AwaitProposal blocks and returns the proposed beacon block // for the slot when available. - AwaitBeaconBlock(ctx context.Context, slot int64) (*eth2spec.VersionedBeaconBlock, error) + AwaitProposal(ctx context.Context, slot int64) (*eth2api.VersionedProposal, error) - // AwaitBlindedBeaconBlock blocks and returns the proposed blinded beacon block + // AwaitBlindedProposal blocks and returns the proposed blinded beacon block // for the slot when available. - AwaitBlindedBeaconBlock(ctx context.Context, slot int64) (*eth2api.VersionedBlindedBeaconBlock, error) + AwaitBlindedProposal(ctx context.Context, slot int64) (*eth2api.VersionedBlindedProposal, error) // AwaitAttestation blocks and returns the attestation data // for the slot and committee index when available. @@ -84,11 +83,11 @@ type Consensus interface { // ValidatorAPI provides a beacon node API to validator clients. It serves duty data from the DutyDB and stores partial signed data in the ParSigDB. type ValidatorAPI interface { - // RegisterAwaitBeaconBlock registers a function to query unsigned beacon block by slot. - RegisterAwaitBeaconBlock(func(ctx context.Context, slot int64) (*eth2spec.VersionedBeaconBlock, error)) + // RegisterAwaitProposal registers a function to query unsigned beacon block proposals by providing the slot. + RegisterAwaitProposal(func(ctx context.Context, slot int64) (*eth2api.VersionedProposal, error)) - // RegisterAwaitBlindedBeaconBlock registers a function to query unsigned blinded beacon block by slot. - RegisterAwaitBlindedBeaconBlock(func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedBeaconBlock, error)) + // RegisterAwaitBlindedProposal registers a function to query unsigned blinded beacon block proposals by providing the slot. + RegisterAwaitBlindedProposal(func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedProposal, error)) // RegisterAwaitAttestation registers a function to query attestation data. RegisterAwaitAttestation(func(ctx context.Context, slot, commIdx int64) (*eth2p0.AttestationData, error)) @@ -206,43 +205,43 @@ type Tracker interface { // wireFuncs defines the core workflow components as a list of input and output functions // instead as interfaces, since functions are easier to wrap than interfaces. type wireFuncs struct { - SchedulerSubscribeDuties func(func(context.Context, Duty, DutyDefinitionSet) error) - SchedulerSubscribeSlots func(func(context.Context, Slot) error) - SchedulerGetDutyDefinition func(context.Context, Duty) (DutyDefinitionSet, error) - FetcherFetch func(context.Context, Duty, DutyDefinitionSet) error - FetcherSubscribe func(func(context.Context, Duty, UnsignedDataSet) error) - FetcherRegisterAggSigDB func(func(context.Context, Duty, PubKey) (SignedData, error)) - FetcherRegisterAwaitAttData func(func(ctx context.Context, slot int64, commIdx int64) (*eth2p0.AttestationData, error)) - ConsensusParticipate func(context.Context, Duty) error - ConsensusPropose func(context.Context, Duty, UnsignedDataSet) error - ConsensusSubscribe func(func(context.Context, Duty, UnsignedDataSet) error) - DutyDBStore func(context.Context, Duty, UnsignedDataSet) error - DutyDBAwaitBeaconBlock func(ctx context.Context, slot int64) (*eth2spec.VersionedBeaconBlock, error) - DutyDBAwaitBlindedBeaconBlock func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedBeaconBlock, error) - DutyDBAwaitAttestation func(ctx context.Context, slot, commIdx int64) (*eth2p0.AttestationData, error) - DutyDBPubKeyByAttestation func(ctx context.Context, slot, commIdx, valCommIdx int64) (PubKey, error) - DutyDBAwaitAggAttestation func(ctx context.Context, slot int64, attestationRoot eth2p0.Root) (*eth2p0.Attestation, error) - DutyDBAwaitSyncContribution func(ctx context.Context, slot, subcommIdx int64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error) - VAPIRegisterAwaitAttestation func(func(ctx context.Context, slot, commIdx int64) (*eth2p0.AttestationData, error)) - VAPIRegisterAwaitSyncContribution func(func(ctx context.Context, slot, subcommIdx int64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error)) - VAPIRegisterAwaitBeaconBlock func(func(ctx context.Context, slot int64) (*eth2spec.VersionedBeaconBlock, error)) - VAPIRegisterAwaitBlindedBeaconBlock func(func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedBeaconBlock, error)) - VAPIRegisterGetDutyDefinition func(func(context.Context, Duty) (DutyDefinitionSet, error)) - VAPIRegisterPubKeyByAttestation func(func(ctx context.Context, slot, commIdx, valCommIdx int64) (PubKey, error)) - VAPIRegisterAwaitAggAttestation func(func(ctx context.Context, slot int64, attestationRoot eth2p0.Root) (*eth2p0.Attestation, error)) - VAPIRegisterAwaitAggSigDB func(func(context.Context, Duty, PubKey) (SignedData, error)) - VAPISubscribe func(func(context.Context, Duty, ParSignedDataSet) error) - ParSigDBStoreInternal func(context.Context, Duty, ParSignedDataSet) error - ParSigDBStoreExternal func(context.Context, Duty, ParSignedDataSet) error - ParSigDBSubscribeInternal func(func(context.Context, Duty, ParSignedDataSet) error) - ParSigDBSubscribeThreshold func(func(context.Context, Duty, map[PubKey][]ParSignedData) error) - ParSigExBroadcast func(context.Context, Duty, ParSignedDataSet) error - ParSigExSubscribe func(func(context.Context, Duty, ParSignedDataSet) error) - SigAggAggregate func(context.Context, Duty, map[PubKey][]ParSignedData) error - SigAggSubscribe func(func(context.Context, Duty, SignedDataSet) error) - AggSigDBStore func(context.Context, Duty, SignedDataSet) error - AggSigDBAwait func(context.Context, Duty, PubKey) (SignedData, error) - BroadcasterBroadcast func(context.Context, Duty, SignedDataSet) error + SchedulerSubscribeDuties func(func(context.Context, Duty, DutyDefinitionSet) error) + SchedulerSubscribeSlots func(func(context.Context, Slot) error) + SchedulerGetDutyDefinition func(context.Context, Duty) (DutyDefinitionSet, error) + FetcherFetch func(context.Context, Duty, DutyDefinitionSet) error + FetcherSubscribe func(func(context.Context, Duty, UnsignedDataSet) error) + FetcherRegisterAggSigDB func(func(context.Context, Duty, PubKey) (SignedData, error)) + FetcherRegisterAwaitAttData func(func(ctx context.Context, slot int64, commIdx int64) (*eth2p0.AttestationData, error)) + ConsensusParticipate func(context.Context, Duty) error + ConsensusPropose func(context.Context, Duty, UnsignedDataSet) error + ConsensusSubscribe func(func(context.Context, Duty, UnsignedDataSet) error) + DutyDBStore func(context.Context, Duty, UnsignedDataSet) error + DutyDBAwaitProposal func(ctx context.Context, slot int64) (*eth2api.VersionedProposal, error) + DutyDBAwaitBlindedProposal func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedProposal, error) + DutyDBAwaitAttestation func(ctx context.Context, slot, commIdx int64) (*eth2p0.AttestationData, error) + DutyDBPubKeyByAttestation func(ctx context.Context, slot, commIdx, valCommIdx int64) (PubKey, error) + DutyDBAwaitAggAttestation func(ctx context.Context, slot int64, attestationRoot eth2p0.Root) (*eth2p0.Attestation, error) + DutyDBAwaitSyncContribution func(ctx context.Context, slot, subcommIdx int64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error) + VAPIRegisterAwaitAttestation func(func(ctx context.Context, slot, commIdx int64) (*eth2p0.AttestationData, error)) + VAPIRegisterAwaitSyncContribution func(func(ctx context.Context, slot, subcommIdx int64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error)) + VAPIRegisterAwaitProposal func(func(ctx context.Context, slot int64) (*eth2api.VersionedProposal, error)) + VAPIRegisterAwaitBlindedProposal func(func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedProposal, error)) + VAPIRegisterGetDutyDefinition func(func(context.Context, Duty) (DutyDefinitionSet, error)) + VAPIRegisterPubKeyByAttestation func(func(ctx context.Context, slot, commIdx, valCommIdx int64) (PubKey, error)) + VAPIRegisterAwaitAggAttestation func(func(ctx context.Context, slot int64, attestationRoot eth2p0.Root) (*eth2p0.Attestation, error)) + VAPIRegisterAwaitAggSigDB func(func(context.Context, Duty, PubKey) (SignedData, error)) + VAPISubscribe func(func(context.Context, Duty, ParSignedDataSet) error) + ParSigDBStoreInternal func(context.Context, Duty, ParSignedDataSet) error + ParSigDBStoreExternal func(context.Context, Duty, ParSignedDataSet) error + ParSigDBSubscribeInternal func(func(context.Context, Duty, ParSignedDataSet) error) + ParSigDBSubscribeThreshold func(func(context.Context, Duty, map[PubKey][]ParSignedData) error) + ParSigExBroadcast func(context.Context, Duty, ParSignedDataSet) error + ParSigExSubscribe func(func(context.Context, Duty, ParSignedDataSet) error) + SigAggAggregate func(context.Context, Duty, map[PubKey][]ParSignedData) error + SigAggSubscribe func(func(context.Context, Duty, SignedDataSet) error) + AggSigDBStore func(context.Context, Duty, SignedDataSet) error + AggSigDBAwait func(context.Context, Duty, PubKey) (SignedData, error) + BroadcasterBroadcast func(context.Context, Duty, SignedDataSet) error } // WireOption defines a functional option to configure wiring. @@ -262,43 +261,43 @@ func Wire(sched Scheduler, opts ...WireOption, ) { w := wireFuncs{ - SchedulerSubscribeDuties: sched.SubscribeDuties, - SchedulerSubscribeSlots: sched.SubscribeSlots, - SchedulerGetDutyDefinition: sched.GetDutyDefinition, - FetcherFetch: fetch.Fetch, - FetcherSubscribe: fetch.Subscribe, - FetcherRegisterAggSigDB: fetch.RegisterAggSigDB, - FetcherRegisterAwaitAttData: fetch.RegisterAwaitAttData, - ConsensusParticipate: cons.Participate, - ConsensusPropose: cons.Propose, - ConsensusSubscribe: cons.Subscribe, - DutyDBStore: dutyDB.Store, - DutyDBAwaitAttestation: dutyDB.AwaitAttestation, - DutyDBAwaitBeaconBlock: dutyDB.AwaitBeaconBlock, - DutyDBAwaitBlindedBeaconBlock: dutyDB.AwaitBlindedBeaconBlock, - DutyDBPubKeyByAttestation: dutyDB.PubKeyByAttestation, - DutyDBAwaitAggAttestation: dutyDB.AwaitAggAttestation, - DutyDBAwaitSyncContribution: dutyDB.AwaitSyncContribution, - VAPIRegisterAwaitBeaconBlock: vapi.RegisterAwaitBeaconBlock, - VAPIRegisterAwaitBlindedBeaconBlock: vapi.RegisterAwaitBlindedBeaconBlock, - VAPIRegisterAwaitAttestation: vapi.RegisterAwaitAttestation, - VAPIRegisterAwaitSyncContribution: vapi.RegisterAwaitSyncContribution, - VAPIRegisterGetDutyDefinition: vapi.RegisterGetDutyDefinition, - VAPIRegisterPubKeyByAttestation: vapi.RegisterPubKeyByAttestation, - VAPIRegisterAwaitAggAttestation: vapi.RegisterAwaitAggAttestation, - VAPIRegisterAwaitAggSigDB: vapi.RegisterAwaitAggSigDB, - VAPISubscribe: vapi.Subscribe, - ParSigDBStoreInternal: parSigDB.StoreInternal, - ParSigDBStoreExternal: parSigDB.StoreExternal, - ParSigDBSubscribeInternal: parSigDB.SubscribeInternal, - ParSigDBSubscribeThreshold: parSigDB.SubscribeThreshold, - ParSigExBroadcast: parSigEx.Broadcast, - ParSigExSubscribe: parSigEx.Subscribe, - SigAggAggregate: sigAgg.Aggregate, - SigAggSubscribe: sigAgg.Subscribe, - AggSigDBStore: aggSigDB.Store, - AggSigDBAwait: aggSigDB.Await, - BroadcasterBroadcast: bcast.Broadcast, + SchedulerSubscribeDuties: sched.SubscribeDuties, + SchedulerSubscribeSlots: sched.SubscribeSlots, + SchedulerGetDutyDefinition: sched.GetDutyDefinition, + FetcherFetch: fetch.Fetch, + FetcherSubscribe: fetch.Subscribe, + FetcherRegisterAggSigDB: fetch.RegisterAggSigDB, + FetcherRegisterAwaitAttData: fetch.RegisterAwaitAttData, + ConsensusParticipate: cons.Participate, + ConsensusPropose: cons.Propose, + ConsensusSubscribe: cons.Subscribe, + DutyDBStore: dutyDB.Store, + DutyDBAwaitAttestation: dutyDB.AwaitAttestation, + DutyDBAwaitProposal: dutyDB.AwaitProposal, + DutyDBAwaitBlindedProposal: dutyDB.AwaitBlindedProposal, + DutyDBPubKeyByAttestation: dutyDB.PubKeyByAttestation, + DutyDBAwaitAggAttestation: dutyDB.AwaitAggAttestation, + DutyDBAwaitSyncContribution: dutyDB.AwaitSyncContribution, + VAPIRegisterAwaitProposal: vapi.RegisterAwaitProposal, + VAPIRegisterAwaitBlindedProposal: vapi.RegisterAwaitBlindedProposal, + VAPIRegisterAwaitAttestation: vapi.RegisterAwaitAttestation, + VAPIRegisterAwaitSyncContribution: vapi.RegisterAwaitSyncContribution, + VAPIRegisterGetDutyDefinition: vapi.RegisterGetDutyDefinition, + VAPIRegisterPubKeyByAttestation: vapi.RegisterPubKeyByAttestation, + VAPIRegisterAwaitAggAttestation: vapi.RegisterAwaitAggAttestation, + VAPIRegisterAwaitAggSigDB: vapi.RegisterAwaitAggSigDB, + VAPISubscribe: vapi.Subscribe, + ParSigDBStoreInternal: parSigDB.StoreInternal, + ParSigDBStoreExternal: parSigDB.StoreExternal, + ParSigDBSubscribeInternal: parSigDB.SubscribeInternal, + ParSigDBSubscribeThreshold: parSigDB.SubscribeThreshold, + ParSigExBroadcast: parSigEx.Broadcast, + ParSigExSubscribe: parSigEx.Subscribe, + SigAggAggregate: sigAgg.Aggregate, + SigAggSubscribe: sigAgg.Subscribe, + AggSigDBStore: aggSigDB.Store, + AggSigDBAwait: aggSigDB.Await, + BroadcasterBroadcast: bcast.Broadcast, } for _, opt := range opts { @@ -313,8 +312,8 @@ func Wire(sched Scheduler, w.FetcherRegisterAggSigDB(w.AggSigDBAwait) w.FetcherRegisterAwaitAttData(w.DutyDBAwaitAttestation) w.ConsensusSubscribe(w.DutyDBStore) - w.VAPIRegisterAwaitBeaconBlock(w.DutyDBAwaitBeaconBlock) - w.VAPIRegisterAwaitBlindedBeaconBlock(w.DutyDBAwaitBlindedBeaconBlock) + w.VAPIRegisterAwaitProposal(w.DutyDBAwaitProposal) + w.VAPIRegisterAwaitBlindedProposal(w.DutyDBAwaitBlindedProposal) w.VAPIRegisterAwaitAttestation(w.DutyDBAwaitAttestation) w.VAPIRegisterAwaitSyncContribution(w.DutyDBAwaitSyncContribution) w.VAPIRegisterGetDutyDefinition(w.SchedulerGetDutyDefinition) diff --git a/core/parsigex/parsigex_test.go b/core/parsigex/parsigex_test.go index 327bf7cc7..102d404c0 100644 --- a/core/parsigex/parsigex_test.go +++ b/core/parsigex/parsigex_test.go @@ -7,6 +7,8 @@ import ( "sync" "testing" + eth2api "github.com/attestantio/go-eth2-client/api" + eth2spec "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/altair" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/libp2p/go-libp2p/core/host" @@ -156,29 +158,29 @@ func TestParSigExVerifier(t *testing.T) { require.NoError(t, verifyFunc(ctx, core.NewAttesterDuty(slot), pubkey, data)) }) - t.Run("Verify block", func(t *testing.T) { - block := testutil.RandomCapellaVersionedSignedBeaconBlock() - block.Capella.Message.Slot = slot - sigRoot, err := block.Root() + t.Run("Verify proposal", func(t *testing.T) { + proposal := testutil.RandomVersionedSignedProposal() + proposal.Capella.Message.Slot = slot + sigRoot, err := versionedSignedProposalRoot(t, proposal) require.NoError(t, err) sigData, err := signing.GetDataRoot(ctx, bmock, signing.DomainBeaconProposer, epoch, sigRoot) require.NoError(t, err) - block.Capella.Signature = sign(sigData[:]) - data, err := core.NewPartialVersionedSignedBeaconBlock(block, shareIdx) + proposal.Capella.Signature = sign(sigData[:]) + data, err := core.NewPartialVersionedSignedProposal(proposal, shareIdx) require.NoError(t, err) require.NoError(t, verifyFunc(ctx, core.NewProposerDuty(slot), pubkey, data)) }) - t.Run("Verify blinded block", func(t *testing.T) { - blindedBlock := testutil.RandomCapellaVersionedSignedBlindedBeaconBlock() + t.Run("Verify blinded proposal", func(t *testing.T) { + blindedBlock := testutil.RandomCapellaVersionedSignedBlindedProposal() blindedBlock.Capella.Message.Slot = slot sigRoot, err := blindedBlock.Root() require.NoError(t, err) sigData, err := signing.GetDataRoot(ctx, bmock, signing.DomainBeaconProposer, epoch, sigRoot) require.NoError(t, err) blindedBlock.Capella.Signature = sign(sigData[:]) - data, err := core.NewPartialVersionedSignedBlindedBeaconBlock(&blindedBlock.VersionedSignedBlindedBeaconBlock, shareIdx) + data, err := core.NewPartialVersionedSignedBlindedProposal(&blindedBlock.VersionedSignedBlindedProposal, shareIdx) require.NoError(t, err) require.NoError(t, verifyFunc(ctx, core.NewBuilderProposerDuty(slot), pubkey, data)) @@ -312,3 +314,24 @@ func TestParSigExVerifier(t *testing.T) { require.NoError(t, verifyFunc(ctx, core.NewPrepareSyncContributionDuty(slot), pubkey, parSigData)) }) } + +func versionedSignedProposalRoot(t *testing.T, p *eth2api.VersionedSignedProposal) (eth2p0.Root, error) { + t.Helper() + + switch p.Version { + case eth2spec.DataVersionPhase0: + return p.Phase0.Message.HashTreeRoot() + case eth2spec.DataVersionAltair: + return p.Altair.Message.HashTreeRoot() + case eth2spec.DataVersionBellatrix: + return p.Bellatrix.Message.HashTreeRoot() + case eth2spec.DataVersionCapella: + return p.Capella.Message.HashTreeRoot() + case eth2spec.DataVersionDeneb: + return p.Deneb.SignedBlock.Message.HashTreeRoot() + default: + require.Equal(t, 0, 1) + } + + return eth2p0.Root{}, nil +} diff --git a/core/proto.go b/core/proto.go index 78fd32637..b2bed4d3a 100644 --- a/core/proto.go +++ b/core/proto.go @@ -62,15 +62,15 @@ func ParSignedDataFromProto(typ DutyType, data *pbv1.ParSignedData) (ParSignedDa } signedData = a case DutyProposer: - var b VersionedSignedBeaconBlock + var b VersionedSignedProposal if err := unmarshal(data.Data, &b); err != nil { - return ParSignedData{}, errors.Wrap(err, "unmarshal block") + return ParSignedData{}, errors.Wrap(err, "unmarshal proposal") } signedData = b case DutyBuilderProposer: - var b VersionedSignedBlindedBeaconBlock + var b VersionedSignedBlindedProposal if err := unmarshal(data.Data, &b); err != nil { - return ParSignedData{}, errors.Wrap(err, "unmarshal blinded block") + return ParSignedData{}, errors.Wrap(err, "unmarshal blinded proposal") } signedData = b case DutyBuilderRegistration: diff --git a/core/proto_test.go b/core/proto_test.go index d448ccb83..08bf57d4c 100644 --- a/core/proto_test.go +++ b/core/proto_test.go @@ -41,19 +41,19 @@ func TestParSignedDataSetProto(t *testing.T) { }, { Type: core.DutyProposer, - Data: testutil.RandomBellatrixCoreVersionedSignedBeaconBlock(), + Data: testutil.RandomBellatrixCoreVersionedSignedProposal(), }, { Type: core.DutyProposer, - Data: testutil.RandomCapellaCoreVersionedSignedBeaconBlock(), + Data: testutil.RandomCapellaCoreVersionedSignedProposal(), }, { Type: core.DutyBuilderProposer, - Data: testutil.RandomBellatrixVersionedSignedBlindedBeaconBlock(), + Data: testutil.RandomBellatrixVersionedSignedBlindedProposal(), }, { Type: core.DutyBuilderProposer, - Data: testutil.RandomCapellaVersionedSignedBlindedBeaconBlock(), + Data: testutil.RandomCapellaVersionedSignedBlindedProposal(), }, { Type: core.DutyBuilderRegistration, @@ -122,11 +122,11 @@ func TestUnsignedDataToProto(t *testing.T) { }, { Type: core.DutyProposer, - Data: testutil.RandomBellatrixCoreVersionedBeaconBlock(), + Data: testutil.RandomBellatrixCoreVersionedProposal(), }, { Type: core.DutyBuilderProposer, - Data: testutil.RandomBellatrixVersionedBlindedBeaconBlock(), + Data: testutil.RandomBellatrixVersionedBlindedProposal(), }, { Type: core.DutyAggregator, @@ -226,7 +226,7 @@ func randomSignedData(t *testing.T) map[core.DutyType]core.SignedData { core.DutyAttester: core.NewAttestation(testutil.RandomAttestation()), core.DutyExit: core.NewSignedVoluntaryExit(testutil.RandomExit()), core.DutyRandao: core.SignedRandao{SignedEpoch: eth2util.SignedEpoch{Epoch: testutil.RandomEpoch(), Signature: testutil.RandomEth2Signature()}}, - core.DutyProposer: testutil.RandomBellatrixCoreVersionedSignedBeaconBlock(), + core.DutyProposer: testutil.RandomBellatrixCoreVersionedSignedProposal(), core.DutyPrepareAggregator: testutil.RandomCoreBeaconCommitteeSelection(), core.DutyAggregator: core.NewSignedAggregateAndProof(testutil.RandomSignedAggregateAndProof()), core.DutyPrepareSyncContribution: core.NewSyncCommitteeSelection(testutil.RandomSyncCommitteeSelection()), diff --git a/core/scheduler/scheduler.go b/core/scheduler/scheduler.go index 4eceb1e86..581860422 100644 --- a/core/scheduler/scheduler.go +++ b/core/scheduler/scheduler.go @@ -10,6 +10,7 @@ import ( "testing" "time" + eth2api "github.com/attestantio/go-eth2-client/api" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/jonboulle/clockwork" "github.com/stretchr/testify/require" @@ -283,10 +284,15 @@ func (s *Scheduler) resolveDuties(ctx context.Context, slot core.Slot) error { // resolveAttDuties resolves attester duties for the given validators. func (s *Scheduler) resolveAttDuties(ctx context.Context, slot core.Slot, vals validators) error { - attDuties, err := s.eth2Cl.AttesterDuties(ctx, eth2p0.Epoch(slot.Epoch()), vals.Indexes()) + opts := ð2api.AttesterDutiesOpts{ + Epoch: eth2p0.Epoch(slot.Epoch()), + Indices: vals.Indexes(), + } + eth2Resp, err := s.eth2Cl.AttesterDuties(ctx, opts) if err != nil { return err } + attDuties := eth2Resp.Data // Check if any of the attester duties returned are nil. for _, duty := range attDuties { @@ -357,10 +363,15 @@ func (s *Scheduler) resolveAttDuties(ctx context.Context, slot core.Slot, vals v // resolveProposerDuties resolves proposer duties for the given validators. func (s *Scheduler) resolveProDuties(ctx context.Context, slot core.Slot, vals validators) error { - proDuties, err := s.eth2Cl.ProposerDuties(ctx, eth2p0.Epoch(slot.Epoch()), vals.Indexes()) + opts := ð2api.ProposerDutiesOpts{ + Epoch: eth2p0.Epoch(slot.Epoch()), + Indices: vals.Indexes(), + } + eth2Resp, err := s.eth2Cl.ProposerDuties(ctx, opts) if err != nil { return err } + proDuties := eth2Resp.Data // Check if any of the proposer duties returned are nil. for _, duty := range proDuties { @@ -410,10 +421,15 @@ func (s *Scheduler) resolveProDuties(ctx context.Context, slot core.Slot, vals v // resolveSyncCommDuties resolves sync committee duties for the validators in the given slot's epoch, caching the results. func (s *Scheduler) resolveSyncCommDuties(ctx context.Context, slot core.Slot, vals validators) error { - duties, err := s.eth2Cl.SyncCommitteeDuties(ctx, eth2p0.Epoch(slot.Epoch()), vals.Indexes()) + opts := ð2api.SyncCommitteeDutiesOpts{ + Epoch: eth2p0.Epoch(slot.Epoch()), + Indices: vals.Indexes(), + } + eth2Resp, err := s.eth2Cl.SyncCommitteeDuties(ctx, opts) if err != nil { return err } + duties := eth2Resp.Data // Check if any of the sync committee duties returned are nil. for _, duty := range duties { @@ -614,10 +630,15 @@ func resolveActiveValidators(ctx context.Context, eth2Cl eth2wrap.Client, e2pks = append(e2pks, e2pk) } - vals, err := eth2Cl.ValidatorsByPubKey(ctx, "head", e2pks) + opts := ð2api.ValidatorsOpts{ + State: "head", + PubKeys: e2pks, + } + eth2Resp, err := eth2Cl.Validators(ctx, opts) if err != nil { return nil, err } + vals := eth2Resp.Data var resp []validator for index, val := range vals { @@ -673,13 +694,14 @@ func waitChainStart(ctx context.Context, eth2Cl eth2wrap.Client, clock clockwork // waitBeaconSync blocks until the beacon node is synced. func waitBeaconSync(ctx context.Context, eth2Cl eth2wrap.Client, clock clockwork.Clock) { for ctx.Err() == nil { - state, err := eth2Cl.NodeSyncing(ctx) + eth2Resp, err := eth2Cl.NodeSyncing(ctx) if err != nil { log.Error(ctx, "Failure getting sync state", err) clock.Sleep(time.Second * 5) // TODO(corver): Improve backoff continue } + state := eth2Resp.Data if state.IsSyncing { log.Info(ctx, "Waiting for beacon node to sync", diff --git a/core/serialise_test.go b/core/serialise_test.go index 513157bb5..747def365 100644 --- a/core/serialise_test.go +++ b/core/serialise_test.go @@ -15,11 +15,11 @@ import ( ) var coreTypeFuncs = []func() any{ - func() any { return new(core.VersionedSignedBeaconBlock) }, + func() any { return new(core.VersionedSignedProposal) }, func() any { return new(core.Attestation) }, func() any { return new(core.Signature) }, func() any { return new(core.SignedVoluntaryExit) }, - func() any { return new(core.VersionedSignedBlindedBeaconBlock) }, + func() any { return new(core.VersionedSignedBlindedProposal) }, func() any { return new(core.SignedRandao) }, func() any { return new(core.BeaconCommitteeSelection) }, @@ -30,8 +30,8 @@ var coreTypeFuncs = []func() any{ func() any { return new(core.SyncCommitteeSelection) }, func() any { return new(core.AttestationData) }, func() any { return new(core.AggregatedAttestation) }, - func() any { return new(core.VersionedBeaconBlock) }, - func() any { return new(core.VersionedBlindedBeaconBlock) }, + func() any { return new(core.VersionedProposal) }, + func() any { return new(core.VersionedBlindedProposal) }, func() any { return new(core.SyncContribution) }, } diff --git a/core/sigagg/sigagg_test.go b/core/sigagg/sigagg_test.go index d77ed5f6e..2ea6b17a2 100644 --- a/core/sigagg/sigagg_test.go +++ b/core/sigagg/sigagg_test.go @@ -326,11 +326,11 @@ func TestSigAgg_DutyProposer(t *testing.T) { tests := []struct { name string - block *eth2spec.VersionedSignedBeaconBlock + block *eth2api.VersionedSignedProposal }{ { name: "phase0 block", - block: ð2spec.VersionedSignedBeaconBlock{ + block: ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionPhase0, Phase0: ð2p0.SignedBeaconBlock{ Message: testutil.RandomPhase0BeaconBlock(), @@ -340,7 +340,7 @@ func TestSigAgg_DutyProposer(t *testing.T) { }, { name: "altair block", - block: ð2spec.VersionedSignedBeaconBlock{ + block: ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionAltair, Altair: &altair.SignedBeaconBlock{ Message: testutil.RandomAltairBeaconBlock(), @@ -350,7 +350,7 @@ func TestSigAgg_DutyProposer(t *testing.T) { }, { name: "bellatrix block", - block: ð2spec.VersionedSignedBeaconBlock{ + block: ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: &bellatrix.SignedBeaconBlock{ Message: testutil.RandomBellatrixBeaconBlock(), @@ -360,7 +360,7 @@ func TestSigAgg_DutyProposer(t *testing.T) { }, { name: "capella block", - block: ð2spec.VersionedSignedBeaconBlock{ + block: ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionCapella, Capella: &capella.SignedBeaconBlock{ Message: testutil.RandomCapellaBeaconBlock(), @@ -372,7 +372,7 @@ func TestSigAgg_DutyProposer(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - block, err := core.NewVersionedSignedBeaconBlock(test.block) + block, err := core.NewVersionedSignedProposal(test.block) require.NoError(t, err) msgRoots, err := block.MessageRoots() @@ -515,11 +515,11 @@ func TestSigAgg_DutyBuilderProposer(t *testing.T) { tests := []struct { name string - block *eth2api.VersionedSignedBlindedBeaconBlock + block *eth2api.VersionedSignedBlindedProposal }{ { name: "bellatrix block", - block: ð2api.VersionedSignedBlindedBeaconBlock{ + block: ð2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: ð2bellatrix.SignedBlindedBeaconBlock{ Message: testutil.RandomBellatrixBlindedBeaconBlock(), @@ -529,7 +529,7 @@ func TestSigAgg_DutyBuilderProposer(t *testing.T) { }, { name: "capella block", - block: ð2api.VersionedSignedBlindedBeaconBlock{ + block: ð2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: ð2capella.SignedBlindedBeaconBlock{ Message: testutil.RandomCapellaBlindedBeaconBlock(), @@ -541,7 +541,7 @@ func TestSigAgg_DutyBuilderProposer(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - block, err := core.NewVersionedSignedBlindedBeaconBlock(test.block) + block, err := core.NewVersionedSignedBlindedProposal(test.block) require.NoError(t, err) msgRoots, err := block.MessageRoots() @@ -565,7 +565,7 @@ func TestSigAgg_DutyBuilderProposer(t *testing.T) { sig, err := tbls.Sign(secret, msg[:]) require.NoError(t, err) - block, err := core.NewVersionedSignedBlindedBeaconBlock(test.block) + block, err := core.NewVersionedSignedBlindedProposal(test.block) require.NoError(t, err) sigCore := tblsconv.SigToCore(sig) diff --git a/core/signeddata.go b/core/signeddata.go index 3bb8c7f2c..9f16e5ea7 100644 --- a/core/signeddata.go +++ b/core/signeddata.go @@ -15,7 +15,6 @@ import ( "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/bellatrix" "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/attestantio/go-eth2-client/spec/deneb" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" ssz "github.com/ferranbt/fastssz" @@ -28,11 +27,11 @@ import ( ) var ( - _ SignedData = VersionedSignedBeaconBlock{} + _ SignedData = VersionedSignedProposal{} _ SignedData = Attestation{} _ SignedData = Signature{} _ SignedData = SignedVoluntaryExit{} - _ SignedData = VersionedSignedBlindedBeaconBlock{} + _ SignedData = VersionedSignedBlindedProposal{} _ SignedData = VersionedSignedValidatorRegistration{} _ SignedData = SignedRandao{} _ SignedData = BeaconCommitteeSelection{} @@ -43,16 +42,16 @@ var ( _ SignedData = SyncCommitteeSelection{} // Some types support SSZ marshalling and unmarshalling. - _ ssz.Marshaler = VersionedSignedBeaconBlock{} + _ ssz.Marshaler = VersionedSignedProposal{} _ ssz.Marshaler = Attestation{} - _ ssz.Marshaler = VersionedSignedBlindedBeaconBlock{} + _ ssz.Marshaler = VersionedSignedBlindedProposal{} _ ssz.Marshaler = SignedAggregateAndProof{} _ ssz.Marshaler = SignedSyncMessage{} _ ssz.Marshaler = SyncContributionAndProof{} _ ssz.Marshaler = SignedSyncContributionAndProof{} - _ ssz.Unmarshaler = new(VersionedSignedBeaconBlock) + _ ssz.Unmarshaler = new(VersionedSignedProposal) _ ssz.Unmarshaler = new(Attestation) - _ ssz.Unmarshaler = new(VersionedSignedBlindedBeaconBlock) + _ ssz.Unmarshaler = new(VersionedSignedBlindedProposal) _ ssz.Unmarshaler = new(SignedAggregateAndProof) _ ssz.Unmarshaler = new(SignedSyncMessage) _ ssz.Unmarshaler = new(SyncContributionAndProof) @@ -158,39 +157,39 @@ func (s Signature) ToETH2() eth2p0.BLSSignature { return sig } -// NewVersionedSignedBeaconBlock validates and returns a new wrapped VersionedSignedBeaconBlock. -func NewVersionedSignedBeaconBlock(block *eth2spec.VersionedSignedBeaconBlock) (VersionedSignedBeaconBlock, error) { - switch block.Version { +// NewVersionedSignedProposal validates and returns a new VersionedSignedProposal. +func NewVersionedSignedProposal(proposal *eth2api.VersionedSignedProposal) (VersionedSignedProposal, error) { + switch proposal.Version { case eth2spec.DataVersionPhase0: - if block.Phase0 == nil { - return VersionedSignedBeaconBlock{}, errors.New("no phase0 block") + if proposal.Phase0 == nil { + return VersionedSignedProposal{}, errors.New("no phase0 proposal") } case eth2spec.DataVersionAltair: - if block.Altair == nil { - return VersionedSignedBeaconBlock{}, errors.New("no altair block") + if proposal.Altair == nil { + return VersionedSignedProposal{}, errors.New("no altair proposal") } case eth2spec.DataVersionBellatrix: - if block.Bellatrix == nil { - return VersionedSignedBeaconBlock{}, errors.New("no bellatrix block") + if proposal.Bellatrix == nil { + return VersionedSignedProposal{}, errors.New("no bellatrix proposal") } case eth2spec.DataVersionCapella: - if block.Capella == nil { - return VersionedSignedBeaconBlock{}, errors.New("no capella block") + if proposal.Capella == nil { + return VersionedSignedProposal{}, errors.New("no capella proposal") } case eth2spec.DataVersionDeneb: - if block.Deneb == nil { - return VersionedSignedBeaconBlock{}, errors.New("no deneb block") + if proposal.Deneb == nil { + return VersionedSignedProposal{}, errors.New("no deneb proposal") } default: - return VersionedSignedBeaconBlock{}, errors.New("unknown version") + return VersionedSignedProposal{}, errors.New("unknown version") } - return VersionedSignedBeaconBlock{VersionedSignedBeaconBlock: *block}, nil + return VersionedSignedProposal{VersionedSignedProposal: *proposal}, nil } -// NewPartialVersionedSignedBeaconBlock is a convenience function that returns a new partial signed block. -func NewPartialVersionedSignedBeaconBlock(block *eth2spec.VersionedSignedBeaconBlock, shareIdx int) (ParSignedData, error) { - wrap, err := NewVersionedSignedBeaconBlock(block) +// NewPartialVersionedSignedProposal validates and returns a new partial VersionedSignedProposal. +func NewPartialVersionedSignedProposal(proposal *eth2api.VersionedSignedProposal, shareIdx int) (ParSignedData, error) { + wrap, err := NewVersionedSignedProposal(proposal) if err != nil { return ParSignedData{}, err } @@ -201,148 +200,177 @@ func NewPartialVersionedSignedBeaconBlock(block *eth2spec.VersionedSignedBeaconB }, nil } -// VersionedSignedBeaconBlock is a signed versioned beacon block and implements SignedData. -type VersionedSignedBeaconBlock struct { - eth2spec.VersionedSignedBeaconBlock // Could subtype instead of embed, but aligning with Attestation that cannot subtype. +// VersionedSignedProposal is a signed versioned proposal and implements SignedData. +type VersionedSignedProposal struct { + eth2api.VersionedSignedProposal } -func (b VersionedSignedBeaconBlock) MessageRoots() ([][32]byte, error) { - switch b.Version { +func (p VersionedSignedProposal) Signatures() []Signature { + switch p.Version { // No block nil checks since `NewVersionedSignedBeaconBlock` assumed. case eth2spec.DataVersionPhase0: - root, err := b.Phase0.Message.HashTreeRoot() + return []Signature{SigFromETH2(p.Phase0.Signature)} + case eth2spec.DataVersionAltair: + return []Signature{SigFromETH2(p.Altair.Signature)} + case eth2spec.DataVersionBellatrix: + return []Signature{SigFromETH2(p.Bellatrix.Signature)} + case eth2spec.DataVersionCapella: + return []Signature{SigFromETH2(p.Capella.Signature)} + case eth2spec.DataVersionDeneb: + // Deneb's signatures consist of block sig and blob sidecar sigs. + var sigs []Signature + sigs = append(sigs, SigFromETH2(p.Deneb.SignedBlock.Signature)) + for _, blobSig := range p.Deneb.SignedBlobSidecars { + sigs = append(sigs, SigFromETH2(blobSig.Signature)) + } + + return sigs + default: + panic("unknown version") // Note this is avoided by using `NewVersionedSignedProposal`. + } +} + +func (p VersionedSignedProposal) SetSignatures(sigs []Signature) (SignedData, error) { + resp, err := p.clone() + if err != nil { + return nil, err + } + + if len(sigs) == 0 { + return nil, errors.Wrap(err, "zero signatures") + } + + switch resp.Version { + // No block nil checks since `NewVersionedSignedProposal` assumed. + case eth2spec.DataVersionPhase0: + resp.Phase0.Signature = sigs[0].ToETH2() + case eth2spec.DataVersionAltair: + resp.Altair.Signature = sigs[0].ToETH2() + case eth2spec.DataVersionBellatrix: + resp.Bellatrix.Signature = sigs[0].ToETH2() + case eth2spec.DataVersionCapella: + resp.Capella.Signature = sigs[0].ToETH2() + case eth2spec.DataVersionDeneb: + sigsRequired := 1 + len(resp.Deneb.SignedBlobSidecars) + if len(sigs) != sigsRequired { + return nil, errors.New("not enough signatures", z.Int("required", sigsRequired), z.Int("got", len(sigs))) + } + + // Set signature of beacon block + resp.Deneb.SignedBlock.Signature = sigs[0].ToETH2() + // Set signatures of each blob sidecar + for i := 1; i < len(sigs); i++ { + resp.Deneb.SignedBlobSidecars[i-1].Signature = sigs[i].ToETH2() + } + default: + return nil, errors.New("unknown type") + } + + return resp, nil +} + +func (p VersionedSignedProposal) MessageRoots() ([][32]byte, error) { + switch p.Version { + // No block nil checks since `NewVersionedSignedProposal` assumed. + case eth2spec.DataVersionPhase0: + root, err := p.Phase0.Message.HashTreeRoot() if err != nil { - return nil, errors.Wrap(err, "hash signed block message", z.Str("version", eth2spec.DataVersionPhase0.String())) + return nil, errors.Wrap(err, "hash phase0 block") } return [][32]byte{root}, nil case eth2spec.DataVersionAltair: - root, err := b.Altair.Message.HashTreeRoot() + root, err := p.Altair.Message.HashTreeRoot() if err != nil { - return nil, errors.Wrap(err, "hash signed block message", z.Str("version", eth2spec.DataVersionAltair.String())) + return nil, errors.Wrap(err, "hash altair block") } return [][32]byte{root}, nil case eth2spec.DataVersionBellatrix: - root, err := b.Bellatrix.Message.HashTreeRoot() + root, err := p.Bellatrix.Message.HashTreeRoot() if err != nil { - return nil, errors.Wrap(err, "hash signed block message", z.Str("version", eth2spec.DataVersionBellatrix.String())) + return nil, errors.Wrap(err, "hash bellatrix block") } return [][32]byte{root}, nil case eth2spec.DataVersionCapella: - root, err := b.Capella.Message.HashTreeRoot() + root, err := p.Capella.Message.HashTreeRoot() if err != nil { - return nil, errors.Wrap(err, "hash signed block message", z.Str("version", eth2spec.DataVersionCapella.String())) + return nil, errors.Wrap(err, "hash capella block") } return [][32]byte{root}, nil case eth2spec.DataVersionDeneb: - root, err := b.Deneb.Message.HashTreeRoot() + var roots [][32]byte + // Append root of deneb beacon block + root, err := p.Deneb.SignedBlock.Message.HashTreeRoot() if err != nil { - return nil, errors.Wrap(err, "hash signed block message", z.Str("version", eth2spec.DataVersionDeneb.String())) + return nil, errors.Wrap(err, "hash deneb block") + } + roots = append(roots, root) + + // Append roots of deneb blob sidecars + for _, blob := range p.Deneb.SignedBlobSidecars { + blobRoot, err := blob.Message.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "hash deneb blob sidecar") + } + roots = append(roots, blobRoot) } - return [][32]byte{root}, nil + return roots, nil default: - panic("unknown version") // Note this is avoided by using `NewVersionedSignedBeaconBlock`. + panic("unknown version") // Note this is avoided by using `NewVersionedSignedProposal`. } } -func (b VersionedSignedBeaconBlock) Clone() (SignedData, error) { - return b.clone() +func (p VersionedSignedProposal) Clone() (SignedData, error) { + return p.clone() } -// clone returns a copy of the VersionedSignedBeaconBlock. +// clone returns a copy of the VersionedSignedProposal. // It is similar to Clone that returns the SignedData interface. -func (b VersionedSignedBeaconBlock) clone() (VersionedSignedBeaconBlock, error) { - var resp VersionedSignedBeaconBlock - err := cloneJSONMarshaler(b, &resp) +func (p VersionedSignedProposal) clone() (VersionedSignedProposal, error) { + var resp VersionedSignedProposal + err := cloneJSONMarshaler(p, &resp) if err != nil { - return VersionedSignedBeaconBlock{}, errors.Wrap(err, "clone block") + return VersionedSignedProposal{}, errors.Wrap(err, "clone proposal") } return resp, nil } -func (b VersionedSignedBeaconBlock) Signatures() []Signature { - switch b.Version { - // No block nil checks since `NewVersionedSignedBeaconBlock` assumed. - case eth2spec.DataVersionPhase0: - return []Signature{SigFromETH2(b.Phase0.Signature)} - case eth2spec.DataVersionAltair: - return []Signature{SigFromETH2(b.Altair.Signature)} - case eth2spec.DataVersionBellatrix: - return []Signature{SigFromETH2(b.Bellatrix.Signature)} - case eth2spec.DataVersionCapella: - return []Signature{SigFromETH2(b.Capella.Signature)} - case eth2spec.DataVersionDeneb: - return []Signature{SigFromETH2(b.Deneb.Signature)} - default: - panic("unknown version") // Note this is avoided by using `NewVersionedSignedBeaconBlock`. - } -} - -func (b VersionedSignedBeaconBlock) SetSignatures(sigs []Signature) (SignedData, error) { - resp, err := b.clone() - if err != nil { - return nil, err - } - - if len(sigs) == 0 { - return nil, errors.Wrap(err, "zero signatures") - } - - switch resp.Version { - // No block nil checks since `NewVersionedSignedBeaconBlock` assumed. - case eth2spec.DataVersionPhase0: - resp.Phase0.Signature = sigs[0].ToETH2() - case eth2spec.DataVersionAltair: - resp.Altair.Signature = sigs[0].ToETH2() - case eth2spec.DataVersionBellatrix: - resp.Bellatrix.Signature = sigs[0].ToETH2() - case eth2spec.DataVersionCapella: - resp.Capella.Signature = sigs[0].ToETH2() - case eth2spec.DataVersionDeneb: - resp.Deneb.Signature = sigs[0].ToETH2() - default: - return nil, errors.New("unknown type") - } - - return resp, nil -} - -func (b VersionedSignedBeaconBlock) MarshalJSON() ([]byte, error) { +func (p VersionedSignedProposal) MarshalJSON() ([]byte, error) { var marshaller json.Marshaler - switch b.Version { - // No block nil checks since `NewVersionedSignedBeaconBlock` assumed. + switch p.Version { + // No proposal nil checks since `NewVersionedSignedProposal` assumed. case eth2spec.DataVersionPhase0: - marshaller = b.VersionedSignedBeaconBlock.Phase0 + marshaller = p.VersionedSignedProposal.Phase0 case eth2spec.DataVersionAltair: - marshaller = b.VersionedSignedBeaconBlock.Altair + marshaller = p.VersionedSignedProposal.Altair case eth2spec.DataVersionBellatrix: - marshaller = b.VersionedSignedBeaconBlock.Bellatrix + marshaller = p.VersionedSignedProposal.Bellatrix case eth2spec.DataVersionCapella: - marshaller = b.VersionedSignedBeaconBlock.Capella + marshaller = p.VersionedSignedProposal.Capella case eth2spec.DataVersionDeneb: - marshaller = b.VersionedSignedBeaconBlock.Deneb + marshaller = p.VersionedSignedProposal.Deneb default: return nil, errors.New("unknown version") } - block, err := marshaller.MarshalJSON() + proposal, err := marshaller.MarshalJSON() if err != nil { - return nil, errors.Wrap(err, "marshal block") + return nil, errors.Wrap(err, "marshal proposal") } - version, err := eth2util.DataVersionFromETH2(b.Version) + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { return nil, errors.Wrap(err, "convert version") } resp, err := json.Marshal(versionedRawBlockJSON{ Version: version, - Block: block, + Block: proposal, }) if err != nil { return nil, errors.Wrap(err, "marshal wrapper") @@ -351,13 +379,13 @@ func (b VersionedSignedBeaconBlock) MarshalJSON() ([]byte, error) { return resp, nil } -func (b *VersionedSignedBeaconBlock) UnmarshalJSON(input []byte) error { +func (p *VersionedSignedProposal) UnmarshalJSON(input []byte) error { var raw versionedRawBlockJSON if err := json.Unmarshal(input, &raw); err != nil { return errors.Wrap(err, "unmarshal block") } - resp := eth2spec.VersionedSignedBeaconBlock{Version: raw.Version.ToETH2()} + resp := eth2api.VersionedSignedProposal{Version: raw.Version.ToETH2()} switch resp.Version { case eth2spec.DataVersionPhase0: block := new(eth2p0.SignedBeaconBlock) @@ -384,7 +412,7 @@ func (b *VersionedSignedBeaconBlock) UnmarshalJSON(input []byte) error { } resp.Capella = block case eth2spec.DataVersionDeneb: - block := new(deneb.SignedBeaconBlock) + block := new(eth2deneb.SignedBlockContents) if err := json.Unmarshal(raw.Block, &block); err != nil { return errors.Wrap(err, "unmarshal deneb") } @@ -393,36 +421,36 @@ func (b *VersionedSignedBeaconBlock) UnmarshalJSON(input []byte) error { return errors.New("unknown version") } - b.VersionedSignedBeaconBlock = resp + p.VersionedSignedProposal = resp return nil } -// NewVersionedSignedBlindedBeaconBlock validates and returns a new wrapped VersionedSignedBlindedBeaconBlock. -func NewVersionedSignedBlindedBeaconBlock(block *eth2api.VersionedSignedBlindedBeaconBlock) (VersionedSignedBlindedBeaconBlock, error) { +// NewVersionedSignedBlindedProposal validates and returns a new wrapped VersionedSignedBlindedProposal. +func NewVersionedSignedBlindedProposal(block *eth2api.VersionedSignedBlindedProposal) (VersionedSignedBlindedProposal, error) { switch block.Version { case eth2spec.DataVersionBellatrix: if block.Bellatrix == nil { - return VersionedSignedBlindedBeaconBlock{}, errors.New("no bellatrix block") + return VersionedSignedBlindedProposal{}, errors.New("no bellatrix block") } case eth2spec.DataVersionCapella: if block.Capella == nil { - return VersionedSignedBlindedBeaconBlock{}, errors.New("no capella block") + return VersionedSignedBlindedProposal{}, errors.New("no capella block") } case eth2spec.DataVersionDeneb: if block.Deneb == nil { - return VersionedSignedBlindedBeaconBlock{}, errors.New("no deneb block") + return VersionedSignedBlindedProposal{}, errors.New("no deneb block") } default: - return VersionedSignedBlindedBeaconBlock{}, errors.New("unknown version") + return VersionedSignedBlindedProposal{}, errors.New("unknown version") } - return VersionedSignedBlindedBeaconBlock{VersionedSignedBlindedBeaconBlock: *block}, nil + return VersionedSignedBlindedProposal{VersionedSignedBlindedProposal: *block}, nil } -// NewPartialVersionedSignedBlindedBeaconBlock is a convenience function that returns a new partial signed block. -func NewPartialVersionedSignedBlindedBeaconBlock(block *eth2api.VersionedSignedBlindedBeaconBlock, shareIdx int) (ParSignedData, error) { - wrap, err := NewVersionedSignedBlindedBeaconBlock(block) +// NewPartialVersionedSignedBlindedProposal is a convenience function that returns a new partial signed proposal. +func NewPartialVersionedSignedBlindedProposal(proposal *eth2api.VersionedSignedBlindedProposal, shareIdx int) (ParSignedData, error) { + wrap, err := NewVersionedSignedBlindedProposal(proposal) if err != nil { return ParSignedData{}, err } @@ -433,73 +461,34 @@ func NewPartialVersionedSignedBlindedBeaconBlock(block *eth2api.VersionedSignedB }, nil } -// VersionedSignedBlindedBeaconBlock is a signed versioned blinded beacon block and implements SignedData. -type VersionedSignedBlindedBeaconBlock struct { - eth2api.VersionedSignedBlindedBeaconBlock // Could subtype instead of embed, but aligning with Attestation that cannot subtype. +// VersionedSignedBlindedProposal is a signed versioned blinded proposal and implements SignedData. +type VersionedSignedBlindedProposal struct { + eth2api.VersionedSignedBlindedProposal } -func (b VersionedSignedBlindedBeaconBlock) MessageRoots() ([][32]byte, error) { - switch b.Version { +func (p VersionedSignedBlindedProposal) Signatures() []Signature { + switch p.Version { // No block nil checks since `NewVersionedSignedBlindedBeaconBlock` assumed. case eth2spec.DataVersionBellatrix: - root, err := b.Bellatrix.Message.HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "hash message root") - } - - return [][32]byte{root}, nil + return []Signature{SigFromETH2(p.Bellatrix.Signature)} case eth2spec.DataVersionCapella: - root, err := b.Capella.Message.HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "hash message root") - } - - return [][32]byte{root}, nil + return []Signature{SigFromETH2(p.Capella.Signature)} case eth2spec.DataVersionDeneb: - root, err := b.Deneb.Message.HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "hash message root") + // Deneb's signatures consist of block sig and blob sidecar sigs. + var sigs []Signature + sigs = append(sigs, SigFromETH2(p.Deneb.SignedBlindedBlock.Signature)) + for _, blobSig := range p.Deneb.SignedBlindedBlobSidecars { + sigs = append(sigs, SigFromETH2(blobSig.Signature)) } - return [][32]byte{root}, nil + return sigs default: - panic("unknown version") // Note this is avoided by using `NewVersionedSignedBlindedBeaconBlock`. + panic("unknown version") // Note this is avoided by using `NewVersionedSignedBlindedProposal`. } } -func (b VersionedSignedBlindedBeaconBlock) Clone() (SignedData, error) { - return b.clone() -} - -// clone returns a copy of the VersionedSignedBlindedBeaconBlock. -// It is similar to Clone that returns the SignedData interface. - -func (b VersionedSignedBlindedBeaconBlock) clone() (VersionedSignedBlindedBeaconBlock, error) { - var resp VersionedSignedBlindedBeaconBlock - err := cloneJSONMarshaler(b, &resp) - if err != nil { - return VersionedSignedBlindedBeaconBlock{}, errors.Wrap(err, "clone block") - } - - return resp, nil -} - -func (b VersionedSignedBlindedBeaconBlock) Signatures() []Signature { - switch b.Version { - // No block nil checks since `NewVersionedSignedBlindedBeaconBlock` assumed. - case eth2spec.DataVersionBellatrix: - return []Signature{SigFromETH2(b.Bellatrix.Signature)} - case eth2spec.DataVersionCapella: - return []Signature{SigFromETH2(b.Capella.Signature)} - case eth2spec.DataVersionDeneb: - return []Signature{SigFromETH2(b.Deneb.Signature)} - default: - panic("unknown version") // Note this is avoided by using `NewVersionedSignedBlindedBeaconBlock`. - } -} - -func (b VersionedSignedBlindedBeaconBlock) SetSignatures(sigs []Signature) (SignedData, error) { - resp, err := b.clone() +func (p VersionedSignedBlindedProposal) SetSignatures(sigs []Signature) (SignedData, error) { + resp, err := p.clone() if err != nil { return nil, err } @@ -515,7 +504,17 @@ func (b VersionedSignedBlindedBeaconBlock) SetSignatures(sigs []Signature) (Sign case eth2spec.DataVersionCapella: resp.Capella.Signature = sigs[0].ToETH2() case eth2spec.DataVersionDeneb: - resp.Deneb.Signature = sigs[0].ToETH2() + sigsRequired := 1 + len(resp.Deneb.SignedBlindedBlobSidecars) + if len(sigs) != sigsRequired { + return nil, errors.New("not enough signatures", z.Int("required", sigsRequired), z.Int("got", len(sigs))) + } + + // Set signature of beacon block + resp.Deneb.SignedBlindedBlock.Signature = sigs[0].ToETH2() + // Set signatures of each blob sidecar + for i := 1; i < len(sigs); i++ { + resp.Deneb.SignedBlindedBlobSidecars[i-1].Signature = sigs[i].ToETH2() + } default: return nil, errors.New("unknown type") } @@ -523,16 +522,73 @@ func (b VersionedSignedBlindedBeaconBlock) SetSignatures(sigs []Signature) (Sign return resp, nil } -func (b VersionedSignedBlindedBeaconBlock) MarshalJSON() ([]byte, error) { - var marshaller json.Marshaler - switch b.Version { +func (p VersionedSignedBlindedProposal) MessageRoots() ([][32]byte, error) { + switch p.Version { // No block nil checks since `NewVersionedSignedBlindedBeaconBlock` assumed. case eth2spec.DataVersionBellatrix: - marshaller = b.VersionedSignedBlindedBeaconBlock.Bellatrix + root, err := p.Bellatrix.Message.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "hash message root") + } + + return [][32]byte{root}, nil + case eth2spec.DataVersionCapella: + root, err := p.Capella.Message.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "hash message root") + } + + return [][32]byte{root}, nil + case eth2spec.DataVersionDeneb: + var roots [][32]byte + // Append root of deneb blinded beacon block + root, err := p.Deneb.SignedBlindedBlock.Message.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "hash deneb blinded block") + } + roots = append(roots, root) + + // Append roots of deneb blinded blob sidecars + for _, blob := range p.Deneb.SignedBlindedBlobSidecars { + blobRoot, err := blob.Message.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "hash deneb blinded blob sidecar") + } + roots = append(roots, blobRoot) + } + + return roots, nil + default: + panic("unknown version") // Note this is avoided by using `NewVersionedSignedBlindedProposal`. + } +} + +func (p VersionedSignedBlindedProposal) Clone() (SignedData, error) { + return p.clone() +} + +// clone returns a copy of the VersionedSignedBlindedProposal. +// It is similar to Clone that returns the SignedData interface. +func (p VersionedSignedBlindedProposal) clone() (VersionedSignedBlindedProposal, error) { + var resp VersionedSignedBlindedProposal + err := cloneJSONMarshaler(p, &resp) + if err != nil { + return VersionedSignedBlindedProposal{}, errors.Wrap(err, "clone blinded proposal") + } + + return resp, nil +} + +func (p VersionedSignedBlindedProposal) MarshalJSON() ([]byte, error) { + var marshaller json.Marshaler + switch p.Version { + // No block nil checks since `NewVersionedSignedBlindedProposal` assumed. + case eth2spec.DataVersionBellatrix: + marshaller = p.VersionedSignedBlindedProposal.Bellatrix case eth2spec.DataVersionCapella: - marshaller = b.VersionedSignedBlindedBeaconBlock.Capella + marshaller = p.VersionedSignedBlindedProposal.Capella case eth2spec.DataVersionDeneb: - marshaller = b.VersionedSignedBlindedBeaconBlock.Deneb + marshaller = p.VersionedSignedBlindedProposal.Deneb default: return nil, errors.New("unknown version") } @@ -542,7 +598,7 @@ func (b VersionedSignedBlindedBeaconBlock) MarshalJSON() ([]byte, error) { return nil, errors.Wrap(err, "marshal block") } - version, err := eth2util.DataVersionFromETH2(b.Version) + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { return nil, errors.Wrap(err, "convert version") } @@ -558,13 +614,13 @@ func (b VersionedSignedBlindedBeaconBlock) MarshalJSON() ([]byte, error) { return resp, nil } -func (b *VersionedSignedBlindedBeaconBlock) UnmarshalJSON(input []byte) error { +func (p *VersionedSignedBlindedProposal) UnmarshalJSON(input []byte) error { var raw versionedRawBlockJSON if err := json.Unmarshal(input, &raw); err != nil { return errors.Wrap(err, "unmarshal block") } - resp := eth2api.VersionedSignedBlindedBeaconBlock{Version: raw.Version.ToETH2()} + resp := eth2api.VersionedSignedBlindedProposal{Version: raw.Version.ToETH2()} switch resp.Version { case eth2spec.DataVersionBellatrix: block := new(eth2bellatrix.SignedBlindedBeaconBlock) @@ -579,7 +635,7 @@ func (b *VersionedSignedBlindedBeaconBlock) UnmarshalJSON(input []byte) error { } resp.Capella = block case eth2spec.DataVersionDeneb: - block := new(eth2deneb.SignedBlindedBeaconBlock) + block := new(eth2deneb.SignedBlindedBlockContents) if err := json.Unmarshal(raw.Block, &block); err != nil { return errors.Wrap(err, "unmarshal deneb") } @@ -588,7 +644,7 @@ func (b *VersionedSignedBlindedBeaconBlock) UnmarshalJSON(input []byte) error { return errors.New("unknown version") } - b.VersionedSignedBlindedBeaconBlock = resp + p.VersionedSignedBlindedProposal = resp return nil } diff --git a/core/signeddata_test.go b/core/signeddata_test.go index c23f805a5..0e86f7cef 100644 --- a/core/signeddata_test.go +++ b/core/signeddata_test.go @@ -25,9 +25,9 @@ func TestSignedDataSetSignature(t *testing.T) { data core.SignedData }{ { - name: "versioned signed beacon block", - data: core.VersionedSignedBeaconBlock{ - VersionedSignedBeaconBlock: eth2spec.VersionedSignedBeaconBlock{ + name: "versioned signed proposal", + data: core.VersionedSignedProposal{ + VersionedSignedProposal: eth2api.VersionedSignedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: &bellatrix.SignedBeaconBlock{ Message: testutil.RandomBellatrixBeaconBlock(), @@ -37,9 +37,9 @@ func TestSignedDataSetSignature(t *testing.T) { }, }, { - name: "versioned signed blinded beacon block bellatrix", - data: core.VersionedSignedBlindedBeaconBlock{ - VersionedSignedBlindedBeaconBlock: eth2api.VersionedSignedBlindedBeaconBlock{ + name: "versioned signed blinded proposal bellatrix", + data: core.VersionedSignedBlindedProposal{ + VersionedSignedBlindedProposal: eth2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: ð2bellatrix.SignedBlindedBeaconBlock{ Message: testutil.RandomBellatrixBlindedBeaconBlock(), @@ -49,9 +49,9 @@ func TestSignedDataSetSignature(t *testing.T) { }, }, { - name: "versioned signed blinded beacon block capella", - data: core.VersionedSignedBlindedBeaconBlock{ - VersionedSignedBlindedBeaconBlock: eth2api.VersionedSignedBlindedBeaconBlock{ + name: "versioned signed blinded proposal capella", + data: core.VersionedSignedBlindedProposal{ + VersionedSignedBlindedProposal: eth2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: ð2capella.SignedBlindedBeaconBlock{ Message: testutil.RandomCapellaBlindedBeaconBlock(), diff --git a/core/ssz.go b/core/ssz.go index cf1f8a6a4..5c9bfc80e 100644 --- a/core/ssz.go +++ b/core/ssz.go @@ -12,7 +12,6 @@ import ( "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/bellatrix" "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/attestantio/go-eth2-client/spec/deneb" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" ssz "github.com/ferranbt/fastssz" "github.com/stretchr/testify/require" @@ -28,49 +27,49 @@ type sszType interface { ssz.Unmarshaler } -// ======================= VersionedSignedBeaconBlock ======================= +// ======================= VersionedSignedProposal ======================= -// MarshalSSZ ssz marshals the VersionedSignedBeaconBlock object. -func (b VersionedSignedBeaconBlock) MarshalSSZ() ([]byte, error) { - resp, err := ssz.MarshalSSZ(b) +// MarshalSSZ ssz marshals the VersionedSignedProposal object. +func (p VersionedSignedProposal) MarshalSSZ() ([]byte, error) { + resp, err := ssz.MarshalSSZ(p) if err != nil { - return nil, errors.Wrap(err, "marshal VersionedSignedBeaconBlock") + return nil, errors.Wrap(err, "marshal VersionedSignedProposal") } return resp, nil } -// MarshalSSZTo ssz marshals the VersionedSignedBeaconBlock object to a target array. -func (b VersionedSignedBeaconBlock) MarshalSSZTo(buf []byte) ([]byte, error) { - version, err := eth2util.DataVersionFromETH2(b.Version) +// MarshalSSZTo ssz marshals the VersionedSignedProposal object to a target array. +func (p VersionedSignedProposal) MarshalSSZTo(buf []byte) ([]byte, error) { + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { return nil, errors.Wrap(err, "invalid version") } - return marshalSSZVersionedTo(buf, version, b.sszValFromVersion) + return marshalSSZVersionedTo(buf, version, p.sszValFromVersion) } -// UnmarshalSSZ ssz unmarshals the VersionedSignedBeaconBlock object. -func (b *VersionedSignedBeaconBlock) UnmarshalSSZ(buf []byte) error { - version, err := unmarshalSSZVersioned(buf, b.sszValFromVersion) +// UnmarshalSSZ ssz unmarshals the VersionedSignedProposal object. +func (p *VersionedSignedProposal) UnmarshalSSZ(buf []byte) error { + version, err := unmarshalSSZVersioned(buf, p.sszValFromVersion) if err != nil { - return errors.Wrap(err, "unmarshal VersionedSignedBeaconBlock") + return errors.Wrap(err, "unmarshal VersionedSignedProposal") } - b.Version = version.ToETH2() + p.Version = version.ToETH2() return nil } -// SizeSSZ returns the ssz encoded size in bytes for the VersionedSignedBeaconBlock object. -func (b VersionedSignedBeaconBlock) SizeSSZ() int { - version, err := eth2util.DataVersionFromETH2(b.Version) +// SizeSSZ returns the ssz encoded size in bytes for the VersionedSignedProposal object. +func (p VersionedSignedProposal) SizeSSZ() int { + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { // SSZMarshaller interface doesn't return an error, so we can't either. return 0 } - val, err := b.sszValFromVersion(version) + val, err := p.sszValFromVersion(version) if err != nil { // SSZMarshaller interface doesn't return an error, so we can't either. return 0 @@ -79,49 +78,49 @@ func (b VersionedSignedBeaconBlock) SizeSSZ() int { return sizeSSZVersioned(val) } -// sszValFromVersion returns the internal value of the VersionedSignedBeaconBlock object for a given version. -func (b *VersionedSignedBeaconBlock) sszValFromVersion(version eth2util.DataVersion) (sszType, error) { +// sszValFromVersion returns the internal value of the VersionedSignedProposal object for a given version. +func (p *VersionedSignedProposal) sszValFromVersion(version eth2util.DataVersion) (sszType, error) { switch version { case eth2util.DataVersionPhase0: - if b.Phase0 == nil { - b.Phase0 = new(eth2p0.SignedBeaconBlock) + if p.Phase0 == nil { + p.Phase0 = new(eth2p0.SignedBeaconBlock) } - return b.Phase0, nil + return p.Phase0, nil case eth2util.DataVersionAltair: - if b.Altair == nil { - b.Altair = new(altair.SignedBeaconBlock) + if p.Altair == nil { + p.Altair = new(altair.SignedBeaconBlock) } - return b.Altair, nil + return p.Altair, nil case eth2util.DataVersionBellatrix: - if b.Bellatrix == nil { - b.Bellatrix = new(bellatrix.SignedBeaconBlock) + if p.Bellatrix == nil { + p.Bellatrix = new(bellatrix.SignedBeaconBlock) } - return b.Bellatrix, nil + return p.Bellatrix, nil case eth2util.DataVersionCapella: - if b.Capella == nil { - b.Capella = new(capella.SignedBeaconBlock) + if p.Capella == nil { + p.Capella = new(capella.SignedBeaconBlock) } - return b.Capella, nil + return p.Capella, nil case eth2util.DataVersionDeneb: - if b.Deneb == nil { - b.Deneb = new(deneb.SignedBeaconBlock) + if p.Deneb == nil { + p.Deneb = new(eth2deneb.SignedBlockContents) } - return b.Deneb, nil + return p.Deneb, nil default: return nil, errors.New("invalid version") } } -// ================== VersionedSignedBeaconBlock =================== +// ================== VersionedProposal =================== -// MarshalSSZ ssz marshals the VersionedBeaconBlock object. -func (b VersionedBeaconBlock) MarshalSSZ() ([]byte, error) { - resp, err := ssz.MarshalSSZ(b) +// MarshalSSZ ssz marshals the VersionedProposal object. +func (p VersionedProposal) MarshalSSZ() ([]byte, error) { + resp, err := ssz.MarshalSSZ(p) if err != nil { return nil, errors.Wrap(err, "marshal VersionedBeaconBlock") } @@ -129,37 +128,37 @@ func (b VersionedBeaconBlock) MarshalSSZ() ([]byte, error) { return resp, nil } -// MarshalSSZTo ssz marshals the VersionedBeaconBlock object to a target array. -func (b VersionedBeaconBlock) MarshalSSZTo(buf []byte) ([]byte, error) { - version, err := eth2util.DataVersionFromETH2(b.Version) +// MarshalSSZTo ssz marshals the VersionedProposal object to a target array. +func (p VersionedProposal) MarshalSSZTo(buf []byte) ([]byte, error) { + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { return nil, errors.Wrap(err, "invalid version") } - return marshalSSZVersionedTo(buf, version, b.sszValFromVersion) + return marshalSSZVersionedTo(buf, version, p.sszValFromVersion) } -// UnmarshalSSZ ssz unmarshals the VersionedBeaconBlock object. -func (b *VersionedBeaconBlock) UnmarshalSSZ(buf []byte) error { - version, err := unmarshalSSZVersioned(buf, b.sszValFromVersion) +// UnmarshalSSZ ssz unmarshalls the VersionedProposal object. +func (p *VersionedProposal) UnmarshalSSZ(buf []byte) error { + version, err := unmarshalSSZVersioned(buf, p.sszValFromVersion) if err != nil { - return errors.Wrap(err, "unmarshal VersionedSignedBeaconBlock") + return errors.Wrap(err, "unmarshal VersionedProposal") } - b.Version = version.ToETH2() + p.Version = version.ToETH2() return nil } -// SizeSSZ returns the ssz encoded size in bytes for the VersionedBeaconBlock object. -func (b VersionedBeaconBlock) SizeSSZ() int { - version, err := eth2util.DataVersionFromETH2(b.Version) +// SizeSSZ returns the ssz encoded size in bytes for the VersionedProposal object. +func (p VersionedProposal) SizeSSZ() int { + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { // SSZMarshaller interface doesn't return an error, so we can't either. return 0 } - val, err := b.sszValFromVersion(version) + val, err := p.sszValFromVersion(version) if err != nil { // SSZMarshaller interface doesn't return an error, so we can't either. return 0 @@ -169,86 +168,86 @@ func (b VersionedBeaconBlock) SizeSSZ() int { } // sszValFromVersion returns the internal value of the VersionedBeaconBlock object for a given version. -func (b *VersionedBeaconBlock) sszValFromVersion(version eth2util.DataVersion) (sszType, error) { +func (p *VersionedProposal) sszValFromVersion(version eth2util.DataVersion) (sszType, error) { switch version { case eth2util.DataVersionPhase0: - if b.Phase0 == nil { - b.Phase0 = new(eth2p0.BeaconBlock) + if p.Phase0 == nil { + p.Phase0 = new(eth2p0.BeaconBlock) } - return b.Phase0, nil + return p.Phase0, nil case eth2util.DataVersionAltair: - if b.Altair == nil { - b.Altair = new(altair.BeaconBlock) + if p.Altair == nil { + p.Altair = new(altair.BeaconBlock) } - return b.Altair, nil + return p.Altair, nil case eth2util.DataVersionBellatrix: - if b.Bellatrix == nil { - b.Bellatrix = new(bellatrix.BeaconBlock) + if p.Bellatrix == nil { + p.Bellatrix = new(bellatrix.BeaconBlock) } - return b.Bellatrix, nil + return p.Bellatrix, nil case eth2util.DataVersionCapella: - if b.Capella == nil { - b.Capella = new(capella.BeaconBlock) + if p.Capella == nil { + p.Capella = new(capella.BeaconBlock) } - return b.Capella, nil + return p.Capella, nil case eth2util.DataVersionDeneb: - if b.Deneb == nil { - b.Deneb = new(deneb.BeaconBlock) + if p.Deneb == nil { + p.Deneb = new(eth2deneb.BlockContents) } - return b.Deneb, nil + return p.Deneb, nil default: return nil, errors.New("invalid version") } } -// ================== VersionedSignedBlindedBeaconBlock =================== +// ================== VersionedSignedBlindedProposal =================== -// MarshalSSZ ssz marshals the VersionedSignedBlindedBeaconBlock object. -func (b VersionedSignedBlindedBeaconBlock) MarshalSSZ() ([]byte, error) { - resp, err := ssz.MarshalSSZ(b) +// MarshalSSZ ssz marshals the VersionedSignedBlindedProposal object. +func (p VersionedSignedBlindedProposal) MarshalSSZ() ([]byte, error) { + resp, err := ssz.MarshalSSZ(p) if err != nil { - return nil, errors.Wrap(err, "marshal VersionedSignedBlindedBeaconBlock") + return nil, errors.Wrap(err, "marshal VersionedSignedBlindedProposal") } return resp, nil } -// MarshalSSZTo ssz marshals the VersionedSignedBlindedBeaconBlock object to a target array. -func (b VersionedSignedBlindedBeaconBlock) MarshalSSZTo(buf []byte) ([]byte, error) { - version, err := eth2util.DataVersionFromETH2(b.Version) +// MarshalSSZTo ssz marshals the VersionedSignedBlindedProposal object to a target array. +func (p VersionedSignedBlindedProposal) MarshalSSZTo(buf []byte) ([]byte, error) { + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { return nil, errors.Wrap(err, "invalid version") } - return marshalSSZVersionedTo(buf, version, b.sszValFromVersion) + return marshalSSZVersionedTo(buf, version, p.sszValFromVersion) } -// UnmarshalSSZ ssz unmarshals the VersionedSignedBlindedBeaconBlock object. -func (b *VersionedSignedBlindedBeaconBlock) UnmarshalSSZ(buf []byte) error { - version, err := unmarshalSSZVersioned(buf, b.sszValFromVersion) +// UnmarshalSSZ ssz unmarshalls the VersionedSignedBlindedProposal object. +func (p *VersionedSignedBlindedProposal) UnmarshalSSZ(buf []byte) error { + version, err := unmarshalSSZVersioned(buf, p.sszValFromVersion) if err != nil { - return errors.Wrap(err, "unmarshal VersionedSignedBlindedBeaconBlock") + return errors.Wrap(err, "unmarshal VersionedSignedBlindedProposal") } - b.Version = version.ToETH2() + p.Version = version.ToETH2() return nil } -// SizeSSZ returns the ssz encoded size in bytes for the VersionedSignedBlindedBeaconBlock object. -func (b VersionedSignedBlindedBeaconBlock) SizeSSZ() int { - version, err := eth2util.DataVersionFromETH2(b.Version) +// SizeSSZ returns the ssz encoded size in bytes for the VersionedSignedBlindedProposal object. +func (p VersionedSignedBlindedProposal) SizeSSZ() int { + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { // SSZMarshaller interface doesn't return an error, so we can't either. return 0 } - val, err := b.sszValFromVersion(version) + val, err := p.sszValFromVersion(version) if err != nil { // SSZMarshaller interface doesn't return an error, so we can't either. return 0 @@ -258,36 +257,36 @@ func (b VersionedSignedBlindedBeaconBlock) SizeSSZ() int { } // sszValFromVersion returns the internal value of the VersionedSignedBlindedBeaconBlock object for a given version. -func (b *VersionedSignedBlindedBeaconBlock) sszValFromVersion(version eth2util.DataVersion) (sszType, error) { +func (p *VersionedSignedBlindedProposal) sszValFromVersion(version eth2util.DataVersion) (sszType, error) { switch version { case eth2util.DataVersionBellatrix: - if b.Bellatrix == nil { - b.Bellatrix = new(eth2bellatrix.SignedBlindedBeaconBlock) + if p.Bellatrix == nil { + p.Bellatrix = new(eth2bellatrix.SignedBlindedBeaconBlock) } - return b.Bellatrix, nil + return p.Bellatrix, nil case eth2util.DataVersionCapella: - if b.Capella == nil { - b.Capella = new(eth2capella.SignedBlindedBeaconBlock) + if p.Capella == nil { + p.Capella = new(eth2capella.SignedBlindedBeaconBlock) } - return b.Capella, nil + return p.Capella, nil case eth2util.DataVersionDeneb: - if b.Deneb == nil { - b.Deneb = new(eth2deneb.SignedBlindedBeaconBlock) + if p.Deneb == nil { + p.Deneb = new(eth2deneb.SignedBlindedBlockContents) } - return b.Deneb, nil + return p.Deneb, nil default: return nil, errors.New("invalid version") } } -// ================== VersionedBlindedBeaconBlock =================== +// ================== VersionedBlindedProposal =================== -// MarshalSSZ ssz marshals the VersionedBlindedBeaconBlock object. -func (b VersionedBlindedBeaconBlock) MarshalSSZ() ([]byte, error) { - resp, err := ssz.MarshalSSZ(b) +// MarshalSSZ ssz marshals the VersionedBlindedProposal object. +func (p VersionedBlindedProposal) MarshalSSZ() ([]byte, error) { + resp, err := ssz.MarshalSSZ(p) if err != nil { return nil, errors.Wrap(err, "marshal VersionedSignedBlindedBeaconBlock") } @@ -295,37 +294,37 @@ func (b VersionedBlindedBeaconBlock) MarshalSSZ() ([]byte, error) { return resp, nil } -// MarshalSSZTo ssz marshals the VersionedBlindedBeaconBlock object to a target array. -func (b VersionedBlindedBeaconBlock) MarshalSSZTo(buf []byte) ([]byte, error) { - version, err := eth2util.DataVersionFromETH2(b.Version) +// MarshalSSZTo ssz marshals the VersionedBlindedProposal object to a target array. +func (p VersionedBlindedProposal) MarshalSSZTo(buf []byte) ([]byte, error) { + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { return nil, errors.Wrap(err, "invalid version") } - return marshalSSZVersionedTo(buf, version, b.sszValFromVersion) + return marshalSSZVersionedTo(buf, version, p.sszValFromVersion) } -// UnmarshalSSZ ssz unmarshals the VersionedBlindedBeaconBlock object. -func (b *VersionedBlindedBeaconBlock) UnmarshalSSZ(buf []byte) error { - version, err := unmarshalSSZVersioned(buf, b.sszValFromVersion) +// UnmarshalSSZ ssz unmarshals the VersionedBlindedProposal object. +func (p *VersionedBlindedProposal) UnmarshalSSZ(buf []byte) error { + version, err := unmarshalSSZVersioned(buf, p.sszValFromVersion) if err != nil { return errors.Wrap(err, "unmarshal VersionedSignedBeaconBlock") } - b.Version = version.ToETH2() + p.Version = version.ToETH2() return nil } -// SizeSSZ returns the ssz encoded size in bytes for the VersionedBlindedBeaconBlock object. -func (b VersionedBlindedBeaconBlock) SizeSSZ() int { - version, err := eth2util.DataVersionFromETH2(b.Version) +// SizeSSZ returns the ssz encoded size in bytes for the VersionedBlindedProposal object. +func (p VersionedBlindedProposal) SizeSSZ() int { + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { // SSZMarshaller interface doesn't return an error, so we can't either. return 0 } - val, err := b.sszValFromVersion(version) + val, err := p.sszValFromVersion(version) if err != nil { // SSZMarshaller interface doesn't return an error, so we can't either. return 0 @@ -334,27 +333,27 @@ func (b VersionedBlindedBeaconBlock) SizeSSZ() int { return sizeSSZVersioned(val) } -// sszValFromVersion returns the internal value of the VersionedBlindedBeaconBlock object for a given version. -func (b *VersionedBlindedBeaconBlock) sszValFromVersion(version eth2util.DataVersion) (sszType, error) { +// sszValFromVersion returns the internal value of the VersionedBlindedProposal object for a given version. +func (p *VersionedBlindedProposal) sszValFromVersion(version eth2util.DataVersion) (sszType, error) { switch version { case eth2util.DataVersionBellatrix: - if b.Bellatrix == nil { - b.Bellatrix = new(eth2bellatrix.BlindedBeaconBlock) + if p.Bellatrix == nil { + p.Bellatrix = new(eth2bellatrix.BlindedBeaconBlock) } - return b.Bellatrix, nil + return p.Bellatrix, nil case eth2util.DataVersionCapella: - if b.Capella == nil { - b.Capella = new(eth2capella.BlindedBeaconBlock) + if p.Capella == nil { + p.Capella = new(eth2capella.BlindedBeaconBlock) } - return b.Capella, nil + return p.Capella, nil case eth2util.DataVersionDeneb: - if b.Deneb == nil { - b.Deneb = new(eth2deneb.BlindedBeaconBlock) + if p.Deneb == nil { + p.Deneb = new(eth2deneb.BlindedBlockContents) } - return b.Deneb, nil + return p.Deneb, nil default: return nil, errors.New("invalid version") } diff --git a/core/ssz_test.go b/core/ssz_test.go index a803150a6..d182521c3 100644 --- a/core/ssz_test.go +++ b/core/ssz_test.go @@ -52,16 +52,16 @@ func TestSSZ(t *testing.T) { tests := []struct { zero func() any }{ - {zero: func() any { return new(core.VersionedSignedBeaconBlock) }}, + {zero: func() any { return new(core.VersionedSignedProposal) }}, {zero: func() any { return new(core.Attestation) }}, - {zero: func() any { return new(core.VersionedSignedBlindedBeaconBlock) }}, + {zero: func() any { return new(core.VersionedSignedBlindedProposal) }}, {zero: func() any { return new(core.SignedAggregateAndProof) }}, {zero: func() any { return new(core.SignedSyncMessage) }}, {zero: func() any { return new(core.SyncContributionAndProof) }}, {zero: func() any { return new(core.SignedSyncContributionAndProof) }}, {zero: func() any { return new(core.AggregatedAttestation) }}, - {zero: func() any { return new(core.VersionedBeaconBlock) }}, - {zero: func() any { return new(core.VersionedBlindedBeaconBlock) }}, + {zero: func() any { return new(core.VersionedProposal) }}, + {zero: func() any { return new(core.VersionedBlindedProposal) }}, {zero: func() any { return new(core.SyncContribution) }}, } @@ -105,11 +105,11 @@ func TestMarshalUnsignedProto(t *testing.T) { }, { dutyType: core.DutyProposer, - unsignedPtr: func() any { return new(core.VersionedBeaconBlock) }, + unsignedPtr: func() any { return new(core.VersionedProposal) }, }, { dutyType: core.DutyBuilderProposer, - unsignedPtr: func() any { return new(core.VersionedBlindedBeaconBlock) }, + unsignedPtr: func() any { return new(core.VersionedBlindedProposal) }, }, { dutyType: core.DutySyncContribution, @@ -183,11 +183,11 @@ func TestMarshalParSignedProto(t *testing.T) { }, { dutyType: core.DutyProposer, - signedPtr: func() any { return new(core.VersionedSignedBeaconBlock) }, + signedPtr: func() any { return new(core.VersionedSignedProposal) }, }, { dutyType: core.DutyBuilderProposer, - signedPtr: func() any { return new(core.VersionedSignedBlindedBeaconBlock) }, + signedPtr: func() any { return new(core.VersionedSignedBlindedProposal) }, }, { dutyType: core.DutySyncContribution, diff --git a/core/testdata/TestJSONSerialisation_VersionedBlindedProposal.json.golden b/core/testdata/TestJSONSerialisation_VersionedBlindedProposal.json.golden new file mode 100644 index 000000000..084c2d6e7 --- /dev/null +++ b/core/testdata/TestJSONSerialisation_VersionedBlindedProposal.json.golden @@ -0,0 +1,577 @@ +{ + "version": 4, + "block": { + "blinded_block": { + "slot": "12258969221770119542", + "proposer_index": "7833179233048568588", + "parent_root": "0x908d45b0164a1ed1fe5f6c6bb64a52fa1a95e2bdff2aea5190ce067ad5d23f96", + "state_root": "0xec4c0e68f23b572665b0e60f46fd4ffbf4ebe0530c03f2ecd45fac9d4aef1d6a", + "body": { + "randao_reveal": "0x9ec7799f34798eb91ff4c4fe748e21819c51945e7ed3df1fb0b5a4e0e895804813d1f4a80680595fb94b57636910c8ea580e905fda113b925adfac8d80ebb68deac0c0d6cb9aa138c60f34218fefbffdf6e04b99c493c785f588d20e8521bdc9", + "eth1_data": { + "deposit_root": "0x82ab0f52cf75924a308bcb99683bccc2813229bf922aaf112694262a4c953678", + "deposit_count": "13954635830841395618", + "block_hash": "0x0b002cee5e71c47935e281ebfc4b8b652b69ccb092e55a20f1b9f97d04629612" + }, + "graffiti": "0xbb97fb7e48b3fbbf085d511d62e526d7dada713df407b4c7822023ea549c538f", + "proposer_slashings": [ + { + "signed_header_1": { + "message": { + "slot": "1443379047061527087", + "proposer_index": "4216468081525476639", + "parent_root": "0xc6d49147f6a2fa1e6bfb7ae0313d3a74e7b68cb7ca96009ae25551158f08e482", + "state_root": "0xa26a00f0d6ed086dd4369f0897c9e5d32d3df8099046f2bbed9d544205208fe1", + "body_root": "0xc47a9329cd2e79e07d6f657ed2087a246b2a63f812829816a3019101a49a6a26" + }, + "signature": "0x76f58e9e788391631743c0ebb6197763775e88568c02afbefd317991659a2d1eac669c417b43efb4e8adc4f4be090e2df1860992a969df2236eb48b575dc29d1b6703396a38bfc3fff490d511e4e2f992e6a28b16ca63b967ec184be1233a6fd" + }, + "signed_header_2": { + "message": { + "slot": "8710010509815014220", + "proposer_index": "11427002176138074026", + "parent_root": "0x3ee79f16c4a5a7f937220f388339a555ca3b7cb6a2d6355bef4b0331399777f9", + "state_root": "0xeecbf5f2242f59ea5be8e14f23a279c59a485a6634044dbd8b8de354847f02ca", + "body_root": "0xc158c5aa735dcff744590cc6e7c8592ba3f60ce1b521491ea9ac7b24a12c96ae" + }, + "signature": "0xd58097e815815d949b57ab971a075abb6481f8aef1e2816598ac364775ae561dcb95d0157f7eec22697c09f840b35c7d5c8fea33425b3727e8d13bbc2428b1559d6f65ddf46916acd2978145e823d20b7b536da9f1194074859a9b26102cb805" + } + }, + { + "signed_header_1": { + "message": { + "slot": "3753582023824823793", + "proposer_index": "17360171144750589851", + "parent_root": "0xdc63d6792b7f5171917b685ff27f71d636dee24d693615996ca85c09558c6215", + "state_root": "0x1738f125029e434fb2c3d9d88a0c9445defc19c473afe934fb752bce78ce6c33", + "body_root": "0x127dad08c5b009807db26a92dfce76b9c76878532b92f41eb02430857268fcae" + }, + "signature": "0xe7c388446cf5299facd134f8cf2864ba6806cc06003a0d535d1b93069b6dbf0eb1240bc31ba38be3f7c544207175a1eb66c447d4cf9478afa37c95c39d4a9db966e89739e0e7952da1a2050928db0edf1152ac9eff9ed1913cff6ca3d21a5840" + }, + "signed_header_2": { + "message": { + "slot": "16207056013116748211", + "proposer_index": "8904857625617278258", + "parent_root": "0xf4f30e5f5512facd4e95c879f5db52de033010ffa180eed7d81077294277b90f", + "state_root": "0xa9b0725db8cac6a70e0aacb7e36d0499cc54ee36bf48952af8824035bdb02edc", + "body_root": "0xd938619c7b83ccf4dfed9ef0ab43f1b879510b7f7e4f1c9f94c9a96eae0bc1b1" + }, + "signature": "0x10aa118bbd64e3c498177c1f91ddfd19ba4829ea1a10b208a9b2eb1a7526f1952a0cfea19d2a07560838369d57ab1177560c7d00f02978424fae53bbc30632a0c2dab6e94b2d8f0e151e3a02c1f0d04b763f5fd190631d90e98b39ca129624f7" + } + }, + { + "signed_header_1": { + "message": { + "slot": "13066106652058020522", + "proposer_index": "15082442079153513282", + "parent_root": "0x9b62f91dd6e6c34877950ae90c27953b4661b51527d46e49b7ea29ed92a42ef7", + "state_root": "0x5434abdad0b8c3b0c828ff6724fb74e4d6fe6f8f5c3490ae61e4829c22618f96", + "body_root": "0x74de7b5bb05a2ce2af56dc9d27e3ec42ac4e6f57955380d25326c99bb9a7e6f7" + }, + "signature": "0xaa05bb1a1ab59c7d07016797bad80a44792de495413a19954da8f77a4d5beef06b4838bdc55bfb6494a2cd49447c123d3d18f4b8df78a94afb826a150b2e914d152170d2d9eba822f1c28e97baeb48e37d6060d8658c6b7c95aa2dcbe97f5324" + }, + "signed_header_2": { + "message": { + "slot": "14870197141001258099", + "proposer_index": "15163092277513918012", + "parent_root": "0xcbd03da2cc9ae47308f38d7c778f6587d7e43277472bbdd64e0626707192f422", + "state_root": "0xa5c15c1d95653fb9c9c7a75cdb8cfd5d79232b2aa380fa6a875498ef72afd594", + "body_root": "0x0b96d740ef55ad9f3bb753a595b8b07a0500d7f84cae8417abebc5b450570051" + }, + "signature": "0x7eda930d664c2cbe0ebc7ad4065cfaf59eb6c9a006eb7c582866897ecd0fb6d6fdc6e7a871a80afac731b770dcc8864583c57d95e715a9ae833412d0daf1fb193647cc5ec17aa2896ef12e1cb72138fbbd950d13e2009c157baae4170f2562bb" + } + }, + { + "signed_header_1": { + "message": { + "slot": "4423882567267761972", + "proposer_index": "17362013782227991992", + "parent_root": "0x0e645c91f28d7b10040279c545e927db8addf301d97e6901f00c8e6a53b0bf22", + "state_root": "0xbc9ff3ea6dcaff559f0af11909200f77d3a53e71b1f307b8fba35cd1d2b18400", + "body_root": "0x0f64d2de37299ef39aec6cb09aadd2b63a8e14c5ca498c70d85d9d380f1dd602" + }, + "signature": "0xbce598896bb8d2fefb7cceeca5b3684427fbe1a7dc9f2d58b54118f9ca8e7f39c521f823a4927981b201534eab117644bc428ced450267873a6d2405a80d82eb7615bfec9f32d2abd17fc782c2af05f31edb40d9aed59c34bc78b85305f33786" + }, + "signed_header_2": { + "message": { + "slot": "2756473157529667098", + "proposer_index": "8302046196302492988", + "parent_root": "0x9866d5573876086e358365fc71f8003397c8dfcec3548b8f557d618ed98d634e", + "state_root": "0x999ba3128fc58623d023bc473c5b47a4b2a47ed14055f7804cea373efa212bb9", + "body_root": "0xe9a877c09a70e4206c1a45166236acb5b335bc4b3b70decb05c53123fdbe888e" + }, + "signature": "0x8b743eeb84065f97ac5c31bb1bf10ec01bf3aec56e73bb84a12f0d78211cf0f1ed43730e255b6d5789ab95cfa50a00c7ed32b84c63d69a4ec98a6b0f297a492cdd1c1c8013ceb804c4a47f7bacda0af4392aa04237bdec6d619aca30fa4641a4" + } + }, + { + "signed_header_1": { + "message": { + "slot": "11045824254400895358", + "proposer_index": "16136532190648778027", + "parent_root": "0x0391106cbfaa50af22cecc9bb7b87777e2a9a6e9553e765baf2bac2056ee8295", + "state_root": "0x82dee29a0bae040d7c2a042926dde4bd6e3fbad192376a08fb61008709b748e5", + "body_root": "0xebcd702f577cb1b76617ad7dd605eba95e038eb938f1f4e696e154ca2930d8b6" + }, + "signature": "0xce4e1f15a3df9a50dfdf0aad66356ffd92d62b3e6a67edb22a01ef3aacfeb4adc1d58e6cffdd04c830a90762bcdf75a9f19dbf73ffb4d22a4d598dd30fb6b1a6acf80b8d2c7db7d0fc50007513a7bfbced61caaf566be024b6682781c752f774" + }, + "signed_header_2": { + "message": { + "slot": "8246471541327176547", + "proposer_index": "8302833441173825771", + "parent_root": "0x3bda45a3ceb020e9c679b6504b6864a7bef80d4889be5f4a4e5c71ba580b451a", + "state_root": "0x36a8f9d358de49327d1ee015b0873f9e88e253633912a766a15c1ff90e9e8bc5", + "body_root": "0x6471aa11317030fbff8e8b6080c7a33df3303fbe286aac11c2d613e246b465bd" + }, + "signature": "0xe412d979710153b8d0a44193998becd21ec14c2de627fce26b299dc1dec245c6df55a4874d5c3bbd70eae6310fb170c771e0b9c92e07a4d4f43b27b4dd13078a741bb6dda597941cc0bfef563c48b5853cd0c874da8cea58b388abbfa35af0d3" + } + }, + { + "signed_header_1": { + "message": { + "slot": "11231276011780030403", + "proposer_index": "4535268073733844648", + "parent_root": "0x0df012163c2712fd8c5f3a0aba47cf9136bb9750a188780ae39e95217ef98732", + "state_root": "0xfea81cc998c09b4fff6e5296d56d713ca1eda9b1936a3dcba59afc963d54eb1a", + "body_root": "0x2e9a4810f8eeb4fe919b9bdc321af1b2b689c139f313333a1cebab327290cf95" + }, + "signature": "0x95cedd6c8fb04090219448d5a5f33038ed4bee728f8e233466f219ba2218834d08d68a0d5f9a7f04ea48bf36fa6adcd691b7289b5c8019765a2032f5ecb21c8a04377d9ef296d094b51d2678ccacc902ade83cde2e22d83ec4b5e6521e8f9e2c" + }, + "signed_header_2": { + "message": { + "slot": "413530364184878844", + "proposer_index": "2762530381805634493", + "parent_root": "0x513732cfd25398b5c86626c045f6c0c13ba449672c88e0a34f7683289a71a77d", + "state_root": "0x1051ae57e353494ddcc035b576f8fcaf1840b4c337464cfe4cdaf42a5f2ee239", + "body_root": "0xfd3f198aee274a6c1bec6c039cc74c76ef5cb98ff31f6b60ba3e2b11501064b7" + }, + "signature": "0x49af0fb0b9c80b895a8b09f9a4bd6255cf591f6b740b6d315f28c0dc7a3e6b4c334ad4e7cd3d66d9693abfdebd60fa15eaa4a8a15bd2b5fa02b9ebd6ee615fa137ecfa198c7598021052a53972d73b122a85b296d5acfe885b8c5ac8011f5737" + } + }, + { + "signed_header_1": { + "message": { + "slot": "9644765991827726829", + "proposer_index": "893066331788262369", + "parent_root": "0xc8110ac0ccd4b717571f82a60345a83e288c7e85956e7f0ece3dfe727f61e56b", + "state_root": "0x40decaffccfd178744d66b23d98ff44163f35cbfab30b1229da6cab1789f1afc", + "body_root": "0x1511aa1f57671457e78e73fb949de53b6a08b43a7756d88810a3bdd7ee7255e8" + }, + "signature": "0xb37e30d518ca15499b4f8cc801439f9ffa0d7a508597ea412d7236e7cafd24e11a9778c4f3306dde6d1a127a2c9a6aa16d5e6738fb1f37253b96c54931b6541b3b4a4c748b459920487e031a7a5680d89d3877a8bde08f2e07e897a4306c6839" + }, + "signed_header_2": { + "message": { + "slot": "2622749781788581409", + "proposer_index": "5936728940722922084", + "parent_root": "0xa4b06a0d12eb35acf7f969ce4e3df25ccb54ae514de3ea1ce3446add46ac2d83", + "state_root": "0xaf4ed0275a93c32e16f97610387f5168facb00317fb89bf8a974f272ab5910fe", + "body_root": "0xf54932557f148483ef44d2331f157e951bd33b7bb78ba8c59bfe6b4aa492880d" + }, + "signature": "0x9e3dcad1fe061526aa2a63e2cf93139d9f5ecf11e98955eed2b9962eefe28ae4cd737f07790451891ba81bf0eec2b77206e46791bb41e63bd082a0fe092f3ed68473b6ca22bf3a2b3cf897bb7fb32be35b5adf253fc79c1d3e393a6c91b6a8cc" + } + } + ], + "attester_slashings": [ + { + "attestation_1": { + "attesting_indices": [ + "17539680117757364262", + "5781627475530218201", + "5506905600699984943" + ], + "data": { + "slot": "4828972672715110647", + "index": "11404741012694454725", + "beacon_block_root": "0x32229c0ff9c7959817a3d90743b9825da4c01e68dfa898339e61a9b2d6b3fe8f", + "source": { + "epoch": "5196043516686486303", + "root": "0x64e6b47fe9c1a2f4fbe38db3ddae6f648f3c0b0c78a2bd12fd2b197f1169dcfa" + }, + "target": { + "epoch": "14361513721093163601", + "root": "0xd185173c3dc8ee4e36a754854ea03ae44cedaa23e29e5676399483ed26f441cc" + } + }, + "signature": "0x74d0a1edf955b3738292fb287bd23d0d4e3bb4c83207ca154b3f8d19e963fbf530bed51b597d2fd228de8e0f28dc5858acb44d5dd640d703d7520c25100c03c3d5c9c5f1091dd12e17a889a01a791ff471ec464eb6338e70bd1af5083f38244e" + }, + "attestation_2": { + "attesting_indices": [ + "3205659272094003927", + "8723309406074214413", + "12108181204264277805" + ], + "data": { + "slot": "14409283664605244108", + "index": "11486493041238181026", + "beacon_block_root": "0x17da4a6fbda3456c118ab1c8585f38a7e57cb6024b100cfbd90f9c736c89f93a", + "source": { + "epoch": "4497779902312325063", + "root": "0xab8cddd8dcaa344e119b3a713079b465ce8db61e31e8451087720523ab818bd0" + }, + "target": { + "epoch": "10662394743459613671", + "root": "0x99b530c1e52bcda6d1156c47e3e4241341e187525378500ab0349b7aafcd8e18" + } + }, + "signature": "0x17117377c3e490b38e15f7561a25b8af06995bdaa21f20a9d7d3292ef1386719918a764297c30c12b19e29fac5675f37bdee74b2f1f559c05d0e381559200650672d680b8398e7caa6c72be0dca396eadaab14c6a110f1705574a822da937598" + } + }, + { + "attestation_1": { + "attesting_indices": [ + "4044780610053584759", + "7435307165620220407", + "16134622791740421828", + "2132945930735811872", + "6414260498866420412" + ], + "data": { + "slot": "393045144288944340", + "index": "17469441142722646210", + "beacon_block_root": "0x18fff028278de33fef923a70412b72d0b8eb865cb9e681055874d27870ee0a3e", + "source": { + "epoch": "9725862182444272965", + "root": "0xe75492ee8a0ef0882894e327331669b3ef1f329adbbbc0ff755ba4683ceeb216" + }, + "target": { + "epoch": "1291337442909776703", + "root": "0x9fc4ac62b90094e588455d4d1d6eb6e0f4fee5c1ea38be5722a016f0db9823ef" + } + }, + "signature": "0x4e6a51850e2a219879088ccf82687d8ecee922ba01e653e5d63ef41f48bf878c99eeaa31c3f56d2b64dd8525b4c4cbcde1e4a1c919c18fc596781df8d5a9205f4b5ba7439e816572e37c6f2d59de9f10973944c57907b616fbbd2d60df8c1af8" + }, + "attestation_2": { + "attesting_indices": [ + "6084093166697219293", + "737263562008020227", + "6924818113102838477", + "11428886990944795377" + ], + "data": { + "slot": "842694213661142645", + "index": "16632392495717814903", + "beacon_block_root": "0x775b7a8decc11afd3de60286d964cb4812ef66b5dfca3643758168ea20e03334", + "source": { + "epoch": "10697515580993499280", + "root": "0xf826ffb49f985c62ad45b15b66168a34b6b486666858c69e419f92641aad40c6" + }, + "target": { + "epoch": "9303739303502036426", + "root": "0x4c1eb2b65e32f13e6399798b3245b7624e07db1b20f0a672c6af10341f1df7ba" + } + }, + "signature": "0x1cf396a75430c5486e5734b2c93886ae3987ff1c77f5d8c76e49ba048c1c24b0d9406c7c01696a161455fe2471fc6c39c983fde3edab26b45525dbacb2701b00b1c8d3f96a3fb227949a28deb9b0cab3673b5b1470f6a0ec44bd8bf9dd8f1d38" + } + } + ], + "attestations": [ + { + "aggregation_bits": "0x7601", + "data": { + "slot": "15300307516884943893", + "index": "10125495742326073003", + "beacon_block_root": "0x442184ebfb6df5618bc49f98d58dd72267db04cb264301ac12379cff20d7783f", + "source": { + "epoch": "1301371927588039996", + "root": "0xd9da7734e9515b24dc2ef179010632c1ec7031a60c39c958c5ed5e51b5a992de" + }, + "target": { + "epoch": "4051636045274551925", + "root": "0x37d98f50e671ed3516ff724da1d7b33d2bc6b9bcc6f470701e179acfa5072011" + } + }, + "signature": "0x937a65bcf61ec466d3c3b9934d43372dc1ffade798adedb4387af3ea33d68f3fbe230e77fedb5be52a021c6c09c7526ea68447f9806d1209265f3a7bd8de9d29e0298336846fb0c0a29e99b8de19d33f9a5887f26d21c00a9ec70bb45b9422ac" + }, + { + "aggregation_bits": "0x6a4d6b4ffef62601", + "data": { + "slot": "16984397302609171039", + "index": "15910524230756209060", + "beacon_block_root": "0x2bd6e2bb3f830427a6537c6a4b69f850c8bc3bd3a10207a5dc0b9b33f17b8f12", + "source": { + "epoch": "13619526095895379891", + "root": "0x4a2b0493ddb16d91da71d1de2382dbd1bbbb6b743a0a78f3d25238e5ab579b0b" + }, + "target": { + "epoch": "699754634382871494", + "root": "0x6431815c53ca6a8d389b5307cd51a5114ba28ce1e945391bf5d4ee9080023822" + } + }, + "signature": "0x7bf5739f9dd79e4b8a022999208abcf4b49afe92f20c408490aa2c5429d86d5b8baed87f0705d335418937e993c4ad1057a2c1a88daa992457ac9984606bd30c80cb7684c17c612b77e17e8920ce06388a9be9764b41d9d30543df12990474ae" + }, + { + "aggregation_bits": "0xe44aaa37bb99196201", + "data": { + "slot": "11688841322589834836", + "index": "16794188245375730201", + "beacon_block_root": "0x7bcea8a69c68f9ebe098ea1eab87d121f994a8b01b474ae6bfe72b98627d67f0", + "source": { + "epoch": "6230665511596386155", + "root": "0xd0d2fba9063393e254ee15d6718f3520ae13e1b1c4d99810f92467b698da446e" + }, + "target": { + "epoch": "7002460317479135536", + "root": "0x7ba50a54cf4cd863571d3db0560fb4d1685ce87b822d93e06f72034530d78e2f" + } + }, + "signature": "0xcde09c6b6f7142de6227f88748a3a6a81227738f307e676cf61ef182e79dac405eaecb49eda086c91f43caa69c035e59b500c5f44bcc8e5b73e25508cc4c5d19bed0315bd37e6c26037757d8a42ef77bf7c0b6c8501582017131c712ba560ef5" + }, + { + "aggregation_bits": "0xdb20760efc321b1e01", + "data": { + "slot": "669398345345509026", + "index": "17292942742400086206", + "beacon_block_root": "0xd5d809b940c0d7bfd9ce2936eda069b15f6b26067b709e8d18a84bb774611980", + "source": { + "epoch": "8640177637667673501", + "root": "0xa00bb5a2206dfa52429787df623cff32e27bdf6ee312158ebee7cf9a50252a22" + }, + "target": { + "epoch": "11093876280480600828", + "root": "0x8f0c7f7009a238c899ca68fad4ebe2bec47326e9fae55713ead48336863f8bb9" + } + }, + "signature": "0x4f79f68c902eaacae9e56ab90af20e8d7161cbf608a53c4fcb65bbdfcf2ec524c5d3b0dbc4eee02ad0f6f86dedb0dafac63979ab84d2dd9f55b40d1ce224f1c1c83065582b3bbe4865f93021ccbb9f8003628fd0dfa2557e249ebaa04461b1a3" + }, + { + "aggregation_bits": "0x022b57048223459df601", + "data": { + "slot": "11500089007668995752", + "index": "2193946105068863478", + "beacon_block_root": "0x18141c0a3bb59146838b9f7ff5b527302afce68ac143b725ee90f516faebe9e4", + "source": { + "epoch": "12997335381693400026", + "root": "0xdd3036476566f0e37a2e175321640d8027383a4bf5313c7c9d78ded240e6a0e1" + }, + "target": { + "epoch": "10827572253665793214", + "root": "0x0df0ef220cc1d9f3d0b97920ef229aa75987482160256beee3c70558c930bb22" + } + }, + "signature": "0x8e19e82d7a190b3c39492d7e57fd51c62b5f8891c8fc8b82f33ca48ed9e7be639f589ee69ff47e463ae873c162f983910a43e517fa9736b0ec656abb7d9c7587038e21ac4359462b0a324824b557a01712387977f855aa6fc18b81eb176f86ff" + } + ], + "deposits": [], + "voluntary_exits": [ + { + "message": { + "epoch": "15018482157318785969", + "validator_index": "18385606883598887718" + }, + "signature": "0x030d28ab456d81fd5d0323c35e1b40cf924c1afb2bb792bdf3b1c634b031914769681dea7bc9c327415285e8bd1c0a1eacb25ee30d847953912cf1db1f7862d73ee1ee846b143d66a3560e171a8ac93f87973e324fa496ba28b860548799748f" + }, + { + "message": { + "epoch": "3161590947260102369", + "validator_index": "4572211032227941474" + }, + "signature": "0x08a745255e83001422225a4c7b89afca57288c3a16f62efec32f96b7080d03aeeef0d8b729e13e5ef3abd372e1d7313b16807f4e4fb984544621e9cf3a9129a407f017322803af2bdb6aebcfe91a4655a2373cf9404759b76a55a5d979fd1bd4" + }, + { + "message": { + "epoch": "14893385273738851877", + "validator_index": "15593987053076001232" + }, + "signature": "0x302cfc43f277ece0c75fbe9ab872d47da61fa7e790cff0daafa22f8f426946c7d618f5193b61462cc55302474f0a961caf740c41d59b0ea434ad2cdeea29995235a4838ab27c1184fa83276a6925f4f7273878494d4ffaf746a564f415d2a3d4" + }, + { + "message": { + "epoch": "4550143485387678889", + "validator_index": "16567475962248278295" + }, + "signature": "0xb970dc7544c73cfe3c842befbfc77ac1f8ee38511495cbf292767a720c46c6ffcfc7302b9f9a951a2d6d41af0808b24482758edf9b53d206ca9e536a2e40cf216a62e1a99e15f9e39da775849368aa105e69955f5c370c4a73243fa45f5d658d" + }, + { + "message": { + "epoch": "10066465926439695730", + "validator_index": "1873650440899993283" + }, + "signature": "0x403b3f9ff5368cb99603ebf5d8018a9ab515463c9e19cda8ee86dcac3e5418ca0461729fa8a860b42c6da97a5d2f30fe62a09facfc0e6eb8a0644e5046d998634147d7f0a3d7b8485dc89d444508d82d7ff223f89925adcbd8dc9a2cbd35f4f9" + }, + { + "message": { + "epoch": "200221781886377895", + "validator_index": "17984838682046851133" + }, + "signature": "0x74107218f29e61ed14e84b41fd58b199abd3552aa6a78f84adb6bc9e067fd9a81872d56c0b175434b83098d2e55c57ed3d270c20b7658a527e73b4db4c2334088a287eb21c3906f52a5a24723926f1d0e4c65524f689d818f64a5e69afe60ab3" + }, + { + "message": { + "epoch": "9497683918427349596", + "validator_index": "16117496434940928171" + }, + "signature": "0x9fbedd603fadeabc86f1089ef565cbbb2d63e1dbd79c60824d67b07e129bd298f59bec45ef44d8a3449238f60742568cf1066163dd2e49e30942fa628a78550f0834c0a8ca82d4b716a92c4e1856d80d5678c501fe9c90a27f139c969cf298f4" + }, + { + "message": { + "epoch": "6425054894525323180", + "validator_index": "1641765794057278081" + }, + "signature": "0xb9767a84bcbe0889985ca83218baa491fc7cabe299d21acabcd999e40cf9f03ad3ac87b5d2a4204f00e8554b71b25fb1185294fbba8f038188d4abcf3aeeccfecf59746bfc36e2c335931b90eba15ad53b4d4b2eba70f8845b7653f6aee21e95" + }, + { + "message": { + "epoch": "10813334744019625031", + "validator_index": "5629123092837270189" + }, + "signature": "0x2d7b68bc9d443c285e5fa721d82af67a7be12f5e364b0789ac03bbfbbffb445ff6d7e22390d1e850f1c8d55cbe508c4005fd16fc7e39a3b7025037a51c3b4d4ec0581c25425ed40667eedd27442b4379bdaad95182fd18ea20b019dc997f1e0a" + }, + { + "message": { + "epoch": "14867058819375632362", + "validator_index": "8246199444797444564" + }, + "signature": "0x77a202c0aaf79c7a7d2b1c5e8c4e287709b0361590ac2150be31210b8c747a5561a744737a221654018d8815cca2f1df17e06d4c076de790c21379506cb645b65d4973996fff0ca2cc5a54bd07087202aad6a6654d5c76dbfd7dd5345a8264d3" + } + ], + "sync_aggregate": { + "sync_committee_bits": "0xffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "sync_committee_signature": "0x489f892a0a03fd22d44fc9c14bb56fb79cfa85c012882fc0233645db9a35dc33a57b4a4e8a757d9bbcca7e1471a9fd0088292202ca114b3b25d14705cddac76246533000b9df7658f8183721a4a5b8444bb5532eb87bc1dde0151d89cd471b98" + }, + "execution_payload_header": { + "parent_hash": "0x4beb9121e3794ce8a05f1ae51971f5c23ff6616e75024bb7115410b0766ffca3", + "fee_recipient": "0x2841B90e5458dC6B2F5b135Af4C6f7310D1a4E8B", + "state_root": "0x0b9f166e42a3e6ef6fc1ae7e43f6dfdca821eb41fac4b1be6a7174c83687adf2", + "receipts_root": "0xa7dad9ab1f1bb531fb55016ac624d714b1371e0644b5d985aab7ccca87c3e690", + "logs_bloom": "0x447f6b80ecb035340bc9120ebc43e89e8d98ecf0562129f2c6e05279134c83cb296c429e62f5e8c92c02ee7df710e36daa539372b5537d53657f388ab0d062fd38fadce4c0b3d917e3aa96f79598250de4cb050bae0f2c363aef8997c492d90559c8982f94528be726b797967c0557247cdc5d57a04fe838e4a9633a7733e02a594e9dafb35e02d15fec1d08d7115e0d60f252239e2b532134fbe2a0095fdd4774b5da01ef46391a114da6dbe1d50089850f18c31abfdf8b5131a019be3d9811557adfe6bdf694eb98a78ac5b59fcf23bf99b41ebb07a9b7ee31410672b391b680d5ba263729a9828477d0ac455f1ecea06e13631fcea403e3c0b8dd234bdbe9", + "prev_randao": "0xcfeb5eff29f14a9ccd17d33760501c0afd0b19f9676489e18f0a70eb4d02e868", + "block_number": "11161037225248869235", + "gas_limit": "1355369026211882316", + "gas_used": "7396354187159843037", + "timestamp": "14400415258642403381", + "extra_data": "0xc3de84bbf67606", + "base_fee_per_gas": "9653785960833907160484490852110513737706371952800195859569002260368104648272", + "block_hash": "0xa183203db3470c43734c2bbde7352897ae68aaaadd9f92b839856ec1e8ddddd1", + "transactions_root": "0x2927ab87994fc1873116cbea166142c4b3bcc530e41bff0e44d6078ba6ba7f53", + "withdrawals_root": "0xfe4499ade3f487c6d4cb554719e143205af2bd8934c45ab682cedeadd7e291a9", + "blob_gas_used": "7804808870165971659", + "excess_blob_gas": "1692362790995049994" + }, + "bls_to_execution_changes": [ + { + "message": { + "validator_index": "13271891873140421357", + "from_bls_pubkey": "0xee3dea2aa5c418f8a28f5dc089496a45e1562dd9d9c9b1a3512973c4bba153c453f7a95a319cc0a8fe9597eb56100869", + "to_execution_address": "0xD63a8180e006D6982F56F3b1FBb56F8a2780f542" + }, + "signature": "0xa7536c2eeea8e729d912f3e18089d99835aef171b4475a80640da39c9762b4e368d1a28d3be58fd3fffe07128427cda54e3fb49a14dcbaf8872f5c5962551169e2808d4dab13f4cb24ea5898ad458d9a0e9fcb0aa62b920673ef8f5bed1e2cdd" + }, + { + "message": { + "validator_index": "8134323075915558917", + "from_bls_pubkey": "0xc25f10a2c29625a1380906833958f970dd7057845acc66a8cf3e0a41c30590627fe49f018c56dbe7bb4f162945d1572a", + "to_execution_address": "0x0890aC603Ed9C81621582b572dD93d7787163F6F" + }, + "signature": "0x6b022064156dfb5bbd16604ad738e393d6325bb3a858b3c2842eeadbad17c20aa21732d852b60cadbed6d2075e71d1bf121fc2d44ab6339090ac956cd13d1b85c91fda1810781eefb161000c864e5bfeb418fd9834f775013317f42a4d672c0d" + }, + { + "message": { + "validator_index": "3107577600780709841", + "from_bls_pubkey": "0x8eb92a4a81e0e181ada5ca5233c129d617b33a927a9905961f589401f15fb033adcf07b6cc7b9e437c3da8a6d780a733", + "to_execution_address": "0x4ed112C38433Bad7468bb44D63a19A37438Aa91a" + }, + "signature": "0x2cb7af7fdf42c94a74469343202d02322e5cfec6e1a10fa1fb1a5e7b15381440ad4cfdeb2d279dac893d60240ab7fa9cb38edd1365e82478cd486565934b115219ad2fa2896d1521de41315b553b670413a38566dad96378372ca6ac9dbed663" + }, + { + "message": { + "validator_index": "14781239339496380599", + "from_bls_pubkey": "0x0912980bcc4d4918901c8a890a708bc679dabcc74fb56ac7cee52b799a4c8d213e27ab1381a217b466a2cbfe4582c370", + "to_execution_address": "0xF7c92429ED1B7ed976CadD13B377979425377b29" + }, + "signature": "0xfd83b3cf8407138d906be33f8b2843989af29c6582e81f1f5946349467a514c63bd7596cfc9852b4635bdbab88c6ac3971224e4a7133573c12a70ecc4992ee947f6d3acd65b1e9d3a6f247d3ca007bf1a9a13ea3ae88768616888a6057179ae7" + }, + { + "message": { + "validator_index": "8713875341123079950", + "from_bls_pubkey": "0x4de127fb4d3b8d561d4cb460a2ec93258e4f65bbda7262f51a192a04e2557f22e548f905b82f242abd2f58c78f51744c", + "to_execution_address": "0x7d1a9D4eb9EcDb98382cbC77589a8A1771F28aDC" + }, + "signature": "0xe5071692f702bb2d1fcac3cdbe647caaa4ebd1c51923b6661c1f077e4dd3a54b2f63cfe62eacd07d41cfdc3377616543901982cb992b5e306a16defaa4a314ed28efd9a17c47ddce4c3e21fc6036a6f303e3efa6ece0ab6255e7e204837492b9" + }, + { + "message": { + "validator_index": "17983333676732765429", + "from_bls_pubkey": "0xdfc5134438319a4cf12ba49a8267d26e8d88fb9b978af9644ad553e35bc58b5984a3554736d5a7eb87a4d4bfebb54807", + "to_execution_address": "0x2B992B2478F76E7fcB757433b81Ed0941117d2F1" + }, + "signature": "0x2d95660baba06c0d01605ac72ba146260be4a261f1c49faaed822f289435563c4e5a9e85d4eb5148e4b6175dd9b2a5fbb81d833e894a7c901cd04f85301d35ab60f35fca7f83606c49b7804b46481dc0b78ee56f21767e8eaf4c1c3884018033" + }, + { + "message": { + "validator_index": "13334092166848412086", + "from_bls_pubkey": "0xb8b85c60d4bee8207e7996f44464b1b8d879e1ccffbd54fe1e7c3cf003c7a016f06f4d2a7743bd4767339e39c9f80fbc", + "to_execution_address": "0x55738374E4B4b6CDD1894AA7f4578F9f34276C02" + }, + "signature": "0xb7c83a7cd390c771d4d86222f30c3f7c5591dba8f347817aee0c795ed6fb76cb27181f08c3e849ad7f960bfd8dc8253b4b1c8996f8bfbf46e5a6a2535321c47ac8719b25e3791e8e13d5dd304fa39f44a30f5e525958ad314b4f4229b4a85f18" + } + ], + "blob_kzg_commitments": [ + "0xc44f0e4f9c5383b0d1ad37df98e5b57388fc716f59a69e7af547d4c8f10cf08d4877beef9302a76e1972c71ee5f646c5", + "0xe3e3fa67b50da785f0eaf7b4032fdd3ab2866f716d059a653520f3b20e0af83c7c228f49b3642f352628ccd6091b2d5e", + "0x83ebc5d6235b6f321970575e64c639799666276522596309fbf206375c695363dc12d31463a6363df2fe12e5fed39e3a" + ] + } + }, + "blinded_blob_sidecars": [ + { + "block_root": "0x060b5160c3f59a89fe6f3335a1d65a8d1daed9dd9bf9590cdcf27f1a7e372d34", + "index": "13551148801075135127", + "slot": "5176501210487358590", + "block_parent_root": "0x52397f3b3f4b95795d3fd65ab9a164e0040cef446460dc5a51518234d3232eeb", + "proposer_index": "3685908771082952230", + "blob_root": "0xd09e9e159c882fb9c011cf1c1457840a3ad79d51cb0094d135208af1bee1cf6b", + "kzg_commitment": "0x9e3e4cfd36cd997206f43e7e93c26df743597b7e66131fb359a04913d466e0bdb188a175591d60c0348e4514a4f070db", + "kzg_proof": "0x99fddad0a4c75a12a74e4073fd879a32d570ae2078f26376424a5ceec9f1aa17136b9b5e3af7ffef57e2f428e4311242" + }, + { + "block_root": "0x35cc69a5e355f3a4d6707abe3ec170c094bf8f97994b858909ce9848a40acb3b", + "index": "2912666395471361773", + "slot": "16361972211573434924", + "block_parent_root": "0xc0da9ea49854ddc1d1f8f79e063cda326f40fe48b719d66e053c0dadd06aa0a8", + "proposer_index": "7479788126612800076", + "blob_root": "0x520b5e452260cacaef28ae8c961016c8005cceb349f1360d65728f69b6dc866a", + "kzg_commitment": "0x5a396dfdd9b42bc952266bdcd45b5dfd274bee6df9b80d14d49be9b1eed11a644c9079746a64e7e7d49372ce8f986499", + "kzg_proof": "0xfbb1a7b2889b2e6b4658246c369d7e10dd76a87a2d42ac00cf658acbf0cb0212e36eb004b5c6d9ae4a1e3a78fd4aa5ab" + }, + { + "block_root": "0xb39da2d7bc6c27921f4c03a37f0d3f6a2ffffb11c021f7864afff28d14f82720", + "index": "12985053176039870443", + "slot": "16840216710660859631", + "block_parent_root": "0x06cacfeac2582d9ed9767b284de988b46f91d699acb0fcf594c6f0dc44f942f5", + "proposer_index": "15374322768337860958", + "blob_root": "0x4a5f6817df5fd97e934cdd375aee69b71af412db155086d99bb5fe653d3605b5", + "kzg_commitment": "0x82b0231fbede4796e89056c20a603b6a8941d4542f45c4445e73fad0a74346969249b63fee8bcfc1de97991a3aaddee9", + "kzg_proof": "0x3e6fac126354ca0a19313ea67d7461278bcd50e04a3aaf167c304466e44423b6212076f445479bf06028b457730542ab" + }, + { + "block_root": "0x4ad648dd42b1d819183de92b48b2cec0a54de143537f0e85345401310c06f5eb", + "index": "1324371237554310650", + "slot": "12396161157840042757", + "block_parent_root": "0xe35411d6fa0b4ce3e9cde8717c9866d37077f35c342fd0777e656c0b9b7fa2ab", + "proposer_index": "11435354629673789914", + "blob_root": "0xab45b264ab23aadb6c802680a1dc41f42357b8822b91cb585427137fe9690aec", + "kzg_commitment": "0x72abcc3741037eed116c83a4c263b3e7e8a2c3618aa5f441585b1258aefe56669356a31f6ac137c1a3d897f52f28dfca", + "kzg_proof": "0xebf14520b08624a76437289a313c039e42158de4de42d8b290f3b710c81059cb8c68cfbfdc39ef9ba4e34139e23b92b2" + }, + { + "block_root": "0xe2c1ead85ce1028a086afb4cb76d3e31fedbbff5d251670e60fe24a74a082c4f", + "index": "17392238294138790127", + "slot": "3516116307684979799", + "block_parent_root": "0x3c2040e1e3916557c5bd249a4f810244331be2bb6da29dbef2714ab6f2d7f12c", + "proposer_index": "16555934733643429508", + "blob_root": "0xcb2ba4289a58833f88f4c5aff4a9dda558f8cab0984f3e78916b973d46abbc09", + "kzg_commitment": "0xaf09e0ee0cd7bb261f1b64680dd04db23ca27e5b29750dbe7d431bb368758de46d9fb949cebbf0f8bed73403ee66aee5", + "kzg_proof": "0xf52ad119944e238969181da4b82769e8e3a9d030a77de7fbe20d694b3d84be4b1b3565cd6b77fc0c0e5e435eed110d33" + }, + { + "block_root": "0xc183babaa9e141a8a12a572469593c584a0b5ac291449d1e0ab66574f03c990d", + "index": "6401616817158288579", + "slot": "11902500773654027678", + "block_parent_root": "0x41f1753e912c2a598a5bf10a642b33b2cf50fd8cb0006d2ea3bc2320d7047840", + "proposer_index": "6233892351201403047", + "blob_root": "0xac49c6f0864d3c1465f14a3b17b0dc3d7a41def87c29797adbed4fede92b9fb9", + "kzg_commitment": "0x0aa47a96feb3f1925543dce49772b539d076b9596763a82a6cce5d766da35d12b9573cdf1072127cf6e666e5a9696d12", + "kzg_proof": "0x170d4dbf2a4b1badae0b1ac754ada7880fabaa863c076e75d5f2c0abb545b2b2af759dca0ad09e31e7c3d3140e410953" + } + ] + } +} \ No newline at end of file diff --git a/core/testdata/TestJSONSerialisation_VersionedProposal.json.golden b/core/testdata/TestJSONSerialisation_VersionedProposal.json.golden new file mode 100644 index 000000000..511245a4e --- /dev/null +++ b/core/testdata/TestJSONSerialisation_VersionedProposal.json.golden @@ -0,0 +1,390 @@ +{ + "version": 1, + "block": { + "slot": "17349330445822630798", + "proposer_index": "8074401586156473090", + "parent_root": "0x58485fe3352bc5b52456f0eff11f99ef25258727c8b2922e22f5563d39490544", + "state_root": "0xd5ce92f83e0212d3077d0549b01b83b78e64fc147e5086ae7c1ac5bbb6496af6", + "body": { + "randao_reveal": "0x41b0d88158d69078e3e244ee141c7cfe1c0ef0c2f60c29616c2f6b3a805e91ebdedc8fef611e1d079aa67a620d157145bb08f5197bb91ffb894a8e40f9a837cbbccd54915ca94d509daa426fe2a33e1b669111cc4ff4fcc5071606dc666e998b", + "eth1_data": { + "deposit_root": "0x4684152c509ad47e009399b5de04763e89ef5dd57558ad80535cb99835d61d2c", + "deposit_count": "13287431414550680410", + "block_hash": "0xe55a20f1b9f97d046296124621928739a86671cc180152b953e3bf9d19f825c3" + }, + "graffiti": "0x33b6c8161d12ff1a9536e5ecfdb4c49a3f8cff429c026a404df8b9f7305d8a82", + "proposer_slashings": [ + { + "signed_header_1": { + "message": { + "slot": "6780535510690741162", + "proposer_index": "16607599382022173126", + "parent_root": "0x350874452a54bc1d4d3021afb9a99adb32f0e7586d114eb003386bd4374680a2", + "state_root": "0x339b0c6346397fb2b009b6e25cac5585194df25566526b33a35cf21ddee3c8c4", + "body_root": "0xb739392c2fece974118d4545f4e49351149d26057e1c0d47dd244fee3a221576" + }, + "signature": "0x1e1e9867ae25640f4e158921c54009b7b78713ebabe0e6f188aab1968170cf910311c84e1469a0aa9696c7c6a5507bcb0400cf695e3ebc1b8668a081e3435809b8c533f091d705d311b8c04616fd3311b1432a23c580babee4bf1d30b37bc369" + }, + "signed_header_2": { + "message": { + "slot": "12993825739415368931", + "proposer_index": "8399745755142253118", + "parent_root": "0x882638a71ed14533c08aaccd646143da1e8000d198fd846c054325f5d00793ee", + "state_root": "0xcebcca54f905dc0272ef398c9b6d6c0a7630fbac34a583e6df09b94b6231dfc1", + "body_root": "0x58e4b24d9b0d4797c7655fb2f3e8e5298a7652a5de720c5d66f2849ea78c8ad5" + }, + "signature": "0x592e40f342c6c2309e7407bd527b730b4ce65e8bd76a154117c86ea9dc2c24825700c8b87f790008c8a2a80ea7323c2d5ee36c6cf90cc0f2ae3ecaa28eca5ec131c34a130cb37ead9808dc6993178bd5cbc43530be0a8e2cedb849a173c20aaa" + } + }, + { + "signed_header_1": { + "message": { + "slot": "10581321243860334266", + "proposer_index": "10024700929387484380", + "parent_root": "0x51b895e36d5ba7db3a85cb282b7ca372df9fffa1eeeeb02e34fe0e0d24efb617", + "state_root": "0x4844b04429c044040b15d79a3e1e9e541a42185bc8b2628ca6d4747fd4e4f512", + "body_root": "0xcbfaf4668785b2158fae65bb08414e047bcc8b29189e6a0ca3ce2367ba7ea8e7" + }, + "signature": "0xfb123df52d39f64b9b1dc35cad8362ca399b0d4efdda8589460ae2908f7ffd620e0ddc2b33d99e1fa7639f38afa1e116883d1864093ee04ba975d1ea9ae4d3b7e5ed17dd3a184918b27ec848b6ad81bb1d3297d37b0d3728bcbb7f909f554493" + }, + "signed_header_2": { + "message": { + "slot": "11410051291753586811", + "proposer_index": "5596893357392887284", + "parent_root": "0x58829c9e0882885c981f02db4705ea8b6691c12124ddd52340e5003189c932a9", + "state_root": "0x29278514e80b9b6cbee11e26d13dc172d172629a42f964e3a6794d6adc86b4d9", + "body_root": "0xb3a8aeb8ac7c41082843b5cc7afa207e98c4b4220491850dfb5821c02e106d10" + }, + "signature": "0x3f2d29f2422b7c49397e5a37e9768383e919971dd4ca7c414471dbfe0d91c0cb8675fdc13ffe620e9ad48f2d8526a0e8d1c5b4208ff61fab6fbe3ae850840d75e1765c58410116e331c184c4ba0e95905ecc721b6a55d5963c3b3a1421541020" + } + }, + { + "signed_header_1": { + "message": { + "slot": "2979521766664979057", + "proposer_index": "5238433353762349723", + "parent_root": "0x5144d8ca5b8f7241f0e83732c7ef860072ca49e2522cbaee0a91bf1b4eb63c54", + "state_root": "0xa441e4123d9037001e57b022d79e029b89af3324cb30205bed2e858024bd8574", + "body_root": "0x8ee0c8c664893564e83d9d65d83f5db43a5364ec8f529cc878e0204090bb2faa" + }, + "signature": "0x15accb260a31d335f4244286d47e9209a45d0953a8c5fa6d85e595ddbc29ebfa64884aedb91a8f8c7401f2e1a35b4c8b55f514e515573e343c1b54b4c7fde86f7566949c2118dbe9851331553f33951cde55c3ec1f28c8b7e8e168b30efd7e83" + }, + "signed_header_2": { + "message": { + "slot": "13956538955870391910", + "proposer_index": "1300064203005031115", + "parent_root": "0x457db4844c8c06c2e5ea47921a75b4a4027e1faa672aa0bf3d9be2052e734ea5", + "state_root": "0x6cba3d3cc587a190b25ebc066375328e6838c9a0cecc6707ef392444c8a2e90b", + "body_root": "0x7f301e9b266200d604471e9b8a202ce3654b1dd7cb3473b7a6bb5bc525a68e7e" + }, + "signature": "0xa66f6932907d1c4c2774359b58f34a5e89d46698929f54126cef5ff40f1d1639412f7e3357cf8f82d2e930275cbf8596b36f928299b018e7541e19f786d44febfcc787cb95b0345867072446077f2d51ddc0c3ca9bc2516389deddd45f5616a7" + } + }, + { + "signed_header_1": { + "message": { + "slot": "802412281975905355", + "proposer_index": "782033051431750926", + "parent_root": "0xf6d57954afda2357417db672814e200222da05eea9c54abc6176aed03b0904bc", + "state_root": "0x962e02929169cdbbda6ad567b600aa9c4bd4eeb9d660bb8ea6856a6aaa239c0f", + "body_root": "0xc1058f13fcc9e17be4e67054a9336a604131cca9faf647ed0e3beeb0a87b08bc" + }, + "signature": "0x885de87b4b9e31608072fa33a208b90f73bbce5550285172a784dad0099baaad5c3d17a54adfb25b87e50eec16e9dee30d69d03e54847854696d2673651989c97e9d0a604dcc5f89ff80450befab4ca92dd15dc6a5308420437188ec536780bb" + }, + "signed_header_2": { + "message": { + "slot": "9763299576071061436", + "proposer_index": "45051465304353432", + "parent_root": "0x05e9c2b6f350b8cb360540c6aa7a6d1582d8123484b27b93e9935c55b5c59e99", + "state_root": "0x076f17dafcd2cb9a370655cb0c51bf8fe48fa1e680775b4c32b0f26659004ee9", + "body_root": "0xe48ca6c79384e3040c5955e4f6d73d09ce0a17decafede513785156ae4180b8b" + }, + "signature": "0x564acc2b6620571d63a1a6f91c319cd35c359b92b35bfdf69f56977da7fdca3ef3e839c80d4d2f09a561a9ddbe83ca8ca44ab8c4848e24f9acb772f6636f9ba28effb18798501e9bda3750ca1537cded9dc22141b7f95bd7e9328186c32a47e1" + } + } + ], + "attester_slashings": [ + { + "attestation_1": { + "attesting_indices": [ + "10985726462708897116", + "9090217406723760665", + "9745637931394224490", + "2185179768523360661", + "4458469894625095452", + "6919702395368883948", + "340704914424421193", + "2665211441269146508", + "4886254011554517856" + ], + "data": { + "slot": "17850498829834082508", + "index": "17369082968550693531", + "beacon_block_root": "0xd70a55d1b3e27df171123112bf72db7e7f8f3b5682dee29a0bae040d7c2a0429", + "source": { + "epoch": "12680851386635505660", + "root": "0xe4bd6e3fbad192376a08fb61008709b748e5462299fe6f2fe924e5480d8a5b56" + }, + "target": { + "epoch": "9020433416363390699", + "root": "0x6d8dc277f226d628a4af482466be2887e1ce4e1f15a3df9a50dfdf0aad66356f" + } + }, + "signature": "0x384bba33e90fbb22744fc13ba6ac860d1519a7a86f58b96cab740a9d8c04248832e88ad3dd6020de04a20cd501b4179337cd28b03081a1af822dcc42826e9e7d604a70436bf346f41af56d074f83a678da2c064d3bda45a3ceb020e9c679b650" + }, + "attestation_2": { + "attesting_indices": [ + "17646366028153061038", + "17059437906291941977", + "14629387757261623769", + "4129297000219453959", + "17125302590574926272" + ], + "data": { + "slot": "11444563674620748872", + "index": "3943479379404086409", + "beacon_block_root": "0xc4aaade6b763595166f6f936a8f9d358de49327d1ee015b0873f9e88e2536339", + "source": { + "epoch": "52848104741666208", + "root": "0x66a15c1ff90e9e8bc511bbaf875f4584c48cd8cc3b6379ce410b80d0623ddcc4" + }, + "target": { + "epoch": "8451623720647829777", + "root": "0xa2589bf00f6e6fcbe412d979710153b8d0a44193998becd21ec14c2de627fce2" + } + }, + "signature": "0x3d940634599994f865b7e6d6e16b193b8297c4e67306529a75b2e8c9d87fb7eb7e75da27963ce551bf5fbb52edffb17e8d40f5f1ddb8616742c55dbd129bf5ef31c1f0fc89998c7784c3a856c2f18439439156ad659a686b721c1b43847ba740" + } + }, + { + "attestation_1": { + "attesting_indices": [ + "6203509991785250549", + "17381309654792563731", + "1349123735924250120", + "14460633572948452098", + "8139615953377492328", + "10099062824871578085", + "4182356959655988111", + "3738030542312945163", + "17051214809166969541", + "10283532359812735730" + ], + "data": { + "slot": "8037362921961820144", + "index": "2463260812663936267", + "beacon_block_root": "0xc998c09b4fff6e5296d56d713ca1eda9b1936a3dcba59afc963d54eb1a6c9655", + "source": { + "epoch": "12754802711912560656", + "root": "0xfc508058ea683b27bae3820f26836f309ca62af8b7fb40d560dd1c0595cedd6c" + }, + "target": { + "epoch": "8694837412482609977", + "root": "0x4090219448d5a5f33038ed4bee728f8e233466f219ba2218834d08d68a0d5f9a" + } + }, + "signature": "0x9cdcf69af8471a22c6c3a3f384d57a485197ce701f3b8a0bb4c0e51e0541417e18e78e803a43d1ccc0306a512561cef204452a9ce2d329663651acbe6d513732cfd25398b5c86626c045f6c0c13ba449672c88e0a34f7683289a71a77d696711" + }, + "attestation_2": { + "attesting_indices": [ + "7902318293386549475", + "16473096689142984787", + "8799779438657164873", + "6903872279116567885" + ], + "data": { + "slot": "11233842088652857718", + "index": "9055690742167872646", + "beacon_block_root": "0xb576f8fcaf1840b4c337464cfe4cdaf42a5f2ee239a0008d6fdb735e04f5f959", + "source": { + "epoch": "15947581858346258691", + "root": "0x125ab837715e0f792830559dee22de822723a7e649af0fb0b9c80b895a8b09f9" + }, + "target": { + "epoch": "4582101064152478550", + "root": "0x6255cf591f6b740b6d315f28c0dc7a3e6b4c334ad4e7cd3d66d9693abfdebd60" + } + }, + "signature": "0xe36db7256e36ea41eee5ea2d2b4c0d73657d0cbffc146454b1fb6c1aee38d0da4a2c408da0df342469fbc2c3eabab57c9af205ede15a6eb8997e1d9204a950ca94a639ea55065b305d2ba296fcc516a2e42b1257447440decaffccfd178744d6" + } + } + ], + "attestations": [ + { + "aggregation_bits": "0xedc13e01", + "data": { + "slot": "7605529528772959946", + "index": "14792864815017753474", + "beacon_block_root": "0x456c09bfeb150d2f3ae3d6ad9ca03333815c146b3b4e8da358d0624ae7b9767a", + "source": { + "epoch": "12118604427295964994", + "root": "0xbe0889985ca83218baa491fc7cabe299d21acabcd999e40cf9f03ad3ac87b5d2" + }, + "target": { + "epoch": "3132211364807776122", + "root": "0x4f00e8554b71b25fb1185294fbba8f038188d4abcf3aeeccfecf59746bfc36e2" + } + }, + "signature": "0xec6e73cfc7366f6bbbd14ad57ebe6fe25984aa092612a4e294a8a0e22d7b68bc9d443c285e5fa721d82af67a7be12f5e364b0789ac03bbfbbffb445ff6d7e22390d1e850f1c8d55cbe508c4005fd16fc7e39a3b7025037a51c3b4d4ec0581c25" + }, + { + "aggregation_bits": "0x907e01", + "data": { + "slot": "1753792947537854958", + "index": "9440316455640439005", + "beacon_block_root": "0x3165a38257fdf769894367a695ee086c88010051d03ab44177a202c0aaf79c7a", + "source": { + "epoch": "17782503248307150002", + "root": "0x1c5e8c4e287709b0361590ac2150be31210b8c747a5561a744737a221654018d" + }, + "target": { + "epoch": "3290511233569349806", + "root": "0xcca2f1df17e06d4c076de790c21379506cb645b65d4973996fff0ca2cc5a54bd" + } + }, + "signature": "0xd8e509e5cab366e06342cd3432b8ed0b62e13a694575ae5d81fa489f892a0a03fd22d44fc9c14bb56fb79cfa85c012882fc0233645db9a35dc33a57b4a4e8a757d9bbcca7e1471a9fd0088292202ca114b3b25d14705cddac76246533000b9df" + }, + { + "aggregation_bits": "0xccc36fe801", + "data": { + "slot": "12552616818195825061", + "index": "6320353536277574328", + "beacon_block_root": "0x0761d0b69aa488e97953dd9b385c2a13438b4812adafcfb08c50eb8a36b62937", + "source": { + "epoch": "3149837539201356482", + "root": "0xbef5a9e15c44712c6a7ebf76b7659d352841b90e5458dc6b2f5b135af4c6f731" + }, + "target": { + "epoch": "15362170910970887257", + "root": "0x4e8bba6dce9879bf63ca8b80f8c8528029e9f53550cabea82291dd6b78e30fa9" + } + }, + "signature": "0xadf219389e1efbf090522ad32f171dc8afd795463f50fb94e063003c47419b045f095b447f6b80ecb035340bc9120ebc43e89e8d98ecf0562129f2c6e05279134c83cb296c429e62f5e8c92c02ee7df710e36daa539372b5537d53657f388ab0" + }, + { + "aggregation_bits": "0xb401", + "data": { + "slot": "2253366054252224250", + "index": "18398926093379230172", + "beacon_block_root": "0x0cbd72df4d6d4aa0fb91f25151fb18c4b9a43c5da36a8acb24cfb4bb8d46c392", + "source": { + "epoch": "8651185050269298580", + "root": "0x6361d1d599a4bb031882ebf7655df962e5b3c8ecba9b491f56e09cf911bfaf75" + }, + "target": { + "epoch": "3505041900108669442", + "root": "0x5ccca88d83b7c28070309b5914891eaf01d4ec1df010009f4bbff9899ab7f13b" + } + }, + "signature": "0x114da6dbe1d50089850f18c31abfdf8b5131a019be3d9811557adfe6bdf694eb98a78ac5b59fcf23bf99b41ebb07a9b7ee31410672b391b680d5ba263729a9828477d0ac455f1ecea06e13631fcea403e3c0b8dd234bdbe919b678436bb0334c" + }, + { + "aggregation_bits": "0x17d3376001", + "data": { + "slot": "18410850637689924782", + "index": "10923495236629280823", + "beacon_block_root": "0x0b19f9676489e18f0a70eb4d02e868734cdd35e9c3de84bbf676064f50955f90", + "source": { + "epoch": "15925560305157684129", + "root": "0xc8920b34944e2127805da77d18e91d9070e0668ad836cc59f9097a5f1505ea29" + }, + "target": { + "epoch": "4497864744237184373", + "root": "0x87994fc1873116cbea166142c4b3bcc530e41bff0e44d6078ba6ba7f53b56df9" + } + }, + "signature": "0xade3f487c6d4cb554719e143205af2bd8934c45ab682cedeadd7e291a9cb0ac4b1eddf97b0d5fc80e674d8f5676a4e33b6b1542ee726553fa37a7dccb5257c5857f22c3946aa7f548ba5c5ea7a3c0a7c577fecd63a8180e006d6982f56f3b1fb" + }, + { + "aggregation_bits": "0xef2b7839fa4ba701", + "data": { + "slot": "11930106248502623580", + "index": "1146104732878192601", + "beacon_block_root": "0xa8e729d912f3e18089d99835aef171b4475a80640da39c9762b4e368d1a28d3b", + "source": { + "epoch": "567673343019894546", + "root": "0xd3fffe07128427cda54e3fb49a14dcbaf8872f5c5962551169e2808d4dab13f4" + }, + "target": { + "epoch": "3985316009908312986", + "root": "0xea5898ad458d9a0e9fcb0aa62b920673ef8f5bed1e2cddc8052ad28df44aec48" + } + }, + "signature": "0xa1380906833958f970dd7057845acc66a8cf3e0a41c30590627fe49f018c56dbe7bb4f162945d1572addff11f9b9fec086283d0d4064fac322a886c0895f6b022064156dfb5bbd16604ad738e393d6325bb3a858b3c2842eeadbad17c20aa217" + }, + { + "aggregation_bits": "0x98daecf0e4e1a5df6701", + "data": { + "slot": "7381140906611249873", + "index": "16785298023986648767", + "beacon_block_root": "0x3e0e886f8336fbe079ec2f0211c9b5e9bdab3d5a0fe59f427d997a2d7070d16c", + "source": { + "epoch": "11536039782213876248", + "root": "0xc50b587dd99a70e1259cf42fbe1b5c828eb92a4a81e0e181ada5ca5233c129d6" + }, + "target": { + "epoch": "800558913110272106", + "root": "0x3a927a9905961f589401f15fb033adcf07b6cc7b9e437c3da8a6d780a733d12c" + } + }, + "signature": "0x12c38433bad7468bb44d63a19a37438aa91aff26a6095fd4bf7bc3e3e0adf2ec4559444c7ec222845ff1f368a949896467da1ecb3e398a0523da6a6667f212dbb5fe6b7aaf76cfb1830fdf0d6070818a135c9be461ac61471e946d29e9eba396" + }, + { + "aggregation_bits": "0x0413a38566dad901", + "data": { + "slot": "18284001478007214308", + "index": "8068393586369952512", + "beacon_block_root": "0xa6ac9dbed66311b73eac869e51c510c626243528bde878688cfa4ee30c7c83f3", + "source": { + "epoch": "13503384754651086", + "root": "0x8399f5b25d65bddfca4b32796a28c76e7441bbd781fa41f7c92429ed1b7ed976" + }, + "target": { + "epoch": "2306325466273496399", + "root": "0x13b377979425377b29e5c1e37111ddbc2f87293d39f9704c87bd7e9a724a1a68" + } + }, + "signature": "0x1f5946349467a514c63bd7596cfc9852b4635bdbab88c6ac3971224e4a7133573c12a70ecc4992ee947f6d3acd65b1e9d3a6f247d3ca007bf1a9a13ea3ae88768616888a6057179ae7120e986aafd101fff4096c44ab1de89257282d1224e413" + }, + { + "aggregation_bits": "0x6201", + "data": { + "slot": "9773892123787019933", + "index": "9895056102592017993", + "beacon_block_root": "0x04e2557f22e548f905b82f242abd2f58c78f51744c9032776e9cdde6705f8806", + "source": { + "epoch": "2970808160491432311", + "root": "0x13c2f07d1ecc0cefe5071692f702bb2d1fcac3cdbe647caaa4ebd1c51923b666" + }, + "target": { + "epoch": "8521800176568952458", + "root": "0x077e4dd3a54b2f63cfe62eacd07d41cfdc3377616543901982cb992b5e306a16" + } + }, + "signature": "0x0e50ca59967cb82ca8f968c64d124c537c4281dc1e8b64fbb1899d48c756f656371a9cc3fa94b2e5dfc5134438319a4cf12ba49a8267d26e8d88fb9b978af9644ad553e35bc58b5984a3554736d5a7eb87a4d4bfebb54807fcc72eb003682385" + } + ], + "deposits": [], + "voluntary_exits": [ + { + "message": { + "epoch": "14912977979618651700", + "validator_index": "2464686655331317131" + }, + "signature": "0xb81ed0941117d2f18bb651384a4a542ed4f04f87b51ff8390fcafb0c6f26f18e3a7098b6da995c472bfb2666765e19af20b93f9b4f0d81580f350539553826be4d6d7ee19772b45ee1a7c07d4a74e4463826a3b836d7c18315bffa9c9facdfaf" + }, + { + "message": { + "epoch": "16380023606986876167", + "validator_index": "4991263050210217235" + }, + "signature": "0x3884018033beb6461e66da55e13b913e23ff04c13c3cefc5d05d1199c155dddedf547bbc44cbe0c1122fe3dee071be67cb424d105cf3ba1255738374e4b4b6cdd1894aa7f4578f9f34276c02935a5ff54da50bea2d62881ccec66ee79ca04e88" + } + ], + "sync_aggregate": { + "sync_committee_bits": "0xffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "sync_committee_signature": "0xd6fb76cb27181f08c3e849ad7f960bfd8dc8253b4b1c8996f8bfbf46e5a6a2535321c47ac8719b25e3791e8e13d5dd304fa39f44a30f5e525958ad314b4f4229b4a85f1809563a45b5852a14b619a9ef6f170cfb113cc20f1da233784cd73c11" + } + } + } +} \ No newline at end of file diff --git a/core/testdata/TestJSONSerialisation_VersionedSignedBlindedProposal.json.golden b/core/testdata/TestJSONSerialisation_VersionedSignedBlindedProposal.json.golden new file mode 100644 index 000000000..499d3d2fb --- /dev/null +++ b/core/testdata/TestJSONSerialisation_VersionedSignedBlindedProposal.json.golden @@ -0,0 +1,467 @@ +{ + "version": 4, + "block": { + "signed_blinded_block": { + "message": { + "slot": "8074401586156473090", + "proposer_index": "12669649448940181106", + "parent_root": "0x485fe3352bc5b52456f0eff11f99ef25258727c8b2922e22f5563d39490544d0", + "state_root": "0xce92f83e0212d3077d0549b01b83b78e64fc147e5086ae7c1ac5bbb6496af670", + "body": { + "randao_reveal": "0xb0d88158d69078e3e244ee141c7cfe1c0ef0c2f60c29616c2f6b3a805e91ebdedc8fef611e1d079aa67a620d157145bb08f5197bb91ffb894a8e40f9a837cbbccd54915ca94d509daa426fe2a33e1b669111cc4ff4fcc5071606dc666e998b59", + "eth1_data": { + "deposit_root": "0x84152c509ad47e009399b5de04763e89ef5dd57558ad80535cb99835d61d2c5a", + "deposit_count": "8303874249530489053", + "block_hash": "0xc35dd93515cefe0b002cee5e71c47935e281ebfc4b8b652b69ccb092e55a20f1" + }, + "graffiti": "0xc6f733b6c8161d12ff1a9536e5ecfdb4c49a3f8cff429c026a404df8b9f7305d", + "proposer_slashings": [ + { + "signed_header_1": { + "message": { + "slot": "4002884295865133464", + "proposer_index": "10401092129559668577", + "parent_root": "0xa5a1350874452a54bc1d4d3021afb9a99adb32f0e7586d114eb003386bd43746", + "state_root": "0xddf2339b0c6346397fb2b009b6e25cac5585194df25566526b33a35cf21ddee3", + "body_root": "0xa216b739392c2fece974118d4545f4e49351149d26057e1c0d47dd244fee3a22" + }, + "signature": "0x8bc71e1e9867ae25640f4e158921c54009b7b78713ebabe0e6f188aab1968170cf910311c84e1469a0aa9696c7c6a5507bcb0400cf695e3ebc1b8668a081e3435809b8c533f091d705d311b8c04616fd3311b1432a23c580babee4bf1d30b37b" + }, + "signed_header_2": { + "message": { + "slot": "2963419752847912041", + "proposer_index": "4283313901335272943", + "parent_root": "0x42ba882638a71ed14533c08aaccd646143da1e8000d198fd846c054325f5d007", + "state_root": "0xceeecebcca54f905dc0272ef398c9b6d6c0a7630fbac34a583e6df09b94b6231", + "body_root": "0x5ac158e4b24d9b0d4797c7655fb2f3e8e5298a7652a5de720c5d66f2849ea78c" + }, + "signature": "0x2fd3592e40f342c6c2309e7407bd527b730b4ce65e8bd76a154117c86ea9dc2c24825700c8b87f790008c8a2a80ea7323c2d5ee36c6cf90cc0f2ae3ecaa28eca5ec131c34a130cb37ead9808dc6993178bd5cbc43530be0a8e2cedb849a173c2" + } + }, + { + "signed_header_1": { + "message": { + "slot": "12514005461132338934", + "proposer_index": "11339736146871302061", + "parent_root": "0x61a451b895e36d5ba7db3a85cb282b7ca372df9fffa1eeeeb02e34fe0e0d24ef", + "state_root": "0x2ad74844b04429c044040b15d79a3e1e9e541a42185bc8b2628ca6d4747fd4e4", + "body_root": "0xbe64cbfaf4668785b2158fae65bb08414e047bcc8b29189e6a0ca3ce2367ba7e" + }, + "signature": "0x61acfb123df52d39f64b9b1dc35cad8362ca399b0d4efdda8589460ae2908f7ffd620e0ddc2b33d99e1fa7639f38afa1e116883d1864093ee04ba975d1ea9ae4d3b7e5ed17dd3a184918b27ec848b6ad81bb1d3297d37b0d3728bcbb7f909f55" + }, + "signed_header_2": { + "message": { + "slot": "14478679172016965523", + "proposer_index": "4949088424957339860", + "parent_root": "0xda7258829c9e0882885c981f02db4705ea8b6691c12124ddd52340e5003189c9", + "state_root": "0x3a3029278514e80b9b6cbee11e26d13dc172d172629a42f964e3a6794d6adc86", + "body_root": "0x1e4cb3a8aeb8ac7c41082843b5cc7afa207e98c4b4220491850dfb5821c02e10" + }, + "signature": "0x55933f2d29f2422b7c49397e5a37e9768383e919971dd4ca7c414471dbfe0d91c0cb8675fdc13ffe620e9ad48f2d8526a0e8d1c5b4208ff61fab6fbe3ae850840d75e1765c58410116e331c184c4ba0e95905ecc721b6a55d5963c3b3a142154" + } + }, + { + "signed_header_1": { + "message": { + "slot": "14978695424185213637", + "proposer_index": "15657162861418879273", + "parent_root": "0x617f5144d8ca5b8f7241f0e83732c7ef860072ca49e2522cbaee0a91bf1b4eb6", + "state_root": "0xf415a441e4123d9037001e57b022d79e029b89af3324cb30205bed2e858024bd", + "body_root": "0x0be98ee0c8c664893564e83d9d65d83f5db43a5364ec8f529cc878e0204090bb" + }, + "signature": "0xa3d015accb260a31d335f4244286d47e9209a45d0953a8c5fa6d85e595ddbc29ebfa64884aedb91a8f8c7401f2e1a35b4c8b55f514e515573e343c1b54b4c7fde86f7566949c2118dbe9851331553f33951cde55c3ec1f28c8b7e8e168b30efd" + }, + "signed_header_2": { + "message": { + "slot": "3356883683953708419", + "proposer_index": "11054301287111598102", + "parent_root": "0x81d9457db4844c8c06c2e5ea47921a75b4a4027e1faa672aa0bf3d9be2052e73", + "state_root": "0x64b16cba3d3cc587a190b25ebc066375328e6838c9a0cecc6707ef392444c8a2", + "body_root": "0xe9987f301e9b266200d604471e9b8a202ce3654b1dd7cb3473b7a6bb5bc525a6" + }, + "signature": "0x4669a66f6932907d1c4c2774359b58f34a5e89d46698929f54126cef5ff40f1d1639412f7e3357cf8f82d2e930275cbf8596b36f928299b018e7541e19f786d44febfcc787cb95b0345867072446077f2d51ddc0c3ca9bc2516389deddd45f56" + } + }, + { + "signed_header_1": { + "message": { + "slot": "4787081931091397057", + "proposer_index": "10811382614581199756", + "parent_root": "0xea90f6d57954afda2357417db672814e200222da05eea9c54abc6176aed03b09", + "state_root": "0xd63d962e02929169cdbbda6ad567b600aa9c4bd4eeb9d660bb8ea6856a6aaa23", + "body_root": "0x3725c1058f13fcc9e17be4e67054a9336a604131cca9faf647ed0e3beeb0a87b" + }, + "signature": "0xd8ee885de87b4b9e31608072fa33a208b90f73bbce5550285172a784dad0099baaad5c3d17a54adfb25b87e50eec16e9dee30d69d03e54847854696d2673651989c97e9d0a604dcc5f89ff80450befab4ca92dd15dc6a5308420437188ec5367" + }, + "signed_header_2": { + "message": { + "slot": "8108327346961970619", + "proposer_index": "8895882612123814663", + "parent_root": "0x112605e9c2b6f350b8cb360540c6aa7a6d1582d8123484b27b93e9935c55b5c5", + "state_root": "0x5aa0076f17dafcd2cb9a370655cb0c51bf8fe48fa1e680775b4c32b0f2665900", + "body_root": "0xeda1e48ca6c79384e3040c5955e4f6d73d09ce0a17decafede513785156ae418" + }, + "signature": "0x87ea564acc2b6620571d63a1a6f91c319cd35c359b92b35bfdf69f56977da7fdca3ef3e839c80d4d2f09a561a9ddbe83ca8ca44ab8c4848e24f9acb772f6636f9ba28effb18798501e9bda3750ca1537cded9dc22141b7f95bd7e9328186c32a" + } + }, + { + "signed_header_1": { + "message": { + "slot": "12241430169457960610", + "proposer_index": "15489455263612697224", + "parent_root": "0x095c196a951cec498c601cef9cd70a55d1b3e27df171123112bf72db7e7f8f3b", + "state_root": "0xa443635e908601f729697dc5a2fc15fc2edf2a1eb3bc3b18a9fb8499527a17ab", + "body_root": "0x462299fe6f2fe924e5480d8a5b56664e6d8dc277f226d628a4af482466be2887" + }, + "signature": "0x67ec5bee090fbbb94330b6f3f313ae58384bba33e90fbb22744fc13ba6ac860d1519a7a86f58b96cab740a9d8c04248832e88ad3dd6020de04a20cd501b4179337cd28b03081a1af822dcc42826e9e7d604a70436bf346f41af56d074f83a678" + }, + "signed_header_2": { + "message": { + "slot": "14339611822790892076", + "proposer_index": "15504947264660018950", + "parent_root": "0x89ff2c15e503d9fba4956835bec5ae59d907c0069a6dc4aaade6b763595166f6", + "state_root": "0x0515bf0489cb195e088b19625d2c0e1353c8de4cbb15a0b8e2b51fb136b826e8", + "body_root": "0x11bbaf875f4584c48cd8cc3b6379ce410b80d0623ddcc4fe7ea2589bf00f6e6f" + }, + "signature": "0x4237376ad640ec0c588613e966e51d615c341fd9ddfea1baac3d940634599994f865b7e6d6e16b193b8297c4e67306529a75b2e8c9d87fb7eb7e75da27963ce551bf5fbb52edffb17e8d40f5f1ddb8616742c55dbd129bf5ef31c1f0fc89998c" + } + }, + { + "signed_header_1": { + "message": { + "slot": "13955344097399898630", + "proposer_index": "16177985131740430920", + "parent_root": "0x56c2f18439439156ad659a686b721c1b43847ba740efcef513080268e58f0bc5", + "state_root": "0x08f00b6ac8454d837de85c6411f3be5e7083a96681bc52c168d17e1acd1b98a9", + "body_root": "0x6c96557d90fc508058ea683b27bae3820f26836f309ca62af8b7fb40d560dd1c" + }, + "signature": "0x9d8c69f73839e8593b3a8cc4310ea512c67fdb1d9211c522ba59eefd794baf5cd4e8e9e93f1cb49cdcf69af8471a22c6c3a3f384d57a485197ce701f3b8a0bb4c0e51e0541417e18e78e803a43d1ccc0306a512561cef204452a9ce2d3296636" + }, + "signed_header_2": { + "message": { + "slot": "17133548747787937708", + "proposer_index": "15930321481495902910", + "parent_root": "0x26b689b8ae9e662c22d2682500e4536b8173ad8b3da35be0fa3f40196118cd16", + "state_root": "0x696711769e29c64223768621fb3acfcb6d69daa33f3fe563247757fcb41dde97", + "body_root": "0xa0008d6fdb735e04f5f9593471125ab837715e0f792830559dee22de822723a7" + }, + "signature": "0xddaea62491af02619aed92853956690a235a2f9c1554affb49655cba6cf6d52014a3a62e38e24d317c7bb657ba2fc5e36db7256e36ea41eee5ea2d2b4c0d73657d0cbffc146454b1fb6c1aee38d0da4a2c408da0df342469fbc2c3eabab57c9a" + } + } + ], + "attester_slashings": [ + { + "attestation_1": { + "attesting_indices": [ + "893066331788262369" + ], + "data": { + "slot": "15247804440919432904", + "index": "1403889905033743889", + "beacon_block_root": "0x997e1d9204a950ca94a639ea55065b305d2ba296fcc516a2e42b1257447440de", + "source": { + "epoch": "7940837671565932034", + "root": "0xccfd178744d66b23d98ff44163f35cbfab30b1229da6cab1789f1afcad3457fe" + }, + "target": { + "epoch": "847787583585081175", + "root": "0xd81f4bdb586f39cf74fbe3d9c7c2b4a7558997b1e31ddaf8af8cd5b37e30d518" + } + }, + "signature": "0xa8d3d1a5e82d3bec42d185a2b05300d2979ff55f0d442af0739b59cc10762d875302ec21019093302e7093ed0a2c5be690d6279ec70546d63cab7ac75c830e0b6152d70fc73ee68806af8e43861046939009b0694c1c64bfa542090784f0a4b0" + }, + "attestation_2": { + "attesting_indices": [ + "8735207622981199872", + "15807877765652200381", + "17626514909741646584", + "9610286011333021172", + "9726791872520084943" + ], + "data": { + "slot": "6542787319576380665", + "index": "4967071366844573801", + "beacon_block_root": "0x20f218cd879e978af8cd5d849496c14d937dd41c00af4ed0275a93c32e16f976", + "source": { + "epoch": "18437843598040230806", + "root": "0x7f5168facb00317fb89bf8a974f272ab5910fe15c762fcb96d486228a0df7885" + }, + "target": { + "epoch": "15813630485965658133", + "root": "0xe33869a047cfff34b10d7c658225262292a09e3dcad1fe061526aa2a63e2cf93" + } + }, + "signature": "0xac7fffd1a232deb19212e6ea5f6414393b2d317fdc134d770cdaeaf0df87f7c1cc7e9f11f65e3ca61792d9eeec2a1d2fc448e4eb394886959fc94b7e5bb2911303ef18c2ec90ee8a376fc6e30b467b4fa0fefd8a238e77ebf7c55337b0379e1e" + } + }, + { + "attestation_1": { + "attesting_indices": [ + "12834633968877827254", + "16028384842644167465", + "9891597630206425107", + "2407052889813376980", + "15101739462282017968", + "17779805899293890522", + "8219995904465343204", + "1904743925013243260" + ], + "data": { + "slot": "3712471358971666084", + "index": "5998616854737989056", + "beacon_block_root": "0xdc798437a567a7af975d095c9dc31fe46877cb08571809d1fce20e40380aff3c", + "source": { + "epoch": "6846126122713505852", + "root": "0xc1510d0adfd1c5b52bbb9b228eba51c678ddcfb5c9636ef1dd32c887bc05c933" + }, + "target": { + "epoch": "7975243728505521389", + "root": "0x1b60b0a7e6a0d36f42edace5ec8674d0a1edf955b3738292fb287bd23d0d4e3b" + } + }, + "signature": "0x1d1831ef319833e469dbd1d0bcfa22aae1d5e184cb729ac2f6aec0dfa1b8593d7ad7a41e58abfa2a723d2bcbef7d1d52e6f574647dfc4ff89bea3cf01260a35b0b467bf3fbf987ed0b762976573d39d70d2d26908e17da4a6fbda3456c118ab1" + }, + "attestation_2": { + "attesting_indices": [ + "7002908683142314270", + "2265431971051241649", + "15768239433913981732", + "11484797692738486381" + ], + "data": { + "slot": "16278253854771540604", + "index": "3921887449114240950", + "beacon_block_root": "0xdc79cd4558c4795161a5fbbad0c7c36bdd748035abf67c033d4fa2e6c531915d", + "source": { + "epoch": "8830875663257838774", + "root": "0x2ff861d60968dc929cf37c344ee7da6d9c047e9e7e1d518ee51f6855777cb411" + }, + "target": { + "epoch": "16654076203214392199", + "root": "0x0f53c6f7c82251a51f8ca49c1917117377c3e490b38e15f7561a25b8af06995b" + } + }, + "signature": "0xf4f4bf5db0efd0825809bd73c78a351a41ef03da6f72a7a0f18a7dffe25a21752ef3e988bc4b93fa847f1573f0604c8049a49220a7d8ef268828458afa556b19afd5adbd5060159835454b5689788879f105f0d4d4c2507700307a46cc60232d" + } + } + ], + "attestations": [ + { + "aggregation_bits": "0x506ba6062d6e01", + "data": { + "slot": "45099439454616", + "index": "3750086134417328117", + "beacon_block_root": "0x59a77bfaeeb6892e09c5a80444411a558142e037c029be8a2e749f44c5aaedc1", + "source": { + "epoch": "9505132055064219328", + "root": "0xcf2cb5456c09bfeb150d2f3ae3d6ad9ca03333815c146b3b4e8da358d0624ae7" + }, + "target": { + "epoch": "220852002765357462", + "root": "0x7a84bcbe0889985ca83218baa491fc7cabe299d21acabcd999e40cf9f03ad3ac" + } + }, + "signature": "0xc8e6fe7a38fe32dbf8d956c3829fbe4e97d203e808c5803a6c2f4ae34f34cf22a257dd9d1dec6e73cfc7366f6bbbd14ad57ebe6fe25984aa092612a4e294a8a0e22d7b68bc9d443c285e5fa721d82af67a7be12f5e364b0789ac03bbfbbffb44" + } + ], + "deposits": [], + "voluntary_exits": [ + { + "message": { + "epoch": "16998290760025894103", + "validator_index": "4446171403600537826" + }, + "signature": "0x77cdd8846cdc4af9b5a537a67f6b1f979184b98a05ccce2ef7e70a05b098fdb7cfb4907e4064ccc53165a38257fdf769894367a695ee086c88010051d03ab44177a202c0aaf79c7a7d2b1c5e8c4e287709b0361590ac2150be31210b8c747a55" + }, + { + "message": { + "epoch": "13112383983593789351", + "validator_index": "7383249158549931332" + }, + "signature": "0xb2c22ea683798dae46e598f614e550cf092a097083168d5204019ea9b4690ccca23424934d46f98ecad8e509e5cab366e06342cd3432b8ed0b62e13a694575ae5d81fa489f892a0a03fd22d44fc9c14bb56fb79cfa85c012882fc0233645db9a" + }, + { + "message": { + "epoch": "1427965508409778396", + "validator_index": "5452087992404512307" + }, + "signature": "0x724534337d06a5ae96d1e42b9a1c413595b888e9bd3bcac38e1cc75d065a92fed959921fb809a0ccc36fe8017d0d1c0761d0b69aa488e97953dd9b385c2a13438b4812adafcfb08c50eb8a36b629378d2abef5a9e15c44712c6a7ebf76b7659d" + }, + { + "message": { + "epoch": "10328258751789621544", + "validator_index": "2131363725498082369" + }, + "signature": "0x262ca596a6158cb1a0db2572e7045957917b0b9f166e42a3e6ef6fc1ae7e43f6dfdca821eb41fac4b1be6a7174c83687adf219389e1efbf090522ad32f171dc8afd795463f50fb94e063003c47419b045f095b447f6b80ecb035340bc9120ebc" + }, + { + "message": { + "epoch": "4190083748766997992", + "validator_index": "4472110232095440286" + }, + "signature": "0x22890ee9a7d3a6a8f26b19edc92bfe09ebd624463077a00bbc3b28e262b4770da55706118ec861c92af45b86406bb40b7ccccf0cbd72df4d6d4aa0fb91f25151fb18c4b9a43c5da36a8acb24cfb4bb8d46c392f7d36361d1d599a4bb031882eb" + }, + { + "message": { + "epoch": "10829947487376358245", + "validator_index": "7850593689424825949" + }, + "signature": "0xa04fe838e4a9633a7733e02a594e9dafb35e02d15fec1d08d7115e0d60f252239e2b532134fbe2a0095fdd4774b5da01ef46391a114da6dbe1d50089850f18c31abfdf8b5131a019be3d9811557adfe6bdf694eb98a78ac5b59fcf23bf99b41e" + }, + { + "message": { + "epoch": "12857063653108192263", + "validator_index": "11049615835183679401" + }, + "signature": "0x0a886909cdd43cd1cce0041649646dff7840cdf18626ce96873c25d93a63f5c7e52b5ba14e802b905acfeb5eff29f14a9ccd17d33760501c0afd0b19f9676489e18f0a70eb4d02e868734cdd35e9c3de84bbf676064f50955f90b827c8920b34" + }, + { + "message": { + "epoch": "17738091289425346382", + "validator_index": "4495441538889603873" + }, + "signature": "0x4c2bbde7352897ae68aaaadd9f92b839856ec1e8ddddd15e1875a7c9e71ed6e4cc6af987a2b0e0701a5b9d9d9bf6d4609c89d0210af50c9cfe4499ade3f487c6d4cb554719e143205af2bd8934c45ab682cedeadd7e291a9cb0ac4b1eddf97b0" + } + ], + "sync_aggregate": { + "sync_committee_bits": "0xffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "sync_committee_signature": "0x496a45e1562dd9d9c9b1a3512973c4bba153c453f7a95a319cc0a8fe9597eb56100869247a4e710988241448933b74b4fa03ef2b7839fa4ba7536c2eeea8e729d912f3e18089d99835aef171b4475a80640da39c9762b4e368d1a28d3be58fd3" + }, + "execution_payload_header": { + "parent_hash": "0xfe07128427cda54e3fb49a14dcbaf8872f5c5962551169e2808d4dab13f4cb24", + "fee_recipient": "0xFE23Fd31Ab40B4dAC415Ccb42d02cB144D7168fD", + "state_root": "0x2cddc8052ad28df44aec48086af6f09a756baeb8b7dec99c276a6650d824f367", + "receipts_root": "0xc30590627fe49f018c56dbe7bb4f162945d1572addff11f9b9fec086283d0d40", + "logs_bloom": "0x2dd93d7787163f6f43ebfcb722ebbc7c374e2a6d5088e9ecfd0ce5d4d76df3e23d8c94a7f346651bbdd566d298daecf0e4e1a5df671e8c9efd3e0e886f8336fbe079ec2f0211c9b5e9bdab3d5a0fe59f427d997a2d7070d16c0fabc50b587dd99a70e1259cf42fbe1b5c828eb92a4a81e0e181ada5ca5233c129d617b33a927a9905961f589401f15fb033adcf07b6cc7b9e437c3da8a6d780a733d12c1bee7790ffb7c4d24e421fb3e3c7a094d4115e2cb7af7fdf42c94a74469343202d02322e5cfec6e1a10fa1fb1a5e7b15381440ad4cfdeb2d279dac893d60240ab7fa9cb38edd1365e82478cd486565934b115219ad2fa2896d1521de41315b553b6704", + "prev_randao": "0x6fe18df67dd6bae400556f434bfc5341ddcb0912980bcc4d4918901c8a890a70", + "block_number": "8634275115911202187", + "gas_limit": "9036531375346604998", + "gas_used": "15270993355054234489", + "timestamp": "14197348212488441818", + "extra_data": "0xc74fb56ac7cee5", + "base_fee_per_gas": "84194627069953712510477238207472958691666380895604131513465447308305737285241", + "block_hash": "0xbddfca4b32796a28c76e7441bbd781fa41f7c92429ed1b7ed976cadd13b37797", + "transactions_root": "0x056e5c9e2ffd83b3cf8407138d906be33f8b2843989af29c6582e81f1f594634", + "withdrawals_root": "0xdc52c72fe265033bc571bf3d831e8beaf82ae5c0c75388df262a744cbc17184a", + "blob_gas_used": "12676070321851471514", + "excess_blob_gas": "14114979738142322833" + }, + "bls_to_execution_changes": [ + { + "message": { + "validator_index": "11585652515655122272", + "from_bls_pubkey": "0x6d3acd65b1e9d3a6f247d3ca007bf1a9a13ea3ae88768616888a6057179ae7120e986aafd101fff4096c44ab1de89257", + "to_execution_address": "0x258e4f65BBDA7262F51A192A04e2557F22E548F9" + }, + "signature": "0x8c88127993f1f11f8579fc6fd07d1a9d4eb9ecdb98382cbc77589a8a1771f28adc6f90b20027f2995dea0d5ceb0e02e1df5c7be265f28b1398c48a607daf2ddcc47a79dfde4ebcdb1f8cf4ab0a96328dd659d8bd25b5bd37fe5df0a80e50ca59" + }, + { + "message": { + "validator_index": "14299930392419578748", + "from_bls_pubkey": "0xefd9a17c47ddce4c3e21fc6036a6f303e3efa6ece0ab6255e7e204837492b97ff57c9e5c641f0d2a2a2dfa93bd1dcbfb", + "to_execution_address": "0x6E8D88fB9b978Af9644aD553E35BC58B5984A355" + }, + "signature": "0x290c6d1366d0acfaaceb7b793f2b992b2478f76e7fcb757433b81ed0941117d2f18bb651384a4a542ed4f04f87b51ff8390fcafb0c6f26f18e3a7098b6da995c472bfb2666765e19af20b93f9b4f0d81580f350539553826be4d6d7ee19772b4" + }, + { + "message": { + "validator_index": "17777774447706846945", + "from_bls_pubkey": "0xf35fca7f83606c49b7804b46481dc0b78ee56f21767e8eaf4c1c3884018033beb6461e66da55e13b913e23ff04c13c3c", + "to_execution_address": "0xb8d879e1CcFFBd54fE1E7C3cf003c7a016F06F4d" + }, + "signature": "0xdee071be67cb424d105cf3ba1255738374e4b4b6cdd1894aa7f4578f9f34276c02935a5ff54da50bea2d62881ccec66ee79ca04e8805ef6384efb7835ddb3c16c84c0a969a1fc7bcc2148564c5b5960e687618a2ea438c8d8a118deff69e6c93" + }, + { + "message": { + "validator_index": "6705286427685662652", + "from_bls_pubkey": "0x719b25e3791e8e13d5dd304fa39f44a30f5e525958ad314b4f4229b4a85f1809563a45b5852a14b619a9ef6f170cfb11", + "to_execution_address": "0x88fC716F59A69e7af547d4C8F10Cf08D4877Beef" + }, + "signature": "0x08d6c0f0c501f94577f82fc2e3e3fa67b50da785f0eaf7b4032fdd3ab2866f716d059a653520f3b20e0af83c7c228f49b3642f352628ccd6091b2d5e3f7bcf89c8a91c00812dd69821ec2ba19399bf5571d2c7ee5708cb022410ecf297550e54" + }, + { + "message": { + "validator_index": "17624840868526334581", + "from_bls_pubkey": "0x363df2fe12e5fed39e3a2868060b5160c3f59a89fe6f3335a1d65a8d1daed9dd9bf9590cdcf27f1a7e372d34977e41f0", + "to_execution_address": "0x7f3B3F4B95795D3Fd65ab9a164e0040Cef446460" + }, + "signature": "0x8388bc639fb1f3847a7fdfd09e9e159c882fb9c011cf1c1457840a3ad79d51cb0094d135208af1bee1cf6bc1ad9027877aac1ee378ee018ac16af59295eaa92f19b23d9d503050ed487f4895203f21da839ec601c1a026272d24b34399fddad0" + }, + { + "message": { + "validator_index": "6869800260265517511", + "from_bls_pubkey": "0xdb5f49685c794503cb4fe564132f64f663c67b9a288190790b2493cd0666992b2c9c931d4dc486302b7d1279126a70c5", + "to_execution_address": "0xf3a4D6707ABe3EC170C094BF8F97994b858909cE" + }, + "signature": "0x23bf8bf474a70914c0da9ea49854ddc1d1f8f79e063cda326f40fe48b719d66e053c0dadd06aa0a84cad46810eb6a5493fa6f8290bbd922c5f898e07a6760fade5076d914f9a4d5259fb5a396dfdd9b42bc952266bdcd45b5dfd274bee6df9b8" + }, + { + "message": { + "validator_index": "6274759018932770324", + "from_bls_pubkey": "0xe69aa61e0b2036694957fe50827e60c3ff2434c7c2bd1a5ffbb1a7b2889b2e6b4658246c369d7e10dd76a87a2d42ac00", + "to_execution_address": "0x4327b97678ce19EB89B9fc3820ad21e9D62e1f26" + }, + "signature": "0x4aa5ab74b39da2d7bc6c27921f4c03a37f0d3f6a2ffffb11c021f7864afff28d14f82720ebefe46026bfdc17eaf59f4e0d482a125bf921e9ff4e6d0367e151da8efd5ab0fa32194b4a5f6817df5fd97e934cdd375aee69b71af412db155086d9" + }, + { + "message": { + "validator_index": "16806950944306333877", + "from_bls_pubkey": "0x6a36b006605e82b0231fbede4796e89056c20a603b6a8941d4542f45c4445e73fad0a74346969249b63fee8bcfc1de97", + "to_execution_address": "0x626560B30bB93e6fac126354CA0A19313eA67D74" + }, + "signature": "0x9543b464d4c6bc040c1c11e7763018ff19d83853c0e7903200c74ecad11b2b42109b63cd3f64e8f6d1b4da2b253f1775761dd2c6fe6f38d3608fed803f0d0a7c24b09fe5ffe35411d6fa0b4ce3e9cde8717c9866d37077f35c342fd0777e656c" + } + ], + "blob_kzg_commitments": [ + "0x31ac9a7290ab45b264ab23aadb6c802680a1dc41f42357b8822b91cb585427137fe9690aecfb559d0743d6a92b7be299", + "0xa4c263b3e7e8a2c3618aa5f441585b1258aefe56669356a31f6ac137c1a3d897f52f28dfca97c017ebb7a9da653d7e5c", + "0x9a313c039e42158de4de42d8b290f3b710c81059cb8c68cfbfdc39ef9ba4e34139e23b92b254e2c1ead85ce1028a086a", + "0x370e27425f9cfbe75019f125c1708857f2697e3cc49427db3c2040e1e3916557c5bd249a4f810244331be2bb6da29dbe" + ] + } + }, + "signature": "0x06393e72152db699e38099105bac49c6f0864d3c1465f14a3b17b0dc3d7a41def87c29797adbed4fede92b9fb9fec31ba211bac7511435682b308b0e09f9205310d6daf6b30c3310b7448d12e62164e7972803fa143776d5990a8b2bf961170d" + }, + "signed_blinded_blob_sidecars": [ + { + "message": { + "block_root": "0x5674ff6ee3fde4dcc269de8e3ea955825778dd891909bac4d1eab0810552a66e", + "index": "7819891668011374641", + "slot": "17574044999695582378", + "block_parent_root": "0x31e7c3d3140e410953c9ec4247cdd8f7996f18f3ec1c38a9561b72af14a0378b", + "proposer_index": "391852438669115837", + "blob_root": "0x13ee7ab98616ee75a1ac01f1aa506f2aaa878d27ff7d6725f066d2678f6ebb14", + "kzg_commitment": "0x626f421630e8d3967a9fb349276dfb728a5b05c09315dab57b3667640b2f24161abc53182130198e758002665199daf7", + "kzg_proof": "0x5e6b09f7c11856179a62d60d691b0beccde8d56492307685e1deca74b6f99062fa06e533c9f6e64e2e9023ad64ebd37a" + }, + "signature": "0xb1e0dcb1e0b53fc3efe8e729d3119678b07a32519b57939593bb52d1185c7884160a914ade37416a0af2e1dcde2d8d367e8d6318bd1830c7613fac2533e7634d9c3de68ba24d971c81ea87a0e1fe781890e6ae10ad72ec7f3e7b7c093e0e3c7d" + }, + { + "message": { + "block_root": "0x3fb66ce622770681790323d122d848acd7a766e000b2e61f1cdb912263e674ad", + "index": "17242512023502111637", + "slot": "3434649974578070558", + "block_parent_root": "0x146dd8ccf9dc824b1a30004c3f175647cc305f8739fc9a3dddbdeb8ab8201b16", + "proposer_index": "10487171017719907006", + "blob_root": "0x78eb332babc8d69b66aa5d4a04443a401768f49effce733d0742e0b1872dd2b6", + "kzg_commitment": "0xff8478cd82e1d03d5eb3653a2199d66c0a18fd27c34345468ca9732ffcf037cb1aab10af1620e90785a089a671bab57a", + "kzg_proof": "0xcf03c920de776f7f681914dcce20d99ed0889cdf681d1fd7908f47938b6f8efe2e31c21215a0be379b1f19d0bceb6ab2" + }, + "signature": "0xda19a285ee6542f23ea17c4c0261ce27198ac989bcc5589a26325780937b07bd44814f0bc3e52acda3cc804ee53eb49753783092634c747b5a40231ab6e96871a34704c3f44828e25e1adae460d2e6869b82632d2145f9ccfcc959991532ae5e" + }, + { + "message": { + "block_root": "0xcda51cdcb7b6f801e3c41e04dc03e87f477d28d220e1a4ab2f5b4974b48549cc", + "index": "9321958914747155786", + "slot": "14525430640886981402", + "block_parent_root": "0x4e0ece99133a2d17dea5a18bde4bb77eaef8a98d9875b4b74fa0865296392cb7", + "proposer_index": "14431476861172757028", + "blob_root": "0x39f347fca16a228147f4ec8fc12c553c88f11a291e2338fd86d50ec3bbad5406", + "kzg_commitment": "0x65b834bd3a09f4da549469fe25dc494d3a972ee576e69a4f4ae6acc7d93a199976da9d9309b43af57b6eace8540fc9a5", + "kzg_proof": "0xc7ef21b7325164bb8dc9389423fc9cf702fad3674849f787491be9bed19fb45157271f9d07bf2f80cb720d4320977c57" + }, + "signature": "0x524179feafa9dcec92d4949a8e2859037abb5c938a3b4712f38ce6ac40b2a855b050a868882aaea9d02ed2c255e7ea5fad015b472985388e0ef658d8843ffbac447b867cf8debaef8d13c05afa3fc9c6058798089479f5a9691096e544ec18af" + } + ] + } +} \ No newline at end of file diff --git a/core/testdata/TestJSONSerialisation_VersionedSignedProposal.json.golden b/core/testdata/TestJSONSerialisation_VersionedSignedProposal.json.golden new file mode 100644 index 000000000..2fe254897 --- /dev/null +++ b/core/testdata/TestJSONSerialisation_VersionedSignedProposal.json.golden @@ -0,0 +1,434 @@ +{ + "version": 1, + "block": { + "message": { + "slot": "12258969221770119542", + "proposer_index": "7833179233048568588", + "parent_root": "0x908d45b0164a1ed1fe5f6c6bb64a52fa1a95e2bdff2aea5190ce067ad5d23f96", + "state_root": "0xec4c0e68f23b572665b0e60f46fd4ffbf4ebe0530c03f2ecd45fac9d4aef1d6a", + "body": { + "randao_reveal": "0x9ec7799f34798eb91ff4c4fe748e21819c51945e7ed3df1fb0b5a4e0e895804813d1f4a80680595fb94b57636910c8ea580e905fda113b925adfac8d80ebb68deac0c0d6cb9aa138c60f34218fefbffdf6e04b99c493c785f588d20e8521bdc9", + "eth1_data": { + "deposit_root": "0x82ab0f52cf75924a308bcb99683bccc2813229bf922aaf112694262a4c953678", + "deposit_count": "13954635830841395618", + "block_hash": "0x0b002cee5e71c47935e281ebfc4b8b652b69ccb092e55a20f1b9f97d04629612" + }, + "graffiti": "0xbb97fb7e48b3fbbf085d511d62e526d7dada713df407b4c7822023ea549c538f", + "proposer_slashings": [ + { + "signed_header_1": { + "message": { + "slot": "1443379047061527087", + "proposer_index": "4216468081525476639", + "parent_root": "0xc6d49147f6a2fa1e6bfb7ae0313d3a74e7b68cb7ca96009ae25551158f08e482", + "state_root": "0xa26a00f0d6ed086dd4369f0897c9e5d32d3df8099046f2bbed9d544205208fe1", + "body_root": "0xc47a9329cd2e79e07d6f657ed2087a246b2a63f812829816a3019101a49a6a26" + }, + "signature": "0x76f58e9e788391631743c0ebb6197763775e88568c02afbefd317991659a2d1eac669c417b43efb4e8adc4f4be090e2df1860992a969df2236eb48b575dc29d1b6703396a38bfc3fff490d511e4e2f992e6a28b16ca63b967ec184be1233a6fd" + }, + "signed_header_2": { + "message": { + "slot": "8710010509815014220", + "proposer_index": "11427002176138074026", + "parent_root": "0x3ee79f16c4a5a7f937220f388339a555ca3b7cb6a2d6355bef4b0331399777f9", + "state_root": "0xeecbf5f2242f59ea5be8e14f23a279c59a485a6634044dbd8b8de354847f02ca", + "body_root": "0xc158c5aa735dcff744590cc6e7c8592ba3f60ce1b521491ea9ac7b24a12c96ae" + }, + "signature": "0xd58097e815815d949b57ab971a075abb6481f8aef1e2816598ac364775ae561dcb95d0157f7eec22697c09f840b35c7d5c8fea33425b3727e8d13bbc2428b1559d6f65ddf46916acd2978145e823d20b7b536da9f1194074859a9b26102cb805" + } + }, + { + "signed_header_1": { + "message": { + "slot": "3753582023824823793", + "proposer_index": "17360171144750589851", + "parent_root": "0xdc63d6792b7f5171917b685ff27f71d636dee24d693615996ca85c09558c6215", + "state_root": "0x1738f125029e434fb2c3d9d88a0c9445defc19c473afe934fb752bce78ce6c33", + "body_root": "0x127dad08c5b009807db26a92dfce76b9c76878532b92f41eb02430857268fcae" + }, + "signature": "0xe7c388446cf5299facd134f8cf2864ba6806cc06003a0d535d1b93069b6dbf0eb1240bc31ba38be3f7c544207175a1eb66c447d4cf9478afa37c95c39d4a9db966e89739e0e7952da1a2050928db0edf1152ac9eff9ed1913cff6ca3d21a5840" + }, + "signed_header_2": { + "message": { + "slot": "16207056013116748211", + "proposer_index": "8904857625617278258", + "parent_root": "0xf4f30e5f5512facd4e95c879f5db52de033010ffa180eed7d81077294277b90f", + "state_root": "0xa9b0725db8cac6a70e0aacb7e36d0499cc54ee36bf48952af8824035bdb02edc", + "body_root": "0xd938619c7b83ccf4dfed9ef0ab43f1b879510b7f7e4f1c9f94c9a96eae0bc1b1" + }, + "signature": "0x10aa118bbd64e3c498177c1f91ddfd19ba4829ea1a10b208a9b2eb1a7526f1952a0cfea19d2a07560838369d57ab1177560c7d00f02978424fae53bbc30632a0c2dab6e94b2d8f0e151e3a02c1f0d04b763f5fd190631d90e98b39ca129624f7" + } + }, + { + "signed_header_1": { + "message": { + "slot": "13066106652058020522", + "proposer_index": "15082442079153513282", + "parent_root": "0x9b62f91dd6e6c34877950ae90c27953b4661b51527d46e49b7ea29ed92a42ef7", + "state_root": "0x5434abdad0b8c3b0c828ff6724fb74e4d6fe6f8f5c3490ae61e4829c22618f96", + "body_root": "0x74de7b5bb05a2ce2af56dc9d27e3ec42ac4e6f57955380d25326c99bb9a7e6f7" + }, + "signature": "0xaa05bb1a1ab59c7d07016797bad80a44792de495413a19954da8f77a4d5beef06b4838bdc55bfb6494a2cd49447c123d3d18f4b8df78a94afb826a150b2e914d152170d2d9eba822f1c28e97baeb48e37d6060d8658c6b7c95aa2dcbe97f5324" + }, + "signed_header_2": { + "message": { + "slot": "14870197141001258099", + "proposer_index": "15163092277513918012", + "parent_root": "0xcbd03da2cc9ae47308f38d7c778f6587d7e43277472bbdd64e0626707192f422", + "state_root": "0xa5c15c1d95653fb9c9c7a75cdb8cfd5d79232b2aa380fa6a875498ef72afd594", + "body_root": "0x0b96d740ef55ad9f3bb753a595b8b07a0500d7f84cae8417abebc5b450570051" + }, + "signature": "0x7eda930d664c2cbe0ebc7ad4065cfaf59eb6c9a006eb7c582866897ecd0fb6d6fdc6e7a871a80afac731b770dcc8864583c57d95e715a9ae833412d0daf1fb193647cc5ec17aa2896ef12e1cb72138fbbd950d13e2009c157baae4170f2562bb" + } + }, + { + "signed_header_1": { + "message": { + "slot": "4423882567267761972", + "proposer_index": "17362013782227991992", + "parent_root": "0x0e645c91f28d7b10040279c545e927db8addf301d97e6901f00c8e6a53b0bf22", + "state_root": "0xbc9ff3ea6dcaff559f0af11909200f77d3a53e71b1f307b8fba35cd1d2b18400", + "body_root": "0x0f64d2de37299ef39aec6cb09aadd2b63a8e14c5ca498c70d85d9d380f1dd602" + }, + "signature": "0xbce598896bb8d2fefb7cceeca5b3684427fbe1a7dc9f2d58b54118f9ca8e7f39c521f823a4927981b201534eab117644bc428ced450267873a6d2405a80d82eb7615bfec9f32d2abd17fc782c2af05f31edb40d9aed59c34bc78b85305f33786" + }, + "signed_header_2": { + "message": { + "slot": "2756473157529667098", + "proposer_index": "8302046196302492988", + "parent_root": "0x9866d5573876086e358365fc71f8003397c8dfcec3548b8f557d618ed98d634e", + "state_root": "0x999ba3128fc58623d023bc473c5b47a4b2a47ed14055f7804cea373efa212bb9", + "body_root": "0xe9a877c09a70e4206c1a45166236acb5b335bc4b3b70decb05c53123fdbe888e" + }, + "signature": "0x8b743eeb84065f97ac5c31bb1bf10ec01bf3aec56e73bb84a12f0d78211cf0f1ed43730e255b6d5789ab95cfa50a00c7ed32b84c63d69a4ec98a6b0f297a492cdd1c1c8013ceb804c4a47f7bacda0af4392aa04237bdec6d619aca30fa4641a4" + } + }, + { + "signed_header_1": { + "message": { + "slot": "11045824254400895358", + "proposer_index": "16136532190648778027", + "parent_root": "0x0391106cbfaa50af22cecc9bb7b87777e2a9a6e9553e765baf2bac2056ee8295", + "state_root": "0x82dee29a0bae040d7c2a042926dde4bd6e3fbad192376a08fb61008709b748e5", + "body_root": "0xebcd702f577cb1b76617ad7dd605eba95e038eb938f1f4e696e154ca2930d8b6" + }, + "signature": "0xce4e1f15a3df9a50dfdf0aad66356ffd92d62b3e6a67edb22a01ef3aacfeb4adc1d58e6cffdd04c830a90762bcdf75a9f19dbf73ffb4d22a4d598dd30fb6b1a6acf80b8d2c7db7d0fc50007513a7bfbced61caaf566be024b6682781c752f774" + }, + "signed_header_2": { + "message": { + "slot": "8246471541327176547", + "proposer_index": "8302833441173825771", + "parent_root": "0x3bda45a3ceb020e9c679b6504b6864a7bef80d4889be5f4a4e5c71ba580b451a", + "state_root": "0x36a8f9d358de49327d1ee015b0873f9e88e253633912a766a15c1ff90e9e8bc5", + "body_root": "0x6471aa11317030fbff8e8b6080c7a33df3303fbe286aac11c2d613e246b465bd" + }, + "signature": "0xe412d979710153b8d0a44193998becd21ec14c2de627fce26b299dc1dec245c6df55a4874d5c3bbd70eae6310fb170c771e0b9c92e07a4d4f43b27b4dd13078a741bb6dda597941cc0bfef563c48b5853cd0c874da8cea58b388abbfa35af0d3" + } + }, + { + "signed_header_1": { + "message": { + "slot": "11231276011780030403", + "proposer_index": "4535268073733844648", + "parent_root": "0x0df012163c2712fd8c5f3a0aba47cf9136bb9750a188780ae39e95217ef98732", + "state_root": "0xfea81cc998c09b4fff6e5296d56d713ca1eda9b1936a3dcba59afc963d54eb1a", + "body_root": "0x2e9a4810f8eeb4fe919b9bdc321af1b2b689c139f313333a1cebab327290cf95" + }, + "signature": "0x95cedd6c8fb04090219448d5a5f33038ed4bee728f8e233466f219ba2218834d08d68a0d5f9a7f04ea48bf36fa6adcd691b7289b5c8019765a2032f5ecb21c8a04377d9ef296d094b51d2678ccacc902ade83cde2e22d83ec4b5e6521e8f9e2c" + }, + "signed_header_2": { + "message": { + "slot": "413530364184878844", + "proposer_index": "2762530381805634493", + "parent_root": "0x513732cfd25398b5c86626c045f6c0c13ba449672c88e0a34f7683289a71a77d", + "state_root": "0x1051ae57e353494ddcc035b576f8fcaf1840b4c337464cfe4cdaf42a5f2ee239", + "body_root": "0xfd3f198aee274a6c1bec6c039cc74c76ef5cb98ff31f6b60ba3e2b11501064b7" + }, + "signature": "0x49af0fb0b9c80b895a8b09f9a4bd6255cf591f6b740b6d315f28c0dc7a3e6b4c334ad4e7cd3d66d9693abfdebd60fa15eaa4a8a15bd2b5fa02b9ebd6ee615fa137ecfa198c7598021052a53972d73b122a85b296d5acfe885b8c5ac8011f5737" + } + }, + { + "signed_header_1": { + "message": { + "slot": "9644765991827726829", + "proposer_index": "893066331788262369", + "parent_root": "0xc8110ac0ccd4b717571f82a60345a83e288c7e85956e7f0ece3dfe727f61e56b", + "state_root": "0x40decaffccfd178744d66b23d98ff44163f35cbfab30b1229da6cab1789f1afc", + "body_root": "0x1511aa1f57671457e78e73fb949de53b6a08b43a7756d88810a3bdd7ee7255e8" + }, + "signature": "0xb37e30d518ca15499b4f8cc801439f9ffa0d7a508597ea412d7236e7cafd24e11a9778c4f3306dde6d1a127a2c9a6aa16d5e6738fb1f37253b96c54931b6541b3b4a4c748b459920487e031a7a5680d89d3877a8bde08f2e07e897a4306c6839" + }, + "signed_header_2": { + "message": { + "slot": "2622749781788581409", + "proposer_index": "5936728940722922084", + "parent_root": "0xa4b06a0d12eb35acf7f969ce4e3df25ccb54ae514de3ea1ce3446add46ac2d83", + "state_root": "0xaf4ed0275a93c32e16f97610387f5168facb00317fb89bf8a974f272ab5910fe", + "body_root": "0xf54932557f148483ef44d2331f157e951bd33b7bb78ba8c59bfe6b4aa492880d" + }, + "signature": "0x9e3dcad1fe061526aa2a63e2cf93139d9f5ecf11e98955eed2b9962eefe28ae4cd737f07790451891ba81bf0eec2b77206e46791bb41e63bd082a0fe092f3ed68473b6ca22bf3a2b3cf897bb7fb32be35b5adf253fc79c1d3e393a6c91b6a8cc" + } + } + ], + "attester_slashings": [ + { + "attestation_1": { + "attesting_indices": [ + "17539680117757364262", + "5781627475530218201", + "5506905600699984943" + ], + "data": { + "slot": "4828972672715110647", + "index": "11404741012694454725", + "beacon_block_root": "0x32229c0ff9c7959817a3d90743b9825da4c01e68dfa898339e61a9b2d6b3fe8f", + "source": { + "epoch": "5196043516686486303", + "root": "0x64e6b47fe9c1a2f4fbe38db3ddae6f648f3c0b0c78a2bd12fd2b197f1169dcfa" + }, + "target": { + "epoch": "14361513721093163601", + "root": "0xd185173c3dc8ee4e36a754854ea03ae44cedaa23e29e5676399483ed26f441cc" + } + }, + "signature": "0x74d0a1edf955b3738292fb287bd23d0d4e3bb4c83207ca154b3f8d19e963fbf530bed51b597d2fd228de8e0f28dc5858acb44d5dd640d703d7520c25100c03c3d5c9c5f1091dd12e17a889a01a791ff471ec464eb6338e70bd1af5083f38244e" + }, + "attestation_2": { + "attesting_indices": [ + "3205659272094003927", + "8723309406074214413", + "12108181204264277805" + ], + "data": { + "slot": "14409283664605244108", + "index": "11486493041238181026", + "beacon_block_root": "0x17da4a6fbda3456c118ab1c8585f38a7e57cb6024b100cfbd90f9c736c89f93a", + "source": { + "epoch": "4497779902312325063", + "root": "0xab8cddd8dcaa344e119b3a713079b465ce8db61e31e8451087720523ab818bd0" + }, + "target": { + "epoch": "10662394743459613671", + "root": "0x99b530c1e52bcda6d1156c47e3e4241341e187525378500ab0349b7aafcd8e18" + } + }, + "signature": "0x17117377c3e490b38e15f7561a25b8af06995bdaa21f20a9d7d3292ef1386719918a764297c30c12b19e29fac5675f37bdee74b2f1f559c05d0e381559200650672d680b8398e7caa6c72be0dca396eadaab14c6a110f1705574a822da937598" + } + }, + { + "attestation_1": { + "attesting_indices": [ + "4044780610053584759", + "7435307165620220407", + "16134622791740421828", + "2132945930735811872", + "6414260498866420412" + ], + "data": { + "slot": "393045144288944340", + "index": "17469441142722646210", + "beacon_block_root": "0x18fff028278de33fef923a70412b72d0b8eb865cb9e681055874d27870ee0a3e", + "source": { + "epoch": "9725862182444272965", + "root": "0xe75492ee8a0ef0882894e327331669b3ef1f329adbbbc0ff755ba4683ceeb216" + }, + "target": { + "epoch": "1291337442909776703", + "root": "0x9fc4ac62b90094e588455d4d1d6eb6e0f4fee5c1ea38be5722a016f0db9823ef" + } + }, + "signature": "0x4e6a51850e2a219879088ccf82687d8ecee922ba01e653e5d63ef41f48bf878c99eeaa31c3f56d2b64dd8525b4c4cbcde1e4a1c919c18fc596781df8d5a9205f4b5ba7439e816572e37c6f2d59de9f10973944c57907b616fbbd2d60df8c1af8" + }, + "attestation_2": { + "attesting_indices": [ + "6084093166697219293", + "737263562008020227", + "6924818113102838477", + "11428886990944795377" + ], + "data": { + "slot": "842694213661142645", + "index": "16632392495717814903", + "beacon_block_root": "0x775b7a8decc11afd3de60286d964cb4812ef66b5dfca3643758168ea20e03334", + "source": { + "epoch": "10697515580993499280", + "root": "0xf826ffb49f985c62ad45b15b66168a34b6b486666858c69e419f92641aad40c6" + }, + "target": { + "epoch": "9303739303502036426", + "root": "0x4c1eb2b65e32f13e6399798b3245b7624e07db1b20f0a672c6af10341f1df7ba" + } + }, + "signature": "0x1cf396a75430c5486e5734b2c93886ae3987ff1c77f5d8c76e49ba048c1c24b0d9406c7c01696a161455fe2471fc6c39c983fde3edab26b45525dbacb2701b00b1c8d3f96a3fb227949a28deb9b0cab3673b5b1470f6a0ec44bd8bf9dd8f1d38" + } + } + ], + "attestations": [ + { + "aggregation_bits": "0x7601", + "data": { + "slot": "15300307516884943893", + "index": "10125495742326073003", + "beacon_block_root": "0x442184ebfb6df5618bc49f98d58dd72267db04cb264301ac12379cff20d7783f", + "source": { + "epoch": "1301371927588039996", + "root": "0xd9da7734e9515b24dc2ef179010632c1ec7031a60c39c958c5ed5e51b5a992de" + }, + "target": { + "epoch": "4051636045274551925", + "root": "0x37d98f50e671ed3516ff724da1d7b33d2bc6b9bcc6f470701e179acfa5072011" + } + }, + "signature": "0x937a65bcf61ec466d3c3b9934d43372dc1ffade798adedb4387af3ea33d68f3fbe230e77fedb5be52a021c6c09c7526ea68447f9806d1209265f3a7bd8de9d29e0298336846fb0c0a29e99b8de19d33f9a5887f26d21c00a9ec70bb45b9422ac" + }, + { + "aggregation_bits": "0x6a4d6b4ffef62601", + "data": { + "slot": "16984397302609171039", + "index": "15910524230756209060", + "beacon_block_root": "0x2bd6e2bb3f830427a6537c6a4b69f850c8bc3bd3a10207a5dc0b9b33f17b8f12", + "source": { + "epoch": "13619526095895379891", + "root": "0x4a2b0493ddb16d91da71d1de2382dbd1bbbb6b743a0a78f3d25238e5ab579b0b" + }, + "target": { + "epoch": "699754634382871494", + "root": "0x6431815c53ca6a8d389b5307cd51a5114ba28ce1e945391bf5d4ee9080023822" + } + }, + "signature": "0x7bf5739f9dd79e4b8a022999208abcf4b49afe92f20c408490aa2c5429d86d5b8baed87f0705d335418937e993c4ad1057a2c1a88daa992457ac9984606bd30c80cb7684c17c612b77e17e8920ce06388a9be9764b41d9d30543df12990474ae" + }, + { + "aggregation_bits": "0xe44aaa37bb99196201", + "data": { + "slot": "11688841322589834836", + "index": "16794188245375730201", + "beacon_block_root": "0x7bcea8a69c68f9ebe098ea1eab87d121f994a8b01b474ae6bfe72b98627d67f0", + "source": { + "epoch": "6230665511596386155", + "root": "0xd0d2fba9063393e254ee15d6718f3520ae13e1b1c4d99810f92467b698da446e" + }, + "target": { + "epoch": "7002460317479135536", + "root": "0x7ba50a54cf4cd863571d3db0560fb4d1685ce87b822d93e06f72034530d78e2f" + } + }, + "signature": "0xcde09c6b6f7142de6227f88748a3a6a81227738f307e676cf61ef182e79dac405eaecb49eda086c91f43caa69c035e59b500c5f44bcc8e5b73e25508cc4c5d19bed0315bd37e6c26037757d8a42ef77bf7c0b6c8501582017131c712ba560ef5" + }, + { + "aggregation_bits": "0xdb20760efc321b1e01", + "data": { + "slot": "669398345345509026", + "index": "17292942742400086206", + "beacon_block_root": "0xd5d809b940c0d7bfd9ce2936eda069b15f6b26067b709e8d18a84bb774611980", + "source": { + "epoch": "8640177637667673501", + "root": "0xa00bb5a2206dfa52429787df623cff32e27bdf6ee312158ebee7cf9a50252a22" + }, + "target": { + "epoch": "11093876280480600828", + "root": "0x8f0c7f7009a238c899ca68fad4ebe2bec47326e9fae55713ead48336863f8bb9" + } + }, + "signature": "0x4f79f68c902eaacae9e56ab90af20e8d7161cbf608a53c4fcb65bbdfcf2ec524c5d3b0dbc4eee02ad0f6f86dedb0dafac63979ab84d2dd9f55b40d1ce224f1c1c83065582b3bbe4865f93021ccbb9f8003628fd0dfa2557e249ebaa04461b1a3" + }, + { + "aggregation_bits": "0x022b57048223459df601", + "data": { + "slot": "11500089007668995752", + "index": "2193946105068863478", + "beacon_block_root": "0x18141c0a3bb59146838b9f7ff5b527302afce68ac143b725ee90f516faebe9e4", + "source": { + "epoch": "12997335381693400026", + "root": "0xdd3036476566f0e37a2e175321640d8027383a4bf5313c7c9d78ded240e6a0e1" + }, + "target": { + "epoch": "10827572253665793214", + "root": "0x0df0ef220cc1d9f3d0b97920ef229aa75987482160256beee3c70558c930bb22" + } + }, + "signature": "0x8e19e82d7a190b3c39492d7e57fd51c62b5f8891c8fc8b82f33ca48ed9e7be639f589ee69ff47e463ae873c162f983910a43e517fa9736b0ec656abb7d9c7587038e21ac4359462b0a324824b557a01712387977f855aa6fc18b81eb176f86ff" + } + ], + "deposits": [], + "voluntary_exits": [ + { + "message": { + "epoch": "15018482157318785969", + "validator_index": "18385606883598887718" + }, + "signature": "0x030d28ab456d81fd5d0323c35e1b40cf924c1afb2bb792bdf3b1c634b031914769681dea7bc9c327415285e8bd1c0a1eacb25ee30d847953912cf1db1f7862d73ee1ee846b143d66a3560e171a8ac93f87973e324fa496ba28b860548799748f" + }, + { + "message": { + "epoch": "3161590947260102369", + "validator_index": "4572211032227941474" + }, + "signature": "0x08a745255e83001422225a4c7b89afca57288c3a16f62efec32f96b7080d03aeeef0d8b729e13e5ef3abd372e1d7313b16807f4e4fb984544621e9cf3a9129a407f017322803af2bdb6aebcfe91a4655a2373cf9404759b76a55a5d979fd1bd4" + }, + { + "message": { + "epoch": "14893385273738851877", + "validator_index": "15593987053076001232" + }, + "signature": "0x302cfc43f277ece0c75fbe9ab872d47da61fa7e790cff0daafa22f8f426946c7d618f5193b61462cc55302474f0a961caf740c41d59b0ea434ad2cdeea29995235a4838ab27c1184fa83276a6925f4f7273878494d4ffaf746a564f415d2a3d4" + }, + { + "message": { + "epoch": "4550143485387678889", + "validator_index": "16567475962248278295" + }, + "signature": "0xb970dc7544c73cfe3c842befbfc77ac1f8ee38511495cbf292767a720c46c6ffcfc7302b9f9a951a2d6d41af0808b24482758edf9b53d206ca9e536a2e40cf216a62e1a99e15f9e39da775849368aa105e69955f5c370c4a73243fa45f5d658d" + }, + { + "message": { + "epoch": "10066465926439695730", + "validator_index": "1873650440899993283" + }, + "signature": "0x403b3f9ff5368cb99603ebf5d8018a9ab515463c9e19cda8ee86dcac3e5418ca0461729fa8a860b42c6da97a5d2f30fe62a09facfc0e6eb8a0644e5046d998634147d7f0a3d7b8485dc89d444508d82d7ff223f89925adcbd8dc9a2cbd35f4f9" + }, + { + "message": { + "epoch": "200221781886377895", + "validator_index": "17984838682046851133" + }, + "signature": "0x74107218f29e61ed14e84b41fd58b199abd3552aa6a78f84adb6bc9e067fd9a81872d56c0b175434b83098d2e55c57ed3d270c20b7658a527e73b4db4c2334088a287eb21c3906f52a5a24723926f1d0e4c65524f689d818f64a5e69afe60ab3" + }, + { + "message": { + "epoch": "9497683918427349596", + "validator_index": "16117496434940928171" + }, + "signature": "0x9fbedd603fadeabc86f1089ef565cbbb2d63e1dbd79c60824d67b07e129bd298f59bec45ef44d8a3449238f60742568cf1066163dd2e49e30942fa628a78550f0834c0a8ca82d4b716a92c4e1856d80d5678c501fe9c90a27f139c969cf298f4" + }, + { + "message": { + "epoch": "6425054894525323180", + "validator_index": "1641765794057278081" + }, + "signature": "0xb9767a84bcbe0889985ca83218baa491fc7cabe299d21acabcd999e40cf9f03ad3ac87b5d2a4204f00e8554b71b25fb1185294fbba8f038188d4abcf3aeeccfecf59746bfc36e2c335931b90eba15ad53b4d4b2eba70f8845b7653f6aee21e95" + }, + { + "message": { + "epoch": "10813334744019625031", + "validator_index": "5629123092837270189" + }, + "signature": "0x2d7b68bc9d443c285e5fa721d82af67a7be12f5e364b0789ac03bbfbbffb445ff6d7e22390d1e850f1c8d55cbe508c4005fd16fc7e39a3b7025037a51c3b4d4ec0581c25425ed40667eedd27442b4379bdaad95182fd18ea20b019dc997f1e0a" + }, + { + "message": { + "epoch": "14867058819375632362", + "validator_index": "8246199444797444564" + }, + "signature": "0x77a202c0aaf79c7a7d2b1c5e8c4e287709b0361590ac2150be31210b8c747a5561a744737a221654018d8815cca2f1df17e06d4c076de790c21379506cb645b65d4973996fff0ca2cc5a54bd07087202aad6a6654d5c76dbfd7dd5345a8264d3" + } + ], + "sync_aggregate": { + "sync_committee_bits": "0xffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "sync_committee_signature": "0x489f892a0a03fd22d44fc9c14bb56fb79cfa85c012882fc0233645db9a35dc33a57b4a4e8a757d9bbcca7e1471a9fd0088292202ca114b3b25d14705cddac76246533000b9df7658f8183721a4a5b8444bb5532eb87bc1dde0151d89cd471b98" + } + } + }, + "signature": "0x8b4812adafcfb08c50eb8a36b629378d2abef5a9e15c44712c6a7ebf76b7659d352841b90e5458dc6b2f5b135af4c6f7310d1a4e8bba6dce9879bf63ca8b80f8c8528029e9f53550cabea82291dd6b78e30fa957eb66a7dad9ab1f1bb531fb55" + } +} \ No newline at end of file diff --git a/core/testdata/TestSSZSerialisation_VersionedBlindedProposal.ssz.golden b/core/testdata/TestSSZSerialisation_VersionedBlindedProposal.ssz.golden new file mode 100644 index 0000000000000000000000000000000000000000..06b79a887759481d42df080f1f895e9c2bd9eb0b GIT binary patch literal 10017 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 INI&ua0OHD=;{X5v literal 0 HcmV?d00001 diff --git a/core/testdata/TestSSZSerialisation_VersionedSignedBlindedProposal.ssz.golden b/core/testdata/TestSSZSerialisation_VersionedSignedBlindedProposal.ssz.golden new file mode 100644 index 0000000000000000000000000000000000000000..79caed81a3f74b5fec1dfeac0b4405198319fa86 GIT binary patch literal 8402 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 T#7sfYZSCE6fkP+AbngEFuGKP| literal 0 HcmV?d00001 diff --git a/core/tracker/inclusion.go b/core/tracker/inclusion.go index a6b13d1a1..97485657a 100644 --- a/core/tracker/inclusion.go +++ b/core/tracker/inclusion.go @@ -101,22 +101,22 @@ func (i *inclusionCore) Submitted(duty core.Duty, pubkey core.PubKey, data core. return errors.Wrap(err, "hash aggregate") } } else if duty.Type == core.DutyProposer { - block, ok := data.(core.VersionedSignedBeaconBlock) + proposal, ok := data.(core.VersionedSignedProposal) if !ok { return errors.New("invalid block") } - if eth2wrap.IsSyntheticBlock(&block.VersionedSignedBeaconBlock) { + if eth2wrap.IsSyntheticProposal(&proposal.VersionedSignedProposal) { // Report inclusion for synthetic blocks as it is already included on-chain. i.trackerInclFunc(duty, pubkey, data, nil) return nil } } else if duty.Type == core.DutyBuilderProposer { - block, ok := data.(core.VersionedSignedBlindedBeaconBlock) + block, ok := data.(core.VersionedSignedBlindedProposal) if !ok { return errors.New("invalid blinded block") } - if eth2wrap.IsSyntheticBlindedBlock(&block.VersionedSignedBlindedBeaconBlock) { + if eth2wrap.IsSyntheticBlindedBlock(&block.VersionedSignedBlindedProposal) { // Report inclusion for synthetic blinded blocks as it is already included on-chain. i.trackerInclFunc(duty, pubkey, data, nil) diff --git a/core/tracker/inclusion_internal_test.go b/core/tracker/inclusion_internal_test.go index 3780e0004..b53663a80 100644 --- a/core/tracker/inclusion_internal_test.go +++ b/core/tracker/inclusion_internal_test.go @@ -97,10 +97,10 @@ func TestInclusion(t *testing.T) { att3 := testutil.RandomAttestation() att3Duty := core.NewAttesterDuty(int64(att3.Data.Slot)) - block4 := testutil.RandomCapellaVersionedSignedBeaconBlock() + block4 := testutil.RandomVersionedSignedProposal() block4Duty := core.NewProposerDuty(int64(block4.Capella.Message.Slot)) - block5 := testutil.RandomCapellaVersionedSignedBlindedBeaconBlock() + block5 := testutil.RandomCapellaVersionedSignedBlindedProposal() block5.Capella.Message.Body.Graffiti = eth2wrap.GetSyntheticGraffiti() // Ignored, not included or missed. block5Duty := core.NewBuilderProposerDuty(int64(block5.Capella.Message.Slot)) @@ -112,7 +112,7 @@ func TestInclusion(t *testing.T) { err = incl.Submitted(att3Duty, "", core.NewAttestation(att3), 0) require.NoError(t, err) - coreBlock4, err := core.NewVersionedSignedBeaconBlock(block4) + coreBlock4, err := core.NewVersionedSignedProposal(block4) require.NoError(t, err) err = incl.Submitted(block4Duty, "", coreBlock4, 0) require.NoError(t, err) diff --git a/core/tracker/tracker.go b/core/tracker/tracker.go index 4a758b8ba..952a7ad3a 100644 --- a/core/tracker/tracker.go +++ b/core/tracker/tracker.go @@ -7,7 +7,7 @@ import ( "encoding/json" "fmt" - eth2http "github.com/attestantio/go-eth2-client/http" + eth2api "github.com/attestantio/go-eth2-client/api" "github.com/obolnetwork/charon/app/errors" "github.com/obolnetwork/charon/app/log" @@ -293,7 +293,7 @@ func analyseDutyFailed(duty core.Duty, allEvents map[core.Duty][]event, msgRootC func analyseFetcherFailed(duty core.Duty, allEvents map[core.Duty][]event, fetchErr error) (bool, step, reason, error) { reason := reasonFetcherError // Check for beacon api errors. - var eth2Error eth2http.Error + var eth2Error eth2api.Error if errors.As(fetchErr, ð2Error) { reason = reasonFetcherBN } else if !errors.Is(fetchErr, context.Canceled) && !errors.Is(fetchErr, context.DeadlineExceeded) { diff --git a/core/tracker/tracker_internal_test.go b/core/tracker/tracker_internal_test.go index 552d0ea76..04f700b80 100644 --- a/core/tracker/tracker_internal_test.go +++ b/core/tracker/tracker_internal_test.go @@ -9,8 +9,8 @@ import ( "reflect" "testing" + eth2api "github.com/attestantio/go-eth2-client/api" eth2v1 "github.com/attestantio/go-eth2-client/api/v1" - eth2http "github.com/attestantio/go-eth2-client/http" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/stretchr/testify/require" @@ -760,7 +760,7 @@ func TestAnalyseFetcherFailed(t *testing.T) { dutyAtt: {event{ duty: dutyAtt, step: fetcher, - stepErr: errors.Wrap(eth2http.Error{ + stepErr: errors.Wrap(eth2api.Error{ Method: http.MethodGet, Endpoint: "/eth/v1/validator/attestation_data", StatusCode: 404, @@ -770,7 +770,7 @@ func TestAnalyseFetcherFailed(t *testing.T) { }, reason: reasonFetcherBN, failed: true, - err: errors.Wrap(eth2http.Error{ + err: errors.Wrap(eth2api.Error{ Method: http.MethodGet, Endpoint: "/eth/v1/validator/attestation_data", StatusCode: 404, @@ -1117,7 +1117,7 @@ func TestAnalyseParSigs(t *testing.T) { var events []event makeEvents := func(n int, pubkey string) { - data := testutil.RandomBellatrixCoreVersionedSignedBeaconBlock() + data := testutil.RandomBellatrixCoreVersionedSignedProposal() offset := len(events) for i := 0; i < n; i++ { data, err := data.SetSignatures([]core.Signature{testutil.RandomCoreSignature()}) diff --git a/core/unsigneddata.go b/core/unsigneddata.go index 67cf6bf15..8726095f5 100644 --- a/core/unsigneddata.go +++ b/core/unsigneddata.go @@ -14,7 +14,6 @@ import ( "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/bellatrix" "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/attestantio/go-eth2-client/spec/deneb" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" ssz "github.com/ferranbt/fastssz" @@ -25,20 +24,20 @@ import ( var ( _ UnsignedData = AttestationData{} _ UnsignedData = AggregatedAttestation{} - _ UnsignedData = VersionedBeaconBlock{} - _ UnsignedData = VersionedBlindedBeaconBlock{} + _ UnsignedData = VersionedProposal{} + _ UnsignedData = VersionedBlindedProposal{} _ UnsignedData = SyncContribution{} // Some types also support SSZ marshalling and unmarshalling. _ ssz.Marshaler = AttestationData{} _ ssz.Marshaler = AggregatedAttestation{} - _ ssz.Marshaler = VersionedBeaconBlock{} - _ ssz.Marshaler = VersionedBlindedBeaconBlock{} + _ ssz.Marshaler = VersionedProposal{} + _ ssz.Marshaler = VersionedBlindedProposal{} _ ssz.Marshaler = SyncContribution{} _ ssz.Unmarshaler = new(AttestationData) _ ssz.Unmarshaler = new(AggregatedAttestation) - _ ssz.Unmarshaler = new(VersionedBeaconBlock) - _ ssz.Unmarshaler = new(VersionedBlindedBeaconBlock) + _ ssz.Unmarshaler = new(VersionedProposal) + _ ssz.Unmarshaler = new(VersionedBlindedProposal) _ ssz.Unmarshaler = new(SyncContribution) ) @@ -140,43 +139,44 @@ func (a *AggregatedAttestation) UnmarshalSSZ(b []byte) error { return a.Attestation.UnmarshalSSZ(b) } -// NewVersionedBeaconBlock validates and returns a new wrapped VersionedBeaconBlock. -func NewVersionedBeaconBlock(block *eth2spec.VersionedBeaconBlock) (VersionedBeaconBlock, error) { - switch block.Version { +// NewVersionedProposal validates and returns a new wrapped VersionedProposal. +func NewVersionedProposal(proposal *eth2api.VersionedProposal) (VersionedProposal, error) { + switch proposal.Version { case eth2spec.DataVersionPhase0: - if block.Phase0 == nil { - return VersionedBeaconBlock{}, errors.New("no phase0 block") + if proposal.Phase0 == nil { + return VersionedProposal{}, errors.New("no phase0 block") } case eth2spec.DataVersionAltair: - if block.Altair == nil { - return VersionedBeaconBlock{}, errors.New("no altair block") + if proposal.Altair == nil { + return VersionedProposal{}, errors.New("no altair block") } case eth2spec.DataVersionBellatrix: - if block.Bellatrix == nil { - return VersionedBeaconBlock{}, errors.New("no bellatrix block") + if proposal.Bellatrix == nil { + return VersionedProposal{}, errors.New("no bellatrix block") } case eth2spec.DataVersionCapella: - if block.Capella == nil { - return VersionedBeaconBlock{}, errors.New("no capella block") + if proposal.Capella == nil { + return VersionedProposal{}, errors.New("no capella block") } case eth2spec.DataVersionDeneb: - if block.Deneb == nil { - return VersionedBeaconBlock{}, errors.New("no deneb block") + if proposal.Deneb == nil { + return VersionedProposal{}, errors.New("no deneb block") } default: - return VersionedBeaconBlock{}, errors.New("unknown version") + return VersionedProposal{}, errors.New("unknown version") } - return VersionedBeaconBlock{VersionedBeaconBlock: *block}, nil + return VersionedProposal{VersionedProposal: *proposal}, nil } -type VersionedBeaconBlock struct { - eth2spec.VersionedBeaconBlock +// VersionedProposal wraps the eth2 versioned proposal and implements UnsignedData. +type VersionedProposal struct { + eth2api.VersionedProposal } -func (b VersionedBeaconBlock) Clone() (UnsignedData, error) { - var resp VersionedBeaconBlock - err := cloneJSONMarshaler(b, &resp) +func (p VersionedProposal) Clone() (UnsignedData, error) { + var resp VersionedProposal + err := cloneJSONMarshaler(p, &resp) if err != nil { return nil, errors.Wrap(err, "clone block") } @@ -184,20 +184,20 @@ func (b VersionedBeaconBlock) Clone() (UnsignedData, error) { return resp, nil } -func (b VersionedBeaconBlock) MarshalJSON() ([]byte, error) { +func (p VersionedProposal) MarshalJSON() ([]byte, error) { var marshaller json.Marshaler - switch b.Version { - // No block nil checks since `NewVersionedSignedBeaconBlock` assumed. + switch p.Version { + // No block nil checks since `NewVersionedProposal` assumed. case eth2spec.DataVersionPhase0: - marshaller = b.Phase0 + marshaller = p.Phase0 case eth2spec.DataVersionAltair: - marshaller = b.Altair + marshaller = p.Altair case eth2spec.DataVersionBellatrix: - marshaller = b.Bellatrix + marshaller = p.Bellatrix case eth2spec.DataVersionCapella: - marshaller = b.Capella + marshaller = p.Capella case eth2spec.DataVersionDeneb: - marshaller = b.Deneb + marshaller = p.Deneb default: return nil, errors.New("unknown version") } @@ -207,7 +207,7 @@ func (b VersionedBeaconBlock) MarshalJSON() ([]byte, error) { return nil, errors.Wrap(err, "marshal block") } - version, err := eth2util.DataVersionFromETH2(b.Version) + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { return nil, errors.Wrap(err, "convert version") } @@ -223,13 +223,13 @@ func (b VersionedBeaconBlock) MarshalJSON() ([]byte, error) { return resp, nil } -func (b *VersionedBeaconBlock) UnmarshalJSON(input []byte) error { +func (p *VersionedProposal) UnmarshalJSON(input []byte) error { var raw versionedRawBlockJSON if err := json.Unmarshal(input, &raw); err != nil { return errors.Wrap(err, "unmarshal block") } - resp := eth2spec.VersionedBeaconBlock{Version: raw.Version.ToETH2()} + resp := eth2api.VersionedProposal{Version: raw.Version.ToETH2()} switch resp.Version { case eth2spec.DataVersionPhase0: block := new(eth2p0.BeaconBlock) @@ -256,7 +256,7 @@ func (b *VersionedBeaconBlock) UnmarshalJSON(input []byte) error { } resp.Capella = block case eth2spec.DataVersionDeneb: - block := new(deneb.BeaconBlock) + block := new(eth2deneb.BlockContents) if err := json.Unmarshal(raw.Block, &block); err != nil { return errors.Wrap(err, "unmarshal deneb") } @@ -265,40 +265,41 @@ func (b *VersionedBeaconBlock) UnmarshalJSON(input []byte) error { return errors.New("unknown version") } - *b = VersionedBeaconBlock{VersionedBeaconBlock: resp} + *p = VersionedProposal{VersionedProposal: resp} return nil } -type VersionedBlindedBeaconBlock struct { - eth2api.VersionedBlindedBeaconBlock -} - -// NewVersionedBlindedBeaconBlock validates and returns a new wrapped VersionedBlindedBeaconBlock. -func NewVersionedBlindedBeaconBlock(block *eth2api.VersionedBlindedBeaconBlock) (VersionedBlindedBeaconBlock, error) { - switch block.Version { +// NewVersionedBlindedProposal validates and returns a new wrapped VersionedBlindedProposal. +func NewVersionedBlindedProposal(proposal *eth2api.VersionedBlindedProposal) (VersionedBlindedProposal, error) { + switch proposal.Version { case eth2spec.DataVersionBellatrix: - if block.Bellatrix == nil { - return VersionedBlindedBeaconBlock{}, errors.New("no bellatrix blinded block") + if proposal.Bellatrix == nil { + return VersionedBlindedProposal{}, errors.New("no bellatrix blinded proposal") } case eth2spec.DataVersionCapella: - if block.Capella == nil { - return VersionedBlindedBeaconBlock{}, errors.New("no capella blinded block") + if proposal.Capella == nil { + return VersionedBlindedProposal{}, errors.New("no capella blinded proposal") } case eth2spec.DataVersionDeneb: - if block.Deneb == nil { - return VersionedBlindedBeaconBlock{}, errors.New("no deneb blinded block") + if proposal.Deneb == nil { + return VersionedBlindedProposal{}, errors.New("no deneb blinded proposal") } default: - return VersionedBlindedBeaconBlock{}, errors.New("unknown version") + return VersionedBlindedProposal{}, errors.New("unknown version") } - return VersionedBlindedBeaconBlock{VersionedBlindedBeaconBlock: *block}, nil + return VersionedBlindedProposal{VersionedBlindedProposal: *proposal}, nil +} + +// VersionedBlindedProposal wraps the eth2 versioned blinded proposal and implements UnsignedData. +type VersionedBlindedProposal struct { + eth2api.VersionedBlindedProposal } -func (b VersionedBlindedBeaconBlock) Clone() (UnsignedData, error) { - var resp VersionedBlindedBeaconBlock - err := cloneJSONMarshaler(b, &resp) +func (p VersionedBlindedProposal) Clone() (UnsignedData, error) { + var resp VersionedBlindedProposal + err := cloneJSONMarshaler(p, &resp) if err != nil { return nil, errors.Wrap(err, "clone block") } @@ -306,16 +307,16 @@ func (b VersionedBlindedBeaconBlock) Clone() (UnsignedData, error) { return resp, nil } -func (b VersionedBlindedBeaconBlock) MarshalJSON() ([]byte, error) { +func (p VersionedBlindedProposal) MarshalJSON() ([]byte, error) { var marshaller json.Marshaler - switch b.Version { + switch p.Version { // No block nil checks since `NewVersionedSignedBlindedBeaconBlock` assumed. case eth2spec.DataVersionBellatrix: - marshaller = b.Bellatrix + marshaller = p.Bellatrix case eth2spec.DataVersionCapella: - marshaller = b.Capella + marshaller = p.Capella case eth2spec.DataVersionDeneb: - marshaller = b.Deneb + marshaller = p.Deneb default: return nil, errors.New("unknown version") } @@ -325,7 +326,7 @@ func (b VersionedBlindedBeaconBlock) MarshalJSON() ([]byte, error) { return nil, errors.Wrap(err, "marshal block") } - version, err := eth2util.DataVersionFromETH2(b.Version) + version, err := eth2util.DataVersionFromETH2(p.Version) if err != nil { return nil, errors.Wrap(err, "convert version") } @@ -341,13 +342,13 @@ func (b VersionedBlindedBeaconBlock) MarshalJSON() ([]byte, error) { return resp, nil } -func (b *VersionedBlindedBeaconBlock) UnmarshalJSON(input []byte) error { +func (p *VersionedBlindedProposal) UnmarshalJSON(input []byte) error { var raw versionedRawBlockJSON if err := json.Unmarshal(input, &raw); err != nil { return errors.Wrap(err, "unmarshal block") } - resp := eth2api.VersionedBlindedBeaconBlock{Version: raw.Version.ToETH2()} + resp := eth2api.VersionedBlindedProposal{Version: raw.Version.ToETH2()} switch resp.Version { case eth2spec.DataVersionBellatrix: block := new(eth2bellatrix.BlindedBeaconBlock) @@ -362,7 +363,7 @@ func (b *VersionedBlindedBeaconBlock) UnmarshalJSON(input []byte) error { } resp.Capella = block case eth2spec.DataVersionDeneb: - block := new(eth2deneb.BlindedBeaconBlock) + block := new(eth2deneb.BlindedBlockContents) if err := json.Unmarshal(raw.Block, &block); err != nil { return errors.Wrap(err, "unmarshal deneb") } @@ -371,7 +372,7 @@ func (b *VersionedBlindedBeaconBlock) UnmarshalJSON(input []byte) error { return errors.New("unknown version") } - *b = VersionedBlindedBeaconBlock{VersionedBlindedBeaconBlock: resp} + *p = VersionedBlindedProposal{VersionedBlindedProposal: resp} return nil } @@ -431,16 +432,16 @@ func UnmarshalUnsignedData(typ DutyType, data []byte) (UnsignedData, error) { return resp, nil case DutyProposer: - var resp VersionedBeaconBlock + var resp VersionedProposal if err := unmarshal(data, &resp); err != nil { - return nil, errors.Wrap(err, "unmarshal block") + return nil, errors.Wrap(err, "unmarshal proposal") } return resp, nil case DutyBuilderProposer: - var resp VersionedBlindedBeaconBlock + var resp VersionedBlindedProposal if err := unmarshal(data, &resp); err != nil { - return nil, errors.Wrap(err, "unmarshal block") + return nil, errors.Wrap(err, "unmarshal blinded proposal") } return resp, nil diff --git a/core/unsigneddata_test.go b/core/unsigneddata_test.go index 3a428d0fb..c1f76a34f 100644 --- a/core/unsigneddata_test.go +++ b/core/unsigneddata_test.go @@ -22,19 +22,19 @@ func TestUnsignedDataClone(t *testing.T) { }, { name: "versioned beacon block bellatrix", - data: testutil.RandomBellatrixCoreVersionedBeaconBlock(), + data: testutil.RandomBellatrixCoreVersionedProposal(), }, { name: "versioned blinded beacon block bellatrix", - data: testutil.RandomBellatrixVersionedBlindedBeaconBlock(), + data: testutil.RandomBellatrixVersionedBlindedProposal(), }, { name: "versioned beacon block capella", - data: testutil.RandomCapellaCoreVersionedBeaconBlock(), + data: testutil.RandomCapellaCoreVersionedProposal(), }, { name: "versioned blinded beacon block capella", - data: testutil.RandomCapellaVersionedBlindedBeaconBlock(), + data: testutil.RandomCapellaVersionedBlindedProposal(), }, { name: "aggregated attestation", diff --git a/core/validatorapi/eth2types.go b/core/validatorapi/eth2types.go index 646034df8..f78a920a6 100644 --- a/core/validatorapi/eth2types.go +++ b/core/validatorapi/eth2types.go @@ -15,7 +15,6 @@ import ( "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/bellatrix" "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/attestantio/go-eth2-client/spec/deneb" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/obolnetwork/charon/app/errors" @@ -105,8 +104,8 @@ type proposeBlindedBlockResponseCapella struct { } type proposeBlindedBlockResponseDeneb struct { - Version string `json:"version"` - Data *eth2deneb.BlindedBeaconBlock `json:"data"` + Version string `json:"version"` + Data *eth2deneb.BlindedBlockContents `json:"data"` } type proposeBlockResponseCapella struct { @@ -115,8 +114,8 @@ type proposeBlockResponseCapella struct { } type proposeBlockResponseDeneb struct { - Version string `json:"version"` - Data *deneb.BeaconBlock `json:"data"` + Version string `json:"version"` + Data *eth2deneb.BlockContents `json:"data"` } type validatorsResponse struct { diff --git a/core/validatorapi/router.go b/core/validatorapi/router.go index 273473c58..83faed7cd 100644 --- a/core/validatorapi/router.go +++ b/core/validatorapi/router.go @@ -58,11 +58,11 @@ type Handler interface { eth2client.AttestationDataProvider eth2client.AttestationsSubmitter eth2client.AttesterDutiesProvider - eth2client.BeaconBlockProposalProvider - eth2client.BeaconBlockSubmitter + eth2client.ProposalProvider + eth2client.ProposalSubmitter eth2exp.BeaconCommitteeSelectionAggregator - eth2client.BlindedBeaconBlockProposalProvider - eth2client.BlindedBeaconBlockSubmitter + eth2client.BlindedProposalProvider + eth2client.BlindedProposalSubmitter eth2client.NodeVersionProvider eth2client.ProposerDutiesProvider eth2client.SyncCommitteeContributionProvider @@ -128,9 +128,14 @@ func NewRouter(ctx context.Context, h Handler, eth2Cl eth2wrap.Client) (*mux.Rou Handler: proposeBlock(h), }, { - Name: "submit_block", + Name: "submit_proposal_v1", Path: "/eth/v1/beacon/blocks", - Handler: submitBlock(h), + Handler: submitProposal(h), + }, + { + Name: "submit_proposal_v2", + Path: "/eth/v2/beacon/blocks", + Handler: submitProposal(h), }, { Name: "propose_blinded_block", @@ -138,10 +143,15 @@ func NewRouter(ctx context.Context, h Handler, eth2Cl eth2wrap.Client) (*mux.Rou Handler: proposeBlindedBlock(h), }, { - Name: "submit_blinded_block", + Name: "submit_blinded_block_v1", Path: "/eth/v1/beacon/blinded_blocks", Handler: submitBlindedBlock(h), }, + { + Name: "submit_blinded_block_v2", + Path: "/eth/v2/beacon/blinded_blocks", + Handler: submitBlindedBlock(h), + }, { Name: "submit_validator_registration", Path: "/eth/v1/validator/register_validator", @@ -364,10 +374,15 @@ func attestationData(p eth2client.AttestationDataProvider) handlerFunc { return nil, nil, err } - data, err := p.AttestationData(ctx, eth2p0.Slot(slot), eth2p0.CommitteeIndex(commIdx)) + opts := ð2api.AttestationDataOpts{ + Slot: eth2p0.Slot(slot), + CommitteeIndex: eth2p0.CommitteeIndex(commIdx), + } + eth2Resp, err := p.AttestationData(ctx, opts) if err != nil { return nil, nil, err } + data := eth2Resp.Data return struct { Data *eth2p0.AttestationData `json:"data"` @@ -400,10 +415,17 @@ func proposerDuties(p eth2client.ProposerDutiesProvider) handlerFunc { // Note the ProposerDutiesProvider interface adds some sugar to the official eth2spec. // ValidatorIndices aren't provided over the wire. - data, err := p.ProposerDuties(ctx, eth2p0.Epoch(epoch), nil) + opts := ð2api.ProposerDutiesOpts{ + Epoch: eth2p0.Epoch(epoch), + Indices: nil, + } + eth2Resp, err := p.ProposerDuties(ctx, opts) if err != nil { return nil, nil, err - } else if len(data) == 0 { // Return empty json array instead of null + } + + data := eth2Resp.Data + if len(data) == 0 { // Return empty json array instead of null data = []*eth2v1.ProposerDuty{} } @@ -428,10 +450,17 @@ func attesterDuties(p eth2client.AttesterDutiesProvider) handlerFunc { return nil, nil, err } - data, err := p.AttesterDuties(ctx, eth2p0.Epoch(epoch), req) + opts := ð2api.AttesterDutiesOpts{ + Epoch: eth2p0.Epoch(epoch), + Indices: req, + } + eth2Resp, err := p.AttesterDuties(ctx, opts) if err != nil { return nil, nil, err - } else if len(data) == 0 { // Return empty json array instead of null + } + + data := eth2Resp.Data + if len(data) == 0 { // Return empty json array instead of null data = []*eth2v1.AttesterDuty{} } @@ -456,10 +485,17 @@ func syncCommitteeDuties(p eth2client.SyncCommitteeDutiesProvider) handlerFunc { return nil, nil, err } - data, err := p.SyncCommitteeDuties(ctx, eth2p0.Epoch(epoch), req) + opts := ð2api.SyncCommitteeDutiesOpts{ + Epoch: eth2p0.Epoch(epoch), + Indices: req, + } + eth2Resp, err := p.SyncCommitteeDuties(ctx, opts) if err != nil { return nil, nil, err - } else if len(data) == 0 { // Return empty json array instead of null + } + + data := eth2Resp.Data + if len(data) == 0 { // Return empty json array instead of null data = []*eth2v1.SyncCommitteeDuty{} } @@ -486,10 +522,16 @@ func syncCommitteeContribution(s eth2client.SyncCommitteeContributionProvider) h return nil, nil, err } - contribution, err := s.SyncCommitteeContribution(ctx, eth2p0.Slot(slot), subcommIdx, beaconBlockRoot) + opts := ð2api.SyncCommitteeContributionOpts{ + Slot: eth2p0.Slot(slot), + SubcommitteeIndex: subcommIdx, + BeaconBlockRoot: beaconBlockRoot, + } + eth2Resp, err := s.SyncCommitteeContribution(ctx, opts) if err != nil { return nil, nil, err } + contribution := eth2Resp.Data return syncCommitteeContributionResponse{Data: contribution}, nil, nil } @@ -509,7 +551,7 @@ func submitContributionAndProofs(s eth2client.SyncCommitteeContributionsSubmitte } // proposeBlock receives the randao from the validator and returns the unsigned BeaconBlock. -func proposeBlock(p eth2client.BeaconBlockProposalProvider) handlerFunc { +func proposeBlock(p eth2client.ProposalProvider) handlerFunc { return func(ctx context.Context, params map[string]string, query url.Values, _ contentType, _ []byte) (any, http.Header, error) { slot, err := uintParam(params, "slot") if err != nil { @@ -526,10 +568,18 @@ func proposeBlock(p eth2client.BeaconBlockProposalProvider) handlerFunc { return nil, nil, err } - block, err := p.BeaconBlockProposal(ctx, eth2p0.Slot(slot), randao, graffiti) + var graff [32]byte + copy(graff[:], graffiti) + opts := ð2api.ProposalOpts{ + Slot: eth2p0.Slot(slot), + RandaoReveal: randao, + Graffiti: graff, + } + eth2Resp, err := p.Proposal(ctx, opts) if err != nil { return nil, nil, err } + block := eth2Resp.Data resHeaders := make(http.Header) resHeaders.Add("Eth-Consensus-Version", block.Version.String()) @@ -587,7 +637,7 @@ func proposeBlock(p eth2client.BeaconBlockProposalProvider) handlerFunc { } // proposeBlindedBlock receives the randao from the validator and returns the unsigned BlindedBeaconBlock. -func proposeBlindedBlock(p eth2client.BlindedBeaconBlockProposalProvider) handlerFunc { +func proposeBlindedBlock(p eth2client.BlindedProposalProvider) handlerFunc { return func(ctx context.Context, params map[string]string, query url.Values, _ contentType, _ []byte) (any, http.Header, error) { slot, err := uintParam(params, "slot") if err != nil { @@ -599,10 +649,16 @@ func proposeBlindedBlock(p eth2client.BlindedBeaconBlockProposalProvider) handle return nil, nil, err } - block, err := p.BlindedBeaconBlockProposal(ctx, eth2p0.Slot(slot), randao, nil) + opts := ð2api.BlindedProposalOpts{ + Slot: eth2p0.Slot(slot), + RandaoReveal: randao, + Graffiti: [32]byte{}, + } + eth2Resp, err := p.BlindedProposal(ctx, opts) if err != nil { return nil, nil, err } + block := eth2Resp.Data resHeaders := make(http.Header) resHeaders.Add("Eth-Consensus-Version", block.Version.String()) @@ -641,79 +697,79 @@ func proposeBlindedBlock(p eth2client.BlindedBeaconBlockProposalProvider) handle } } -func submitBlock(p eth2client.BeaconBlockSubmitter) handlerFunc { +func submitProposal(p eth2client.ProposalSubmitter) handlerFunc { return func(ctx context.Context, _ map[string]string, _ url.Values, typ contentType, body []byte) (any, http.Header, error) { capellaBlock := new(capella.SignedBeaconBlock) err := unmarshal(typ, body, capellaBlock) if err == nil { - block := ð2spec.VersionedSignedBeaconBlock{ + block := ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionCapella, Capella: capellaBlock, } - return nil, nil, p.SubmitBeaconBlock(ctx, block) + return nil, nil, p.SubmitProposal(ctx, block) } bellatrixBlock := new(bellatrix.SignedBeaconBlock) err = unmarshal(typ, body, bellatrixBlock) if err == nil { - block := ð2spec.VersionedSignedBeaconBlock{ + block := ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: bellatrixBlock, } - return nil, nil, p.SubmitBeaconBlock(ctx, block) + return nil, nil, p.SubmitProposal(ctx, block) } altairBlock := new(altair.SignedBeaconBlock) err = unmarshal(typ, body, altairBlock) if err == nil { - block := ð2spec.VersionedSignedBeaconBlock{ + block := ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionAltair, Altair: altairBlock, } - return nil, nil, p.SubmitBeaconBlock(ctx, block) + return nil, nil, p.SubmitProposal(ctx, block) } phase0Block := new(eth2p0.SignedBeaconBlock) err = unmarshal(typ, body, phase0Block) if err == nil { - block := ð2spec.VersionedSignedBeaconBlock{ + block := ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionPhase0, Phase0: phase0Block, } - return nil, nil, p.SubmitBeaconBlock(ctx, block) + return nil, nil, p.SubmitProposal(ctx, block) } return nil, nil, errors.New("invalid submitted block", z.Hex("body", body)) } } -func submitBlindedBlock(p eth2client.BlindedBeaconBlockSubmitter) handlerFunc { +func submitBlindedBlock(p eth2client.BlindedProposalSubmitter) handlerFunc { return func(ctx context.Context, _ map[string]string, _ url.Values, typ contentType, body []byte) (any, http.Header, error) { // The blinded block maybe either bellatrix or capella. capellaBlock := new(eth2capella.SignedBlindedBeaconBlock) err := unmarshal(typ, body, capellaBlock) if err == nil { - block := ð2api.VersionedSignedBlindedBeaconBlock{ + block := ð2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: capellaBlock, } - return nil, nil, p.SubmitBlindedBeaconBlock(ctx, block) + return nil, nil, p.SubmitBlindedProposal(ctx, block) } bellatrixBlock := new(eth2bellatrix.SignedBlindedBeaconBlock) err = unmarshal(typ, body, bellatrixBlock) if err == nil { - block := ð2api.VersionedSignedBlindedBeaconBlock{ + block := ð2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: bellatrixBlock, } - return nil, nil, p.SubmitBlindedBeaconBlock(ctx, block) + return nil, nil, p.SubmitBlindedProposal(ctx, block) } return nil, nil, errors.New("invalid block") @@ -809,10 +865,15 @@ func aggregateAttestation(p eth2client.AggregateAttestationProvider) handlerFunc return nil, nil, err } - data, err := p.AggregateAttestation(ctx, eth2p0.Slot(slot), attDataRoot) + opts := ð2api.AggregateAttestationOpts{ + Slot: eth2p0.Slot(slot), + AttestationDataRoot: attDataRoot, + } + eth2Resp, err := p.AggregateAttestation(ctx, opts) if err != nil { return nil, nil, err } + data := eth2Resp.Data return struct { Data *eth2p0.Attestation `json:"data"` @@ -867,10 +928,11 @@ func submitProposalPreparations() handlerFunc { // nodeVersion returns the version of the node. func nodeVersion(p eth2client.NodeVersionProvider) handlerFunc { return func(ctx context.Context, _ map[string]string, _ url.Values, _ contentType, _ []byte) (any, http.Header, error) { - version, err := p.NodeVersion(ctx) + eth2Resp, err := p.NodeVersion(ctx) if err != nil { return nil, nil, err } + version := eth2Resp.Data return nodeVersionResponse{ Data: struct { @@ -1191,10 +1253,15 @@ func getValidatorsByID(ctx context.Context, p eth2client.ValidatorsProvider, sta pubkeys = append(pubkeys, eth2Pubkey) } - vals, err := p.ValidatorsByPubKey(ctx, stateID, pubkeys) + opts := ð2api.ValidatorsOpts{ + State: stateID, + PubKeys: pubkeys, + } + eth2Resp, err := p.Validators(ctx, opts) if err != nil { return nil, err } + vals := eth2Resp.Data return flatten(vals), nil } @@ -1208,10 +1275,15 @@ func getValidatorsByID(ctx context.Context, p eth2client.ValidatorsProvider, sta vIdxs = append(vIdxs, eth2p0.ValidatorIndex(vIdx)) } - vals, err := p.Validators(ctx, stateID, vIdxs) + opts := ð2api.ValidatorsOpts{ + State: stateID, + Indices: vIdxs, + } + eth2Resp, err := p.Validators(ctx, opts) if err != nil { return nil, err } + vals := eth2Resp.Data return flatten(vals), nil } diff --git a/core/validatorapi/router_internal_test.go b/core/validatorapi/router_internal_test.go index 0f3be869b..749fbfb23 100644 --- a/core/validatorapi/router_internal_test.go +++ b/core/validatorapi/router_internal_test.go @@ -175,11 +175,11 @@ func TestRawRouter(t *testing.T) { t.Run("empty graffiti", func(t *testing.T) { handler := testHandler{} - handler.BeaconBlockProposalFunc = func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2spec.VersionedBeaconBlock, error) { - require.Empty(t, graffiti) - resp := testutil.RandomBellatrixCoreVersionedBeaconBlock().VersionedBeaconBlock + handler.ProposalFunc = func(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.Response[*eth2api.VersionedProposal], error) { + require.Empty(t, opts.Graffiti) + resp := testutil.RandomVersionedProposal() - return &resp, nil + return wrapResponse(resp), nil } callback := func(ctx context.Context, baseURL string) { @@ -264,7 +264,7 @@ func TestRawRouter(t *testing.T) { t.Run("client timeout", func(t *testing.T) { cctx, cancel := context.WithCancel(context.Background()) handler := testHandler{ - ValidatorsFunc: func(sctx context.Context, stateID string, indices []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { + ValidatorsFunc: func(sctx context.Context, opts *eth2api.ValidatorsOpts) (*eth2api.Response[map[eth2p0.ValidatorIndex]*eth2v1.Validator], error) { cancel() // Ensure that cancelling client context (cctx) <-sctx.Done() // Results in server context (sctx) being closed. @@ -287,9 +287,9 @@ func TestRawRouter(t *testing.T) { t.Run("get_single_validators", func(t *testing.T) { handler := testHandler{ - ValidatorsFunc: func(_ context.Context, stateID string, indices []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { + ValidatorsFunc: func(_ context.Context, opts *eth2api.ValidatorsOpts) (*eth2api.Response[map[eth2p0.ValidatorIndex]*eth2v1.Validator], error) { res := make(map[eth2p0.ValidatorIndex]*eth2v1.Validator) - for _, index := range indices { + for _, index := range opts.Indices { res[index] = ð2v1.Validator{ Index: index, Status: eth2v1.ValidatorStateActiveOngoing, @@ -300,7 +300,7 @@ func TestRawRouter(t *testing.T) { } } - return res, nil + return wrapResponse(res), nil }, } @@ -319,14 +319,14 @@ func TestRawRouter(t *testing.T) { testRawRouter(t, handler, callback) }) - t.Run("submit bellatrix ssz beacon block", func(t *testing.T) { + t.Run("submit bellatrix ssz proposal", func(t *testing.T) { var done atomic.Bool - coreBlock := testutil.RandomBellatrixCoreVersionedSignedBeaconBlock() - block := &coreBlock.VersionedSignedBeaconBlock + coreBlock := testutil.RandomBellatrixCoreVersionedSignedProposal() + proposal := &coreBlock.VersionedSignedProposal handler := testHandler{ - SubmitBeaconBlockFunc: func(ctx context.Context, actual *eth2spec.VersionedSignedBeaconBlock) error { - require.Equal(t, block, actual) + SubmitProposalFunc: func(ctx context.Context, actual *eth2api.VersionedSignedProposal) error { + require.Equal(t, proposal, actual) done.Store(true) return nil @@ -334,7 +334,7 @@ func TestRawRouter(t *testing.T) { } callback := func(ctx context.Context, baseURL string) { - b, err := ssz.MarshalSSZ(block.Bellatrix) + b, err := ssz.MarshalSSZ(proposal.Bellatrix) require.NoError(t, err) req, err := http.NewRequestWithContext(ctx, http.MethodPost, @@ -353,10 +353,10 @@ func TestRawRouter(t *testing.T) { t.Run("submit capella ssz beacon block", func(t *testing.T) { var done atomic.Bool - block := testutil.RandomCapellaVersionedSignedBeaconBlock() + block := testutil.RandomVersionedSignedProposal() handler := testHandler{ - SubmitBeaconBlockFunc: func(ctx context.Context, actual *eth2spec.VersionedSignedBeaconBlock) error { + SubmitProposalFunc: func(ctx context.Context, actual *eth2api.VersionedSignedProposal) error { require.Equal(t, block, actual) done.Store(true) @@ -383,7 +383,7 @@ func TestRawRouter(t *testing.T) { }) t.Run("get response header for beacon block proposal", func(t *testing.T) { - block := ð2spec.VersionedBeaconBlock{ + block := ð2api.VersionedProposal{ Version: eth2spec.DataVersionCapella, Capella: testutil.RandomCapellaBeaconBlock(), } @@ -391,11 +391,11 @@ func TestRawRouter(t *testing.T) { require.NoError(t, err) randao := block.Capella.Body.RANDAOReveal handler := testHandler{ - BeaconBlockProposalFunc: func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2spec.VersionedBeaconBlock, error) { - require.Equal(t, expectedSlot, slot) - require.Equal(t, randao, randaoReveal) + ProposalFunc: func(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.Response[*eth2api.VersionedProposal], error) { + require.Equal(t, expectedSlot, opts.Slot) + require.Equal(t, randao, opts.RandaoReveal) - return block, nil + return wrapResponse(block), nil }, } @@ -416,7 +416,7 @@ func TestRawRouter(t *testing.T) { }) t.Run("get response header for blinded block proposal", func(t *testing.T) { - block := ð2api.VersionedBlindedBeaconBlock{ + block := ð2api.VersionedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: testutil.RandomCapellaBlindedBeaconBlock(), } @@ -424,11 +424,11 @@ func TestRawRouter(t *testing.T) { require.NoError(t, err) randao := block.Capella.Body.RANDAOReveal handler := testHandler{ - BlindedBeaconBlockProposalFunc: func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2api.VersionedBlindedBeaconBlock, error) { - require.Equal(t, expectedSlot, slot) - require.Equal(t, randao, randaoReveal) + BlindedProposalFunc: func(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.Response[*eth2api.VersionedBlindedProposal], error) { + require.Equal(t, expectedSlot, opts.Slot) + require.Equal(t, randao, opts.RandaoReveal) - return block, nil + return wrapResponse(block), nil }, } @@ -453,18 +453,18 @@ func TestRawRouter(t *testing.T) { func TestRouter(t *testing.T) { t.Run("attesterduty", func(t *testing.T) { handler := testHandler{ - AttesterDutiesFunc: func(ctx context.Context, epoch eth2p0.Epoch, il []eth2p0.ValidatorIndex) ([]*eth2v1.AttesterDuty, error) { + AttesterDutiesFunc: func(ctx context.Context, opts *eth2api.AttesterDutiesOpts) (*eth2api.Response[[]*eth2v1.AttesterDuty], error) { var res []*eth2v1.AttesterDuty - for _, index := range il { + for _, index := range opts.Indices { res = append(res, ð2v1.AttesterDuty{ - ValidatorIndex: index, // Echo index - Slot: eth2p0.Slot(epoch), // Echo epoch as slot - CommitteeLength: 1, // 0 fails validation - CommitteesAtSlot: 1, // 0 fails validation + ValidatorIndex: index, // Echo index + Slot: eth2p0.Slot(slotsPerEpoch * opts.Epoch), // Echo first slot of epoch + CommitteeLength: 1, // 0 fails validation + CommitteesAtSlot: 1, // 0 fails validation }) } - return res, nil + return wrapResponse(res), nil }, } @@ -472,16 +472,21 @@ func TestRouter(t *testing.T) { const slotEpoch = 1 const index0 = 2 const index1 = 3 - res, err := cl.AttesterDuties(ctx, eth2p0.Epoch(slotEpoch), []eth2p0.ValidatorIndex{ - eth2p0.ValidatorIndex(index0), - eth2p0.ValidatorIndex(index1), - }) + opts := ð2api.AttesterDutiesOpts{ + Epoch: eth2p0.Epoch(slotEpoch), + Indices: []eth2p0.ValidatorIndex{ + eth2p0.ValidatorIndex(index0), + eth2p0.ValidatorIndex(index1), + }, + } + resp, err := cl.AttesterDuties(ctx, opts) require.NoError(t, err) + res := resp.Data require.Len(t, res, 2) - require.Equal(t, int(res[0].Slot), slotEpoch) + require.Equal(t, int(res[0].Slot), slotEpoch*slotsPerEpoch) require.Equal(t, int(res[0].ValidatorIndex), index0) - require.Equal(t, int(res[1].Slot), slotEpoch) + require.Equal(t, int(res[1].Slot), slotEpoch*slotsPerEpoch) require.Equal(t, int(res[1].ValidatorIndex), index1) } @@ -491,27 +496,32 @@ func TestRouter(t *testing.T) { t.Run("proposerduty", func(t *testing.T) { const total = 2 handler := testHandler{ - ProposerDutiesFunc: func(ctx context.Context, epoch eth2p0.Epoch, _ []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) { + ProposerDutiesFunc: func(ctx context.Context, opts *eth2api.ProposerDutiesOpts) (*eth2api.Response[[]*eth2v1.ProposerDuty], error) { // Returns ordered total number of duties for the epoch var res []*eth2v1.ProposerDuty for i := 0; i < total; i++ { res = append(res, ð2v1.ProposerDuty{ ValidatorIndex: eth2p0.ValidatorIndex(i), - Slot: eth2p0.Slot(int(epoch)*slotsPerEpoch + i), + Slot: eth2p0.Slot(int(opts.Epoch)*slotsPerEpoch + i), }) } - return res, nil + return wrapResponse(res), nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { const epoch = 4 const validator = 1 - res, err := cl.ProposerDuties(ctx, eth2p0.Epoch(epoch), []eth2p0.ValidatorIndex{ - eth2p0.ValidatorIndex(validator), // Only request 1 of total 2 validators - }) + opts := ð2api.ProposerDutiesOpts{ + Epoch: eth2p0.Epoch(epoch), + Indices: []eth2p0.ValidatorIndex{ + eth2p0.ValidatorIndex(validator), // Only request 1 of total 2 validators + }, + } + resp, err := cl.ProposerDuties(ctx, opts) require.NoError(t, err) + res := resp.Data require.Len(t, res, 1) require.Equal(t, int(res[0].Slot), epoch*slotsPerEpoch+validator) @@ -523,27 +533,32 @@ func TestRouter(t *testing.T) { t.Run("synccommduty", func(t *testing.T) { handler := testHandler{ - SyncCommitteeDutiesFunc: func(ctx context.Context, epoch eth2p0.Epoch, vIdxs []eth2p0.ValidatorIndex) ([]*eth2v1.SyncCommitteeDuty, error) { + SyncCommitteeDutiesFunc: func(ctx context.Context, opts *eth2api.SyncCommitteeDutiesOpts) (*eth2api.Response[[]*eth2v1.SyncCommitteeDuty], error) { // Returns ordered total number of duties for the epoch var res []*eth2v1.SyncCommitteeDuty - for _, vIdx := range vIdxs { + for _, vIdx := range opts.Indices { res = append(res, ð2v1.SyncCommitteeDuty{ ValidatorIndex: vIdx, ValidatorSyncCommitteeIndices: []eth2p0.CommitteeIndex{eth2p0.CommitteeIndex(vIdx)}, }) } - return res, nil + return wrapResponse(res), nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { const epoch = 4 const validator = 1 - res, err := cl.SyncCommitteeDuties(ctx, eth2p0.Epoch(epoch), []eth2p0.ValidatorIndex{ - eth2p0.ValidatorIndex(validator), // Only request 1 of total 2 validators - }) + opts := ð2api.SyncCommitteeDutiesOpts{ + Epoch: eth2p0.Epoch(epoch), + Indices: []eth2p0.ValidatorIndex{ + eth2p0.ValidatorIndex(validator), // Only request 1 of total 2 validators + }, + } + resp, err := cl.SyncCommitteeDuties(ctx, opts) require.NoError(t, err) + res := resp.Data require.Len(t, res, 1) require.Equal(t, res[0].ValidatorSyncCommitteeIndices, []eth2p0.CommitteeIndex{eth2p0.CommitteeIndex(validator)}) @@ -555,9 +570,9 @@ func TestRouter(t *testing.T) { t.Run("get validator index", func(t *testing.T) { handler := testHandler{ - ValidatorsFunc: func(_ context.Context, stateID string, indices []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { + ValidatorsFunc: func(_ context.Context, opts *eth2api.ValidatorsOpts) (*eth2api.Response[map[eth2p0.ValidatorIndex]*eth2v1.Validator], error) { res := make(map[eth2p0.ValidatorIndex]*eth2v1.Validator) - for _, index := range indices { + for _, index := range opts.Indices { res[index] = ð2v1.Validator{ Index: index, Status: eth2v1.ValidatorStateActiveOngoing, @@ -568,7 +583,7 @@ func TestRouter(t *testing.T) { } } - return res, nil + return wrapResponse(res), nil }, } @@ -577,11 +592,16 @@ func TestRouter(t *testing.T) { val1 = 1 val2 = 2 ) - res, err := cl.Validators(ctx, "head", []eth2p0.ValidatorIndex{ - eth2p0.ValidatorIndex(val1), - eth2p0.ValidatorIndex(val2), - }) + opts := ð2api.ValidatorsOpts{ + State: "head", + Indices: []eth2p0.ValidatorIndex{ + eth2p0.ValidatorIndex(val1), + eth2p0.ValidatorIndex(val2), + }, + } + resp, err := cl.Validators(ctx, opts) require.NoError(t, err) + res := resp.Data require.Len(t, res, 2) require.EqualValues(t, val1, res[val1].Index) @@ -591,12 +611,12 @@ func TestRouter(t *testing.T) { testRouter(t, handler, callback) }) - t.Run("get validator pubkeu", func(t *testing.T) { + t.Run("get validator pubkey", func(t *testing.T) { var idx eth2p0.ValidatorIndex handler := testHandler{ - ValidatorsByPubKeyFunc: func(_ context.Context, stateID string, pubkeys []eth2p0.BLSPubKey) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { + ValidatorsFunc: func(ctx context.Context, opts *eth2api.ValidatorsOpts) (*eth2api.Response[map[eth2p0.ValidatorIndex]*eth2v1.Validator], error) { res := make(map[eth2p0.ValidatorIndex]*eth2v1.Validator) - for _, pubkey := range pubkeys { + for _, pubkey := range opts.PubKeys { idx++ res[idx] = ð2v1.Validator{ Index: idx, @@ -608,16 +628,21 @@ func TestRouter(t *testing.T) { } } - return res, nil + return wrapResponse(res), nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - res, err := cl.ValidatorsByPubKey(ctx, "head", []eth2p0.BLSPubKey{ - testutil.RandomEth2PubKey(t), - testutil.RandomEth2PubKey(t), - }) + opts := ð2api.ValidatorsOpts{ + State: "head", + PubKeys: []eth2p0.BLSPubKey{ + testutil.RandomEth2PubKey(t), + testutil.RandomEth2PubKey(t), + }, + } + resp, err := cl.Validators(ctx, opts) require.NoError(t, err) + res := resp.Data require.Len(t, res, 2) require.EqualValues(t, 1, res[1].Index) @@ -629,18 +654,22 @@ func TestRouter(t *testing.T) { t.Run("empty validators", func(t *testing.T) { handler := testHandler{ - ValidatorsByPubKeyFunc: func(context.Context, string, []eth2p0.BLSPubKey) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { - return nil, nil //nolint:nilnil + ValidatorsFunc: func(ctx context.Context, opts *eth2api.ValidatorsOpts) (*eth2api.Response[map[eth2p0.ValidatorIndex]*eth2v1.Validator], error) { + return ð2api.Response[map[eth2p0.ValidatorIndex]*eth2v1.Validator]{Data: nil}, nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - res, err := cl.ValidatorsByPubKey(ctx, "head", []eth2p0.BLSPubKey{ - testutil.RandomEth2PubKey(t), - testutil.RandomEth2PubKey(t), - }) + opts := ð2api.ValidatorsOpts{ + State: "head", + PubKeys: []eth2p0.BLSPubKey{ + testutil.RandomEth2PubKey(t), + testutil.RandomEth2PubKey(t), + }, + } + resp, err := cl.Validators(ctx, opts) require.NoError(t, err) - require.Len(t, res, 0) + require.Len(t, resp.Data, 0) } testRouter(t, handler, callback) @@ -654,8 +683,12 @@ func TestRouter(t *testing.T) { } callback := func(ctx context.Context, cl *eth2http.Service) { - res, err := cl.Validators(ctx, "head", nil) + opts := ð2api.ValidatorsOpts{ + State: "head", + } + resp, err := cl.Validators(ctx, opts) require.NoError(t, err) + res := resp.Data // Two validators are expected as the testutil.RandomBeaconState(t) returns two validators. require.Equal(t, 2, len(res)) @@ -666,15 +699,19 @@ func TestRouter(t *testing.T) { t.Run("empty attester duties", func(t *testing.T) { handler := testHandler{ - AttesterDutiesFunc: func(context.Context, eth2p0.Epoch, []eth2p0.ValidatorIndex) ([]*eth2v1.AttesterDuty, error) { - return nil, nil + AttesterDutiesFunc: func(ctx context.Context, opts *eth2api.AttesterDutiesOpts) (*eth2api.Response[[]*eth2v1.AttesterDuty], error) { + return ð2api.Response[[]*eth2v1.AttesterDuty]{}, nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - res, err := cl.AttesterDuties(ctx, eth2p0.Epoch(1), []eth2p0.ValidatorIndex{1, 2, 3}) + opts := ð2api.AttesterDutiesOpts{ + Epoch: eth2p0.Epoch(1), + Indices: []eth2p0.ValidatorIndex{1, 2, 3}, + } + resp, err := cl.AttesterDuties(ctx, opts) require.NoError(t, err) - require.Len(t, res, 0) + require.Len(t, resp.Data, 0) } testRouter(t, handler, callback) @@ -682,15 +719,19 @@ func TestRouter(t *testing.T) { t.Run("empty synccomm duties", func(t *testing.T) { handler := testHandler{ - SyncCommitteeDutiesFunc: func(context.Context, eth2p0.Epoch, []eth2p0.ValidatorIndex) ([]*eth2v1.SyncCommitteeDuty, error) { - return nil, nil + SyncCommitteeDutiesFunc: func(ctx context.Context, opts *eth2api.SyncCommitteeDutiesOpts) (*eth2api.Response[[]*eth2v1.SyncCommitteeDuty], error) { + return ð2api.Response[[]*eth2v1.SyncCommitteeDuty]{}, nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - res, err := cl.SyncCommitteeDuties(ctx, eth2p0.Epoch(1), []eth2p0.ValidatorIndex{1, 2, 3}) + opts := ð2api.SyncCommitteeDutiesOpts{ + Epoch: eth2p0.Epoch(1), + Indices: []eth2p0.ValidatorIndex{1, 2, 3}, + } + res, err := cl.SyncCommitteeDuties(ctx, opts) require.NoError(t, err) - require.Len(t, res, 0) + require.Len(t, res.Data, 0) } testRouter(t, handler, callback) @@ -698,15 +739,19 @@ func TestRouter(t *testing.T) { t.Run("empty proposer duties", func(t *testing.T) { handler := testHandler{ - ProposerDutiesFunc: func(context.Context, eth2p0.Epoch, []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) { - return nil, nil + ProposerDutiesFunc: func(ctx context.Context, opts *eth2api.ProposerDutiesOpts) (*eth2api.Response[[]*eth2v1.ProposerDuty], error) { + return ð2api.Response[[]*eth2v1.ProposerDuty]{}, nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - res, err := cl.ProposerDuties(ctx, eth2p0.Epoch(1), []eth2p0.ValidatorIndex{1, 2, 3}) + opts := ð2api.ProposerDutiesOpts{ + Epoch: eth2p0.Epoch(1), + Indices: []eth2p0.ValidatorIndex{1, 2, 3}, + } + res, err := cl.ProposerDuties(ctx, opts) require.NoError(t, err) - require.Len(t, res, 0) + require.Len(t, res.Data, 0) } testRouter(t, handler, callback) @@ -714,22 +759,26 @@ func TestRouter(t *testing.T) { t.Run("attestation data", func(t *testing.T) { handler := testHandler{ - AttestationDataFunc: func(ctx context.Context, slot eth2p0.Slot, commIdx eth2p0.CommitteeIndex) (*eth2p0.AttestationData, error) { + AttestationDataFunc: func(ctx context.Context, opts *eth2api.AttestationDataOpts) (*eth2api.Response[*eth2p0.AttestationData], error) { data := testutil.RandomAttestationData() - data.Slot = slot - data.Index = commIdx + data.Slot = opts.Slot + data.Index = opts.CommitteeIndex - return data, nil + return wrapResponse(data), nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { const slot, commIdx = 12, 23 - res, err := cl.AttestationData(ctx, slot, commIdx) + opts := ð2api.AttestationDataOpts{ + Slot: slot, + CommitteeIndex: commIdx, + } + res, err := cl.AttestationData(ctx, opts) require.NoError(t, err) - require.EqualValues(t, slot, res.Slot) - require.EqualValues(t, commIdx, res.Index) + require.EqualValues(t, slot, res.Data.Slot) + require.EqualValues(t, commIdx, res.Data.Index) } testRouter(t, handler, callback) @@ -737,18 +786,25 @@ func TestRouter(t *testing.T) { t.Run("submit randao", func(t *testing.T) { handler := testHandler{ - BeaconBlockProposalFunc: func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2spec.VersionedBeaconBlock, error) { - return nil, errors.New("not implemented") + ProposalFunc: func(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.Response[*eth2api.VersionedProposal], error) { + return ð2api.Response[*eth2api.VersionedProposal]{Data: nil}, errors.New("not implemented") }, } callback := func(ctx context.Context, cl *eth2http.Service) { slot := eth2p0.Slot(1) randaoReveal := testutil.RandomEth2Signature() - graffiti := testutil.RandomBytes32() + graffiti := testutil.RandomArray32() - res, err := cl.BeaconBlockProposal(ctx, slot, randaoReveal, graffiti) + opts := ð2api.ProposalOpts{ + Slot: slot, + RandaoReveal: randaoReveal, + Graffiti: graffiti, + } + res, err := cl.Proposal(ctx, opts) require.Error(t, err) + // TODO(xenowits): Fix this test prior to merging. Debug why res is nil. + // require.ErrorContains(t, err, "not implemented") require.Nil(t, res) } @@ -757,18 +813,24 @@ func TestRouter(t *testing.T) { t.Run("submit randao blinded block", func(t *testing.T) { handler := testHandler{ - BlindedBeaconBlockProposalFunc: func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2api.VersionedBlindedBeaconBlock, error) { - return nil, errors.New("not implemented") + BlindedProposalFunc: func(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.Response[*eth2api.VersionedBlindedProposal], error) { + return ð2api.Response[*eth2api.VersionedBlindedProposal]{}, errors.New("not implemented") }, } callback := func(ctx context.Context, cl *eth2http.Service) { slot := eth2p0.Slot(1) randaoReveal := testutil.RandomEth2Signature() - graffiti := testutil.RandomBytes32() + graffiti := testutil.RandomArray32() - res, err := cl.BlindedBeaconBlockProposal(ctx, slot, randaoReveal, graffiti) + opts := ð2api.BlindedProposalOpts{ + Slot: slot, + RandaoReveal: randaoReveal, + Graffiti: graffiti, + } + res, err := cl.BlindedProposal(ctx, opts) require.Error(t, err) + // TODO(xenowits): Fix this test prior to merging. Debug why res is nil. require.Nil(t, res) } @@ -776,7 +838,7 @@ func TestRouter(t *testing.T) { }) t.Run("submit block phase0", func(t *testing.T) { - block1 := ð2spec.VersionedSignedBeaconBlock{ + block1 := ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionPhase0, Phase0: ð2p0.SignedBeaconBlock{ Message: testutil.RandomPhase0BeaconBlock(), @@ -784,14 +846,14 @@ func TestRouter(t *testing.T) { }, } handler := testHandler{ - SubmitBeaconBlockFunc: func(ctx context.Context, block *eth2spec.VersionedSignedBeaconBlock) error { + SubmitProposalFunc: func(ctx context.Context, block *eth2api.VersionedSignedProposal) error { require.Equal(t, block, block1) return nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - err := cl.SubmitBeaconBlock(ctx, block1) + err := cl.SubmitProposal(ctx, block1) require.NoError(t, err) } @@ -799,7 +861,7 @@ func TestRouter(t *testing.T) { }) t.Run("submit block altair", func(t *testing.T) { - block1 := ð2spec.VersionedSignedBeaconBlock{ + block1 := ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionAltair, Altair: &altair.SignedBeaconBlock{ Message: testutil.RandomAltairBeaconBlock(), @@ -807,14 +869,14 @@ func TestRouter(t *testing.T) { }, } handler := testHandler{ - SubmitBeaconBlockFunc: func(ctx context.Context, block *eth2spec.VersionedSignedBeaconBlock) error { + SubmitProposalFunc: func(ctx context.Context, block *eth2api.VersionedSignedProposal) error { require.Equal(t, block, block1) return nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - err := cl.SubmitBeaconBlock(ctx, block1) + err := cl.SubmitProposal(ctx, block1) require.NoError(t, err) } @@ -822,7 +884,7 @@ func TestRouter(t *testing.T) { }) t.Run("submit block bellatrix", func(t *testing.T) { - block1 := ð2spec.VersionedSignedBeaconBlock{ + block1 := ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: &bellatrix.SignedBeaconBlock{ Message: testutil.RandomBellatrixBeaconBlock(), @@ -830,14 +892,14 @@ func TestRouter(t *testing.T) { }, } handler := testHandler{ - SubmitBeaconBlockFunc: func(ctx context.Context, block *eth2spec.VersionedSignedBeaconBlock) error { + SubmitProposalFunc: func(ctx context.Context, block *eth2api.VersionedSignedProposal) error { require.Equal(t, block, block1) return nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - err := cl.SubmitBeaconBlock(ctx, block1) + err := cl.SubmitProposal(ctx, block1) require.NoError(t, err) } @@ -845,7 +907,7 @@ func TestRouter(t *testing.T) { }) t.Run("submit block capella", func(t *testing.T) { - block1 := ð2spec.VersionedSignedBeaconBlock{ + block1 := ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionCapella, Capella: &capella.SignedBeaconBlock{ Message: testutil.RandomCapellaBeaconBlock(), @@ -853,14 +915,14 @@ func TestRouter(t *testing.T) { }, } handler := testHandler{ - SubmitBeaconBlockFunc: func(ctx context.Context, block *eth2spec.VersionedSignedBeaconBlock) error { + SubmitProposalFunc: func(ctx context.Context, block *eth2api.VersionedSignedProposal) error { require.Equal(t, block, block1) return nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - err := cl.SubmitBeaconBlock(ctx, block1) + err := cl.SubmitProposal(ctx, block1) require.NoError(t, err) } @@ -868,7 +930,7 @@ func TestRouter(t *testing.T) { }) t.Run("submit blinded block bellatrix", func(t *testing.T) { - block1 := ð2api.VersionedSignedBlindedBeaconBlock{ + block1 := ð2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: ð2bellatrix.SignedBlindedBeaconBlock{ Message: testutil.RandomBellatrixBlindedBeaconBlock(), @@ -876,14 +938,14 @@ func TestRouter(t *testing.T) { }, } handler := testHandler{ - SubmitBlindedBeaconBlockFunc: func(ctx context.Context, block *eth2api.VersionedSignedBlindedBeaconBlock) error { + SubmitBlindedProposalFunc: func(ctx context.Context, block *eth2api.VersionedSignedBlindedProposal) error { require.Equal(t, block, block1) return nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - err := cl.SubmitBlindedBeaconBlock(ctx, block1) + err := cl.SubmitBlindedProposal(ctx, block1) require.NoError(t, err) } @@ -891,7 +953,7 @@ func TestRouter(t *testing.T) { }) t.Run("submit blinded block capella", func(t *testing.T) { - block1 := ð2api.VersionedSignedBlindedBeaconBlock{ + block1 := ð2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: ð2capella.SignedBlindedBeaconBlock{ Message: testutil.RandomCapellaBlindedBeaconBlock(), @@ -899,14 +961,14 @@ func TestRouter(t *testing.T) { }, } handler := testHandler{ - SubmitBlindedBeaconBlockFunc: func(ctx context.Context, block *eth2api.VersionedSignedBlindedBeaconBlock) error { + SubmitBlindedProposalFunc: func(ctx context.Context, block *eth2api.VersionedSignedBlindedProposal) error { require.Equal(t, block1, block) return nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - err := cl.SubmitBlindedBeaconBlock(ctx, block1) + err := cl.SubmitBlindedProposal(ctx, block1) require.NoError(t, err) } @@ -956,13 +1018,13 @@ func TestRouter(t *testing.T) { t.Run("sync committee contribution", func(t *testing.T) { handler := testHandler{ - SyncCommitteeContributionFunc: func(ctx context.Context, slot eth2p0.Slot, subcommitteeIndex uint64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error) { + SyncCommitteeContributionFunc: func(ctx context.Context, opts *eth2api.SyncCommitteeContributionOpts) (*eth2api.Response[*altair.SyncCommitteeContribution], error) { contrib := testutil.RandomSyncCommitteeContribution() - contrib.Slot = slot - contrib.SubcommitteeIndex = subcommitteeIndex - contrib.BeaconBlockRoot = beaconBlockRoot + contrib.Slot = opts.Slot + contrib.SubcommitteeIndex = opts.SubcommitteeIndex + contrib.BeaconBlockRoot = opts.BeaconBlockRoot - return contrib, nil + return wrapResponse(contrib), nil }, } @@ -973,12 +1035,17 @@ func TestRouter(t *testing.T) { beaconBlockRoot = testutil.RandomRoot() ) - resp, err := cl.SyncCommitteeContribution(ctx, slot, uint64(subcommIdx), beaconBlockRoot) + opts := ð2api.SyncCommitteeContributionOpts{ + Slot: slot, + SubcommitteeIndex: uint64(subcommIdx), + BeaconBlockRoot: beaconBlockRoot, + } + resp, err := cl.SyncCommitteeContribution(ctx, opts) require.NoError(t, err) - require.Equal(t, resp.Slot, slot) - require.EqualValues(t, resp.SubcommitteeIndex, subcommIdx) - require.EqualValues(t, resp.BeaconBlockRoot, beaconBlockRoot) + require.Equal(t, resp.Data.Slot, slot) + require.EqualValues(t, resp.Data.SubcommitteeIndex, subcommIdx) + require.EqualValues(t, resp.Data.BeaconBlockRoot, beaconBlockRoot) } testRouter(t, handler, callback) @@ -1031,14 +1098,15 @@ func TestRouter(t *testing.T) { expectedVersion := "obolnetwork/charon/v0.25.0-eth123b/darwin-arm64" handler := testHandler{ - NodeVersionFunc: func(ctx context.Context) (string, error) { - return expectedVersion, nil + NodeVersionFunc: func(ctx context.Context) (*eth2api.Response[string], error) { + return wrapResponse(expectedVersion), nil }, } callback := func(ctx context.Context, cl *eth2http.Service) { - actualVersion, err := cl.NodeVersion(ctx) + eth2Resp, err := cl.NodeVersion(ctx) require.NoError(t, err) + actualVersion := eth2Resp.Data require.Equal(t, expectedVersion, actualVersion) } @@ -1191,15 +1259,15 @@ type testHandler struct { eth2client.BeaconStateProvider ProxyHandler http.HandlerFunc AggregateSyncCommitteeSelectionsFunc func(ctx context.Context, partialSelections []*eth2exp.SyncCommitteeSelection) ([]*eth2exp.SyncCommitteeSelection, error) - AttestationDataFunc func(ctx context.Context, slot eth2p0.Slot, commIdx eth2p0.CommitteeIndex) (*eth2p0.AttestationData, error) - AttesterDutiesFunc func(ctx context.Context, epoch eth2p0.Epoch, il []eth2p0.ValidatorIndex) ([]*eth2v1.AttesterDuty, error) - BeaconBlockProposalFunc func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2spec.VersionedBeaconBlock, error) - SubmitBeaconBlockFunc func(ctx context.Context, block *eth2spec.VersionedSignedBeaconBlock) error - BlindedBeaconBlockProposalFunc func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2api.VersionedBlindedBeaconBlock, error) - SubmitBlindedBeaconBlockFunc func(ctx context.Context, block *eth2api.VersionedSignedBlindedBeaconBlock) error - ProposerDutiesFunc func(ctx context.Context, epoch eth2p0.Epoch, il []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) - NodeVersionFunc func(ctx context.Context) (string, error) - ValidatorsFunc func(ctx context.Context, stateID string, indices []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) + AttestationDataFunc func(ctx context.Context, opts *eth2api.AttestationDataOpts) (*eth2api.Response[*eth2p0.AttestationData], error) + AttesterDutiesFunc func(ctx context.Context, opts *eth2api.AttesterDutiesOpts) (*eth2api.Response[[]*eth2v1.AttesterDuty], error) + ProposalFunc func(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.Response[*eth2api.VersionedProposal], error) + SubmitProposalFunc func(ctx context.Context, proposal *eth2api.VersionedSignedProposal) error + BlindedProposalFunc func(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.Response[*eth2api.VersionedBlindedProposal], error) + SubmitBlindedProposalFunc func(ctx context.Context, proposal *eth2api.VersionedSignedBlindedProposal) error + ProposerDutiesFunc func(ctx context.Context, opts *eth2api.ProposerDutiesOpts) (*eth2api.Response[[]*eth2v1.ProposerDuty], error) + NodeVersionFunc func(ctx context.Context) (*eth2api.Response[string], error) + ValidatorsFunc func(ctx context.Context, opts *eth2api.ValidatorsOpts) (*eth2api.Response[map[eth2p0.ValidatorIndex]*eth2v1.Validator], error) BeaconStateFunc func(ctx context.Context, stateId string) (*eth2spec.VersionedBeaconState, error) ValidatorsByPubKeyFunc func(ctx context.Context, stateID string, pubkeys []eth2p0.BLSPubKey) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) SubmitVoluntaryExitFunc func(ctx context.Context, exit *eth2p0.SignedVoluntaryExit) error @@ -1207,36 +1275,36 @@ type testHandler struct { AggregateBeaconCommitteeSelectionsFunc func(ctx context.Context, selections []*eth2exp.BeaconCommitteeSelection) ([]*eth2exp.BeaconCommitteeSelection, error) SubmitAggregateAttestationsFunc func(ctx context.Context, aggregateAndProofs []*eth2p0.SignedAggregateAndProof) error SubmitSyncCommitteeMessagesFunc func(ctx context.Context, messages []*altair.SyncCommitteeMessage) error - SyncCommitteeDutiesFunc func(ctx context.Context, epoch eth2p0.Epoch, validatorIndices []eth2p0.ValidatorIndex) ([]*eth2v1.SyncCommitteeDuty, error) - SyncCommitteeContributionFunc func(ctx context.Context, slot eth2p0.Slot, subcommitteeIndex uint64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error) + SyncCommitteeDutiesFunc func(ctx context.Context, opts *eth2api.SyncCommitteeDutiesOpts) (*eth2api.Response[[]*eth2v1.SyncCommitteeDuty], error) + SyncCommitteeContributionFunc func(ctx context.Context, opts *eth2api.SyncCommitteeContributionOpts) (*eth2api.Response[*altair.SyncCommitteeContribution], error) } -func (h testHandler) AttestationData(ctx context.Context, slot eth2p0.Slot, commIdx eth2p0.CommitteeIndex) (*eth2p0.AttestationData, error) { - return h.AttestationDataFunc(ctx, slot, commIdx) +func (h testHandler) AttestationData(ctx context.Context, opts *eth2api.AttestationDataOpts) (*eth2api.Response[*eth2p0.AttestationData], error) { + return h.AttestationDataFunc(ctx, opts) } -func (h testHandler) AttesterDuties(ctx context.Context, epoch eth2p0.Epoch, il []eth2p0.ValidatorIndex) ([]*eth2v1.AttesterDuty, error) { - return h.AttesterDutiesFunc(ctx, epoch, il) +func (h testHandler) AttesterDuties(ctx context.Context, opts *eth2api.AttesterDutiesOpts) (*eth2api.Response[[]*eth2v1.AttesterDuty], error) { + return h.AttesterDutiesFunc(ctx, opts) } -func (h testHandler) BeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2spec.VersionedBeaconBlock, error) { - return h.BeaconBlockProposalFunc(ctx, slot, randaoReveal, graffiti) +func (h testHandler) Proposal(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.Response[*eth2api.VersionedProposal], error) { + return h.ProposalFunc(ctx, opts) } -func (h testHandler) SubmitBeaconBlock(ctx context.Context, block *eth2spec.VersionedSignedBeaconBlock) error { - return h.SubmitBeaconBlockFunc(ctx, block) +func (h testHandler) SubmitProposal(ctx context.Context, proposal *eth2api.VersionedSignedProposal) error { + return h.SubmitProposalFunc(ctx, proposal) } -func (h testHandler) BlindedBeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2api.VersionedBlindedBeaconBlock, error) { - return h.BlindedBeaconBlockProposalFunc(ctx, slot, randaoReveal, graffiti) +func (h testHandler) BlindedProposal(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.Response[*eth2api.VersionedBlindedProposal], error) { + return h.BlindedProposalFunc(ctx, opts) } -func (h testHandler) SubmitBlindedBeaconBlock(ctx context.Context, block *eth2api.VersionedSignedBlindedBeaconBlock) error { - return h.SubmitBlindedBeaconBlockFunc(ctx, block) +func (h testHandler) SubmitBlindedProposal(ctx context.Context, block *eth2api.VersionedSignedBlindedProposal) error { + return h.SubmitBlindedProposalFunc(ctx, block) } -func (h testHandler) Validators(ctx context.Context, stateID string, indices []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { - return h.ValidatorsFunc(ctx, stateID, indices) +func (h testHandler) Validators(ctx context.Context, opts *eth2api.ValidatorsOpts) (*eth2api.Response[map[eth2p0.ValidatorIndex]*eth2v1.Validator], error) { + return h.ValidatorsFunc(ctx, opts) } func (h testHandler) BeaconState(ctx context.Context, stateID string) (*eth2spec.VersionedBeaconState, error) { @@ -1247,16 +1315,16 @@ func (h testHandler) ValidatorsByPubKey(ctx context.Context, stateID string, pub return h.ValidatorsByPubKeyFunc(ctx, stateID, pubkeys) } -func (h testHandler) ProposerDuties(ctx context.Context, epoch eth2p0.Epoch, il []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) { - return h.ProposerDutiesFunc(ctx, epoch, il) +func (h testHandler) ProposerDuties(ctx context.Context, opts *eth2api.ProposerDutiesOpts) (*eth2api.Response[[]*eth2v1.ProposerDuty], error) { + return h.ProposerDutiesFunc(ctx, opts) } -func (h testHandler) NodeVersion(ctx context.Context) (string, error) { +func (h testHandler) NodeVersion(ctx context.Context) (*eth2api.Response[string], error) { if h.NodeVersionFunc != nil { return h.NodeVersionFunc(ctx) } - return "mock_version", nil + return wrapResponse("mock_version"), nil } func (h testHandler) SubmitVoluntaryExit(ctx context.Context, exit *eth2p0.SignedVoluntaryExit) error { @@ -1279,12 +1347,12 @@ func (h testHandler) SubmitSyncCommitteeMessages(ctx context.Context, messages [ return h.SubmitSyncCommitteeMessagesFunc(ctx, messages) } -func (h testHandler) SyncCommitteeDuties(ctx context.Context, epoch eth2p0.Epoch, validatorIndices []eth2p0.ValidatorIndex) ([]*eth2v1.SyncCommitteeDuty, error) { - return h.SyncCommitteeDutiesFunc(ctx, epoch, validatorIndices) +func (h testHandler) SyncCommitteeDuties(ctx context.Context, opts *eth2api.SyncCommitteeDutiesOpts) (*eth2api.Response[[]*eth2v1.SyncCommitteeDuty], error) { + return h.SyncCommitteeDutiesFunc(ctx, opts) } -func (h testHandler) SyncCommitteeContribution(ctx context.Context, slot eth2p0.Slot, subcommitteeIndex uint64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error) { - return h.SyncCommitteeContributionFunc(ctx, slot, subcommitteeIndex, beaconBlockRoot) +func (h testHandler) SyncCommitteeContribution(ctx context.Context, opts *eth2api.SyncCommitteeContributionOpts) (*eth2api.Response[*altair.SyncCommitteeContribution], error) { + return h.SyncCommitteeContributionFunc(ctx, opts) } func (h testHandler) AggregateSyncCommitteeSelections(ctx context.Context, partialSelections []*eth2exp.SyncCommitteeSelection) ([]*eth2exp.SyncCommitteeSelection, error) { @@ -1303,7 +1371,7 @@ func (h testHandler) newBeaconHandler(t *testing.T) http.Handler { mux.HandleFunc("/eth/v1/beacon/genesis", func(w http.ResponseWriter, r *http.Request) { res, err := mock.Genesis(ctx) require.NoError(t, err) - writeResponse(ctx, w, "", res, nil) + writeResponse(ctx, w, "", res.Data, nil) }) mux.HandleFunc("/eth/v1/config/spec", func(w http.ResponseWriter, r *http.Request) { res := map[string]any{ @@ -1314,12 +1382,12 @@ func (h testHandler) newBeaconHandler(t *testing.T) http.Handler { mux.HandleFunc("/eth/v1/config/deposit_contract", func(w http.ResponseWriter, r *http.Request) { res, err := mock.DepositContract(ctx) require.NoError(t, err) - writeResponse(ctx, w, "", res, nil) + writeResponse(ctx, w, "", res.Data, nil) }) mux.HandleFunc("/eth/v1/config/fork_schedule", func(w http.ResponseWriter, r *http.Request) { res, err := mock.ForkSchedule(ctx) require.NoError(t, err) - writeResponse(ctx, w, "", nest(res, "data"), nil) + writeResponse(ctx, w, "", nest(res.Data, "data"), nil) }) mux.HandleFunc("/eth/v2/debug/beacon/states/head", func(w http.ResponseWriter, r *http.Request) { res := testutil.RandomBeaconState(t) diff --git a/core/validatorapi/validatorapi.go b/core/validatorapi/validatorapi.go index 904414857..bd98477e3 100644 --- a/core/validatorapi/validatorapi.go +++ b/core/validatorapi/validatorapi.go @@ -11,7 +11,6 @@ import ( eth2api "github.com/attestantio/go-eth2-client/api" eth2v1 "github.com/attestantio/go-eth2-client/api/v1" - eth2spec "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/altair" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "go.opentelemetry.io/otel/trace" @@ -155,8 +154,8 @@ type Component struct { pubKeyByAttFunc func(ctx context.Context, slot, commIdx, valCommIdx int64) (core.PubKey, error) awaitAttFunc func(ctx context.Context, slot, commIdx int64) (*eth2p0.AttestationData, error) - awaitBlockFunc func(ctx context.Context, slot int64) (*eth2spec.VersionedBeaconBlock, error) - awaitBlindedBlockFunc func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedBeaconBlock, error) + awaitProposalFunc func(ctx context.Context, slot int64) (*eth2api.VersionedProposal, error) + awaitBlindedProposalFunc func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedProposal, error) awaitSyncContributionFunc func(ctx context.Context, slot, subcommIdx int64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error) awaitAggAttFunc func(ctx context.Context, slot int64, attestationRoot eth2p0.Root) (*eth2p0.Attestation, error) awaitAggSigDBFunc func(context.Context, core.Duty, core.PubKey) (core.SignedData, error) @@ -164,16 +163,16 @@ type Component struct { subs []func(context.Context, core.Duty, core.ParSignedDataSet) error } -// RegisterAwaitBeaconBlock registers a function to query unsigned beacon block. +// RegisterAwaitProposal registers a function to query unsigned beacon block proposals by providing necessary options. // It supports a single function, since it is an input of the component. -func (c *Component) RegisterAwaitBeaconBlock(fn func(ctx context.Context, slot int64) (*eth2spec.VersionedBeaconBlock, error)) { - c.awaitBlockFunc = fn +func (c *Component) RegisterAwaitProposal(fn func(ctx context.Context, slot int64) (*eth2api.VersionedProposal, error)) { + c.awaitProposalFunc = fn } -// RegisterAwaitBlindedBeaconBlock registers a function to query unsigned blinded beacon block. +// RegisterAwaitBlindedProposal registers a function to query unsigned blinded beacon block proposals by providing necessary options. // It supports a single function, since it is an input of the component. -func (c *Component) RegisterAwaitBlindedBeaconBlock(fn func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedBeaconBlock, error)) { - c.awaitBlindedBlockFunc = fn +func (c *Component) RegisterAwaitBlindedProposal(fn func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedProposal, error)) { + c.awaitBlindedProposalFunc = fn } // RegisterAwaitAttestation registers a function to query attestation data. @@ -226,11 +225,16 @@ func (c *Component) Subscribe(fn func(context.Context, core.Duty, core.ParSigned } // AttestationData implements the eth2client.AttesterDutiesProvider for the router. -func (c Component) AttestationData(parent context.Context, slot eth2p0.Slot, committeeIndex eth2p0.CommitteeIndex) (*eth2p0.AttestationData, error) { - ctx, span := core.StartDutyTrace(parent, core.NewAttesterDuty(int64(slot)), "core/validatorapi.AttestationData") +func (c Component) AttestationData(parent context.Context, opts *eth2api.AttestationDataOpts) (*eth2api.Response[*eth2p0.AttestationData], error) { + ctx, span := core.StartDutyTrace(parent, core.NewAttesterDuty(int64(opts.Slot)), "core/validatorapi.AttestationData") defer span.End() - return c.awaitAttFunc(ctx, int64(slot), int64(committeeIndex)) + att, err := c.awaitAttFunc(ctx, int64(opts.Slot), int64(opts.CommitteeIndex)) + if err != nil { + return nil, err + } + + return wrapResponse(att), nil } // SubmitAttestations implements the eth2client.AttestationsSubmitter for the router. @@ -295,25 +299,24 @@ func (c Component) SubmitAttestations(ctx context.Context, attestations []*eth2p return nil } -// BeaconBlockProposal submits the randao for aggregation and inclusion in DutyProposer and then queries the dutyDB for an unsigned beacon block. -func (c Component) BeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, randao eth2p0.BLSSignature, _ []byte) (*eth2spec.VersionedBeaconBlock, error) { +func (c Component) Proposal(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.Response[*eth2api.VersionedProposal], error) { // Get proposer pubkey (this is a blocking query). - pubkey, err := c.getProposerPubkey(ctx, core.NewProposerDuty(int64(slot))) + pubkey, err := c.getProposerPubkey(ctx, core.NewProposerDuty(int64(opts.Slot))) if err != nil { return nil, err } - epoch, err := eth2util.EpochFromSlot(ctx, c.eth2Cl, slot) + epoch, err := eth2util.EpochFromSlot(ctx, c.eth2Cl, opts.Slot) if err != nil { return nil, err } sigEpoch := eth2util.SignedEpoch{ Epoch: epoch, - Signature: randao, + Signature: opts.RandaoReveal, } - duty := core.NewRandaoDuty(int64(slot)) + duty := core.NewRandaoDuty(int64(opts.Slot)) parSig := core.NewPartialSignedRandao(sigEpoch.Epoch, sigEpoch.Signature, c.shareIdx) // Verify randao signature @@ -345,75 +348,33 @@ func (c Component) BeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, ra // - Consensus will agree upon the unsigned block and insert the resulting block in the DutyDB. // - Once inserted, the query below will return. - // Query unsigned block (this is blocking). - block, err := c.awaitBlockFunc(ctx, int64(slot)) + // Query unsigned proposal (this is blocking). + proposal, err := c.awaitProposalFunc(ctx, int64(opts.Slot)) if err != nil { return nil, err } - return block, nil -} - -func (c Component) SubmitBeaconBlock(ctx context.Context, block *eth2spec.VersionedSignedBeaconBlock) error { - // Calculate slot epoch - slot, err := block.Slot() - if err != nil { - return err - } - - pubkey, err := c.getProposerPubkey(ctx, core.NewProposerDuty(int64(slot))) - if err != nil { - return err - } - - // Save Partially Signed Block to ParSigDB - duty := core.NewProposerDuty(int64(slot)) - ctx = log.WithCtx(ctx, z.Any("duty", duty)) - - signedData, err := core.NewPartialVersionedSignedBeaconBlock(block, c.shareIdx) - if err != nil { - return err - } - - // Verify block signature - err = c.verifyPartialSig(ctx, signedData, pubkey) - if err != nil { - return err - } - - log.Debug(ctx, "Beacon block submitted by validator client", z.Str("block_version", block.Version.String())) - - set := core.ParSignedDataSet{pubkey: signedData} - for _, sub := range c.subs { - // No need to clone since sub auto clones. - err = sub(ctx, duty, set) - if err != nil { - return err - } - } - - return nil + return wrapResponse(proposal), nil } -// BlindedBeaconBlockProposal submits the randao for aggregation and inclusion in DutyBuilderProposer and then queries the dutyDB for an unsigned blinded beacon block. -func (c Component) BlindedBeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, randao eth2p0.BLSSignature, _ []byte) (*eth2api.VersionedBlindedBeaconBlock, error) { +func (c Component) BlindedProposal(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.Response[*eth2api.VersionedBlindedProposal], error) { // Get proposer pubkey (this is a blocking query). - pubkey, err := c.getProposerPubkey(ctx, core.NewBuilderProposerDuty(int64(slot))) + pubkey, err := c.getProposerPubkey(ctx, core.NewBuilderProposerDuty(int64(opts.Slot))) if err != nil { return nil, err } - epoch, err := eth2util.EpochFromSlot(ctx, c.eth2Cl, slot) + epoch, err := eth2util.EpochFromSlot(ctx, c.eth2Cl, opts.Slot) if err != nil { return nil, err } sigEpoch := eth2util.SignedEpoch{ Epoch: epoch, - Signature: randao, + Signature: opts.RandaoReveal, } - duty := core.NewRandaoDuty(int64(slot)) + duty := core.NewRandaoDuty(int64(opts.Slot)) parSig := core.NewPartialSignedRandao(sigEpoch.Epoch, sigEpoch.Signature, c.shareIdx) // Verify randao signature @@ -446,17 +407,56 @@ func (c Component) BlindedBeaconBlockProposal(ctx context.Context, slot eth2p0.S // - Once inserted, the query below will return. // Query unsigned block (this is blocking). - block, err := c.awaitBlindedBlockFunc(ctx, int64(slot)) + proposal, err := c.awaitBlindedProposalFunc(ctx, int64(opts.Slot)) if err != nil { return nil, err } - return block, nil + return wrapResponse(proposal), nil +} + +func (c Component) SubmitProposal(ctx context.Context, proposal *eth2api.VersionedSignedProposal) error { + slot, err := proposal.Slot() + if err != nil { + return err + } + + pubkey, err := c.getProposerPubkey(ctx, core.NewProposerDuty(int64(slot))) + if err != nil { + return err + } + + // Save Partially Signed Block to ParSigDB + duty := core.NewProposerDuty(int64(slot)) + ctx = log.WithCtx(ctx, z.Any("duty", duty)) + + signedData, err := core.NewPartialVersionedSignedProposal(proposal, c.shareIdx) + if err != nil { + return err + } + + // Verify proposal signature + err = c.verifyPartialSig(ctx, signedData, pubkey) + if err != nil { + return err + } + + log.Debug(ctx, "Beacon proposal submitted by validator client", z.Str("block_version", proposal.Version.String())) + + set := core.ParSignedDataSet{pubkey: signedData} + for _, sub := range c.subs { + // No need to clone since sub auto clones. + err = sub(ctx, duty, set) + if err != nil { + return err + } + } + + return nil } -func (c Component) SubmitBlindedBeaconBlock(ctx context.Context, block *eth2api.VersionedSignedBlindedBeaconBlock) error { - // Calculate slot epoch - slot, err := block.Slot() +func (c Component) SubmitBlindedProposal(ctx context.Context, proposal *eth2api.VersionedSignedBlindedProposal) error { + slot, err := proposal.Slot() if err != nil { return err } @@ -470,7 +470,7 @@ func (c Component) SubmitBlindedBeaconBlock(ctx context.Context, block *eth2api. duty := core.NewBuilderProposerDuty(int64(slot)) ctx = log.WithCtx(ctx, z.Any("duty", duty)) - signedData, err := core.NewPartialVersionedSignedBlindedBeaconBlock(block, c.shareIdx) + signedData, err := core.NewPartialVersionedSignedBlindedProposal(proposal, c.shareIdx) if err != nil { return err } @@ -674,8 +674,13 @@ func (c Component) AggregateBeaconCommitteeSelections(ctx context.Context, selec // AggregateAttestation returns the aggregate attestation for the given attestation root. // It does a blocking query to DutyAggregator unsigned data from dutyDB. -func (c Component) AggregateAttestation(ctx context.Context, slot eth2p0.Slot, attestationDataRoot eth2p0.Root) (*eth2p0.Attestation, error) { - return c.awaitAggAttFunc(ctx, int64(slot), attestationDataRoot) +func (c Component) AggregateAttestation(ctx context.Context, opts *eth2api.AggregateAttestationOpts) (*eth2api.Response[*eth2p0.Attestation], error) { + aggAtt, err := c.awaitAggAttFunc(ctx, int64(opts.Slot), opts.AttestationDataRoot) + if err != nil { + return nil, err + } + + return wrapResponse(aggAtt), nil } // SubmitAggregateAttestations receives partially signed aggregateAndProofs. @@ -738,8 +743,13 @@ func (c Component) SubmitAggregateAttestations(ctx context.Context, aggregateAnd } // SyncCommitteeContribution returns sync committee contribution data for the given subcommittee and beacon block root. -func (c Component) SyncCommitteeContribution(ctx context.Context, slot eth2p0.Slot, subcommitteeIndex uint64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error) { - return c.awaitSyncContributionFunc(ctx, int64(slot), int64(subcommitteeIndex), beaconBlockRoot) +func (c Component) SyncCommitteeContribution(ctx context.Context, opts *eth2api.SyncCommitteeContributionOpts) (*eth2api.Response[*altair.SyncCommitteeContribution], error) { + contrib, err := c.awaitSyncContributionFunc(ctx, int64(opts.Slot), int64(opts.SubcommitteeIndex), opts.BeaconBlockRoot) + if err != nil { + return nil, err + } + + return wrapResponse(contrib), nil } // SubmitSyncCommitteeMessages receives the partially signed altair.SyncCommitteeMessage. @@ -899,11 +909,13 @@ func (c Component) AggregateSyncCommitteeSelections(ctx context.Context, partial return c.getAggregateSyncCommSelection(ctx, psigsBySlot) } -func (c Component) ProposerDuties(ctx context.Context, epoch eth2p0.Epoch, validatorIndices []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) { - duties, err := c.eth2Cl.ProposerDuties(ctx, epoch, validatorIndices) +// ProposerDuties obtains proposer duties for the given options. +func (c Component) ProposerDuties(ctx context.Context, opts *eth2api.ProposerDutiesOpts) (*eth2api.Response[[]*eth2v1.ProposerDuty], error) { + eth2Resp, err := c.eth2Cl.ProposerDuties(ctx, opts) if err != nil { return nil, err } + duties := eth2Resp.Data // Replace root public keys with public shares for i := 0; i < len(duties); i++ { @@ -919,14 +931,15 @@ func (c Component) ProposerDuties(ctx context.Context, epoch eth2p0.Epoch, valid duties[i].PubKey = pubshare } - return duties, nil + return wrapResponse(duties), nil } -func (c Component) AttesterDuties(ctx context.Context, epoch eth2p0.Epoch, validatorIndices []eth2p0.ValidatorIndex) ([]*eth2v1.AttesterDuty, error) { - duties, err := c.eth2Cl.AttesterDuties(ctx, epoch, validatorIndices) +func (c Component) AttesterDuties(ctx context.Context, opts *eth2api.AttesterDutiesOpts) (*eth2api.Response[[]*eth2v1.AttesterDuty], error) { + eth2Resp, err := c.eth2Cl.AttesterDuties(ctx, opts) if err != nil { return nil, err } + duties := eth2Resp.Data // Replace root public keys with public shares. for i := 0; i < len(duties); i++ { @@ -941,14 +954,16 @@ func (c Component) AttesterDuties(ctx context.Context, epoch eth2p0.Epoch, valid duties[i].PubKey = pubshare } - return duties, nil + return wrapResponse(duties), nil } -func (c Component) SyncCommitteeDuties(ctx context.Context, epoch eth2p0.Epoch, validatorIndices []eth2p0.ValidatorIndex) ([]*eth2v1.SyncCommitteeDuty, error) { - duties, err := c.eth2Cl.SyncCommitteeDuties(ctx, epoch, validatorIndices) +// SyncCommitteeDuties obtains sync committee duties. If validatorIndices is nil it will return all duties for the given epoch. +func (c Component) SyncCommitteeDuties(ctx context.Context, opts *eth2api.SyncCommitteeDutiesOpts) (*eth2api.Response[[]*eth2v1.SyncCommitteeDuty], error) { + eth2Resp, err := c.eth2Cl.SyncCommitteeDuties(ctx, opts) if err != nil { return nil, err } + duties := eth2Resp.Data // Replace root public keys with public shares. for i := 0; i < len(duties); i++ { @@ -963,16 +978,22 @@ func (c Component) SyncCommitteeDuties(ctx context.Context, epoch eth2p0.Epoch, duties[i].PubKey = pubshare } - return duties, nil + return wrapResponse(duties), nil } -func (c Component) Validators(ctx context.Context, stateID string, validatorIndices []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { - vals, err := c.eth2Cl.Validators(ctx, stateID, validatorIndices) +func (c Component) Validators(ctx context.Context, opts *eth2api.ValidatorsOpts) (*eth2api.Response[map[eth2p0.ValidatorIndex]*eth2v1.Validator], error) { + eth2Resp, err := c.eth2Cl.Validators(ctx, opts) if err != nil { return nil, err } + vals := eth2Resp.Data - return c.convertValidators(vals, len(validatorIndices) == 0) + convertedVals, err := c.convertValidators(vals, len(opts.Indices) == 0) + if err != nil { + return nil, err + } + + return wrapResponse(convertedVals), nil } func (c Component) ValidatorsByPubKey(ctx context.Context, stateID string, pubshares []eth2p0.BLSPubKey) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { @@ -987,20 +1008,26 @@ func (c Component) ValidatorsByPubKey(ctx context.Context, stateID string, pubsh pubkeys = append(pubkeys, pubkey) } - valMap, err := c.eth2Cl.ValidatorsByPubKey(ctx, stateID, pubkeys) + opts := ð2api.ValidatorsOpts{ + State: stateID, + PubKeys: pubkeys, + } + eth2Resp, err := c.eth2Cl.Validators(ctx, opts) if err != nil { return nil, err } + valMap := eth2Resp.Data // Then convert back. return c.convertValidators(valMap, len(pubkeys) == 0) } // NodeVersion returns the current version of charon. -func (Component) NodeVersion(context.Context) (string, error) { +func (Component) NodeVersion(context.Context) (*eth2api.Response[string], error) { commitSHA, _ := version.GitCommit() + charonVersion := fmt.Sprintf("obolnetwork/charon/%v-%s/%s-%s", version.Version, commitSHA, runtime.GOARCH, runtime.GOOS) - return fmt.Sprintf("obolnetwork/charon/%v-%s/%s-%s", version.Version, commitSHA, runtime.GOARCH, runtime.GOOS), nil + return wrapResponse(charonVersion), nil } // convertValidators returns the validator map with root public keys replaced by public shares for all validators that are part of the cluster. @@ -1174,3 +1201,8 @@ func (c Component) ProposerConfig(ctx context.Context) (*eth2exp.ProposerConfigR return &resp, nil } + +// wrapResponse wraps the provided data into an API Response and returns the response. +func wrapResponse[T any](data T) *eth2api.Response[T] { + return ð2api.Response[T]{Data: data} +} diff --git a/core/validatorapi/validatorapi_test.go b/core/validatorapi/validatorapi_test.go index 95cf9e0c5..ef7539ef7 100644 --- a/core/validatorapi/validatorapi_test.go +++ b/core/validatorapi/validatorapi_test.go @@ -333,7 +333,7 @@ func padTo(b []byte, size int) []byte { return append(b, make([]byte, size-len(b))...) } -func TestComponent_BeaconBlockProposal(t *testing.T) { +func TestComponent_Proposal(t *testing.T) { ctx := context.Background() eth2Cl, err := beaconmock.New() require.NoError(t, err) @@ -365,7 +365,7 @@ func TestComponent_BeaconBlockProposal(t *testing.T) { pubkey, err := core.PubKeyFromBytes(pk[:]) require.NoError(t, err) - block1 := ð2spec.VersionedBeaconBlock{ + block1 := ð2api.VersionedProposal{ Version: eth2spec.DataVersionPhase0, Phase0: testutil.RandomPhase0BeaconBlock(), } @@ -377,7 +377,7 @@ func TestComponent_BeaconBlockProposal(t *testing.T) { return core.DutyDefinitionSet{pubkey: nil}, nil }) - component.RegisterAwaitBeaconBlock(func(ctx context.Context, slot int64) (*eth2spec.VersionedBeaconBlock, error) { + component.RegisterAwaitProposal(func(ctx context.Context, slot int64) (*eth2api.VersionedProposal, error) { return block1, nil }) @@ -390,12 +390,19 @@ func TestComponent_BeaconBlockProposal(t *testing.T) { return nil }) - block2, err := component.BeaconBlockProposal(ctx, slot, randao, []byte{}) + opts := ð2api.ProposalOpts{ + Slot: slot, + RandaoReveal: randao, + Graffiti: [32]byte{}, + } + eth2Resp2, err := component.Proposal(ctx, opts) require.NoError(t, err) + block2 := eth2Resp2.Data + require.Equal(t, block1, block2) } -func TestComponent_SubmitBeaconBlock(t *testing.T) { +func TestComponent_SubmitProposal(t *testing.T) { ctx := context.Background() // Create keys (just use normal keys, not split tbls) @@ -456,7 +463,7 @@ func TestComponent_SubmitBeaconBlock(t *testing.T) { s, err := tbls.Sign(secret, sigData[:]) require.NoError(t, err) - signedBlock := ð2spec.VersionedSignedBeaconBlock{ + signedBlock := ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionPhase0, Phase0: ð2p0.SignedBeaconBlock{ Message: unsignedBlock.Phase0, @@ -466,18 +473,18 @@ func TestComponent_SubmitBeaconBlock(t *testing.T) { // Register subscriber vapi.Subscribe(func(ctx context.Context, duty core.Duty, set core.ParSignedDataSet) error { - block, ok := set[corePubKey].SignedData.(core.VersionedSignedBeaconBlock) + block, ok := set[corePubKey].SignedData.(core.VersionedSignedProposal) require.True(t, ok) - require.Equal(t, *signedBlock, block.VersionedSignedBeaconBlock) + require.Equal(t, *signedBlock, block.VersionedSignedProposal) return nil }) - err = vapi.SubmitBeaconBlock(ctx, signedBlock) + err = vapi.SubmitProposal(ctx, signedBlock) require.NoError(t, err) } -func TestComponent_SubmitBeaconBlockInvalidSignature(t *testing.T) { +func TestComponent_SubmitProposalInvalidSignature(t *testing.T) { ctx := context.Background() // Create keys (just use normal keys, not split tbls) @@ -524,7 +531,7 @@ func TestComponent_SubmitBeaconBlockInvalidSignature(t *testing.T) { unsignedBlock.Slot = slot unsignedBlock.ProposerIndex = vIdx - signedBlock := ð2spec.VersionedSignedBeaconBlock{ + signedBlock := ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionPhase0, Phase0: ð2p0.SignedBeaconBlock{ Message: unsignedBlock, @@ -534,18 +541,18 @@ func TestComponent_SubmitBeaconBlockInvalidSignature(t *testing.T) { // Register subscriber vapi.Subscribe(func(ctx context.Context, duty core.Duty, set core.ParSignedDataSet) error { - block, ok := set[corePubKey].SignedData.(core.VersionedSignedBeaconBlock) + block, ok := set[corePubKey].SignedData.(core.VersionedSignedProposal) require.True(t, ok) require.Equal(t, signedBlock, block) return nil }) - err = vapi.SubmitBeaconBlock(ctx, signedBlock) + err = vapi.SubmitProposal(ctx, signedBlock) require.ErrorContains(t, err, "signature not verified") } -func TestComponent_SubmitBeaconBlockInvalidBlock(t *testing.T) { +func TestComponent_SubmitProposalInvalidBlock(t *testing.T) { ctx := context.Background() shareIdx := 1 // Create keys (just use normal keys, not split tbls) @@ -573,42 +580,42 @@ func TestComponent_SubmitBeaconBlockInvalidBlock(t *testing.T) { // invalid block scenarios tests := []struct { name string - block *eth2spec.VersionedSignedBeaconBlock + block *eth2api.VersionedSignedProposal errMsg string }{ { name: "no phase 0 block", - block: ð2spec.VersionedSignedBeaconBlock{Version: eth2spec.DataVersionPhase0}, + block: ð2api.VersionedSignedProposal{Version: eth2spec.DataVersionPhase0}, errMsg: "no phase0 block", }, { name: "no altair block", - block: ð2spec.VersionedSignedBeaconBlock{Version: eth2spec.DataVersionAltair}, + block: ð2api.VersionedSignedProposal{Version: eth2spec.DataVersionAltair}, errMsg: "no altair block", }, { name: "no bellatrix block", - block: ð2spec.VersionedSignedBeaconBlock{Version: eth2spec.DataVersionBellatrix}, + block: ð2api.VersionedSignedProposal{Version: eth2spec.DataVersionBellatrix}, errMsg: "no bellatrix block", }, { name: "no capella block", - block: ð2spec.VersionedSignedBeaconBlock{Version: eth2spec.DataVersionCapella}, + block: ð2api.VersionedSignedProposal{Version: eth2spec.DataVersionCapella}, errMsg: "no capella block", }, { name: "no deneb block", - block: ð2spec.VersionedSignedBeaconBlock{Version: eth2spec.DataVersionDeneb}, - errMsg: "no denb block", + block: ð2api.VersionedSignedProposal{Version: eth2spec.DataVersionDeneb}, + errMsg: "no deneb block", }, { name: "none", - block: ð2spec.VersionedSignedBeaconBlock{Version: eth2spec.DataVersion(6)}, - errMsg: "unknown version", + block: ð2api.VersionedSignedProposal{Version: eth2spec.DataVersion(6)}, + errMsg: "unsupported version", }, { name: "no phase 0 sig", - block: ð2spec.VersionedSignedBeaconBlock{ + block: ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionPhase0, Phase0: ð2p0.SignedBeaconBlock{ Message: ð2p0.BeaconBlock{Slot: eth2p0.Slot(123), Body: testutil.RandomPhase0BeaconBlockBody()}, @@ -619,7 +626,7 @@ func TestComponent_SubmitBeaconBlockInvalidBlock(t *testing.T) { }, { name: "no altair sig", - block: ð2spec.VersionedSignedBeaconBlock{ + block: ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionAltair, Altair: &altair.SignedBeaconBlock{ Message: &altair.BeaconBlock{Slot: eth2p0.Slot(123), Body: testutil.RandomAltairBeaconBlockBody()}, @@ -630,7 +637,7 @@ func TestComponent_SubmitBeaconBlockInvalidBlock(t *testing.T) { }, { name: "no bellatrix sig", - block: ð2spec.VersionedSignedBeaconBlock{ + block: ð2api.VersionedSignedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: &bellatrix.SignedBeaconBlock{ Message: &bellatrix.BeaconBlock{Slot: eth2p0.Slot(123), Body: testutil.RandomBellatrixBeaconBlockBody()}, @@ -643,13 +650,13 @@ func TestComponent_SubmitBeaconBlockInvalidBlock(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - err = vapi.SubmitBeaconBlock(ctx, test.block) + err = vapi.SubmitProposal(ctx, test.block) require.ErrorContains(t, err, test.errMsg) }) } } -func TestComponent_BlindedBeaconBlockProposal(t *testing.T) { +func TestComponent_BlindedProposal(t *testing.T) { ctx := context.Background() eth2Cl, err := beaconmock.New() require.NoError(t, err) @@ -681,7 +688,7 @@ func TestComponent_BlindedBeaconBlockProposal(t *testing.T) { pubkey, err := core.PubKeyFromBytes(pk[:]) require.NoError(t, err) - block1 := ð2api.VersionedBlindedBeaconBlock{ + block1 := ð2api.VersionedBlindedProposal{ Version: eth2spec.DataVersionPhase0, Bellatrix: testutil.RandomBellatrixBlindedBeaconBlock(), } @@ -693,10 +700,14 @@ func TestComponent_BlindedBeaconBlockProposal(t *testing.T) { return core.DutyDefinitionSet{pubkey: nil}, nil }) - component.RegisterAwaitBlindedBeaconBlock(func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedBeaconBlock, error) { + component.RegisterAwaitBlindedProposal(func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedProposal, error) { return block1, nil }) + // component.RegisterAwaitBlindedBeaconBlock(func(ctx context.Context, slot int64) (*eth2api.VersionedBlindedBeaconBlock, error) { + // return block1, nil + // }) + component.Subscribe(func(ctx context.Context, duty core.Duty, set core.ParSignedDataSet) error { require.Equal(t, set, core.ParSignedDataSet{ pubkey: core.NewPartialSignedRandao(epoch, randao, vIdx), @@ -706,12 +717,19 @@ func TestComponent_BlindedBeaconBlockProposal(t *testing.T) { return nil }) - block2, err := component.BlindedBeaconBlockProposal(ctx, slot, randao, []byte{}) + opts := ð2api.BlindedProposalOpts{ + Slot: slot, + RandaoReveal: randao, + Graffiti: [32]byte{}, + } + ethResp2, err := component.BlindedProposal(ctx, opts) require.NoError(t, err) + block2 := ethResp2.Data + require.Equal(t, block1, block2) } -func TestComponent_SubmitBlindedBeaconBlock(t *testing.T) { +func TestComponent_SubmitBlindedProposal(t *testing.T) { ctx := context.Background() // Create keys (just use normal keys, not split tbls) @@ -768,7 +786,7 @@ func TestComponent_SubmitBlindedBeaconBlock(t *testing.T) { s, err := tbls.Sign(secret, sigData[:]) require.NoError(t, err) - signedBlindedBlock := ð2api.VersionedSignedBlindedBeaconBlock{ + signedBlindedBlock := ð2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: ð2capella.SignedBlindedBeaconBlock{ Message: unsignedBlindedBlock, @@ -778,18 +796,18 @@ func TestComponent_SubmitBlindedBeaconBlock(t *testing.T) { // Register subscriber vapi.Subscribe(func(ctx context.Context, duty core.Duty, set core.ParSignedDataSet) error { - block, ok := set[corePubKey].SignedData.(core.VersionedSignedBlindedBeaconBlock) + block, ok := set[corePubKey].SignedData.(core.VersionedSignedBlindedProposal) require.True(t, ok) - require.Equal(t, *signedBlindedBlock, block.VersionedSignedBlindedBeaconBlock) + require.Equal(t, *signedBlindedBlock, block.VersionedSignedBlindedProposal) return nil }) - err = vapi.SubmitBlindedBeaconBlock(ctx, signedBlindedBlock) + err = vapi.SubmitBlindedProposal(ctx, signedBlindedBlock) require.NoError(t, err) } -func TestComponent_SubmitBlindedBeaconBlockInvalidSignature(t *testing.T) { +func TestComponent_SubmitBlindedProposalInvalidSignature(t *testing.T) { ctx := context.Background() // Create keys (just use normal keys, not split tbls) @@ -837,7 +855,7 @@ func TestComponent_SubmitBlindedBeaconBlockInvalidSignature(t *testing.T) { s, err := tbls.Sign(secret, []byte("invalid msg")) require.NoError(t, err) - signedBlindedBlock := ð2api.VersionedSignedBlindedBeaconBlock{ + signedBlindedBlock := ð2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: ð2capella.SignedBlindedBeaconBlock{ Message: unsignedBlindedBlock, @@ -847,18 +865,18 @@ func TestComponent_SubmitBlindedBeaconBlockInvalidSignature(t *testing.T) { // Register subscriber vapi.Subscribe(func(ctx context.Context, duty core.Duty, set core.ParSignedDataSet) error { - block, ok := set[corePubKey].SignedData.(core.VersionedSignedBlindedBeaconBlock) + block, ok := set[corePubKey].SignedData.(core.VersionedSignedBlindedProposal) require.True(t, ok) require.Equal(t, signedBlindedBlock, block) return nil }) - err = vapi.SubmitBlindedBeaconBlock(ctx, signedBlindedBlock) + err = vapi.SubmitBlindedProposal(ctx, signedBlindedBlock) require.ErrorContains(t, err, "signature not verified") } -func TestComponent_SubmitBlindedBeaconBlockInvalidBlock(t *testing.T) { +func TestComponent_SubmitBlindedProposalInvalidBlock(t *testing.T) { ctx := context.Background() shareIdx := 1 // Create keys (just use normal keys, not split tbls) @@ -885,27 +903,27 @@ func TestComponent_SubmitBlindedBeaconBlockInvalidBlock(t *testing.T) { // invalid block scenarios tests := []struct { name string - block *eth2api.VersionedSignedBlindedBeaconBlock + block *eth2api.VersionedSignedBlindedProposal errMsg string }{ { name: "no bellatrix block", - block: ð2api.VersionedSignedBlindedBeaconBlock{Version: eth2spec.DataVersionBellatrix}, + block: ð2api.VersionedSignedBlindedProposal{Version: eth2spec.DataVersionBellatrix}, errMsg: "no bellatrix block", }, { name: "no deneb block", - block: ð2api.VersionedSignedBlindedBeaconBlock{Version: eth2spec.DataVersionDeneb}, + block: ð2api.VersionedSignedBlindedProposal{Version: eth2spec.DataVersionDeneb}, errMsg: "no deneb block", }, { name: "none", - block: ð2api.VersionedSignedBlindedBeaconBlock{Version: eth2spec.DataVersion(6)}, + block: ð2api.VersionedSignedBlindedProposal{Version: eth2spec.DataVersion(6)}, errMsg: "unsupported version", }, { name: "no bellatrix sig", - block: ð2api.VersionedSignedBlindedBeaconBlock{ + block: ð2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: ð2bellatrix.SignedBlindedBeaconBlock{ Message: ð2bellatrix.BlindedBeaconBlock{Slot: eth2p0.Slot(123), Body: testutil.RandomBellatrixBlindedBeaconBlockBody()}, @@ -916,7 +934,7 @@ func TestComponent_SubmitBlindedBeaconBlockInvalidBlock(t *testing.T) { }, { name: "no capella sig", - block: ð2api.VersionedSignedBlindedBeaconBlock{ + block: ð2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: ð2capella.SignedBlindedBeaconBlock{ Message: ð2capella.BlindedBeaconBlock{Slot: eth2p0.Slot(123), Body: testutil.RandomCapellaBlindedBeaconBlockBody()}, @@ -929,7 +947,7 @@ func TestComponent_SubmitBlindedBeaconBlockInvalidBlock(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - err = vapi.SubmitBlindedBeaconBlock(ctx, test.block) + err = vapi.SubmitBlindedProposal(ctx, test.block) require.ErrorContains(t, err, test.errMsg) }) } @@ -1095,8 +1113,14 @@ func TestComponent_Duties(t *testing.T) { // Construct the validator api component vapi, err := validatorapi.NewComponent(bmock, allPubSharesByKey, shareIdx, nil, testutil.BuilderFalse, nil) require.NoError(t, err) - duties, err := vapi.ProposerDuties(ctx, eth2p0.Epoch(epch), []eth2p0.ValidatorIndex{eth2p0.ValidatorIndex(vIdx)}) + + opts := ð2api.ProposerDutiesOpts{ + Epoch: eth2p0.Epoch(epch), + Indices: []eth2p0.ValidatorIndex{eth2p0.ValidatorIndex(vIdx)}, + } + eth2Resp, err := vapi.ProposerDuties(ctx, opts) require.NoError(t, err) + duties := eth2Resp.Data require.Len(t, duties, 1) require.Equal(t, duties[0].PubKey, eth2Share) }) @@ -1115,8 +1139,14 @@ func TestComponent_Duties(t *testing.T) { // Construct the validator api component vapi, err := validatorapi.NewComponent(bmock, allPubSharesByKey, shareIdx, nil, testutil.BuilderFalse, nil) require.NoError(t, err) - duties, err := vapi.AttesterDuties(ctx, eth2p0.Epoch(epch), []eth2p0.ValidatorIndex{eth2p0.ValidatorIndex(vIdx)}) + + opts := ð2api.AttesterDutiesOpts{ + Epoch: eth2p0.Epoch(epch), + Indices: []eth2p0.ValidatorIndex{eth2p0.ValidatorIndex(vIdx)}, + } + resp, err := vapi.AttesterDuties(ctx, opts) require.NoError(t, err) + duties := resp.Data require.Len(t, duties, 1) require.Equal(t, duties[0].PubKey, eth2Share) }) @@ -1135,8 +1165,14 @@ func TestComponent_Duties(t *testing.T) { // Construct the validator api component vapi, err := validatorapi.NewComponent(bmock, allPubSharesByKey, shareIdx, nil, testutil.BuilderFalse, nil) require.NoError(t, err) - duties, err := vapi.SyncCommitteeDuties(ctx, eth2p0.Epoch(epch), []eth2p0.ValidatorIndex{eth2p0.ValidatorIndex(vIdx)}) + + opts := ð2api.SyncCommitteeDutiesOpts{ + Epoch: eth2p0.Epoch(epch), + Indices: []eth2p0.ValidatorIndex{eth2p0.ValidatorIndex(vIdx)}, + } + eth2Resp, err := vapi.SyncCommitteeDuties(ctx, opts) require.NoError(t, err) + duties := eth2Resp.Data require.Len(t, duties, 1) require.Equal(t, duties[0].PubKey, eth2Share) }) @@ -1656,8 +1692,12 @@ func TestComponent_GetAllValidators(t *testing.T) { vapi, err := validatorapi.NewComponent(bmock, allPubSharesByKey, shareIdx, nil, testutil.BuilderFalse, nil) require.NoError(t, err) - vals, err := vapi.Validators(context.Background(), "head", nil) + opts := ð2api.ValidatorsOpts{ + State: "head", + } + resp, err := vapi.Validators(context.Background(), opts) require.NoError(t, err) + vals := resp.Data require.Len(t, vals, totalVals) for _, val := range clusterVals { @@ -1689,7 +1729,11 @@ func TestComponent_GetClusterValidatorsWithError(t *testing.T) { vapi, err := validatorapi.NewComponent(bmock, make(map[core.PubKey]map[int]tbls.PublicKey), shareIdx, nil, testutil.BuilderFalse, nil) require.NoError(t, err) - _, err = vapi.Validators(context.Background(), "head", indices) + opts := ð2api.ValidatorsOpts{ + State: "head", + Indices: indices, + } + _, err = vapi.Validators(context.Background(), opts) require.ErrorContains(t, err, "pubshare not found") } diff --git a/eth2util/eth2exp/attagg_old.go b/eth2util/eth2exp/attagg_old.go index 992534218..7cbae2110 100644 --- a/eth2util/eth2exp/attagg_old.go +++ b/eth2util/eth2exp/attagg_old.go @@ -16,10 +16,11 @@ import ( // IsAttAggregator returns true if the validator is the attestation aggregator for the given committee. // Refer: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/validator.md#aggregation-selection func IsAttAggregator(ctx context.Context, specProvider eth2client.SpecProvider, commLen uint64, slotSig eth2p0.BLSSignature) (bool, error) { - spec, err := specProvider.Spec(ctx) + resp, err := specProvider.Spec(ctx) if err != nil { return false, errors.Wrap(err, "get eth2 spec") } + spec := resp.Data aggsPerComm, ok := spec["TARGET_AGGREGATORS_PER_COMMITTEE"].(uint64) if !ok { @@ -37,10 +38,11 @@ func IsAttAggregator(ctx context.Context, specProvider eth2client.SpecProvider, // IsSyncCommAggregator returns true if the validator is the aggregator for the provided sync subcommittee. // Refer: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/validator.md#aggregation-selection func IsSyncCommAggregator(ctx context.Context, specProvider eth2client.SpecProvider, sig eth2p0.BLSSignature) (bool, error) { - spec, err := specProvider.Spec(ctx) + resp, err := specProvider.Spec(ctx) if err != nil { return false, errors.Wrap(err, "get eth2 spec") } + spec := resp.Data commSize, ok := spec["SYNC_COMMITTEE_SIZE"].(uint64) if !ok { diff --git a/eth2util/signing/signing.go b/eth2util/signing/signing.go index a490562de..0cef74f8a 100644 --- a/eth2util/signing/signing.go +++ b/eth2util/signing/signing.go @@ -30,14 +30,16 @@ const ( DomainSyncCommitteeSelectionProof DomainName = "DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF" DomainContributionAndProof DomainName = "DOMAIN_CONTRIBUTION_AND_PROOF" DomainDeposit DomainName = "DOMAIN_DEPOSIT" + DomainBlobSidecar DomainName = "DOMAIN_BLOB_SIDECAR" ) // GetDomain returns the beacon domain for the provided type. func GetDomain(ctx context.Context, eth2Cl eth2wrap.Client, name DomainName, epoch eth2p0.Epoch) (eth2p0.Domain, error) { - spec, err := eth2Cl.Spec(ctx) + resp, err := eth2Cl.Spec(ctx) if err != nil { return eth2p0.Domain{}, err } + spec := resp.Data domainType, ok := spec[string(name)] if !ok { diff --git a/go.mod b/go.mod index 1354918c2..a28d3cf2b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/obolnetwork/charon go 1.21 require ( - github.com/attestantio/go-eth2-client v0.18.3 + github.com/attestantio/go-eth2-client v0.19.4 github.com/bufbuild/buf v1.27.1 github.com/coinbase/kryptology v1.5.6-0.20220316191335-269410e1b06b github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 @@ -96,6 +96,7 @@ require ( github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.2 // indirect + github.com/huandu/go-clone v1.6.0 // indirect github.com/huin/goupnp v1.2.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect diff --git a/go.sum b/go.sum index 4f2f148d7..ea036250f 100644 --- a/go.sum +++ b/go.sum @@ -58,8 +58,8 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5 github.com/ObolNetwork/kryptology v0.0.0-20231016091344-eed023b6cac8 h1:IXoKQKGzebwtIzKADtZyAjL3MIr0m3zQFxlSxxWIdCU= github.com/ObolNetwork/kryptology v0.0.0-20231016091344-eed023b6cac8/go.mod h1:qcn33Qgj0WVLH1nuXqPt8JHY+yZabhyKxI5dHRk0fbo= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/attestantio/go-eth2-client v0.18.3 h1:hUSYh+uMLyw4mJcXWcvrPLd8ozJl61aWMdx5Cpq9hxk= -github.com/attestantio/go-eth2-client v0.18.3/go.mod h1:KSVlZSW1A3jUg5H8O89DLtqxgJprRfTtI7k89fLdhu0= +github.com/attestantio/go-eth2-client v0.19.4 h1:SiiqYqx1EhIgdaToer4FrUuiyG3wnTR4Xwb7/YkbGxA= +github.com/attestantio/go-eth2-client v0.19.4/go.mod h1:mZve1kV9Ctj0I1HH9gdg+MnI8lZ+Cb2EktEtOYrBlsM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= @@ -298,6 +298,8 @@ github.com/herumi/bls-eth-go-binary v1.32.1 h1:FbSbbNiWmuR9CWkMzFQWT5yujSn4wof48 github.com/herumi/bls-eth-go-binary v1.32.1/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U= github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= +github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= +github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= github.com/huandu/go-clone v1.6.0 h1:HMo5uvg4wgfiy5FoGOqlFLQED/VGRm2D9Pi8g1FXPGc= github.com/huandu/go-clone v1.6.0/go.mod h1:ReGivhG6op3GYr+UY3lS6mxjKp7MIGTknuU5TbTVaXE= github.com/huandu/go-clone/generic v1.6.0 h1:Wgmt/fUZ28r16F2Y3APotFD59sHk1p78K0XLdbUYN5U= diff --git a/testutil/beaconmock/beaconmock.go b/testutil/beaconmock/beaconmock.go index c84f8efb6..790b71eb9 100644 --- a/testutil/beaconmock/beaconmock.go +++ b/testutil/beaconmock/beaconmock.go @@ -116,16 +116,16 @@ type Mock struct { AttesterDutiesFunc func(context.Context, eth2p0.Epoch, []eth2p0.ValidatorIndex) ([]*eth2v1.AttesterDuty, error) BlockAttestationsFunc func(ctx context.Context, stateID string) ([]*eth2p0.Attestation, error) NodePeerCountFunc func(ctx context.Context) (int, error) - BlindedBeaconBlockProposalFunc func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2api.VersionedBlindedBeaconBlock, error) - BeaconBlockProposalFunc func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2spec.VersionedBeaconBlock, error) + ProposalFunc func(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.VersionedProposal, error) + BlindedProposalFunc func(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.VersionedBlindedProposal, error) SignedBeaconBlockFunc func(ctx context.Context, blockID string) (*eth2spec.VersionedSignedBeaconBlock, error) ProposerDutiesFunc func(context.Context, eth2p0.Epoch, []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) SubmitAttestationsFunc func(context.Context, []*eth2p0.Attestation) error - SubmitBeaconBlockFunc func(context.Context, *eth2spec.VersionedSignedBeaconBlock) error - SubmitBlindedBeaconBlockFunc func(context.Context, *eth2api.VersionedSignedBlindedBeaconBlock) error + SubmitProposalFunc func(context.Context, *eth2api.VersionedSignedProposal) error + SubmitBlindedProposalFunc func(context.Context, *eth2api.VersionedSignedBlindedProposal) error SubmitVoluntaryExitFunc func(context.Context, *eth2p0.SignedVoluntaryExit) error ValidatorsByPubKeyFunc func(context.Context, string, []eth2p0.BLSPubKey) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) - ValidatorsFunc func(context.Context, string, []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) + ValidatorsFunc func(context.Context, *eth2api.ValidatorsOpts) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) GenesisTimeFunc func(context.Context) (time.Time, error) NodeSyncingFunc func(context.Context) (*eth2v1.SyncState, error) SubmitValidatorRegistrationsFunc func(context.Context, []*eth2api.VersionedSignedValidatorRegistration) error @@ -145,60 +145,144 @@ type Mock struct { ProposerConfigFunc func(context.Context) (*eth2exp.ProposerConfigResponse, error) } -func (Mock) SetValidatorCache(func(context.Context) (eth2wrap.ActiveValidators, error)) { - // Ignore this, only rely on WithValidator functional option. +func (m Mock) AggregateAttestation(ctx context.Context, opts *eth2api.AggregateAttestationOpts) (*eth2api.Response[*eth2p0.Attestation], error) { + aggAtt, err := m.AggregateAttestationFunc(ctx, opts.Slot, opts.AttestationDataRoot) + if err != nil { + return nil, err + } + + return wrapResponse(aggAtt), nil } -func (m Mock) ActiveValidators(ctx context.Context) (eth2wrap.ActiveValidators, error) { - return m.ActiveValidatorsFunc(ctx) +func (m Mock) AttestationData(ctx context.Context, opts *eth2api.AttestationDataOpts) (*eth2api.Response[*eth2p0.AttestationData], error) { + attData, err := m.AttestationDataFunc(ctx, opts.Slot, opts.CommitteeIndex) + if err != nil { + return nil, err + } + + return wrapResponse(attData), nil } -func (m Mock) BlockAttestations(ctx context.Context, stateID string) ([]*eth2p0.Attestation, error) { - return m.BlockAttestationsFunc(ctx, stateID) +func (m Mock) AttesterDuties(ctx context.Context, opts *eth2api.AttesterDutiesOpts) (*eth2api.Response[[]*eth2v1.AttesterDuty], error) { + duties, err := m.AttesterDutiesFunc(ctx, opts.Epoch, opts.Indices) + if err != nil { + return nil, err + } + + return wrapResponse(duties), nil } -func (m Mock) NodePeerCount(ctx context.Context) (int, error) { - return m.NodePeerCountFunc(ctx) +func (m Mock) Proposal(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.Response[*eth2api.VersionedProposal], error) { + block, err := m.ProposalFunc(ctx, opts) + if err != nil { + return nil, err + } + + return wrapResponse(block), nil } -func (m Mock) SubmitAttestations(ctx context.Context, attestations []*eth2p0.Attestation) error { - return m.SubmitAttestationsFunc(ctx, attestations) +func (m Mock) BlindedProposal(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.Response[*eth2api.VersionedBlindedProposal], error) { + block, err := m.BlindedProposalFunc(ctx, opts) + if err != nil { + return nil, err + } + + return wrapResponse(block), nil } -func (m Mock) SubmitBeaconBlock(ctx context.Context, block *eth2spec.VersionedSignedBeaconBlock) error { - return m.SubmitBeaconBlockFunc(ctx, block) +func (m Mock) SubmitBlindedProposal(ctx context.Context, block *eth2api.VersionedSignedBlindedProposal) error { + return m.SubmitBlindedProposalFunc(ctx, block) } -func (m Mock) SubmitBlindedBeaconBlock(ctx context.Context, block *eth2api.VersionedSignedBlindedBeaconBlock) error { - return m.SubmitBlindedBeaconBlockFunc(ctx, block) +func (m Mock) ForkSchedule(ctx context.Context) (*eth2api.Response[[]*eth2p0.Fork], error) { + schedule, err := m.ForkScheduleFunc(ctx) + if err != nil { + return nil, err + } + + return wrapResponse(schedule), nil } -func (m Mock) SubmitVoluntaryExit(ctx context.Context, exit *eth2p0.SignedVoluntaryExit) error { - return m.SubmitVoluntaryExitFunc(ctx, exit) +func (m Mock) NodeSyncing(ctx context.Context) (*eth2api.Response[*eth2v1.SyncState], error) { + schedule, err := m.NodeSyncingFunc(ctx) + if err != nil { + return nil, err + } + + return wrapResponse(schedule), nil +} + +func (m Mock) SubmitProposal(ctx context.Context, block *eth2api.VersionedSignedProposal) error { + return m.SubmitProposalFunc(ctx, block) +} + +func (m Mock) ProposerDuties(ctx context.Context, opts *eth2api.ProposerDutiesOpts) (*eth2api.Response[[]*eth2v1.ProposerDuty], error) { + duties, err := m.ProposerDutiesFunc(ctx, opts.Epoch, opts.Indices) + if err != nil { + return nil, err + } + + return wrapResponse(duties), nil +} + +func (m Mock) SignedBeaconBlock(ctx context.Context, opts *eth2api.SignedBeaconBlockOpts) (*eth2api.Response[*eth2spec.VersionedSignedBeaconBlock], error) { + block, err := m.SignedBeaconBlockFunc(ctx, opts.Block) + if err != nil { + return nil, err + } + + return wrapResponse(block), nil } -func (m Mock) AttestationData(ctx context.Context, slot eth2p0.Slot, committeeIndex eth2p0.CommitteeIndex) (*eth2p0.AttestationData, error) { - return m.AttestationDataFunc(ctx, slot, committeeIndex) +func (m Mock) SyncCommitteeContribution(ctx context.Context, opts *eth2api.SyncCommitteeContributionOpts) (*eth2api.Response[*altair.SyncCommitteeContribution], error) { + contrib, err := m.SyncCommitteeContributionFunc(ctx, opts.Slot, opts.SubcommitteeIndex, opts.BeaconBlockRoot) + if err != nil { + return nil, err + } + + return wrapResponse(contrib), nil } -func (m Mock) BlindedBeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2api.VersionedBlindedBeaconBlock, error) { - return m.BlindedBeaconBlockProposalFunc(ctx, slot, randaoReveal, graffiti) +func (m Mock) SyncCommitteeDuties(ctx context.Context, opts *eth2api.SyncCommitteeDutiesOpts) (*eth2api.Response[[]*eth2v1.SyncCommitteeDuty], error) { + duties, err := m.SyncCommitteeDutiesFunc(ctx, opts.Epoch, opts.Indices) + if err != nil { + return nil, err + } + + return wrapResponse(duties), nil +} + +func (m Mock) Validators(ctx context.Context, opts *eth2api.ValidatorsOpts) (*eth2api.Response[map[eth2p0.ValidatorIndex]*eth2v1.Validator], error) { + vals, err := m.ValidatorsFunc(ctx, opts) + if err != nil { + return nil, err + } + + return wrapResponse(vals), nil } -func (m Mock) BeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2spec.VersionedBeaconBlock, error) { - return m.BeaconBlockProposalFunc(ctx, slot, randaoReveal, graffiti) +func (Mock) SetValidatorCache(func(context.Context) (eth2wrap.ActiveValidators, error)) { + // Ignore this, only rely on WithValidator functional option. } -func (m Mock) ProposerDuties(ctx context.Context, epoch eth2p0.Epoch, validatorIndices []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) { - return m.ProposerDutiesFunc(ctx, epoch, validatorIndices) +func (m Mock) ActiveValidators(ctx context.Context) (eth2wrap.ActiveValidators, error) { + return m.ActiveValidatorsFunc(ctx) } -func (m Mock) AttesterDuties(ctx context.Context, epoch eth2p0.Epoch, validatorIndices []eth2p0.ValidatorIndex) ([]*eth2v1.AttesterDuty, error) { - return m.AttesterDutiesFunc(ctx, epoch, validatorIndices) +func (m Mock) BlockAttestations(ctx context.Context, stateID string) ([]*eth2p0.Attestation, error) { + return m.BlockAttestationsFunc(ctx, stateID) } -func (m Mock) Validators(ctx context.Context, stateID string, validatorIndices []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { - return m.ValidatorsFunc(ctx, stateID, validatorIndices) +func (m Mock) NodePeerCount(ctx context.Context) (int, error) { + return m.NodePeerCountFunc(ctx) +} + +func (m Mock) SubmitAttestations(ctx context.Context, attestations []*eth2p0.Attestation) error { + return m.SubmitAttestationsFunc(ctx, attestations) +} + +func (m Mock) SubmitVoluntaryExit(ctx context.Context, exit *eth2p0.SignedVoluntaryExit) error { + return m.SubmitVoluntaryExitFunc(ctx, exit) } func (m Mock) ValidatorsByPubKey(ctx context.Context, stateID string, validatorPubKeys []eth2p0.BLSPubKey) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { @@ -209,10 +293,6 @@ func (m Mock) GenesisTime(ctx context.Context) (time.Time, error) { return m.GenesisTimeFunc(ctx) } -func (m Mock) NodeSyncing(ctx context.Context) (*eth2v1.SyncState, error) { - return m.NodeSyncingFunc(ctx) -} - func (m Mock) SubmitValidatorRegistrations(ctx context.Context, registrations []*eth2api.VersionedSignedValidatorRegistration) error { return m.SubmitValidatorRegistrationsFunc(ctx, registrations) } @@ -229,18 +309,10 @@ func (m Mock) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscripti return m.SubmitBeaconCommitteeSubscriptionsFunc(ctx, subscriptions) } -func (m Mock) AggregateAttestation(ctx context.Context, slot eth2p0.Slot, attestationDataRoot eth2p0.Root) (*eth2p0.Attestation, error) { - return m.AggregateAttestationFunc(ctx, slot, attestationDataRoot) -} - func (m Mock) SubmitAggregateAttestations(ctx context.Context, aggregateAndProofs []*eth2p0.SignedAggregateAndProof) error { return m.SubmitAggregateAttestationsFunc(ctx, aggregateAndProofs) } -func (m Mock) SyncCommitteeDuties(ctx context.Context, epoch eth2p0.Epoch, validatorIndices []eth2p0.ValidatorIndex) ([]*eth2v1.SyncCommitteeDuty, error) { - return m.SyncCommitteeDutiesFunc(ctx, epoch, validatorIndices) -} - func (m Mock) SubmitSyncCommitteeMessages(ctx context.Context, messages []*altair.SyncCommitteeMessage) error { return m.SubmitSyncCommitteeMessagesFunc(ctx, messages) } @@ -249,10 +321,6 @@ func (m Mock) SubmitSyncCommitteeContributions(ctx context.Context, contribution return m.SubmitSyncCommitteeContributionsFunc(ctx, contributionAndProofs) } -func (m Mock) SyncCommitteeContribution(ctx context.Context, slot eth2p0.Slot, subcommitteeIndex uint64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error) { - return m.SyncCommitteeContributionFunc(ctx, slot, subcommitteeIndex, beaconBlockRoot) -} - func (m Mock) SubmitSyncCommitteeSubscriptions(ctx context.Context, subscriptions []*eth2v1.SyncCommitteeSubscription) error { return m.SubmitSyncCommitteeSubscriptionsFunc(ctx, subscriptions) } @@ -261,18 +329,10 @@ func (m Mock) SubmitProposalPreparations(ctx context.Context, preparations []*et return m.SubmitProposalPreparationsFunc(ctx, preparations) } -func (m Mock) SignedBeaconBlock(ctx context.Context, blockID string) (*eth2spec.VersionedSignedBeaconBlock, error) { - return m.SignedBeaconBlockFunc(ctx, blockID) -} - func (m Mock) SlotsPerEpoch(ctx context.Context) (uint64, error) { return m.SlotsPerEpochFunc(ctx) } -func (m Mock) ForkSchedule(ctx context.Context) ([]*eth2p0.Fork, error) { - return m.ForkScheduleFunc(ctx) -} - func (m Mock) ProposerConfig(ctx context.Context) (*eth2exp.ProposerConfigResponse, error) { return m.ProposerConfigFunc(ctx) } @@ -295,3 +355,8 @@ func (m Mock) Close() error { return nil } + +// wrapResponse wraps the provided data into an API Response and returns the response. +func wrapResponse[T any](data T) *eth2api.Response[T] { + return ð2api.Response[T]{Data: data} +} diff --git a/testutil/beaconmock/beaconmock_fuzz.go b/testutil/beaconmock/beaconmock_fuzz.go index 14ef3eba1..3c23a252d 100644 --- a/testutil/beaconmock/beaconmock_fuzz.go +++ b/testutil/beaconmock/beaconmock_fuzz.go @@ -8,7 +8,6 @@ import ( eth2api "github.com/attestantio/go-eth2-client/api" eth2v1 "github.com/attestantio/go-eth2-client/api/v1" - eth2spec "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/altair" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" fuzz "github.com/google/gofuzz" @@ -109,8 +108,8 @@ func WithBeaconMockFuzzer() Option { return attData, nil } - mock.BeaconBlockProposalFunc = func(context.Context, eth2p0.Slot, eth2p0.BLSSignature, []byte) (*eth2spec.VersionedBeaconBlock, error) { - var block *eth2spec.VersionedBeaconBlock + mock.ProposalFunc = func(context.Context, *eth2api.ProposalOpts) (*eth2api.VersionedProposal, error) { + var block *eth2api.VersionedProposal fuzz.New().Fuzz(&block) return block, nil @@ -123,15 +122,15 @@ func WithBeaconMockFuzzer() Option { return att, nil } - mock.ValidatorsFunc = func(context.Context, string, []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { + mock.ValidatorsFunc = func(context.Context, *eth2api.ValidatorsOpts) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { var vals map[eth2p0.ValidatorIndex]*eth2v1.Validator fuzz.New().Fuzz(&vals) return vals, nil } - mock.BlindedBeaconBlockProposalFunc = func(context.Context, eth2p0.Slot, eth2p0.BLSSignature, []byte) (*eth2api.VersionedBlindedBeaconBlock, error) { - var block *eth2api.VersionedBlindedBeaconBlock + mock.BlindedProposalFunc = func(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.VersionedBlindedProposal, error) { + var block *eth2api.VersionedBlindedProposal fuzz.New().Fuzz(&block) return block, nil diff --git a/testutil/beaconmock/beaconmock_test.go b/testutil/beaconmock/beaconmock_test.go index 0d5a5e045..4b1a3589e 100644 --- a/testutil/beaconmock/beaconmock_test.go +++ b/testutil/beaconmock/beaconmock_test.go @@ -6,6 +6,7 @@ import ( "context" "testing" + eth2api "github.com/attestantio/go-eth2-client/api" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/stretchr/testify/require" @@ -22,9 +23,13 @@ func TestDeterministicAttesterDuties(t *testing.T) { ) require.NoError(t, err) - attDuty, err := bmock.AttesterDuties(context.Background(), 1, []eth2p0.ValidatorIndex{2}) + opts := ð2api.AttesterDutiesOpts{ + Epoch: 1, + Indices: []eth2p0.ValidatorIndex{2}, + } + resp, err := bmock.AttesterDuties(context.Background(), opts) require.NoError(t, err) - testutil.RequireGoldenJSON(t, attDuty) + testutil.RequireGoldenJSON(t, resp.Data) } func TestDeterministicProposerDuties(t *testing.T) { @@ -34,9 +39,13 @@ func TestDeterministicProposerDuties(t *testing.T) { ) require.NoError(t, err) - proDuty, err := bmock.ProposerDuties(context.Background(), 1, []eth2p0.ValidatorIndex{2}) + opts := ð2api.ProposerDutiesOpts{ + Epoch: 1, + Indices: []eth2p0.ValidatorIndex{2}, + } + resp, err := bmock.ProposerDuties(context.Background(), opts) require.NoError(t, err) - testutil.RequireGoldenJSON(t, proDuty) + testutil.RequireGoldenJSON(t, resp.Data) } func TestAttestationStore(t *testing.T) { @@ -45,24 +54,46 @@ func TestAttestationStore(t *testing.T) { ctx := context.Background() - attData, err := bmock.AttestationData(ctx, 1, 2) + opts := ð2api.AttestationDataOpts{ + Slot: 1, + CommitteeIndex: 2, + } + resp, err := bmock.AttestationData(ctx, opts) require.NoError(t, err) + attData := resp.Data testutil.RequireGoldenJSON(t, attData) root, err := attData.HashTreeRoot() require.NoError(t, err) - att, err := bmock.AggregateAttestation(ctx, 0, root) // Slot is ignored. + aggAttOpts := ð2api.AggregateAttestationOpts{ + Slot: 0, + AttestationDataRoot: root, + } + bmockResp, err := bmock.AggregateAttestation(ctx, aggAttOpts) // Slot is ignored. require.NoError(t, err) + att := bmockResp.Data require.Equal(t, attData, att.Data) - _, err = bmock.AggregateAttestation(ctx, attData.Slot, eth2p0.Root{}) // Not found + aggAttopts2 := ð2api.AggregateAttestationOpts{ + Slot: attData.Slot, + AttestationDataRoot: eth2p0.Root{}, + } + _, err = bmock.AggregateAttestation(ctx, aggAttopts2) // Not found require.Error(t, err) // New attestation data with much larger slots delete old ones. - _, err = bmock.AttestationData(ctx, 99, 2) + attDataOpts := ð2api.AttestationDataOpts{ + Slot: 99, + CommitteeIndex: 2, + } + _, err = bmock.AttestationData(ctx, attDataOpts) require.NoError(t, err) - _, err = bmock.AggregateAttestation(ctx, 0, root) // Deleted. + aggDataOpts := ð2api.AggregateAttestationOpts{ + Slot: 0, + AttestationDataRoot: root, + } + _, err = bmock.AggregateAttestation(ctx, aggDataOpts) // Deleted. require.Error(t, err) } diff --git a/testutil/beaconmock/options.go b/testutil/beaconmock/options.go index 090e52bf3..5a74f88ad 100644 --- a/testutil/beaconmock/options.go +++ b/testutil/beaconmock/options.go @@ -160,9 +160,9 @@ func WithValidatorSet(set ValidatorSet) Option { return resp, nil } - mock.ValidatorsFunc = func(ctx context.Context, stateID string, indexes []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { + mock.ValidatorsFunc = func(ctx context.Context, opts *eth2api.ValidatorsOpts) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { resp := make(map[eth2p0.ValidatorIndex]*eth2v1.Validator) - if len(indexes) == 0 { + if len(opts.Indices) == 0 { for idx, val := range set { resp[idx] = cloneValidator(val) } @@ -170,7 +170,7 @@ func WithValidatorSet(set ValidatorSet) Option { return resp, nil } - for _, index := range indexes { + for _, index := range opts.Indices { val, ok := set[index] if ok { resp[index] = cloneValidator(val) @@ -273,10 +273,15 @@ func WithDeterministicAttesterDuties(factor int) Option { return func(mock *Mock) { mock.AttesterDutiesFunc = func(ctx context.Context, epoch eth2p0.Epoch, indices []eth2p0.ValidatorIndex) ([]*eth2v1.AttesterDuty, error) { - vals, err := mock.Validators(ctx, "", indices) + opts := ð2api.ValidatorsOpts{ + State: "", + Indices: indices, + } + eth2Resp, err := mock.Validators(ctx, opts) if err != nil { return nil, err } + vals := eth2Resp.Data slotsPerEpoch, err := mock.SlotsPerEpoch(ctx) if err != nil { @@ -397,10 +402,15 @@ func WithDeterministicSyncCommDuties(n, k int) Option { return nil, nil } - vals, err := mock.Validators(ctx, "", indices) + opts := ð2api.ValidatorsOpts{ + State: "", + Indices: indices, + } + eth2Resp, err := mock.Validators(ctx, opts) if err != nil { return nil, err } + vals := eth2Resp.Data var resp []*eth2v1.SyncCommitteeDuty for i, index := range indices { @@ -465,25 +475,25 @@ func defaultMock(httpMock HTTPMock, httpServer *http.Server, clock clockwork.Clo HTTPMock: httpMock, httpServer: httpServer, headProducer: headProducer, - BeaconBlockProposalFunc: func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2spec.VersionedBeaconBlock, error) { - block := ð2spec.VersionedBeaconBlock{ + ProposalFunc: func(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.VersionedProposal, error) { + block := ð2api.VersionedProposal{ Version: eth2spec.DataVersionCapella, Capella: testutil.RandomCapellaBeaconBlock(), } - block.Capella.Slot = slot - block.Capella.Body.RANDAOReveal = randaoReveal - block.Capella.Body.Graffiti = array32(graffiti) + block.Capella.Slot = opts.Slot + block.Capella.Body.RANDAOReveal = opts.RandaoReveal + block.Capella.Body.Graffiti = opts.Graffiti return block, nil }, - BlindedBeaconBlockProposalFunc: func(ctx context.Context, slot eth2p0.Slot, randaoReveal eth2p0.BLSSignature, graffiti []byte) (*eth2api.VersionedBlindedBeaconBlock, error) { - block := ð2api.VersionedBlindedBeaconBlock{ + BlindedProposalFunc: func(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.VersionedBlindedProposal, error) { + block := ð2api.VersionedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: testutil.RandomCapellaBlindedBeaconBlock(), } - block.Capella.Slot = slot - block.Capella.Body.RANDAOReveal = randaoReveal - block.Capella.Body.Graffiti = array32(graffiti) + block.Capella.Slot = opts.Slot + block.Capella.Body.RANDAOReveal = opts.RandaoReveal + block.Capella.Body.Graffiti = opts.Graffiti return block, nil }, @@ -519,7 +529,7 @@ func defaultMock(httpMock HTTPMock, httpServer *http.Server, clock clockwork.Clo ActiveValidatorsFunc: func(ctx context.Context) (eth2wrap.ActiveValidators, error) { return nil, nil }, - ValidatorsFunc: func(context.Context, string, []eth2p0.ValidatorIndex) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { + ValidatorsFunc: func(context.Context, *eth2api.ValidatorsOpts) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { return nil, nil }, ValidatorsByPubKeyFunc: func(context.Context, string, []eth2p0.BLSPubKey) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) { @@ -528,10 +538,10 @@ func defaultMock(httpMock HTTPMock, httpServer *http.Server, clock clockwork.Clo SubmitAttestationsFunc: func(context.Context, []*eth2p0.Attestation) error { return nil }, - SubmitBeaconBlockFunc: func(context.Context, *eth2spec.VersionedSignedBeaconBlock) error { + SubmitProposalFunc: func(context.Context, *eth2api.VersionedSignedProposal) error { return nil }, - SubmitBlindedBeaconBlockFunc: func(context.Context, *eth2api.VersionedSignedBlindedBeaconBlock) error { + SubmitBlindedProposalFunc: func(context.Context, *eth2api.VersionedSignedBlindedProposal) error { return nil }, SubmitVoluntaryExitFunc: func(context.Context, *eth2p0.SignedVoluntaryExit) error { @@ -541,7 +551,12 @@ func defaultMock(httpMock HTTPMock, httpServer *http.Server, clock clockwork.Clo return httpMock.GenesisTime(ctx) }, NodeSyncingFunc: func(ctx context.Context) (*eth2v1.SyncState, error) { - return httpMock.NodeSyncing(ctx) + resp, err := httpMock.NodeSyncing(ctx) + if err != nil { + return nil, err + } + + return resp.Data, nil }, SubmitValidatorRegistrationsFunc: func(context.Context, []*eth2api.VersionedSignedValidatorRegistration) error { return nil @@ -586,7 +601,12 @@ func defaultMock(httpMock HTTPMock, httpServer *http.Server, clock clockwork.Clo return nil }, ForkScheduleFunc: func(ctx context.Context) ([]*eth2p0.Fork, error) { - return httpMock.ForkSchedule(ctx) + eth2Resp, err := httpMock.ForkSchedule(ctx) + if err != nil { + return nil, err + } + + return eth2Resp.Data, nil }, ProposerConfigFunc: func(ctx context.Context) (*eth2exp.ProposerConfigResponse, error) { return nil, nil @@ -594,13 +614,6 @@ func defaultMock(httpMock HTTPMock, httpServer *http.Server, clock clockwork.Clo } } -func array32(slice []byte) [32]byte { - var resp [32]byte - copy(resp[:], slice) - - return resp -} - func mustPKFromHex(pubkeyHex string) eth2p0.BLSPubKey { pubkeyHex = strings.TrimPrefix(pubkeyHex, "0x") b, err := hex.DecodeString(pubkeyHex) diff --git a/testutil/beaconmock/server_test.go b/testutil/beaconmock/server_test.go index 3fc1baf01..9ccefa50d 100644 --- a/testutil/beaconmock/server_test.go +++ b/testutil/beaconmock/server_test.go @@ -18,29 +18,29 @@ func TestStatic(t *testing.T) { eth2Cl, err := beaconmock.New() require.NoError(t, err) - gen, err := eth2Cl.Genesis(ctx) + genesisResp, err := eth2Cl.Genesis(ctx) require.NoError(t, err) - require.Equal(t, "2022-03-01 00:00:00 +0000 UTC", gen.GenesisTime.UTC().String()) + require.Equal(t, "2022-03-01 00:00:00 +0000 UTC", genesisResp.Data.GenesisTime.UTC().String()) - config, err := eth2Cl.Spec(ctx) + configResp, err := eth2Cl.Spec(ctx) require.NoError(t, err) - require.Equal(t, uint64(36660), config["ALTAIR_FORK_EPOCH"]) + require.Equal(t, uint64(36660), configResp.Data["ALTAIR_FORK_EPOCH"]) - contract, err := eth2Cl.DepositContract(ctx) + contractResp, err := eth2Cl.DepositContract(ctx) require.NoError(t, err) - require.Equal(t, uint64(5), contract.ChainID) + require.Equal(t, uint64(5), contractResp.Data.ChainID) slotsPerEpoch, err := eth2Cl.SlotsPerEpoch(ctx) require.NoError(t, err) require.Equal(t, uint64(16), slotsPerEpoch) - state, err := eth2Cl.NodeSyncing(ctx) + stateResp, err := eth2Cl.NodeSyncing(ctx) require.NoError(t, err) - require.False(t, state.IsSyncing) + require.False(t, stateResp.Data.IsSyncing) - version, err := eth2Cl.NodeVersion(ctx) + versionResp, err := eth2Cl.NodeVersion(ctx) require.NoError(t, err) - require.Equal(t, "charon/static_beacon_mock", version) + require.Equal(t, "charon/static_beacon_mock", versionResp.Data) } func TestGenesisTimeOverride(t *testing.T) { @@ -50,13 +50,13 @@ func TestGenesisTimeOverride(t *testing.T) { eth2Cl, err := beaconmock.New(beaconmock.WithGenesisTime(t0)) require.NoError(t, err) - gen, err := eth2Cl.Genesis(ctx) + genesisResp, err := eth2Cl.Genesis(ctx) require.NoError(t, err) - require.Equal(t, t0, gen.GenesisTime) + require.Equal(t, t0, genesisResp.Data.GenesisTime) - t1, err := eth2Cl.GenesisTime(ctx) + genesisTime, err := eth2Cl.GenesisTime(ctx) require.NoError(t, err) - require.Equal(t, t0, t1) + require.Equal(t, t0, genesisTime) } func TestSlotsPerEpochOverride(t *testing.T) { @@ -70,9 +70,9 @@ func TestSlotsPerEpochOverride(t *testing.T) { require.NoError(t, err) require.EqualValues(t, expect, actual) - spec, err := eth2Cl.Spec(ctx) + specResp, err := eth2Cl.Spec(ctx) require.NoError(t, err) - require.EqualValues(t, expect, spec["SLOTS_PER_EPOCH"]) + require.EqualValues(t, expect, specResp.Data["SLOTS_PER_EPOCH"]) } func TestSlotsDurationOverride(t *testing.T) { @@ -86,9 +86,9 @@ func TestSlotsDurationOverride(t *testing.T) { require.NoError(t, err) require.EqualValues(t, expect, actual) - spec, err := eth2Cl.Spec(ctx) + specResp, err := eth2Cl.Spec(ctx) require.NoError(t, err) - require.EqualValues(t, expect, spec["SECONDS_PER_SLOT"]) + require.EqualValues(t, expect, specResp.Data["SECONDS_PER_SLOT"]) } func TestEndpointOverride(t *testing.T) { @@ -105,11 +105,11 @@ func TestEndpointOverride(t *testing.T) { ) require.NoError(t, err) - fs, err := bmock.ForkSchedule(ctx) + fsResp, err := bmock.ForkSchedule(ctx) require.NoError(t, err) - require.Len(t, fs, 1) - require.EqualValues(t, [4]byte{}, fs[0].CurrentVersion) - require.EqualValues(t, [4]byte{0x12, 0x34, 0x56, 0x78}, fs[0].PreviousVersion) + require.Len(t, fsResp.Data, 1) + require.EqualValues(t, [4]byte{}, fsResp.Data[0].CurrentVersion) + require.EqualValues(t, [4]byte{0x12, 0x34, 0x56, 0x78}, fsResp.Data[0].PreviousVersion) } func TestDefaultOverrides(t *testing.T) { @@ -117,8 +117,9 @@ func TestDefaultOverrides(t *testing.T) { bmock, err := beaconmock.New() require.NoError(t, err) - spec, err := bmock.Spec(ctx) + resp, err := bmock.Spec(ctx) require.NoError(t, err) + spec := resp.Data require.Equal(t, "charon-simnet", spec["CONFIG_NAME"]) require.EqualValues(t, 16, spec["SLOTS_PER_EPOCH"]) diff --git a/testutil/fuzz.go b/testutil/fuzz.go index f34f55c86..c149b2035 100644 --- a/testutil/fuzz.go +++ b/testutil/fuzz.go @@ -61,7 +61,7 @@ func NewEth2Fuzzer(t *testing.T, seed int64) *fuzz.Fuzzer { *e = (*e)[:2] } }, - // eth2p0.AttesterSlashings has max + // eth2p0.ProposerSlashings has max func(e *[]*eth2p0.ProposerSlashing, c fuzz.Continue) { c.FuzzNoCustom(e) if len(*e) > 16 { @@ -104,38 +104,66 @@ func NewEth2Fuzzer(t *testing.T, seed int64) *fuzz.Fuzzer { *e = (*e)[:4] } }, - // Populate one of the versions of these Versioned*Block types. - func(e *core.VersionedSignedBlindedBeaconBlock, c fuzz.Continue) { + // Populate one of the versions of these Versioned*Proposal types. + func(e *core.VersionedSignedBlindedProposal, c fuzz.Continue) { e.Version = blindedVersions[(c.Intn(len(blindedVersions)))] version, err := eth2util.DataVersionFromETH2(e.Version) require.NoError(t, err) val := core.VersionedSSZValueForT(t, e, version) c.Fuzz(val) + + // Limit length of blob sidecars to 6 + // See https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/beacon-chain.md#execution + maxBlobSidecars := 6 + if e.Version == eth2spec.DataVersionDeneb && len(e.Deneb.SignedBlindedBlobSidecars) > maxBlobSidecars { + e.Deneb.SignedBlindedBlobSidecars = e.Deneb.SignedBlindedBlobSidecars[:maxBlobSidecars] + } }, - func(e *core.VersionedBlindedBeaconBlock, c fuzz.Continue) { + func(e *core.VersionedBlindedProposal, c fuzz.Continue) { e.Version = blindedVersions[(c.Intn(len(blindedVersions)))] version, err := eth2util.DataVersionFromETH2(e.Version) require.NoError(t, err) val := core.VersionedSSZValueForT(t, e, version) c.Fuzz(val) + + // Limit length of blob sidecars to 6 + // See https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/beacon-chain.md#execution + maxBlobSidecars := 6 + if e.Version == eth2spec.DataVersionDeneb && len(e.Deneb.BlindedBlobSidecars) > maxBlobSidecars { + e.Deneb.BlindedBlobSidecars = e.Deneb.BlindedBlobSidecars[:maxBlobSidecars] + } }, - func(e *core.VersionedSignedBeaconBlock, c fuzz.Continue) { + func(e *core.VersionedSignedProposal, c fuzz.Continue) { e.Version = allVersions[(c.Intn(len(allVersions)))] version, err := eth2util.DataVersionFromETH2(e.Version) require.NoError(t, err) val := core.VersionedSSZValueForT(t, e, version) c.Fuzz(val) + + // Limit length of blob sidecars to 6 + // See https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/beacon-chain.md#execution + maxBlobSidecars := 6 + if e.Version == eth2spec.DataVersionDeneb && len(e.Deneb.SignedBlobSidecars) > maxBlobSidecars { + e.Deneb.SignedBlobSidecars = e.Deneb.SignedBlobSidecars[:maxBlobSidecars] + } }, - func(e *core.VersionedBeaconBlock, c fuzz.Continue) { + func(e *core.VersionedProposal, c fuzz.Continue) { e.Version = allVersions[(c.Intn(len(allVersions)))] version, err := eth2util.DataVersionFromETH2(e.Version) require.NoError(t, err) val := core.VersionedSSZValueForT(t, e, version) c.Fuzz(val) + + // Limit length of blob sidecars to 6 + // See https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/beacon-chain.md#execution + maxBlobSidecars := 6 + if e.Version == eth2spec.DataVersionDeneb && len(e.Deneb.BlobSidecars) > maxBlobSidecars { + e.Deneb.BlobSidecars = e.Deneb.BlobSidecars[:maxBlobSidecars] + } }, ) } diff --git a/testutil/random.go b/testutil/random.go index c328460d4..fe559f2ea 100644 --- a/testutil/random.go +++ b/testutil/random.go @@ -256,27 +256,27 @@ func RandomCapellaExecutionPayload() *capella.ExecutionPayload { } } -func RandomBellatrixCoreVersionedBeaconBlock() core.VersionedBeaconBlock { - return core.VersionedBeaconBlock{ - VersionedBeaconBlock: eth2spec.VersionedBeaconBlock{ +func RandomBellatrixCoreVersionedProposal() core.VersionedProposal { + return core.VersionedProposal{ + VersionedProposal: eth2api.VersionedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: RandomBellatrixBeaconBlock(), }, } } -func RandomCapellaCoreVersionedBeaconBlock() core.VersionedBeaconBlock { - return core.VersionedBeaconBlock{ - VersionedBeaconBlock: eth2spec.VersionedBeaconBlock{ +func RandomCapellaCoreVersionedProposal() core.VersionedProposal { + return core.VersionedProposal{ + VersionedProposal: eth2api.VersionedProposal{ Version: eth2spec.DataVersionCapella, Capella: RandomCapellaBeaconBlock(), }, } } -func RandomBellatrixCoreVersionedSignedBeaconBlock() core.VersionedSignedBeaconBlock { - return core.VersionedSignedBeaconBlock{ - VersionedSignedBeaconBlock: eth2spec.VersionedSignedBeaconBlock{ +func RandomBellatrixCoreVersionedSignedProposal() core.VersionedSignedProposal { + return core.VersionedSignedProposal{ + VersionedSignedProposal: eth2api.VersionedSignedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: &bellatrix.SignedBeaconBlock{ Message: RandomBellatrixBeaconBlock(), @@ -286,9 +286,9 @@ func RandomBellatrixCoreVersionedSignedBeaconBlock() core.VersionedSignedBeaconB } } -func RandomCapellaCoreVersionedSignedBeaconBlock() core.VersionedSignedBeaconBlock { - return core.VersionedSignedBeaconBlock{ - VersionedSignedBeaconBlock: eth2spec.VersionedSignedBeaconBlock{ +func RandomCapellaCoreVersionedSignedProposal() core.VersionedSignedProposal { + return core.VersionedSignedProposal{ + VersionedSignedProposal: eth2api.VersionedSignedProposal{ Version: eth2spec.DataVersionCapella, Capella: &capella.SignedBeaconBlock{ Message: RandomCapellaBeaconBlock(), @@ -309,6 +309,25 @@ func RandomCapellaVersionedSignedBeaconBlock() *eth2spec.VersionedSignedBeaconBl } } +// RandomVersionedSignedProposal returns a random versioned signed proposal containing capella beacon block. +func RandomVersionedSignedProposal() *eth2api.VersionedSignedProposal { + return ð2api.VersionedSignedProposal{ + Version: eth2spec.DataVersionCapella, + Capella: &capella.SignedBeaconBlock{ + Message: RandomCapellaBeaconBlock(), + Signature: RandomEth2Signature(), + }, + } +} + +// RandomVersionedProposal returns a random versioned proposal containing capella beacon block. +func RandomVersionedProposal() *eth2api.VersionedProposal { + return ð2api.VersionedProposal{ + Version: eth2spec.DataVersionCapella, + Capella: RandomCapellaBeaconBlock(), + } +} + func RandomBellatrixBlindedBeaconBlock() *eth2bellatrix.BlindedBeaconBlock { return ð2bellatrix.BlindedBeaconBlock{ Slot: RandomSlot(), @@ -368,27 +387,27 @@ func RandomCapellaBlindedBeaconBlockBody() *eth2capella.BlindedBeaconBlockBody { } } -func RandomBellatrixVersionedBlindedBeaconBlock() core.VersionedBlindedBeaconBlock { - return core.VersionedBlindedBeaconBlock{ - VersionedBlindedBeaconBlock: eth2api.VersionedBlindedBeaconBlock{ +func RandomBellatrixVersionedBlindedProposal() core.VersionedBlindedProposal { + return core.VersionedBlindedProposal{ + VersionedBlindedProposal: eth2api.VersionedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: RandomBellatrixBlindedBeaconBlock(), }, } } -func RandomCapellaVersionedBlindedBeaconBlock() core.VersionedBlindedBeaconBlock { - return core.VersionedBlindedBeaconBlock{ - VersionedBlindedBeaconBlock: eth2api.VersionedBlindedBeaconBlock{ +func RandomCapellaVersionedBlindedProposal() core.VersionedBlindedProposal { + return core.VersionedBlindedProposal{ + VersionedBlindedProposal: eth2api.VersionedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: RandomCapellaBlindedBeaconBlock(), }, } } -func RandomBellatrixVersionedSignedBlindedBeaconBlock() core.VersionedSignedBlindedBeaconBlock { - return core.VersionedSignedBlindedBeaconBlock{ - VersionedSignedBlindedBeaconBlock: eth2api.VersionedSignedBlindedBeaconBlock{ +func RandomBellatrixVersionedSignedBlindedProposal() core.VersionedSignedBlindedProposal { + return core.VersionedSignedBlindedProposal{ + VersionedSignedBlindedProposal: eth2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionBellatrix, Bellatrix: ð2bellatrix.SignedBlindedBeaconBlock{ Message: RandomBellatrixBlindedBeaconBlock(), @@ -398,9 +417,9 @@ func RandomBellatrixVersionedSignedBlindedBeaconBlock() core.VersionedSignedBlin } } -func RandomCapellaVersionedSignedBlindedBeaconBlock() core.VersionedSignedBlindedBeaconBlock { - return core.VersionedSignedBlindedBeaconBlock{ - VersionedSignedBlindedBeaconBlock: eth2api.VersionedSignedBlindedBeaconBlock{ +func RandomCapellaVersionedSignedBlindedProposal() core.VersionedSignedBlindedProposal { + return core.VersionedSignedBlindedProposal{ + VersionedSignedBlindedProposal: eth2api.VersionedSignedBlindedProposal{ Version: eth2spec.DataVersionCapella, Capella: ð2capella.SignedBlindedBeaconBlock{ Message: RandomCapellaBlindedBeaconBlock(), diff --git a/testutil/validatormock/attest.go b/testutil/validatormock/attest.go index 81bdefa07..cee55517e 100644 --- a/testutil/validatormock/attest.go +++ b/testutil/validatormock/attest.go @@ -6,6 +6,7 @@ import ( "context" "sync" + eth2api "github.com/attestantio/go-eth2-client/api" eth2v1 "github.com/attestantio/go-eth2-client/api/v1" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/prysmaticlabs/go-bitfield" @@ -194,10 +195,15 @@ func prepareAttesters(ctx context.Context, eth2Cl eth2wrap.Client, vals eth2wrap return nil, err } - epochDuties, err := eth2Cl.AttesterDuties(ctx, epoch, vals.Indices()) + opts := ð2api.AttesterDutiesOpts{ + Epoch: epoch, + Indices: vals.Indices(), + } + eth2Resp, err := eth2Cl.AttesterDuties(ctx, opts) if err != nil { return nil, err } + epochDuties := eth2Resp.Data var duties attDuties for _, duty := range epochDuties { @@ -299,10 +305,15 @@ func attest(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc, slot datas attDatas ) for commIdx, duties := range dutyByComm { - data, err := eth2Cl.AttestationData(ctx, slot, commIdx) + opts := ð2api.AttestationDataOpts{ + Slot: slot, + CommitteeIndex: commIdx, + } + eth2Resp, err := eth2Cl.AttestationData(ctx, opts) if err != nil { return nil, err } + data := eth2Resp.Data datas = append(datas, data) root, err := data.HashTreeRoot() @@ -431,7 +442,16 @@ func getAggregateAttestation(ctx context.Context, eth2Cl eth2wrap.Client, datas return nil, errors.Wrap(err, "hash attestation data") } - return eth2Cl.AggregateAttestation(ctx, data.Slot, root) + opts := ð2api.AggregateAttestationOpts{ + Slot: data.Slot, + AttestationDataRoot: root, + } + eth2Resp, err := eth2Cl.AggregateAttestation(ctx, opts) + if err != nil { + return nil, err + } + + return eth2Resp.Data, nil } return nil, errors.New("missing attestation data for committee index") diff --git a/testutil/validatormock/propose.go b/testutil/validatormock/propose.go index 91236922b..8adb7ca56 100644 --- a/testutil/validatormock/propose.go +++ b/testutil/validatormock/propose.go @@ -12,10 +12,12 @@ import ( eth2v1 "github.com/attestantio/go-eth2-client/api/v1" eth2bellatrix "github.com/attestantio/go-eth2-client/api/v1/bellatrix" eth2capella "github.com/attestantio/go-eth2-client/api/v1/capella" + eth2deneb "github.com/attestantio/go-eth2-client/api/v1/deneb" eth2spec "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/bellatrix" "github.com/attestantio/go-eth2-client/spec/capella" + "github.com/attestantio/go-eth2-client/spec/deneb" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/obolnetwork/charon/app/errors" @@ -49,10 +51,15 @@ func ProposeBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc indexes = append(indexes, index) } - duties, err := eth2Cl.ProposerDuties(ctx, epoch, indexes) + opts := ð2api.ProposerDutiesOpts{ + Epoch: epoch, + Indices: indexes, + } + eth2Resp, err := eth2Cl.ProposerDuties(ctx, opts) if err != nil { return err } + duties := eth2Resp.Data var slotProposer *eth2v1.ProposerDuty for _, duty := range duties { @@ -68,7 +75,7 @@ func ProposeBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc var ( pubkey eth2p0.BLSPubKey - block *eth2spec.VersionedBeaconBlock + block *eth2api.VersionedProposal ) pubkey = slotProposer.PubKey @@ -89,10 +96,15 @@ func ProposeBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc } // Get Unsigned beacon block with given randao and slot - block, err = eth2Cl.BeaconBlockProposal(ctx, slot, randao, nil) + proposalOpts := ð2api.ProposalOpts{ + Slot: slot, + RandaoReveal: randao, + } + eth2ProposalResp, err := eth2Cl.Proposal(ctx, proposalOpts) if err != nil { return errors.Wrap(err, "vmock beacon block proposal") } + block = eth2ProposalResp.Data if block == nil { return errors.New("block not found") @@ -114,8 +126,8 @@ func ProposeBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc return err } - // create signed beacon block - signedBlock := new(eth2spec.VersionedSignedBeaconBlock) + // Create signed beacon block proposal. + signedBlock := new(eth2api.VersionedSignedProposal) signedBlock.Version = block.Version switch block.Version { case eth2spec.DataVersionPhase0: @@ -138,11 +150,43 @@ func ProposeBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc Message: block.Capella, Signature: sig, } + case eth2spec.DataVersionDeneb: + // Sign blob sidecars + var blobSidecars []*deneb.SignedBlobSidecar + for _, blob := range block.Deneb.BlobSidecars { + blobSigRoot, err := blob.HashTreeRoot() + if err != nil { + return err + } + + blobSigData, err := signing.GetDataRoot(ctx, eth2Cl, signing.DomainBlobSidecar, epoch, blobSigRoot) + if err != nil { + return err + } + + blobSig, err := signFunc(pubkey, blobSigData[:]) + if err != nil { + return err + } + + blobSidecars = append(blobSidecars, &deneb.SignedBlobSidecar{ + Message: blob, + Signature: blobSig, + }) + } + + signedBlock.Deneb = ð2deneb.SignedBlockContents{ + SignedBlock: &deneb.SignedBeaconBlock{ + Message: block.Deneb.Block, + Signature: sig, + }, + SignedBlobSidecars: blobSidecars, + } default: return errors.New("invalid block") } - return eth2Cl.SubmitBeaconBlock(ctx, signedBlock) + return eth2Cl.SubmitProposal(ctx, signedBlock) } // ProposeBlindedBlock proposes blinded block for the given slot. @@ -166,10 +210,15 @@ func ProposeBlindedBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc S indexes = append(indexes, index) } - duties, err := eth2Cl.ProposerDuties(ctx, epoch, indexes) + opts := ð2api.ProposerDutiesOpts{ + Epoch: epoch, + Indices: indexes, + } + eth2Resp, err := eth2Cl.ProposerDuties(ctx, opts) if err != nil { return err } + duties := eth2Resp.Data var slotProposer *eth2v1.ProposerDuty for _, duty := range duties { @@ -185,7 +234,7 @@ func ProposeBlindedBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc S var ( pubkey eth2p0.BLSPubKey - block *eth2api.VersionedBlindedBeaconBlock + block *eth2api.VersionedBlindedProposal ) pubkey = slotProposer.PubKey @@ -206,10 +255,15 @@ func ProposeBlindedBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc S } // Get Unsigned beacon block with given randao and slot - block, err = eth2Cl.BlindedBeaconBlockProposal(ctx, slot, randao, nil) + proposalOpts := ð2api.BlindedProposalOpts{ + Slot: slot, + RandaoReveal: randao, + } + proposalResp, err := eth2Cl.BlindedProposal(ctx, proposalOpts) if err != nil { return errors.Wrap(err, "vmock blinded beacon block proposal") } + block = proposalResp.Data if block == nil { return errors.New("block not found") @@ -234,7 +288,7 @@ func ProposeBlindedBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc S } // create signed beacon block - signedBlock := new(eth2api.VersionedSignedBlindedBeaconBlock) + signedBlock := new(eth2api.VersionedSignedBlindedProposal) signedBlock.Version = block.Version switch block.Version { case eth2spec.DataVersionBellatrix: @@ -247,11 +301,43 @@ func ProposeBlindedBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc S Message: block.Capella, Signature: sig, } + case eth2spec.DataVersionDeneb: + // Sign blinded blob sidecars + var blindedBlobSidecars []*eth2deneb.SignedBlindedBlobSidecar + for _, blob := range block.Deneb.BlindedBlobSidecars { + blobSigRoot, err := blob.HashTreeRoot() + if err != nil { + return err + } + + blobSigData, err := signing.GetDataRoot(ctx, eth2Cl, signing.DomainBlobSidecar, epoch, blobSigRoot) + if err != nil { + return err + } + + blobSig, err := signFunc(pubkey, blobSigData[:]) + if err != nil { + return err + } + + blindedBlobSidecars = append(blindedBlobSidecars, ð2deneb.SignedBlindedBlobSidecar{ + Message: blob, + Signature: blobSig, + }) + } + + signedBlock.Deneb = ð2deneb.SignedBlindedBlockContents{ + SignedBlindedBlock: ð2deneb.SignedBlindedBeaconBlock{ + Message: block.Deneb.BlindedBlock, + Signature: sig, + }, + SignedBlindedBlobSidecars: blindedBlobSidecars, + } default: return errors.New("invalid block") } - return eth2Cl.SubmitBlindedBeaconBlock(ctx, signedBlock) + return eth2Cl.SubmitBlindedProposal(ctx, signedBlock) } // RegistrationsFromProposerConfig returns all enabled builder-API registrations from upstream proposer config. diff --git a/testutil/validatormock/synccomm.go b/testutil/validatormock/synccomm.go index 25bff6d9e..d2f040fbc 100644 --- a/testutil/validatormock/synccomm.go +++ b/testutil/validatormock/synccomm.go @@ -7,6 +7,7 @@ import ( "sync" eth2client "github.com/attestantio/go-eth2-client" + eth2api "github.com/attestantio/go-eth2-client/api" eth2v1 "github.com/attestantio/go-eth2-client/api/v1" "github.com/attestantio/go-eth2-client/spec/altair" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" @@ -230,10 +231,12 @@ func (s *SyncCommMember) Message(ctx context.Context, slot eth2p0.Slot) error { return s.setBlockRoot(slot, eth2p0.Root{}) } - blockRoot, err := s.eth2Cl.BeaconBlockRoot(ctx, "head") + opts := ð2api.BeaconBlockRootOpts{Block: "head"} + eth2Resp, err := s.eth2Cl.BeaconBlockRoot(ctx, opts) if err != nil { return err } + blockRoot := eth2Resp.Data err = submitSyncMessages(ctx, s.eth2Cl, slot, *blockRoot, s.signFunc, duties) if err != nil { @@ -257,7 +260,16 @@ func prepareSyncCommDuties(ctx context.Context, eth2Cl eth2wrap.Client, vals eth return nil, nil } - return eth2Cl.SyncCommitteeDuties(ctx, epoch, vals.Indices()) + opts := ð2api.SyncCommitteeDutiesOpts{ + Epoch: epoch, + Indices: vals.Indices(), + } + eth2Resp, err := eth2Cl.SyncCommitteeDuties(ctx, opts) + if err != nil { + return nil, err + } + + return eth2Resp.Data, nil } // subscribeSyncCommSubnets submits sync committee subscriptions at the start of an epoch until next epoch. @@ -360,10 +372,11 @@ func prepareSyncSelections(ctx context.Context, eth2Cl eth2wrap.Client, signFunc // getSubcommittees returns the subcommittee indexes for the provided sync committee duty. func getSubcommittees(ctx context.Context, eth2Cl eth2client.SpecProvider, duty *eth2v1.SyncCommitteeDuty) ([]eth2p0.CommitteeIndex, error) { - spec, err := eth2Cl.Spec(ctx) + eth2Resp, err := eth2Cl.Spec(ctx) if err != nil { return nil, err } + spec := eth2Resp.Data commSize, ok := spec["SYNC_COMMITTEE_SIZE"].(uint64) if !ok { @@ -441,10 +454,16 @@ func aggContributions(ctx context.Context, eth2Cl eth2wrap.Client, signFunc Sign var signedContribAndProofs []*altair.SignedContributionAndProof for _, selection := range selections { // Query BN to get sync committee contribution. - contrib, err := eth2Cl.SyncCommitteeContribution(ctx, selection.Slot, uint64(selection.SubcommitteeIndex), blockRoot) + opts := ð2api.SyncCommitteeContributionOpts{ + Slot: selection.Slot, + SubcommitteeIndex: uint64(selection.SubcommitteeIndex), + BeaconBlockRoot: blockRoot, + } + eth2Resp, err := eth2Cl.SyncCommitteeContribution(ctx, opts) if err != nil { return false, err } + contrib := eth2Resp.Data vIdx := selection.ValidatorIndex contribAndProof := &altair.ContributionAndProof{