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 000000000..06b79a887 Binary files /dev/null and b/core/testdata/TestSSZSerialisation_VersionedBlindedProposal.ssz.golden differ diff --git a/core/testdata/TestSSZSerialisation_VersionedProposal.ssz.golden b/core/testdata/TestSSZSerialisation_VersionedProposal.ssz.golden new file mode 100644 index 000000000..b21ffc108 Binary files /dev/null and b/core/testdata/TestSSZSerialisation_VersionedProposal.ssz.golden differ diff --git a/core/testdata/TestSSZSerialisation_VersionedSignedBlindedProposal.ssz.golden b/core/testdata/TestSSZSerialisation_VersionedSignedBlindedProposal.ssz.golden new file mode 100644 index 000000000..79caed81a Binary files /dev/null and b/core/testdata/TestSSZSerialisation_VersionedSignedBlindedProposal.ssz.golden differ diff --git a/core/testdata/TestSSZSerialisation_VersionedSignedProposal.ssz.golden b/core/testdata/TestSSZSerialisation_VersionedSignedProposal.ssz.golden new file mode 100644 index 000000000..425ebf475 Binary files /dev/null and b/core/testdata/TestSSZSerialisation_VersionedSignedProposal.ssz.golden differ 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{