diff --git a/changelog/james-prysm_fix-web3signer-e2e.md b/changelog/james-prysm_fix-web3signer-e2e.md new file mode 100644 index 0000000000..87f95f2d3f --- /dev/null +++ b/changelog/james-prysm_fix-web3signer-e2e.md @@ -0,0 +1,7 @@ +### Fixed + +- Fixed web3signer e2e, issues caused due to a regression on old fork support + +### Changed + +- updated web3signer to 25.9.1 diff --git a/testing/endtoend/components/web3remotesigner.go b/testing/endtoend/components/web3remotesigner.go index 10619a66c5..f84d8bfc1a 100644 --- a/testing/endtoend/components/web3remotesigner.go +++ b/testing/endtoend/components/web3remotesigner.go @@ -256,17 +256,12 @@ func (w *Web3RemoteSigner) UnderlyingProcess() *os.Process { func createTestnetDir() (string, error) { testNetDir := e2e.TestParams.TestPath + "/web3signer-testnet" configPath := filepath.Join(testNetDir, "config.yaml") - - // TODO: add blob schedule back in as soon as web3signer supports it! configCopy := params.BeaconConfig().Copy() - configCopy.BlobSchedule = nil - // --- - rawYaml := params.ConfigToYaml(configCopy) - // Add in deposit contract in yaml - depContractStr := fmt.Sprintf("\nDEPOSIT_CONTRACT_ADDRESS: %s\n", params.BeaconConfig().DepositContractAddress) - rawYaml = append(rawYaml, []byte(depContractStr)...) + // TODO: remove this when it's removed from web3signer + maxBlobsStr := fmt.Sprintf("\nMAX_BLOBS_PER_BLOCK_ELECTRA: %s\n", fmt.Sprintf("%d", params.BeaconConfig().DeprecatedMaxBlobsPerBlockElectra)) + rawYaml = append(rawYaml, []byte(maxBlobsStr)...) if err := file.MkdirAll(testNetDir); err != nil { return "", err diff --git a/testing/endtoend/deps.bzl b/testing/endtoend/deps.bzl index 33f424a369..574a1b6d54 100644 --- a/testing/endtoend/deps.bzl +++ b/testing/endtoend/deps.bzl @@ -6,10 +6,10 @@ lighthouse_archive_name = "lighthouse-%s-x86_64-unknown-linux-gnu.tar.gz" % ligh def e2e_deps(): http_archive( name = "web3signer", - urls = ["https://github.com/Consensys/web3signer/releases/download/25.9.0/web3signer-25.9.0.tar.gz"], - sha256 = "4bc95a86e232050ff071279043e1d04616572d551f6f72aee31108f96dc77bd8", + urls = ["https://github.com/Consensys/web3signer/releases/download/25.9.1/web3signer-25.9.1.tar.gz"], + sha256 = "d84498abbe46fcf10ca44f930eafcd80d7339cbf3f7f7f42a77eb1763ab209cf", build_file = "@prysm//testing/endtoend:web3signer.BUILD", - strip_prefix = "web3signer-25.9.0", + strip_prefix = "web3signer-25.9.1", ) http_archive( diff --git a/validator/keymanager/remote-web3signer/types/mock/BUILD.bazel b/validator/keymanager/remote-web3signer/types/mock/BUILD.bazel index a9a32929c2..40df946d36 100644 --- a/validator/keymanager/remote-web3signer/types/mock/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/types/mock/BUILD.bazel @@ -8,6 +8,8 @@ go_library( visibility = ["//visibility:public"], deps = [ "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//consensus-types/primitives:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", "//runtime/version:go_default_library", diff --git a/validator/keymanager/remote-web3signer/types/mock/mocks.go b/validator/keymanager/remote-web3signer/types/mock/mocks.go index 5d4d4b164b..765980508a 100644 --- a/validator/keymanager/remote-web3signer/types/mock/mocks.go +++ b/validator/keymanager/remote-web3signer/types/mock/mocks.go @@ -1,10 +1,13 @@ package mock import ( + "encoding/json" "fmt" "strings" fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" + "github.com/OffchainLabs/prysm/v6/config/params" + "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" eth "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" validatorpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1/validator-client" "github.com/OffchainLabs/prysm/v6/runtime/version" @@ -55,6 +58,32 @@ func GetMockSignRequest(t string) *validatorpb.SignRequest { }, SigningSlot: 0, } + case "AGGREGATE_AND_PROOF": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_AggregateAttestationAndProof{ + AggregateAttestationAndProof: ð.AggregateAttestationAndProof{ + AggregatorIndex: 0, + Aggregate: ð.Attestation{ + AggregationBits: bitfield.Bitlist{0b1101}, + Data: ð.AttestationData{ + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: ð.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + Target: ð.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + }, + Signature: make([]byte, 96), + }, + SelectionProof: make([]byte, fieldparams.BLSSignatureLength), + }, + }, + SigningSlot: 0, + } case "AGGREGATE_AND_PROOF_V2": committeeBits := bitfield.NewBitvector64() committeeBits.SetBitAt(0, true) @@ -82,7 +111,7 @@ func GetMockSignRequest(t string) *validatorpb.SignRequest { SelectionProof: make([]byte, fieldparams.BLSSignatureLength), }, }, - SigningSlot: 0, + SigningSlot: primitives.Slot(params.BeaconConfig().ElectraForkEpoch) * primitives.Slot(params.BeaconConfig().SlotsPerEpoch), } case "ATTESTATION": return &validatorpb.SignRequest{ @@ -521,17 +550,34 @@ func AggregationSlotSignRequest() *types.AggregationSlotSignRequest { // AggregateAndProofV2SignRequest is a mock implementation of the AggregateAndProofV2SignRequest. func AggregateAndProofV2SignRequest(ver int) *types.AggregateAndProofV2SignRequest { + var aggregateAndProofJSON []byte + var slot primitives.Slot + if ver < version.Electra { + aggregateAndProofData := &types.AggregateAndProof{ + AggregatorIndex: "0", + Aggregate: Attestation(), + SelectionProof: make([]byte, fieldparams.BLSSignatureLength), + } + aggregateAndProofJSON, _ = json.Marshal(aggregateAndProofData) + slot = 0 // Pre-Electra slot + } else { + aggregateAndProofData := &types.AggregateAndProofElectra{ + AggregatorIndex: "0", + Aggregate: AttestationElectra(), + SelectionProof: make([]byte, fieldparams.BLSSignatureLength), + } + aggregateAndProofJSON, _ = json.Marshal(aggregateAndProofData) + slot = primitives.Slot(params.BeaconConfig().ElectraForkEpoch) * primitives.Slot(params.BeaconConfig().SlotsPerEpoch) + } + // Generate ForkInfo dynamically based on the slot + forkInfo, _ := types.MapForkInfo(slot, make([]byte, fieldparams.RootLength)) return &types.AggregateAndProofV2SignRequest{ Type: "AGGREGATE_AND_PROOF_V2", - ForkInfo: ForkInfo(), + ForkInfo: forkInfo, SigningRoot: make([]byte, fieldparams.RootLength), AggregateAndProof: &types.AggregateAndProofV2{ Version: strings.ToUpper(version.String(ver)), - Data: &types.AggregateAndProofElectra{ - AggregatorIndex: "0", - Aggregate: AttestationElectra(), - SelectionProof: make([]byte, fieldparams.BLSSignatureLength), - }, + Data: aggregateAndProofJSON, }, } } diff --git a/validator/keymanager/remote-web3signer/types/requests.go b/validator/keymanager/remote-web3signer/types/requests.go index c458c6c7f0..a3f99babd2 100644 --- a/validator/keymanager/remote-web3signer/types/requests.go +++ b/validator/keymanager/remote-web3signer/types/requests.go @@ -1,6 +1,7 @@ package types import ( + "encoding/json" "fmt" "strings" @@ -67,28 +68,53 @@ func GetAggregationSlotSignRequest(request *validatorpb.SignRequest, genesisVali // GetAggregateAndProofV2SignRequest maps the request for signing type AGGREGATE_AND_PROOF_V2 on Electra changes. func GetAggregateAndProofV2SignRequest(v int, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) (*AggregateAndProofV2SignRequest, 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 + + var aggregateAndProofJSON []byte + if v < version.Electra { + aggregateAttestationAndProof, ok := request.Object.(*validatorpb.SignRequest_AggregateAttestationAndProof) + 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") + } + aggregateAndProof, err := MapAggregateAndProof(aggregateAttestationAndProof.AggregateAttestationAndProof) + if err != nil { + return nil, err + } + aggregateAndProofJSON, err = json.Marshal(aggregateAndProof) + if err != nil { + return nil, err + } + } else { + aggregateAttestationAndProof, ok := request.Object.(*validatorpb.SignRequest_AggregateAttestationAndProofElectra) + if !ok { + return nil, errors.New("failed to cast request object to aggregate attestation and proof Electra") + } + if aggregateAttestationAndProof == nil { + return nil, errors.New("invalid sign request: AggregateAndProof is nil") + } + aggregateAndProof, err := MapAggregateAndProofElectra(aggregateAttestationAndProof.AggregateAttestationAndProofElectra) + if err != nil { + return nil, err + } + aggregateAndProofJSON, err = json.Marshal(aggregateAndProof) + if err != nil { + return nil, err + } } + return &AggregateAndProofV2SignRequest{ Type: "AGGREGATE_AND_PROOF_V2", ForkInfo: fork, SigningRoot: request.SigningRoot, AggregateAndProof: &AggregateAndProofV2{ Version: strings.ToUpper(version.String(v)), - Data: aggregateAndProof, + Data: aggregateAndProofJSON, }, }, nil } diff --git a/validator/keymanager/remote-web3signer/types/requests_test.go b/validator/keymanager/remote-web3signer/types/requests_test.go index 32a678bf00..a12619146e 100644 --- a/validator/keymanager/remote-web3signer/types/requests_test.go +++ b/validator/keymanager/remote-web3signer/types/requests_test.go @@ -1,6 +1,7 @@ package types_test import ( + "encoding/json" "reflect" "testing" @@ -15,6 +16,7 @@ import ( func TestGetAggregateAndProofV2SignRequest(t *testing.T) { type args struct { + version int request *validatorpb.SignRequest genesisValidatorsRoot []byte } @@ -25,24 +27,40 @@ func TestGetAggregateAndProofV2SignRequest(t *testing.T) { wantErr bool }{ { - name: "Happy Path Test", + name: "Happy Path Test Electra", args: args{ + version: version.Electra, request: mock.GetMockSignRequest("AGGREGATE_AND_PROOF_V2"), genesisValidatorsRoot: make([]byte, fieldparams.RootLength), }, want: mock.AggregateAndProofV2SignRequest(version.Electra), wantErr: false, }, + { + name: "Happy Path Test Pre-Electra", + args: args{ + version: version.Deneb, + request: mock.GetMockSignRequest("AGGREGATE_AND_PROOF"), + genesisValidatorsRoot: make([]byte, fieldparams.RootLength), + }, + want: mock.AggregateAndProofV2SignRequest(version.Deneb), + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := types.GetAggregateAndProofV2SignRequest(version.Electra, tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetAggregateAndProofV2SignRequest(tt.args.version, tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetAggregateAndProofV2SignRequest() error = %v, wantErr %v", err, tt.wantErr) return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAggregateAndProofV2SignRequest() got = %v, want %v", got, tt.want) + // Marshal to JSON for comparison since ForkInfo is generated dynamically + gotJSON, err := json.Marshal(got) + require.NoError(t, err) + wantJSON, err := json.Marshal(tt.want) + require.NoError(t, err) + if string(gotJSON) != string(wantJSON) { + t.Errorf("JSON mismatch:\ngot: %s\nwant: %s", string(gotJSON), string(wantJSON)) } }) } diff --git a/validator/keymanager/remote-web3signer/types/web3signer_types.go b/validator/keymanager/remote-web3signer/types/web3signer_types.go index 49a7028320..682bb23da8 100644 --- a/validator/keymanager/remote-web3signer/types/web3signer_types.go +++ b/validator/keymanager/remote-web3signer/types/web3signer_types.go @@ -3,6 +3,8 @@ package types import ( + "encoding/json" + "github.com/ethereum/go-ethereum/common/hexutil" ) @@ -32,8 +34,8 @@ type AggregateAndProofV2SignRequest struct { // AggregateAndProofV2 is a wrapper object for AggregateAndProofV2SignRequest type AggregateAndProofV2 struct { - Version string `json:"version" validate:"required"` - Data *AggregateAndProofElectra `json:"data" validate:"required"` // specifies Electra for now + Version string `json:"version" validate:"required"` + Data json.RawMessage `json:"data" validate:"required"` } // AttestationSignRequest is a request object for web3signer sign api.