diff --git a/CHANGELOG.md b/CHANGELOG.md index 58f96e2ece12..70e85b4d91b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve - Added SubmitPoolAttesterSlashingV2 endpoint. - Added SubmitAggregateAndProofsRequestV2 endpoint. - Updated the `beacon-chain/monitor` package to Electra. [PR](https://github.com/prysmaticlabs/prysm/pull/14562) +- Remote signer electra fork support. ### Changed diff --git a/validator/keymanager/remote-web3signer/BUILD.bazel b/validator/keymanager/remote-web3signer/BUILD.bazel index 50f84cf2d714..0e99bd6eab58 100644 --- a/validator/keymanager/remote-web3signer/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/BUILD.bazel @@ -23,7 +23,7 @@ go_library( "//validator/accounts/petnames:go_default_library", "//validator/keymanager:go_default_library", "//validator/keymanager/remote-web3signer/internal:go_default_library", - "//validator/keymanager/remote-web3signer/v1:go_default_library", + "//validator/keymanager/remote-web3signer/types:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_fsnotify_fsnotify//:go_default_library", "@com_github_go_playground_validator_v10//:go_default_library", @@ -48,7 +48,7 @@ go_test( "//testing/require:go_default_library", "//validator/keymanager:go_default_library", "//validator/keymanager/remote-web3signer/internal:go_default_library", - "//validator/keymanager/remote-web3signer/v1/mock:go_default_library", + "//validator/keymanager/remote-web3signer/types/mock:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", diff --git a/validator/keymanager/remote-web3signer/keymanager.go b/validator/keymanager/remote-web3signer/keymanager.go index 3c346a1c5497..0935f6b65ff9 100644 --- a/validator/keymanager/remote-web3signer/keymanager.go +++ b/validator/keymanager/remote-web3signer/keymanager.go @@ -27,7 +27,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/validator/accounts/petnames" "github.com/prysmaticlabs/prysm/v5/validator/keymanager" "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/internal" - web3signerv1 "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types" "github.com/sirupsen/logrus" "golang.org/x/exp/maps" ) @@ -406,6 +406,8 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ return handleAttestationData(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_AggregateAttestationAndProof: return handleAggregateAttestationAndProof(ctx, validator, request, genesisValidatorsRoot) + case *validatorpb.SignRequest_AggregateAttestationAndProofElectra: + return handleAggregateAttestationAndProofV2Electra(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_Slot: return handleAggregationSlot(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_BlockAltair: @@ -422,6 +424,10 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ return handleBlockDeneb(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_BlindedBlockDeneb: return handleBlindedBlockDeneb(ctx, validator, request, genesisValidatorsRoot) + case *validatorpb.SignRequest_BlockElectra: + return handleBlockElectra(ctx, validator, request, genesisValidatorsRoot) + case *validatorpb.SignRequest_BlindedBlockElectra: + return handleBlindedBlockElectra(ctx, validator, request, genesisValidatorsRoot) // We do not support "DEPOSIT" type. /* case *validatorpb.: @@ -447,7 +453,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ } func handleBlock(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - bockSignRequest, err := web3signerv1.GetBlockSignRequest(request, genesisValidatorsRoot) + bockSignRequest, err := types.GetBlockSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -459,7 +465,7 @@ func handleBlock(ctx context.Context, validator *validator.Validate, request *va } func handleAttestationData(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - attestationSignRequest, err := web3signerv1.GetAttestationSignRequest(request, genesisValidatorsRoot) + attestationSignRequest, err := types.GetAttestationSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -471,7 +477,7 @@ func handleAttestationData(ctx context.Context, validator *validator.Validate, r } func handleAggregateAttestationAndProof(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - aggregateAndProofSignRequest, err := web3signerv1.GetAggregateAndProofSignRequest(request, genesisValidatorsRoot) + aggregateAndProofSignRequest, err := types.GetAggregateAndProofSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -482,8 +488,20 @@ func handleAggregateAttestationAndProof(ctx context.Context, validator *validato return json.Marshal(aggregateAndProofSignRequest) } +func handleAggregateAttestationAndProofV2Electra(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + aggregateAndProofSignRequestV2, err := types.GetAggregateAndProofV2ElectraSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, aggregateAndProofSignRequestV2); err != nil { + return nil, err + } + aggregateAndProofSignRequestsTotal.Inc() + return json.Marshal(aggregateAndProofSignRequestV2) +} + func handleAggregationSlot(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - aggregationSlotSignRequest, err := web3signerv1.GetAggregationSlotSignRequest(request, genesisValidatorsRoot) + aggregationSlotSignRequest, err := types.GetAggregationSlotSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -495,7 +513,7 @@ func handleAggregationSlot(ctx context.Context, validator *validator.Validate, r } func handleBlockAltair(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blockv2AltairSignRequest, err := web3signerv1.GetBlockAltairSignRequest(request, genesisValidatorsRoot) + blockv2AltairSignRequest, err := types.GetBlockAltairSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -507,7 +525,7 @@ func handleBlockAltair(ctx context.Context, validator *validator.Validate, reque } func handleBlockBellatrix(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blockv2BellatrixSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blockv2BellatrixSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -519,7 +537,7 @@ func handleBlockBellatrix(ctx context.Context, validator *validator.Validate, re } func handleBlindedBlockBellatrix(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blindedBlockv2SignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blindedBlockv2SignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -531,7 +549,7 @@ func handleBlindedBlockBellatrix(ctx context.Context, validator *validator.Valid } func handleBlockCapella(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blockv2CapellaSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blockv2CapellaSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -543,7 +561,7 @@ func handleBlockCapella(ctx context.Context, validator *validator.Validate, requ } func handleBlindedBlockCapella(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blindedBlockv2CapellaSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blindedBlockv2CapellaSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -555,7 +573,7 @@ func handleBlindedBlockCapella(ctx context.Context, validator *validator.Validat } func handleBlockDeneb(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blockv2DenebSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blockv2DenebSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -567,7 +585,7 @@ func handleBlockDeneb(ctx context.Context, validator *validator.Validate, reques } func handleBlindedBlockDeneb(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blindedBlockv2DenebSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blindedBlockv2DenebSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -578,8 +596,32 @@ func handleBlindedBlockDeneb(ctx context.Context, validator *validator.Validate, return json.Marshal(blindedBlockv2DenebSignRequest) } +func handleBlockElectra(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blockv2ElectraSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blockv2ElectraSignRequest); err != nil { + return nil, err + } + blockElectraSignRequestsTotal.Inc() + return json.Marshal(blockv2ElectraSignRequest) +} + +func handleBlindedBlockElectra(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blindedBlockv2ElectraSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blindedBlockv2ElectraSignRequest); err != nil { + return nil, err + } + blindedBlockElectraSignRequestsTotal.Inc() + return json.Marshal(blindedBlockv2ElectraSignRequest) +} + func handleRandaoReveal(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - randaoRevealSignRequest, err := web3signerv1.GetRandaoRevealSignRequest(request, genesisValidatorsRoot) + randaoRevealSignRequest, err := types.GetRandaoRevealSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -591,7 +633,7 @@ func handleRandaoReveal(ctx context.Context, validator *validator.Validate, requ } func handleVoluntaryExit(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - voluntaryExitRequest, err := web3signerv1.GetVoluntaryExitSignRequest(request, genesisValidatorsRoot) + voluntaryExitRequest, err := types.GetVoluntaryExitSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -603,7 +645,7 @@ func handleVoluntaryExit(ctx context.Context, validator *validator.Validate, req } func handleSyncMessageBlockRoot(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - syncCommitteeMessageRequest, err := web3signerv1.GetSyncCommitteeMessageSignRequest(request, genesisValidatorsRoot) + syncCommitteeMessageRequest, err := types.GetSyncCommitteeMessageSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -615,7 +657,7 @@ func handleSyncMessageBlockRoot(ctx context.Context, validator *validator.Valida } func handleSyncAggregatorSelectionData(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - syncCommitteeSelectionProofRequest, err := web3signerv1.GetSyncCommitteeSelectionProofSignRequest(request, genesisValidatorsRoot) + syncCommitteeSelectionProofRequest, err := types.GetSyncCommitteeSelectionProofSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -627,7 +669,7 @@ func handleSyncAggregatorSelectionData(ctx context.Context, validator *validator } func handleContributionAndProof(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - contributionAndProofRequest, err := web3signerv1.GetSyncCommitteeContributionAndProofSignRequest(request, genesisValidatorsRoot) + contributionAndProofRequest, err := types.GetSyncCommitteeContributionAndProofSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -639,7 +681,7 @@ func handleContributionAndProof(ctx context.Context, validator *validator.Valida } func handleRegistration(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest) ([]byte, error) { - validatorRegistrationRequest, err := web3signerv1.GetValidatorRegistrationSignRequest(request) + validatorRegistrationRequest, err := types.GetValidatorRegistrationSignRequest(request) if err != nil { return nil, err } diff --git a/validator/keymanager/remote-web3signer/keymanager_test.go b/validator/keymanager/remote-web3signer/keymanager_test.go index 9d47eda75359..22d8ae0a2b6f 100644 --- a/validator/keymanager/remote-web3signer/keymanager_test.go +++ b/validator/keymanager/remote-web3signer/keymanager_test.go @@ -22,7 +22,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/validator/keymanager" "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/internal" - "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1/mock" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types/mock" logTest "github.com/sirupsen/logrus/hooks/test" "github.com/stretchr/testify/assert" ) diff --git a/validator/keymanager/remote-web3signer/metrics.go b/validator/keymanager/remote-web3signer/metrics.go index 0e6b23974e5d..cc279a0b897b 100644 --- a/validator/keymanager/remote-web3signer/metrics.go +++ b/validator/keymanager/remote-web3signer/metrics.go @@ -58,6 +58,14 @@ var ( Name: "remote_web3signer_blinded_block_deneb_sign_requests_total", Help: "Total number of blinded block deneb sign requests", }) + blockElectraSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ + Name: "remote_web3signer_block_electra_sign_requests_total", + Help: "Total number of block electra sign requests", + }) + blindedBlockElectraSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ + Name: "remote_web3signer_blinded_block_electra_sign_requests_total", + Help: "Total number of blinded block electra sign requests", + }) randaoRevealSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ Name: "remote_web3signer_randao_reveal_sign_requests_total", Help: "Total number of randao reveal sign requests", diff --git a/validator/keymanager/remote-web3signer/v1/BUILD.bazel b/validator/keymanager/remote-web3signer/types/BUILD.bazel similarity index 92% rename from validator/keymanager/remote-web3signer/v1/BUILD.bazel rename to validator/keymanager/remote-web3signer/types/BUILD.bazel index ebc1a0fcae58..9875d3c12bd3 100644 --- a/validator/keymanager/remote-web3signer/v1/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/types/BUILD.bazel @@ -7,7 +7,7 @@ go_library( "requests.go", "web3signer_types.go", ], - importpath = "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1", + importpath = "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types", visibility = ["//visibility:public"], deps = [ "//consensus-types/blocks:go_default_library", @@ -35,7 +35,7 @@ go_test( "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", "//testing/require:go_default_library", - "//validator/keymanager/remote-web3signer/v1/mock:go_default_library", + "//validator/keymanager/remote-web3signer/types/mock:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", ], diff --git a/validator/keymanager/remote-web3signer/v1/custom_mappers.go b/validator/keymanager/remote-web3signer/types/custom_mappers.go similarity index 91% rename from validator/keymanager/remote-web3signer/v1/custom_mappers.go rename to validator/keymanager/remote-web3signer/types/custom_mappers.go index 69581fb5b00a..b36796ad9c6d 100644 --- a/validator/keymanager/remote-web3signer/v1/custom_mappers.go +++ b/validator/keymanager/remote-web3signer/types/custom_mappers.go @@ -1,4 +1,4 @@ -package v1 +package types import ( "fmt" @@ -44,6 +44,22 @@ func MapAggregateAndProof(from *ethpb.AggregateAttestationAndProof) (*AggregateA }, nil } +// MapAggregateAndProofElectra maps the eth2.AggregateAndProofElectra proto to the Web3Signer spec. +func MapAggregateAndProofElectra(from *ethpb.AggregateAttestationAndProofElectra) (*AggregateAndProofElectra, error) { + if from == nil { + return nil, fmt.Errorf("AggregateAttestationAndProof is nil") + } + aggregate, err := MapAttestationElectra(from.Aggregate) + if err != nil { + return nil, err + } + return &AggregateAndProofElectra{ + AggregatorIndex: fmt.Sprint(from.AggregatorIndex), + Aggregate: aggregate, + SelectionProof: from.SelectionProof, + }, nil +} + // MapAttestation maps the eth2.Attestation proto to the Web3Signer spec. func MapAttestation(attestation *ethpb.Attestation) (*Attestation, error) { if attestation == nil { @@ -63,6 +79,29 @@ func MapAttestation(attestation *ethpb.Attestation) (*Attestation, error) { }, nil } +// MapAttestationElectra maps the eth2.Attestation proto to the Web3Signer spec. +func MapAttestationElectra(attestation *ethpb.AttestationElectra) (*AttestationElectra, error) { + if attestation == nil { + return nil, fmt.Errorf("attestation is nil") + } + if attestation.AggregationBits == nil { + return nil, fmt.Errorf("aggregation bits in attestation is nil") + } + if attestation.CommitteeBits == nil { + return nil, fmt.Errorf("committee bits in attestation is nil") + } + data, err := MapAttestationData(attestation.Data) + if err != nil { + return nil, err + } + return &AttestationElectra{ + AggregationBits: []byte(attestation.AggregationBits), + Data: data, + Signature: attestation.Signature, + CommitteeBits: attestation.CommitteeBits.Bytes(), + }, nil +} + // MapAttestationData maps the eth2.AttestationData proto to the Web3Signer spec. func MapAttestationData(data *ethpb.AttestationData) (*AttestationData, error) { if data == nil { diff --git a/validator/keymanager/remote-web3signer/v1/custom_mappers_test.go b/validator/keymanager/remote-web3signer/types/custom_mappers_test.go similarity index 79% rename from validator/keymanager/remote-web3signer/v1/custom_mappers_test.go rename to validator/keymanager/remote-web3signer/types/custom_mappers_test.go index 3088f84f32a3..fa189d11d947 100644 --- a/validator/keymanager/remote-web3signer/v1/custom_mappers_test.go +++ b/validator/keymanager/remote-web3signer/types/custom_mappers_test.go @@ -1,4 +1,4 @@ -package v1_test +package types_test import ( "reflect" @@ -8,8 +8,8 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - v1 "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1" - "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1/mock" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types/mock" ) func TestMapAggregateAndProof(t *testing.T) { @@ -19,7 +19,7 @@ func TestMapAggregateAndProof(t *testing.T) { tests := []struct { name string args args - want *v1.AggregateAndProof + want *types.AggregateAndProof wantErr bool }{ { @@ -43,7 +43,7 @@ func TestMapAggregateAndProof(t *testing.T) { SelectionProof: make([]byte, fieldparams.BLSSignatureLength), }, }, - want: &v1.AggregateAndProof{ + want: &types.AggregateAndProof{ AggregatorIndex: "0", Aggregate: mock.Attestation(), SelectionProof: make([]byte, fieldparams.BLSSignatureLength), @@ -53,7 +53,65 @@ func TestMapAggregateAndProof(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapAggregateAndProof(tt.args.from) + got, err := types.MapAggregateAndProof(tt.args.from) + if (err != nil) != tt.wantErr { + t.Errorf("MapAggregateAndProof() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got.Aggregate, tt.want.Aggregate) { + t.Errorf("MapAggregateAndProof() got = %v, want %v", got.Aggregate, tt.want.Aggregate) + } + }) + } +} + +func TestMapAggregateAndProofElectra(t *testing.T) { + type args struct { + from *ethpb.AggregateAttestationAndProofElectra + } + tests := []struct { + name string + args args + want *types.AggregateAndProofElectra + wantErr bool + }{ + { + name: "HappyPathTest", + args: args{ + from: ðpb.AggregateAttestationAndProofElectra{ + AggregatorIndex: 0, + Aggregate: ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1101}, + Data: ðpb.AttestationData{ + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: ðpb.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + Target: ðpb.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + }, + Signature: make([]byte, 96), + CommitteeBits: func() bitfield.Bitvector64 { + committeeBits := bitfield.NewBitvector64() + committeeBits.SetBitAt(0, true) + return committeeBits + }(), + }, + SelectionProof: make([]byte, fieldparams.BLSSignatureLength), + }, + }, + want: &types.AggregateAndProofElectra{ + AggregatorIndex: "0", + Aggregate: mock.AttestationElectra(), + SelectionProof: make([]byte, fieldparams.BLSSignatureLength), + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := types.MapAggregateAndProofElectra(tt.args.from) if (err != nil) != tt.wantErr { t.Errorf("MapAggregateAndProof() error = %v, wantErr %v", err, tt.wantErr) return @@ -72,7 +130,7 @@ func TestMapAttestation(t *testing.T) { tests := []struct { name string args args - want *v1.Attestation + want *types.Attestation wantErr bool }{ { @@ -98,7 +156,57 @@ func TestMapAttestation(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapAttestation(tt.args.attestation) + got, err := types.MapAttestation(tt.args.attestation) + if (err != nil) != tt.wantErr { + t.Errorf("MapAttestation() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("MapAttestation() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestMapAttestationElectra(t *testing.T) { + type args struct { + attestation *ethpb.AttestationElectra + } + tests := []struct { + name string + args args + want *types.AttestationElectra + wantErr bool + }{ + { + name: "HappyPathTest", + args: args{ + attestation: ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1101}, + Data: ðpb.AttestationData{ + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: ðpb.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + Target: ðpb.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + }, + CommitteeBits: func() bitfield.Bitvector64 { + committeeBits := bitfield.NewBitvector64() + committeeBits.SetBitAt(0, true) + return committeeBits + }(), + Signature: make([]byte, 96), + }, + }, + want: mock.AttestationElectra(), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := types.MapAttestationElectra(tt.args.attestation) if (err != nil) != tt.wantErr { t.Errorf("MapAttestation() error = %v, wantErr %v", err, tt.wantErr) return @@ -117,7 +225,7 @@ func TestMapAttestationData(t *testing.T) { tests := []struct { name string args args - want *v1.AttestationData + want *types.AttestationData wantErr bool }{ { @@ -139,7 +247,7 @@ func TestMapAttestationData(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapAttestationData(tt.args.data) + got, err := types.MapAttestationData(tt.args.data) if (err != nil) != tt.wantErr { t.Errorf("MapAttestationData() error = %v, wantErr %v", err, tt.wantErr) return @@ -158,7 +266,7 @@ func TestMapAttesterSlashing(t *testing.T) { tests := []struct { name string args args - want *v1.AttesterSlashing + want *types.AttesterSlashing wantErr bool }{ { @@ -193,7 +301,7 @@ func TestMapAttesterSlashing(t *testing.T) { }, }, }, - want: &v1.AttesterSlashing{ + want: &types.AttesterSlashing{ Attestation1: mock.IndexedAttestation(), Attestation2: mock.IndexedAttestation(), }, @@ -202,7 +310,7 @@ func TestMapAttesterSlashing(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapAttesterSlashing(tt.args.slashing) + got, err := types.MapAttesterSlashing(tt.args.slashing) if (err != nil) != tt.wantErr { t.Errorf("MapAttesterSlashing() error = %v, wantErr %v", err, tt.wantErr) return @@ -221,7 +329,7 @@ func TestMapBeaconBlockAltair(t *testing.T) { tests := []struct { name string args args - want *v1.BeaconBlockAltair + want *types.BeaconBlockAltair wantErr bool }{ { @@ -342,7 +450,7 @@ func TestMapBeaconBlockAltair(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapBeaconBlockAltair(tt.args.block) + got, err := types.MapBeaconBlockAltair(tt.args.block) if (err != nil) != tt.wantErr { t.Errorf("MapBeaconBlockAltair() error = %v, wantErr %v", err, tt.wantErr) return @@ -361,7 +469,7 @@ func TestMapBeaconBlockBody(t *testing.T) { tests := []struct { name string args args - want *v1.BeaconBlockBody + want *types.BeaconBlockBody wantErr bool }{ { @@ -472,7 +580,7 @@ func TestMapBeaconBlockBody(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapBeaconBlockBody(tt.args.body) + got, err := types.MapBeaconBlockBody(tt.args.body) if (err != nil) != tt.wantErr { t.Errorf("MapBeaconBlockBody() error = %v, wantErr %v", err, tt.wantErr) return @@ -491,7 +599,7 @@ func TestMapContributionAndProof(t *testing.T) { tests := []struct { name string args args - want *v1.ContributionAndProof + want *types.ContributionAndProof wantErr bool }{ { @@ -514,7 +622,7 @@ func TestMapContributionAndProof(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapContributionAndProof(tt.args.contribution) + got, err := types.MapContributionAndProof(tt.args.contribution) if (err != nil) != tt.wantErr { t.Errorf("MapContributionAndProof() error = %v, wantErr %v", err, tt.wantErr) return @@ -535,7 +643,7 @@ func TestMapForkInfo(t *testing.T) { tests := []struct { name string args args - want *v1.ForkInfo + want *types.ForkInfo wantErr bool }{ { @@ -550,7 +658,7 @@ func TestMapForkInfo(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapForkInfo(tt.args.slot, tt.args.genesisValidatorsRoot) + got, err := types.MapForkInfo(tt.args.slot, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("MapForkInfo() error = %v, wantErr %v", err, tt.wantErr) return @@ -569,7 +677,7 @@ func TestMapSyncAggregatorSelectionData(t *testing.T) { tests := []struct { name string args args - want *v1.SyncAggregatorSelectionData + want *types.SyncAggregatorSelectionData wantErr bool }{ { @@ -580,7 +688,7 @@ func TestMapSyncAggregatorSelectionData(t *testing.T) { SubcommitteeIndex: 0, }, }, - want: &v1.SyncAggregatorSelectionData{ + want: &types.SyncAggregatorSelectionData{ Slot: "0", SubcommitteeIndex: "0", }, @@ -589,7 +697,7 @@ func TestMapSyncAggregatorSelectionData(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapSyncAggregatorSelectionData(tt.args.data) + got, err := types.MapSyncAggregatorSelectionData(tt.args.data) if (err != nil) != tt.wantErr { t.Errorf("MapSyncAggregatorSelectionData() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel b/validator/keymanager/remote-web3signer/types/mock/BUILD.bazel similarity index 84% rename from validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel rename to validator/keymanager/remote-web3signer/types/mock/BUILD.bazel index 6c09a88be40b..87d535c95c46 100644 --- a/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/types/mock/BUILD.bazel @@ -4,14 +4,14 @@ go_library( name = "go_default_library", testonly = True, srcs = ["mocks.go"], - importpath = "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1/mock", + importpath = "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types/mock", visibility = ["//visibility:public"], deps = [ "//config/fieldparams:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", "//testing/util:go_default_library", - "//validator/keymanager/remote-web3signer/v1:go_default_library", + "//validator/keymanager/remote-web3signer/types:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", ], diff --git a/validator/keymanager/remote-web3signer/v1/mock/mocks.go b/validator/keymanager/remote-web3signer/types/mock/mocks.go similarity index 82% rename from validator/keymanager/remote-web3signer/v1/mock/mocks.go rename to validator/keymanager/remote-web3signer/types/mock/mocks.go index fdd7c3dc5a76..e48b5c49306b 100644 --- a/validator/keymanager/remote-web3signer/v1/mock/mocks.go +++ b/validator/keymanager/remote-web3signer/types/mock/mocks.go @@ -9,7 +9,7 @@ import ( eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v5/testing/util" - v1 "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types" ) ///////////////////////////////////////////////////////////////////////////////////////////////// @@ -381,6 +381,24 @@ func GetMockSignRequest(t string) *validatorpb.SignRequest { BlindedBlockDeneb: util.HydrateBlindedBeaconBlockDeneb(ð.BlindedBeaconBlockDeneb{}), }, } + case "BLOCK_V2_ELECTRA": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_BlockElectra{ + BlockElectra: util.HydrateBeaconBlockElectra(ð.BeaconBlockElectra{}), + }, + } + case "BLOCK_V2_BLINDED_ELECTRA": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_BlindedBlockElectra{ + BlindedBlockElectra: util.HydrateBlindedBeaconBlockElectra(ð.BlindedBeaconBlockElectra{}), + }, + } case "RANDAO_REVEAL": return &validatorpb.SignRequest{ PublicKey: make([]byte, fieldparams.BLSPubkeyLength), @@ -469,22 +487,22 @@ func GetMockSignRequest(t string) *validatorpb.SignRequest { } // AggregationSlotSignRequest is a mock implementation of the AggregationSlotSignRequest. -func AggregationSlotSignRequest() *v1.AggregationSlotSignRequest { - return &v1.AggregationSlotSignRequest{ +func AggregationSlotSignRequest() *types.AggregationSlotSignRequest { + return &types.AggregationSlotSignRequest{ Type: "AGGREGATION_SLOT", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - AggregationSlot: &v1.AggregationSlot{Slot: "0"}, + AggregationSlot: &types.AggregationSlot{Slot: "0"}, } } // AggregateAndProofSignRequest is a mock implementation of the AggregateAndProofSignRequest. -func AggregateAndProofSignRequest() *v1.AggregateAndProofSignRequest { - return &v1.AggregateAndProofSignRequest{ +func AggregateAndProofSignRequest() *types.AggregateAndProofSignRequest { + return &types.AggregateAndProofSignRequest{ Type: "AGGREGATE_AND_PROOF", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - AggregateAndProof: &v1.AggregateAndProof{ + AggregateAndProof: &types.AggregateAndProof{ AggregatorIndex: "0", Aggregate: Attestation(), SelectionProof: make([]byte, fieldparams.BLSSignatureLength), @@ -493,8 +511,8 @@ func AggregateAndProofSignRequest() *v1.AggregateAndProofSignRequest { } // AttestationSignRequest is a mock implementation of the AttestationSignRequest. -func AttestationSignRequest() *v1.AttestationSignRequest { - return &v1.AttestationSignRequest{ +func AttestationSignRequest() *types.AttestationSignRequest { + return &types.AttestationSignRequest{ Type: "ATTESTATION", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), @@ -503,12 +521,12 @@ func AttestationSignRequest() *v1.AttestationSignRequest { } // BlockSignRequest is a mock implementation of the BlockSignRequest. -func BlockSignRequest() *v1.BlockSignRequest { - return &v1.BlockSignRequest{ +func BlockSignRequest() *types.BlockSignRequest { + return &types.BlockSignRequest{ Type: "BLOCK", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - Block: &v1.BeaconBlock{ + Block: &types.BeaconBlock{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -519,26 +537,26 @@ func BlockSignRequest() *v1.BlockSignRequest { } // BlockV2AltairSignRequest is a mock implementation of the BlockAltairSignRequest. -func BlockV2AltairSignRequest() *v1.BlockAltairSignRequest { - return &v1.BlockAltairSignRequest{ +func BlockV2AltairSignRequest() *types.BlockAltairSignRequest { + return &types.BlockAltairSignRequest{ Type: "BLOCK_V2", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - BeaconBlock: &v1.BeaconBlockAltairBlockV2{ + BeaconBlock: &types.BeaconBlockAltairBlockV2{ Version: "ALTAIR", Block: BeaconBlockAltair(), }, } } -func BlockV2BlindedSignRequest(bodyRoot []byte, version string) *v1.BlockV2BlindedSignRequest { - return &v1.BlockV2BlindedSignRequest{ +func BlockV2BlindedSignRequest(bodyRoot []byte, version string) *types.BlockV2BlindedSignRequest { + return &types.BlockV2BlindedSignRequest{ Type: "BLOCK_V2", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - BeaconBlock: &v1.BeaconBlockV2Blinded{ + BeaconBlock: &types.BeaconBlockV2Blinded{ Version: version, - BlockHeader: &v1.BeaconBlockHeader{ + BlockHeader: &types.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -550,20 +568,20 @@ func BlockV2BlindedSignRequest(bodyRoot []byte, version string) *v1.BlockV2Blind } // RandaoRevealSignRequest is a mock implementation of the RandaoRevealSignRequest. -func RandaoRevealSignRequest() *v1.RandaoRevealSignRequest { - return &v1.RandaoRevealSignRequest{ +func RandaoRevealSignRequest() *types.RandaoRevealSignRequest { + return &types.RandaoRevealSignRequest{ Type: "RANDAO_REVEAL", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - RandaoReveal: &v1.RandaoReveal{ + RandaoReveal: &types.RandaoReveal{ Epoch: "0", }, } } // SyncCommitteeContributionAndProofSignRequest is a mock implementation of the SyncCommitteeContributionAndProofSignRequest. -func SyncCommitteeContributionAndProofSignRequest() *v1.SyncCommitteeContributionAndProofSignRequest { - return &v1.SyncCommitteeContributionAndProofSignRequest{ +func SyncCommitteeContributionAndProofSignRequest() *types.SyncCommitteeContributionAndProofSignRequest { + return &types.SyncCommitteeContributionAndProofSignRequest{ Type: "SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), @@ -572,12 +590,12 @@ func SyncCommitteeContributionAndProofSignRequest() *v1.SyncCommitteeContributio } // SyncCommitteeMessageSignRequest is a mock implementation of the SyncCommitteeMessageSignRequest. -func SyncCommitteeMessageSignRequest() *v1.SyncCommitteeMessageSignRequest { - return &v1.SyncCommitteeMessageSignRequest{ +func SyncCommitteeMessageSignRequest() *types.SyncCommitteeMessageSignRequest { + return &types.SyncCommitteeMessageSignRequest{ Type: "SYNC_COMMITTEE_MESSAGE", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - SyncCommitteeMessage: &v1.SyncCommitteeMessage{ + SyncCommitteeMessage: &types.SyncCommitteeMessage{ BeaconBlockRoot: make([]byte, fieldparams.RootLength), Slot: "0", }, @@ -585,12 +603,12 @@ func SyncCommitteeMessageSignRequest() *v1.SyncCommitteeMessageSignRequest { } // SyncCommitteeSelectionProofSignRequest is a mock implementation of the SyncCommitteeSelectionProofSignRequest. -func SyncCommitteeSelectionProofSignRequest() *v1.SyncCommitteeSelectionProofSignRequest { - return &v1.SyncCommitteeSelectionProofSignRequest{ +func SyncCommitteeSelectionProofSignRequest() *types.SyncCommitteeSelectionProofSignRequest { + return &types.SyncCommitteeSelectionProofSignRequest{ Type: "SYNC_COMMITTEE_SELECTION_PROOF", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - SyncAggregatorSelectionData: &v1.SyncAggregatorSelectionData{ + SyncAggregatorSelectionData: &types.SyncAggregatorSelectionData{ Slot: "0", SubcommitteeIndex: "0", }, @@ -598,12 +616,12 @@ func SyncCommitteeSelectionProofSignRequest() *v1.SyncCommitteeSelectionProofSig } // VoluntaryExitSignRequest is a mock implementation of the VoluntaryExitSignRequest. -func VoluntaryExitSignRequest() *v1.VoluntaryExitSignRequest { - return &v1.VoluntaryExitSignRequest{ +func VoluntaryExitSignRequest() *types.VoluntaryExitSignRequest { + return &types.VoluntaryExitSignRequest{ Type: "VOLUNTARY_EXIT", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - VoluntaryExit: &v1.VoluntaryExit{ + VoluntaryExit: &types.VoluntaryExit{ Epoch: "0", ValidatorIndex: "0", }, @@ -611,11 +629,11 @@ func VoluntaryExitSignRequest() *v1.VoluntaryExitSignRequest { } // ValidatorRegistrationSignRequest is a mock implementation of the ValidatorRegistrationSignRequest. -func ValidatorRegistrationSignRequest() *v1.ValidatorRegistrationSignRequest { - return &v1.ValidatorRegistrationSignRequest{ +func ValidatorRegistrationSignRequest() *types.ValidatorRegistrationSignRequest { + return &types.ValidatorRegistrationSignRequest{ Type: "VALIDATOR_REGISTRATION", SigningRoot: make([]byte, fieldparams.RootLength), - ValidatorRegistration: &v1.ValidatorRegistration{ + ValidatorRegistration: &types.ValidatorRegistration{ FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), GasLimit: fmt.Sprint(0), Timestamp: fmt.Sprint(0), @@ -629,9 +647,9 @@ func ValidatorRegistrationSignRequest() *v1.ValidatorRegistrationSignRequest { ///////////////////////////////////////////////////////////////////////////////////////////////// // ForkInfo is a mock implementation of the ForkInfo. -func ForkInfo() *v1.ForkInfo { - return &v1.ForkInfo{ - Fork: &v1.Fork{ +func ForkInfo() *types.ForkInfo { + return &types.ForkInfo{ + Fork: &types.Fork{ PreviousVersion: make([]byte, 4), CurrentVersion: make([]byte, 4), Epoch: "0", @@ -641,18 +659,18 @@ func ForkInfo() *v1.ForkInfo { } // Attestation is a mock implementation of the Attestation. -func Attestation() *v1.Attestation { - return &v1.Attestation{ +func Attestation() *types.Attestation { + return &types.Attestation{ AggregationBits: []byte(bitfield.Bitlist{0b1101}), - Data: &v1.AttestationData{ + Data: &types.AttestationData{ Slot: "0", Index: "0", BeaconBlockRoot: make([]byte, fieldparams.RootLength), - Source: &v1.Checkpoint{ + Source: &types.Checkpoint{ Epoch: "0", Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), }, - Target: &v1.Checkpoint{ + Target: &types.Checkpoint{ Epoch: "0", Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), }, @@ -661,18 +679,42 @@ func Attestation() *v1.Attestation { } } -func IndexedAttestation() *v1.IndexedAttestation { - return &v1.IndexedAttestation{ +// AttestationElectra is a mock implementation of the AttestationElectra. +func AttestationElectra() *types.AttestationElectra { + committeeBits := bitfield.NewBitvector64() + committeeBits.SetBitAt(0, true) + return &types.AttestationElectra{ + AggregationBits: []byte(bitfield.Bitlist{0b1101}), + Data: &types.AttestationData{ + Slot: "0", + Index: "0", + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: &types.Checkpoint{ + Epoch: "0", + Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), + }, + Target: &types.Checkpoint{ + Epoch: "0", + Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), + }, + }, + Signature: make([]byte, fieldparams.BLSSignatureLength), + CommitteeBits: []byte(committeeBits), + } +} + +func IndexedAttestation() *types.IndexedAttestation { + return &types.IndexedAttestation{ AttestingIndices: []string{"0", "1", "2"}, - Data: &v1.AttestationData{ + Data: &types.AttestationData{ Slot: "0", Index: "0", BeaconBlockRoot: make([]byte, fieldparams.RootLength), - Source: &v1.Checkpoint{ + Source: &types.Checkpoint{ Epoch: "0", Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), }, - Target: &v1.Checkpoint{ + Target: &types.Checkpoint{ Epoch: "0", Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), }, @@ -681,24 +723,24 @@ func IndexedAttestation() *v1.IndexedAttestation { } } -func BeaconBlockAltair() *v1.BeaconBlockAltair { - return &v1.BeaconBlockAltair{ +func BeaconBlockAltair() *types.BeaconBlockAltair { + return &types.BeaconBlockAltair{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), StateRoot: make([]byte, fieldparams.RootLength), - Body: &v1.BeaconBlockBodyAltair{ + Body: &types.BeaconBlockBodyAltair{ RandaoReveal: make([]byte, 32), - Eth1Data: &v1.Eth1Data{ + Eth1Data: &types.Eth1Data{ DepositRoot: make([]byte, fieldparams.RootLength), DepositCount: "0", BlockHash: make([]byte, 32), }, Graffiti: make([]byte, 32), - ProposerSlashings: []*v1.ProposerSlashing{ + ProposerSlashings: []*types.ProposerSlashing{ { - Signedheader1: &v1.SignedBeaconBlockHeader{ - Message: &v1.BeaconBlockHeader{ + Signedheader1: &types.SignedBeaconBlockHeader{ + Message: &types.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -707,8 +749,8 @@ func BeaconBlockAltair() *v1.BeaconBlockAltair { }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, - Signedheader2: &v1.SignedBeaconBlockHeader{ - Message: &v1.BeaconBlockHeader{ + Signedheader2: &types.SignedBeaconBlockHeader{ + Message: &types.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -719,19 +761,19 @@ func BeaconBlockAltair() *v1.BeaconBlockAltair { }, }, }, - AttesterSlashings: []*v1.AttesterSlashing{ + AttesterSlashings: []*types.AttesterSlashing{ { Attestation1: IndexedAttestation(), Attestation2: IndexedAttestation(), }, }, - Attestations: []*v1.Attestation{ + Attestations: []*types.Attestation{ Attestation(), }, - Deposits: []*v1.Deposit{ + Deposits: []*types.Deposit{ { Proof: []string{"0x41"}, - Data: &v1.DepositData{ + Data: &types.DepositData{ PublicKey: make([]byte, fieldparams.BLSPubkeyLength), WithdrawalCredentials: make([]byte, 32), Amount: "0", @@ -739,16 +781,16 @@ func BeaconBlockAltair() *v1.BeaconBlockAltair { }, }, }, - VoluntaryExits: []*v1.SignedVoluntaryExit{ + VoluntaryExits: []*types.SignedVoluntaryExit{ { - Message: &v1.VoluntaryExit{ + Message: &types.VoluntaryExit{ Epoch: "0", ValidatorIndex: "0", }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, }, - SyncAggregate: &v1.SyncAggregate{ + SyncAggregate: &types.SyncAggregate{ SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), SyncCommitteeBits: SyncComitteeBits(), }, @@ -756,19 +798,19 @@ func BeaconBlockAltair() *v1.BeaconBlockAltair { } } -func BeaconBlockBody() *v1.BeaconBlockBody { - return &v1.BeaconBlockBody{ +func BeaconBlockBody() *types.BeaconBlockBody { + return &types.BeaconBlockBody{ RandaoReveal: make([]byte, 32), - Eth1Data: &v1.Eth1Data{ + Eth1Data: &types.Eth1Data{ DepositRoot: make([]byte, fieldparams.RootLength), DepositCount: "0", BlockHash: make([]byte, 32), }, Graffiti: make([]byte, 32), - ProposerSlashings: []*v1.ProposerSlashing{ + ProposerSlashings: []*types.ProposerSlashing{ { - Signedheader1: &v1.SignedBeaconBlockHeader{ - Message: &v1.BeaconBlockHeader{ + Signedheader1: &types.SignedBeaconBlockHeader{ + Message: &types.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -777,8 +819,8 @@ func BeaconBlockBody() *v1.BeaconBlockBody { }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, - Signedheader2: &v1.SignedBeaconBlockHeader{ - Message: &v1.BeaconBlockHeader{ + Signedheader2: &types.SignedBeaconBlockHeader{ + Message: &types.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -789,19 +831,19 @@ func BeaconBlockBody() *v1.BeaconBlockBody { }, }, }, - AttesterSlashings: []*v1.AttesterSlashing{ + AttesterSlashings: []*types.AttesterSlashing{ { Attestation1: IndexedAttestation(), Attestation2: IndexedAttestation(), }, }, - Attestations: []*v1.Attestation{ + Attestations: []*types.Attestation{ Attestation(), }, - Deposits: []*v1.Deposit{ + Deposits: []*types.Deposit{ { Proof: []string{"0x41"}, - Data: &v1.DepositData{ + Data: &types.DepositData{ PublicKey: make([]byte, fieldparams.BLSPubkeyLength), WithdrawalCredentials: make([]byte, 32), Amount: "0", @@ -809,9 +851,9 @@ func BeaconBlockBody() *v1.BeaconBlockBody { }, }, }, - VoluntaryExits: []*v1.SignedVoluntaryExit{ + VoluntaryExits: []*types.SignedVoluntaryExit{ { - Message: &v1.VoluntaryExit{ + Message: &types.VoluntaryExit{ Epoch: "0", ValidatorIndex: "0", }, @@ -821,10 +863,10 @@ func BeaconBlockBody() *v1.BeaconBlockBody { } } -func ContributionAndProof() *v1.ContributionAndProof { - return &v1.ContributionAndProof{ +func ContributionAndProof() *types.ContributionAndProof { + return &types.ContributionAndProof{ AggregatorIndex: "0", - Contribution: &v1.SyncCommitteeContribution{ + Contribution: &types.SyncCommitteeContribution{ Slot: "0", BeaconBlockRoot: make([]byte, fieldparams.RootLength), SubcommitteeIndex: "0", diff --git a/validator/keymanager/remote-web3signer/v1/requests.go b/validator/keymanager/remote-web3signer/types/requests.go similarity index 87% rename from validator/keymanager/remote-web3signer/v1/requests.go rename to validator/keymanager/remote-web3signer/types/requests.go index c78fcf08dc68..d45d49881372 100644 --- a/validator/keymanager/remote-web3signer/v1/requests.go +++ b/validator/keymanager/remote-web3signer/types/requests.go @@ -1,4 +1,4 @@ -package v1 +package types import ( "fmt" @@ -88,6 +88,34 @@ func GetAggregateAndProofSignRequest(request *validatorpb.SignRequest, genesisVa }, nil } +// GetAggregateAndProofV2ElectraSignRequest maps the request for signing type AGGREGATE_AND_PROOF_V2 on Electra changes. +func GetAggregateAndProofV2ElectraSignRequest(request *validatorpb.SignRequest, genesisValidatorsRoot []byte) (*AggregateAndProofV2ElectraSignRequest, error) { + aggregateAttestationAndProof, ok := request.Object.(*validatorpb.SignRequest_AggregateAttestationAndProofElectra) + if !ok { + return nil, errors.New("failed to cast request object to aggregate attestation and proof") + } + if aggregateAttestationAndProof == nil { + return nil, errors.New("invalid sign request: AggregateAndProof is nil") + } + fork, err := MapForkInfo(request.SigningSlot, genesisValidatorsRoot) + if err != nil { + return nil, err + } + aggregateAndProof, err := MapAggregateAndProofElectra(aggregateAttestationAndProof.AggregateAttestationAndProofElectra) + if err != nil { + return nil, err + } + return &AggregateAndProofV2ElectraSignRequest{ + Type: "AGGREGATE_AND_PROOF_V2", + ForkInfo: fork, + SigningRoot: request.SigningRoot, + AggregateAndProof: &AggregateAndProofV2Electra{ + Version: "ELECTRA", + Data: aggregateAndProof, + }, + }, nil +} + // GetAttestationSignRequest maps the request for signing type ATTESTATION. func GetAttestationSignRequest(request *validatorpb.SignRequest, genesisValidatorsRoot []byte) (*AttestationSignRequest, error) { attestation, ok := request.Object.(*validatorpb.SignRequest_AttestationData) @@ -365,6 +393,34 @@ func GetBlockV2BlindedSignRequest(request *validatorpb.SignRequest, genesisValid return nil, err } b = beaconBlock + case *validatorpb.SignRequest_BlockElectra: + version = "ELECTRA" + blockElectra, ok := request.Object.(*validatorpb.SignRequest_BlockElectra) + if !ok { + return nil, errors.New("failed to cast request object to electra block") + } + if blockElectra == nil { + return nil, errors.New("invalid sign request: electra block is nil") + } + beaconBlock, err := blocks.NewBeaconBlock(blockElectra.BlockElectra) + if err != nil { + return nil, err + } + b = beaconBlock + case *validatorpb.SignRequest_BlindedBlockElectra: + version = "ELECTRA" + blindedBlockElectra, ok := request.Object.(*validatorpb.SignRequest_BlindedBlockElectra) + if !ok { + return nil, errors.New("failed to cast request object to blinded electra block") + } + if blindedBlockElectra == nil { + return nil, errors.New("invalid sign request: blinded electra block is nil") + } + beaconBlock, err := blocks.NewBeaconBlock(blindedBlockElectra.BlindedBlockElectra) + if err != nil { + return nil, err + } + b = beaconBlock default: return nil, errors.New("invalid sign request - invalid object type") } diff --git a/validator/keymanager/remote-web3signer/v1/requests_test.go b/validator/keymanager/remote-web3signer/types/requests_test.go similarity index 83% rename from validator/keymanager/remote-web3signer/v1/requests_test.go rename to validator/keymanager/remote-web3signer/types/requests_test.go index b5562043c665..d7a93b0279b6 100644 --- a/validator/keymanager/remote-web3signer/v1/requests_test.go +++ b/validator/keymanager/remote-web3signer/types/requests_test.go @@ -1,4 +1,4 @@ -package v1_test +package types_test import ( "reflect" @@ -8,8 +8,8 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v5/testing/require" - v1 "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1" - "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1/mock" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types/mock" ) func TestGetAggregateAndProofSignRequest(t *testing.T) { @@ -20,7 +20,7 @@ func TestGetAggregateAndProofSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.AggregateAndProofSignRequest + want *types.AggregateAndProofSignRequest wantErr bool }{ { @@ -35,7 +35,7 @@ func TestGetAggregateAndProofSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetAggregateAndProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetAggregateAndProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetAggregateAndProofSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -55,7 +55,7 @@ func TestGetAggregationSlotSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.AggregationSlotSignRequest + want *types.AggregationSlotSignRequest wantErr bool }{ { @@ -70,7 +70,7 @@ func TestGetAggregationSlotSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetAggregationSlotSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetAggregationSlotSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetAggregationSlotSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -90,7 +90,7 @@ func TestGetAttestationSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.AttestationSignRequest + want *types.AttestationSignRequest wantErr bool }{ { @@ -104,7 +104,7 @@ func TestGetAttestationSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetAttestationSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetAttestationSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetAttestationSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -124,7 +124,7 @@ func TestGetBlockSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.BlockSignRequest + want *types.BlockSignRequest wantErr bool }{ { @@ -139,7 +139,7 @@ func TestGetBlockSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetBlockSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetBlockSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetBlockSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -159,7 +159,7 @@ func TestGetBlockV2AltairSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.BlockAltairSignRequest + want *types.BlockAltairSignRequest wantErr bool }{ { @@ -174,7 +174,7 @@ func TestGetBlockV2AltairSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetBlockAltairSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetBlockAltairSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetBlockAltairSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -194,7 +194,7 @@ func TestGetRandaoRevealSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.RandaoRevealSignRequest + want *types.RandaoRevealSignRequest wantErr bool }{ { @@ -209,7 +209,7 @@ func TestGetRandaoRevealSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetRandaoRevealSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetRandaoRevealSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetRandaoRevealSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -229,7 +229,7 @@ func TestGetSyncCommitteeContributionAndProofSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.SyncCommitteeContributionAndProofSignRequest + want *types.SyncCommitteeContributionAndProofSignRequest wantErr bool }{ { @@ -244,7 +244,7 @@ func TestGetSyncCommitteeContributionAndProofSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetSyncCommitteeContributionAndProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetSyncCommitteeContributionAndProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetSyncCommitteeContributionAndProofSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -264,7 +264,7 @@ func TestGetSyncCommitteeMessageSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.SyncCommitteeMessageSignRequest + want *types.SyncCommitteeMessageSignRequest wantErr bool }{ { @@ -279,7 +279,7 @@ func TestGetSyncCommitteeMessageSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetSyncCommitteeMessageSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetSyncCommitteeMessageSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetSyncCommitteeMessageSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -299,7 +299,7 @@ func TestGetSyncCommitteeSelectionProofSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.SyncCommitteeSelectionProofSignRequest + want *types.SyncCommitteeSelectionProofSignRequest wantErr bool }{ { @@ -314,7 +314,7 @@ func TestGetSyncCommitteeSelectionProofSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetSyncCommitteeSelectionProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetSyncCommitteeSelectionProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetSyncCommitteeSelectionProofSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -334,7 +334,7 @@ func TestGetVoluntaryExitSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.VoluntaryExitSignRequest + want *types.VoluntaryExitSignRequest wantErr bool }{ { @@ -349,7 +349,7 @@ func TestGetVoluntaryExitSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetVoluntaryExitSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetVoluntaryExitSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetVoluntaryExitSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -369,7 +369,7 @@ func TestGetBlockV2BlindedSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.BlockV2BlindedSignRequest + want *types.BlockV2BlindedSignRequest wantErr bool }{ { @@ -450,10 +450,36 @@ func TestGetBlockV2BlindedSignRequest(t *testing.T) { }(t), "DENEB"), wantErr: false, }, + { + name: "Happy Path Test non blinded Electra", + args: args{ + request: mock.GetMockSignRequest("BLOCK_V2_ELECTRA"), + genesisValidatorsRoot: make([]byte, fieldparams.RootLength), + }, + want: mock.BlockV2BlindedSignRequest(func(t *testing.T) []byte { + bytevalue, err := hexutil.Decode("0xb5d0ae72716c50f01a6bf4edd98f282b909b31a81e7234e2a0363bee23447579") + require.NoError(t, err) + return bytevalue + }(t), "ELECTRA"), + wantErr: false, + }, + { + name: "Happy Path Test blinded Electra", + args: args{ + request: mock.GetMockSignRequest("BLOCK_V2_BLINDED_ELECTRA"), + genesisValidatorsRoot: make([]byte, fieldparams.RootLength), + }, + want: mock.BlockV2BlindedSignRequest(func(t *testing.T) []byte { + bytevalue, err := hexutil.Decode("0xedb1bcb0d8b4be2d1ccca09c113c7f2dc4b126a8379e6aeb02652fa182195d12") + require.NoError(t, err) + return bytevalue + }(t), "ELECTRA"), + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetBlockV2BlindedSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetBlockV2BlindedSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetBlockV2BlindedSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -472,7 +498,7 @@ func TestGetValidatorRegistrationSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.ValidatorRegistrationSignRequest + want *types.ValidatorRegistrationSignRequest wantErr bool }{ { @@ -486,7 +512,7 @@ func TestGetValidatorRegistrationSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetValidatorRegistrationSignRequest(tt.args.request) + got, err := types.GetValidatorRegistrationSignRequest(tt.args.request) if (err != nil) != tt.wantErr { t.Errorf("GetValidatorRegistrationSignRequest() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/validator/keymanager/remote-web3signer/v1/web3signer_types.go b/validator/keymanager/remote-web3signer/types/web3signer_types.go similarity index 91% rename from validator/keymanager/remote-web3signer/v1/web3signer_types.go rename to validator/keymanager/remote-web3signer/types/web3signer_types.go index 075204677384..b21a1447ce27 100644 --- a/validator/keymanager/remote-web3signer/v1/web3signer_types.go +++ b/validator/keymanager/remote-web3signer/types/web3signer_types.go @@ -1,6 +1,6 @@ // Package v1 defines mappings of types as defined by the web3signer official specification for its v1 version i.e. /api/v1/eth2 /* Web3Signer Specs are found by searching Consensys' Web3Signer API specification*/ -package v1 +package types import ( "github.com/ethereum/go-ethereum/common/hexutil" @@ -22,6 +22,20 @@ type AggregateAndProofSignRequest struct { AggregateAndProof *AggregateAndProof `json:"aggregate_and_proof" validate:"required"` } +// AggregateAndProofV2ElectraSignRequest is a request object for web3signer sign api. +type AggregateAndProofV2ElectraSignRequest struct { + Type string `json:"type" validate:"required"` + ForkInfo *ForkInfo `json:"fork_info" validate:"required"` + SigningRoot hexutil.Bytes `json:"signingRoot"` + AggregateAndProof *AggregateAndProofV2Electra `json:"aggregate_and_proof" validate:"required"` +} + +// AggregateAndProofV2Electra is a wrapper object for AggregateAndProofV2ElectraSignRequest +type AggregateAndProofV2Electra struct { + Version string `json:"version" validate:"required"` + Data *AggregateAndProofElectra `json:"data" validate:"required"` +} + // AttestationSignRequest is a request object for web3signer sign api. type AttestationSignRequest struct { Type string `json:"type" validate:"required"` @@ -134,6 +148,13 @@ type AggregateAndProof struct { SelectionProof hexutil.Bytes `json:"selection_proof"` /* 96 bytes */ } +// AggregateAndProofElectra a sub property of AggregateAndProofV2ElectraSignRequest. +type AggregateAndProofElectra struct { + AggregatorIndex string `json:"aggregator_index"` /* uint64 */ + Aggregate *AttestationElectra `json:"aggregate"` + SelectionProof hexutil.Bytes `json:"selection_proof"` /* 96 bytes */ +} + // Attestation a sub property of AggregateAndProofSignRequest. type Attestation struct { AggregationBits hexutil.Bytes `json:"aggregation_bits"` /*hex bitlist*/ @@ -141,6 +162,14 @@ type Attestation struct { Signature hexutil.Bytes `json:"signature"` } +// AttestationElectra a sub property of AggregateAndProofElectra. +type AttestationElectra struct { + AggregationBits hexutil.Bytes `json:"aggregation_bits"` /*hex bitlist*/ + Data *AttestationData `json:"data"` + Signature hexutil.Bytes `json:"signature"` + CommitteeBits hexutil.Bytes `json:"committee_bits"` /* SSZ hexadecimal string */ +} + // AttestationData a sub property of Attestation. type AttestationData struct { Slot string `json:"slot"` /* uint64 */