From 493a7179d7cf8c1034553081fb6fc59c507b3dfd Mon Sep 17 00:00:00 2001 From: james-prysm <90280386+james-prysm@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:06:36 -0500 Subject: [PATCH] Deneb - web3signer (#12767) * wip * adding deneb block * adding in support for blobs and fixing unit tests for deneb * fixing linting * gaz * adding support for new web3signer version * fixing tag name * addressing feedback * fixing tests * adding unit test for review * updating test name * updating unit tests and length logic * adding in lengthfor root * adjusting max blob length * fixing mock * fixing another mock * gaz * adding network configs * removing duplicate * changing based on nishant's feedback * Update validator/keymanager/remote-web3signer/v1/requests.go Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com> * Update validator/keymanager/remote-web3signer/metrics.go Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com> * sammy's suggestions * removing temp file --------- Co-authored-by: Nishant Das Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> --- config/params/loader.go | 25 ++ encoding/ssz/htrutils.go | 16 +- encoding/ssz/htrutils_test.go | 52 +++ .../endtoend/components/web3remotesigner.go | 10 +- testing/endtoend/deps.bzl | 6 +- .../keymanager/remote-web3signer/README.md | 15 +- .../remote-web3signer/keymanager.go | 387 ++++++++++++------ .../remote-web3signer/keymanager_test.go | 10 +- .../keymanager/remote-web3signer/metrics.go | 16 + .../remote-web3signer/v1/BUILD.bazel | 2 + .../remote-web3signer/v1/mock/BUILD.bazel | 2 + .../remote-web3signer/v1/mock/mocks.go | 87 ++++ .../remote-web3signer/v1/requests.go | 97 ++++- .../remote-web3signer/v1/requests_test.go | 67 +++ .../remote-web3signer/v1/web3signer_types.go | 20 + 15 files changed, 659 insertions(+), 153 deletions(-) diff --git a/config/params/loader.go b/config/params/loader.go index 61b438dcaa..653609a90d 100644 --- a/config/params/loader.go +++ b/config/params/loader.go @@ -214,3 +214,28 @@ func ConfigToYaml(cfg *BeaconChainConfig) []byte { yamlFile := []byte(strings.Join(lines, "\n")) return yamlFile } + +// NetworkConfigToYaml takes a provided network config and outputs its contents +// in yaml. This allows prysm's network configs to be read by other clients. +func NetworkConfigToYaml(cfg *NetworkConfig) []byte { + lines := []string{ + fmt.Sprintf("GOSSIP_MAX_SIZE: %d", cfg.GossipMaxSize), + fmt.Sprintf("GOSSIP_MAX_SIZE_BELLATRIX: %d", cfg.GossipMaxSizeBellatrix), + fmt.Sprintf("MAX_CHUNK_SIZE: %d", cfg.MaxChunkSize), + fmt.Sprintf("MAX_CHUNK_SIZE_BELLATRIX: %d", cfg.MaxChunkSizeBellatrix), + fmt.Sprintf("ATTESTATION_SUBNET_COUNT: %d", cfg.AttestationSubnetCount), + fmt.Sprintf("ATTESTATION_PROPAGATION_SLOT_RANGE: %d", cfg.AttestationPropagationSlotRange), + fmt.Sprintf("MAX_REQUEST_BLOCKS: %d", cfg.MaxRequestBlocks), + fmt.Sprintf("TTFB_TIMEOUT: %d", int(cfg.TtfbTimeout.Seconds())), + fmt.Sprintf("RESP_TIMEOUT: %d", int(cfg.RespTimeout.Seconds())), + fmt.Sprintf("MAXIMUM_GOSSIP_CLOCK_DISPARITY: %d", int(cfg.MaximumGossipClockDisparity.Seconds())), + fmt.Sprintf("MESSAGE_DOMAIN_INVALID_SNAPPY: %#x", cfg.MessageDomainInvalidSnappy), + fmt.Sprintf("MESSAGE_DOMAIN_VALID_SNAPPY: %#x", cfg.MessageDomainValidSnappy), + fmt.Sprintf("MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUEST: %d", cfg.MinEpochsForBlobsSidecarsRequest), + fmt.Sprintf("MAX_REQUEST_BLOB_SIDECARS: %d", cfg.MaxRequestBlobSidecars), + fmt.Sprintf("MAX_REQUEST_BLOCKS_DENEB: %d", cfg.MaxRequestBlocksDeneb), + } + + yamlFile := []byte(strings.Join(lines, "\n")) + return yamlFile +} diff --git a/encoding/ssz/htrutils.go b/encoding/ssz/htrutils.go index 68d5320780..84e3c1aa0c 100644 --- a/encoding/ssz/htrutils.go +++ b/encoding/ssz/htrutils.go @@ -96,7 +96,7 @@ func SlashingsRoot(slashings []uint64) ([32]byte, error) { func TransactionsRoot(txs [][]byte) ([32]byte, error) { txRoots := make([][32]byte, 0) for i := 0; i < len(txs); i++ { - rt, err := transactionRoot(txs[i]) + rt, err := ByteSliceRoot(txs[i], fieldparams.MaxBytesPerTxLength) // getting the transaction root here if err != nil { return [32]byte{}, err } @@ -141,19 +141,21 @@ func WithdrawalSliceRoot(withdrawals []*enginev1.Withdrawal, limit uint64) ([32] return MixInLength(bytesRoot, bytesRootBufRoot), nil } -func transactionRoot(tx []byte) ([32]byte, error) { - chunkedRoots, err := PackByChunk([][]byte{tx}) +// ByteSliceRoot is a helper func to merkleize an arbitrary List[Byte, N] +// this func runs Chunkify + MerkleizeVector +// max length is dividable by 32 ( root length ) +func ByteSliceRoot(slice []byte, maxLength uint64) ([32]byte, error) { + chunkedRoots, err := PackByChunk([][]byte{slice}) if err != nil { return [32]byte{}, err } - - maxLength := (fieldparams.MaxBytesPerTxLength + 31) / 32 - bytesRoot, err := BitwiseMerkleize(chunkedRoots, uint64(len(chunkedRoots)), uint64(maxLength)) + maxRootLength := (maxLength + 31) / 32 // nearest number divisible by root length (32) + bytesRoot, err := BitwiseMerkleize(chunkedRoots, uint64(len(chunkedRoots)), maxRootLength) if err != nil { return [32]byte{}, errors.Wrap(err, "could not compute merkleization") } bytesRootBuf := new(bytes.Buffer) - if err := binary.Write(bytesRootBuf, binary.LittleEndian, uint64(len(tx))); err != nil { + if err := binary.Write(bytesRootBuf, binary.LittleEndian, uint64(len(slice))); err != nil { return [32]byte{}, errors.Wrap(err, "could not marshal length") } bytesRootBufRoot := make([]byte, 32) diff --git a/encoding/ssz/htrutils_test.go b/encoding/ssz/htrutils_test.go index dae1fb085a..fa10d81b3b 100644 --- a/encoding/ssz/htrutils_test.go +++ b/encoding/ssz/htrutils_test.go @@ -122,6 +122,58 @@ func TestTransactionsRoot(t *testing.T) { } } +func TestByteSliceRoot(t *testing.T) { + tests := []struct { + name string + slice []byte + maxLength uint64 + want [32]byte + wantErr bool + }{ + { + name: "nil", + slice: nil, + want: [32]byte{245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169, 39, 89, 251, 75}, + }, + { + name: "empty", + slice: []byte{}, + want: [32]byte{245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169, 39, 89, 251, 75}, + }, + { + name: "byte slice 3 values", + slice: []byte{1, 2, 3}, + want: [32]byte{20, 159, 26, 252, 247, 204, 44, 159, 161, 135, 211, 195, 106, 59, 220, 149, 199, 163, 228, 155, 113, 118, 64, 126, 173, 223, 102, 1, 241, 158, 164, 185}, + }, + { + name: "byte slice 32 values", + slice: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}, + want: [32]byte{7, 30, 46, 77, 237, 240, 59, 126, 232, 232, 232, 6, 145, 210, 31, 18, 117, 12, 217, 40, 204, 141, 90, 236, 241, 128, 221, 45, 126, 39, 39, 202}, + }, + { + name: "over max length", + slice: make([]byte, fieldparams.RootLength+1), + want: [32]byte{}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.maxLength == 0 { + tt.maxLength = fieldparams.RootLength + } + got, err := ssz.ByteSliceRoot(tt.slice, tt.maxLength) + if (err != nil) != tt.wantErr { + t.Errorf("ByteSliceRoot() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("ByteSliceRoot() got = %v, want %v", got, tt.want) + } + }) + } +} + func TestPackByChunk_SingleList(t *testing.T) { tests := []struct { name string diff --git a/testing/endtoend/components/web3remotesigner.go b/testing/endtoend/components/web3remotesigner.go index 45f28f91cd..4068b8f484 100644 --- a/testing/endtoend/components/web3remotesigner.go +++ b/testing/endtoend/components/web3remotesigner.go @@ -256,9 +256,17 @@ func createTestnetDir() (string, error) { testNetDir := e2e.TestParams.TestPath + "/web3signer-testnet" configPath := filepath.Join(testNetDir, "config.yaml") rawYaml := params.ConfigToYaml(params.BeaconConfig()) + // Add in deposit contract in yaml - depContractStr := fmt.Sprintf("\nDEPOSIT_CONTRACT_ADDRESS: %s", params.BeaconConfig().DepositContractAddress) + depContractStr := fmt.Sprintf("\nDEPOSIT_CONTRACT_ADDRESS: %s\n", params.BeaconConfig().DepositContractAddress) rawYaml = append(rawYaml, []byte(depContractStr)...) + rawYaml = append(rawYaml, params.NetworkConfigToYaml(params.BeaconNetworkConfig())...) + + rawYaml = append(rawYaml, []byte("\nEPOCHS_PER_SUBNET_SUBSCRIPTION: 256\n")...) + rawYaml = append(rawYaml, []byte("\nMIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024\n")...) + rawYaml = append(rawYaml, []byte("\nSUBNETS_PER_NODE: 2\n")...) + rawYaml = append(rawYaml, []byte("\nATTESTATION_SUBNET_EXTRA_BITS: 0\n")...) + rawYaml = append(rawYaml, []byte("\nATTESTATION_SUBNET_PREFIX_BITS: 6\n")...) if err := file.MkdirAll(testNetDir); err != nil { return "", err diff --git a/testing/endtoend/deps.bzl b/testing/endtoend/deps.bzl index f6ec88a796..1e239f292d 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-portable.tar.g def e2e_deps(): http_archive( name = "web3signer", - urls = ["https://artifacts.consensys.net/public/web3signer/raw/names/web3signer.tar.gz/versions/23.3.1/web3signer-23.3.1.tar.gz"], - sha256 = "32dfbfd8d5900f19aa426d3519724dd696e6529b7ec2f99e0cb1690dae52b3d6", + urls = ["https://artifacts.consensys.net/public/web3signer/raw/names/web3signer.tar.gz/versions/23.9.1/web3signer-23.9.1.tar.gz"], + sha256 = "aec9dc745cb25fd8d7b38b06e435e3138972c2cf842dd6f851d50be7bf081629", build_file = "@prysm//testing/endtoend:web3signer.BUILD", - strip_prefix = "web3signer-23.3.1", + strip_prefix = "web3signer-23.9.1", ) http_archive( diff --git a/validator/keymanager/remote-web3signer/README.md b/validator/keymanager/remote-web3signer/README.md index 7a6e438a75..9a94fc2d03 100644 --- a/validator/keymanager/remote-web3signer/README.md +++ b/validator/keymanager/remote-web3signer/README.md @@ -6,15 +6,22 @@ searching `Consensys' Web3Signer API specification` issue: https://github.com/prysmaticlabs/prysm/issues/9994 -## Support - -WIP +API interface: https://github.com/ethereum/remote-signing-api ## Features ### CLI -WIP +detailed info found on https://docs.prylabs.network/docs/wallet/web3signer + +Flags used on validator client +- `--validators-external-signer-url=http://localhost:9000` + +with hex keys +- `--validators-external-signer-public-keys=0xa99a...e44c,0xb89b...4a0b` + +with url +- `--validators-external-signer-public-keys=https://web3signer.com/api/v1/eth2/publicKeys` ### API diff --git a/validator/keymanager/remote-web3signer/keymanager.go b/validator/keymanager/remote-web3signer/keymanager.go index 047d6b9a4f..f59326c3b5 100644 --- a/validator/keymanager/remote-web3signer/keymanager.go +++ b/validator/keymanager/remote-web3signer/keymanager.go @@ -113,95 +113,27 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ } switch request.Object.(type) { case *validatorpb.SignRequest_Block: - bockSignRequest, err := web3signerv1.GetBlockSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, bockSignRequest); err != nil { - return nil, err - } - blockSignRequestsTotal.Inc() - return json.Marshal(bockSignRequest) + return handleBlock(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_AttestationData: - attestationSignRequest, err := web3signerv1.GetAttestationSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, attestationSignRequest); err != nil { - return nil, err - } - attestationSignRequestsTotal.Inc() - return json.Marshal(attestationSignRequest) + return handleAttestationData(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_AggregateAttestationAndProof: - aggregateAndProofSignRequest, err := web3signerv1.GetAggregateAndProofSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, aggregateAndProofSignRequest); err != nil { - return nil, err - } - aggregateAndProofSignRequestsTotal.Inc() - return json.Marshal(aggregateAndProofSignRequest) + return handleAggregateAttestationAndProof(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_Slot: - aggregationSlotSignRequest, err := web3signerv1.GetAggregationSlotSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, aggregationSlotSignRequest); err != nil { - return nil, err - } - aggregationSlotSignRequestsTotal.Inc() - return json.Marshal(aggregationSlotSignRequest) + return handleAggregationSlot(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_BlockAltair: - blockv2AltairSignRequest, err := web3signerv1.GetBlockAltairSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, blockv2AltairSignRequest); err != nil { - return nil, err - } - blockAltairSignRequestsTotal.Inc() - return json.Marshal(blockv2AltairSignRequest) + return handleBlockAltair(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_BlockBellatrix: - blockv2BellatrixSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, blockv2BellatrixSignRequest); err != nil { - return nil, err - } - blockBellatrixSignRequestsTotal.Inc() - return json.Marshal(blockv2BellatrixSignRequest) + return handleBlockBellatrix(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_BlindedBlockBellatrix: - blindedBlockv2SignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, blindedBlockv2SignRequest); err != nil { - return nil, err - } - blindedBlockBellatrixSignRequestsTotal.Inc() - return json.Marshal(blindedBlockv2SignRequest) + return handleBlindedBlockBellatrix(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_BlockCapella: - blockv2CapellaSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, blockv2CapellaSignRequest); err != nil { - return nil, err - } - blockCapellaSignRequestsTotal.Inc() - return json.Marshal(blockv2CapellaSignRequest) + return handleBlockCapella(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_BlindedBlockCapella: - blindedBlockv2CapellaSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, blindedBlockv2CapellaSignRequest); err != nil { - return nil, err - } - blindedBlockCapellaSignRequestsTotal.Inc() - return json.Marshal(blindedBlockv2CapellaSignRequest) + return handleBlindedBlockCapella(ctx, validator, request, genesisValidatorsRoot) + case *validatorpb.SignRequest_BlockDeneb: + return handleBlockDeneb(ctx, validator, request, genesisValidatorsRoot) + case *validatorpb.SignRequest_BlindedBlockDeneb: + return handleBlindedBlockDeneb(ctx, validator, request, genesisValidatorsRoot) // We do not support "DEPOSIT" type. /* case *validatorpb.: @@ -209,70 +141,255 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ */ case *validatorpb.SignRequest_Epoch: - randaoRevealSignRequest, err := web3signerv1.GetRandaoRevealSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, randaoRevealSignRequest); err != nil { - return nil, err - } - randaoRevealSignRequestsTotal.Inc() - return json.Marshal(randaoRevealSignRequest) + // tech debt that prysm uses signing type epoch + return handleRandaoReveal(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_Exit: - voluntaryExitRequest, err := web3signerv1.GetVoluntaryExitSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, voluntaryExitRequest); err != nil { - return nil, err - } - voluntaryExitSignRequestsTotal.Inc() - return json.Marshal(voluntaryExitRequest) + return handleVoluntaryExit(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_SyncMessageBlockRoot: - syncCommitteeMessageRequest, err := web3signerv1.GetSyncCommitteeMessageSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, syncCommitteeMessageRequest); err != nil { - return nil, err - } - syncCommitteeMessageSignRequestsTotal.Inc() - return json.Marshal(syncCommitteeMessageRequest) + return handleSyncMessageBlockRoot(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_SyncAggregatorSelectionData: - syncCommitteeSelectionProofRequest, err := web3signerv1.GetSyncCommitteeSelectionProofSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, syncCommitteeSelectionProofRequest); err != nil { - return nil, err - } - syncCommitteeSelectionProofSignRequestsTotal.Inc() - return json.Marshal(syncCommitteeSelectionProofRequest) + return handleSyncAggregatorSelectionData(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_ContributionAndProof: - contributionAndProofRequest, err := web3signerv1.GetSyncCommitteeContributionAndProofSignRequest(request, genesisValidatorsRoot) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, contributionAndProofRequest); err != nil { - return nil, err - } - syncCommitteeContributionAndProofSignRequestsTotal.Inc() - return json.Marshal(contributionAndProofRequest) + return handleContributionAndProof(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_Registration: - validatorRegistrationRequest, err := web3signerv1.GetValidatorRegistrationSignRequest(request) - if err != nil { - return nil, err - } - if err = validator.StructCtx(ctx, validatorRegistrationRequest); err != nil { - return nil, err - } - validatorRegistrationSignRequestsTotal.Inc() - return json.Marshal(validatorRegistrationRequest) + return handleRegistration(ctx, validator, request) + case *validatorpb.SignRequest_Blob: + return handleBlob(ctx, validator, request, genesisValidatorsRoot) + case *validatorpb.SignRequest_BlindedBlob: + return handleBlindedBlob(ctx, validator, request, genesisValidatorsRoot) default: return nil, fmt.Errorf("web3signer sign request type %T not supported", request.Object) } } +func handleBlock(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + bockSignRequest, err := web3signerv1.GetBlockSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, bockSignRequest); err != nil { + return nil, err + } + blockSignRequestsTotal.Inc() + return json.Marshal(bockSignRequest) +} + +func handleAttestationData(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + attestationSignRequest, err := web3signerv1.GetAttestationSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, attestationSignRequest); err != nil { + return nil, err + } + attestationSignRequestsTotal.Inc() + return json.Marshal(attestationSignRequest) +} + +func handleAggregateAttestationAndProof(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + aggregateAndProofSignRequest, err := web3signerv1.GetAggregateAndProofSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, aggregateAndProofSignRequest); err != nil { + return nil, err + } + aggregateAndProofSignRequestsTotal.Inc() + return json.Marshal(aggregateAndProofSignRequest) +} + +func handleAggregationSlot(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + aggregationSlotSignRequest, err := web3signerv1.GetAggregationSlotSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, aggregationSlotSignRequest); err != nil { + return nil, err + } + aggregationSlotSignRequestsTotal.Inc() + return json.Marshal(aggregationSlotSignRequest) +} + +func handleBlockAltair(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blockv2AltairSignRequest, err := web3signerv1.GetBlockAltairSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blockv2AltairSignRequest); err != nil { + return nil, err + } + blockAltairSignRequestsTotal.Inc() + return json.Marshal(blockv2AltairSignRequest) +} + +func handleBlockBellatrix(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blockv2BellatrixSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blockv2BellatrixSignRequest); err != nil { + return nil, err + } + blockBellatrixSignRequestsTotal.Inc() + return json.Marshal(blockv2BellatrixSignRequest) +} + +func handleBlindedBlockBellatrix(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blindedBlockv2SignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blindedBlockv2SignRequest); err != nil { + return nil, err + } + blindedBlockBellatrixSignRequestsTotal.Inc() + return json.Marshal(blindedBlockv2SignRequest) +} + +func handleBlockCapella(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blockv2CapellaSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blockv2CapellaSignRequest); err != nil { + return nil, err + } + blockCapellaSignRequestsTotal.Inc() + return json.Marshal(blockv2CapellaSignRequest) +} + +func handleBlindedBlockCapella(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blindedBlockv2CapellaSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blindedBlockv2CapellaSignRequest); err != nil { + return nil, err + } + blindedBlockCapellaSignRequestsTotal.Inc() + return json.Marshal(blindedBlockv2CapellaSignRequest) +} + +func handleBlockDeneb(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blockv2DenebSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blockv2DenebSignRequest); err != nil { + return nil, err + } + blockDenebSignRequestsTotal.Inc() + return json.Marshal(blockv2DenebSignRequest) +} + +func handleBlindedBlockDeneb(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blindedBlockv2DenebSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blindedBlockv2DenebSignRequest); err != nil { + return nil, err + } + blindedBlockDenebSignRequestsTotal.Inc() + return json.Marshal(blindedBlockv2DenebSignRequest) +} + +func handleRandaoReveal(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + randaoRevealSignRequest, err := web3signerv1.GetRandaoRevealSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, randaoRevealSignRequest); err != nil { + return nil, err + } + randaoRevealSignRequestsTotal.Inc() + return json.Marshal(randaoRevealSignRequest) +} + +func handleVoluntaryExit(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + voluntaryExitRequest, err := web3signerv1.GetVoluntaryExitSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, voluntaryExitRequest); err != nil { + return nil, err + } + voluntaryExitSignRequestsTotal.Inc() + return json.Marshal(voluntaryExitRequest) +} + +func handleSyncMessageBlockRoot(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + syncCommitteeMessageRequest, err := web3signerv1.GetSyncCommitteeMessageSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, syncCommitteeMessageRequest); err != nil { + return nil, err + } + syncCommitteeMessageSignRequestsTotal.Inc() + return json.Marshal(syncCommitteeMessageRequest) +} + +func handleSyncAggregatorSelectionData(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + syncCommitteeSelectionProofRequest, err := web3signerv1.GetSyncCommitteeSelectionProofSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, syncCommitteeSelectionProofRequest); err != nil { + return nil, err + } + syncCommitteeSelectionProofSignRequestsTotal.Inc() + return json.Marshal(syncCommitteeSelectionProofRequest) +} + +func handleContributionAndProof(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + contributionAndProofRequest, err := web3signerv1.GetSyncCommitteeContributionAndProofSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, contributionAndProofRequest); err != nil { + return nil, err + } + syncCommitteeContributionAndProofSignRequestsTotal.Inc() + return json.Marshal(contributionAndProofRequest) +} + +func handleRegistration(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest) ([]byte, error) { + validatorRegistrationRequest, err := web3signerv1.GetValidatorRegistrationSignRequest(request) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, validatorRegistrationRequest); err != nil { + return nil, err + } + validatorRegistrationSignRequestsTotal.Inc() + return json.Marshal(validatorRegistrationRequest) +} + +func handleBlob(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blobRequest, err := web3signerv1.GetBlobSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blobRequest); err != nil { + return nil, err + } + blobSignRequestsTotal.Inc() + return json.Marshal(blobRequest) +} + +func handleBlindedBlob(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blindedBlobRequest, err := web3signerv1.GetBlobSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blindedBlobRequest); err != nil { + return nil, err + } + blindedBlobSignRequestsTotal.Inc() + return json.Marshal(blindedBlobRequest) +} + // SubscribeAccountChanges returns the event subscription for changes to public keys. func (km *Keymanager) SubscribeAccountChanges(pubKeysChan chan [][fieldparams.BLSPubkeyLength]byte) event.Subscription { return km.accountsChangedFeed.Subscribe(pubKeysChan) diff --git a/validator/keymanager/remote-web3signer/keymanager_test.go b/validator/keymanager/remote-web3signer/keymanager_test.go index 623e19f327..f7c5d043c8 100644 --- a/validator/keymanager/remote-web3signer/keymanager_test.go +++ b/validator/keymanager/remote-web3signer/keymanager_test.go @@ -171,12 +171,20 @@ func TestKeymanager_Sign(t *testing.T) { want: desiredSig, wantErr: false, }, + { + name: "BLOB_SIDECAR", + args: args{ + request: mock.GetMockSignRequest("BLOB_SIDECAR"), + }, + want: desiredSig, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := km.Sign(ctx, tt.args.request) if (err != nil) != tt.wantErr { - t.Errorf("GetVoluntaryExitSignRequest() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("name:%s error = %v, wantErr %v", tt.name, err, tt.wantErr) return } require.DeepEqual(t, got, tt.want) diff --git a/validator/keymanager/remote-web3signer/metrics.go b/validator/keymanager/remote-web3signer/metrics.go index 7b0c5964e2..8ac93316fc 100644 --- a/validator/keymanager/remote-web3signer/metrics.go +++ b/validator/keymanager/remote-web3signer/metrics.go @@ -50,6 +50,14 @@ var ( Name: "remote_web3signer_blinded_block_capella_sign_requests_total", Help: "Total number of block capella sign requests", }) + blockDenebSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ + Name: "remote_web3signer_block_deneb_sign_requests_total", + Help: "Total number of block deneb sign requests", + }) + blindedBlockDenebSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ + Name: "remote_web3signer_blinded_block_deneb_sign_requests_total", + Help: "Total number of blinded block deneb sign requests", + }) randaoRevealSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ Name: "remote_web3signer_randao_reveal_sign_requests_total", Help: "Total number of randao reveal sign requests", @@ -74,4 +82,12 @@ var ( Name: "remote_web3signer_validator_registration_sign_requests_total", Help: "Total number of validator registration sign requests", }) + blobSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ + Name: "remote_web3signer_blob_sign_requests_total", + Help: "Total number of blob sign requests", + }) + blindedBlobSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ + Name: "remote_web3signer_blinded_blob_sign_requests_total", + Help: "Total number of blinded blob sign requests", + }) ) diff --git a/validator/keymanager/remote-web3signer/v1/BUILD.bazel b/validator/keymanager/remote-web3signer/v1/BUILD.bazel index d5e5cd5810..18b1b1133b 100644 --- a/validator/keymanager/remote-web3signer/v1/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/v1/BUILD.bazel @@ -10,9 +10,11 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v4/validator/keymanager/remote-web3signer/v1", visibility = ["//visibility:public"], deps = [ + "//config/fieldparams:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", + "//encoding/ssz:go_default_library", "//network/forks:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", diff --git a/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel b/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel index 6612406d41..fddd3817c9 100644 --- a/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel @@ -8,11 +8,13 @@ go_library( visibility = ["//visibility:public"], deps = [ "//config/fieldparams:go_default_library", + "//encoding/ssz: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", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", ], ) diff --git a/validator/keymanager/remote-web3signer/v1/mock/mocks.go b/validator/keymanager/remote-web3signer/v1/mock/mocks.go index 6537f41fbd..fd341f557c 100644 --- a/validator/keymanager/remote-web3signer/v1/mock/mocks.go +++ b/validator/keymanager/remote-web3signer/v1/mock/mocks.go @@ -6,10 +6,12 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/prysmaticlabs/go-bitfield" fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" + "github.com/prysmaticlabs/prysm/v4/encoding/ssz" eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v4/testing/util" v1 "github.com/prysmaticlabs/prysm/v4/validator/keymanager/remote-web3signer/v1" + log "github.com/sirupsen/logrus" ) ///////////////////////////////////////////////////////////////////////////////////////////////// @@ -363,6 +365,24 @@ func GetMockSignRequest(t string) *validatorpb.SignRequest { BlindedBlockCapella: util.HydrateBlindedBeaconBlockCapella(ð.BlindedBeaconBlockCapella{}), }, } + case "BLOCK_V2_DENEB": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_BlockDeneb{ + BlockDeneb: util.HydrateBeaconBlockDeneb(ð.BeaconBlockDeneb{}), + }, + } + case "BLOCK_V2_BLINDED_DENEB": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_BlindedBlockDeneb{ + BlindedBlockDeneb: util.HydrateBlindedBeaconBlockDeneb(ð.BlindedBeaconBlockDeneb{}), + }, + } case "RANDAO_REVEAL": return &validatorpb.SignRequest{ PublicKey: make([]byte, fieldparams.BLSPubkeyLength), @@ -444,6 +464,49 @@ func GetMockSignRequest(t string) *validatorpb.SignRequest { }, SigningSlot: 0, } + case "BLOB_SIDECAR": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_Blob{ + Blob: ð.BlobSidecar{ + BlockRoot: make([]byte, fieldparams.RootLength), + Index: uint64(0), + Slot: 0, + BlockParentRoot: make([]byte, fieldparams.RootLength), + ProposerIndex: 0, + Blob: make([]byte, fieldparams.BlobLength), + KzgCommitment: make([]byte, fieldparams.BLSPubkeyLength), + KzgProof: make([]byte, fieldparams.BLSPubkeyLength), + }, + }, + SigningSlot: 0, + } + case "BLINDED_BLOB_SIDECAR": + blobRoot, err := ssz.ByteSliceRoot(make([]byte, fieldparams.BlobLength), fieldparams.BlobLength) + if err != nil { + log.Error(err) + return nil + } + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_BlindedBlob{ + BlindedBlob: ð.BlindedBlobSidecar{ + BlockRoot: make([]byte, fieldparams.RootLength), + Index: uint64(0), + Slot: 0, + BlockParentRoot: make([]byte, fieldparams.RootLength), + ProposerIndex: 0, + BlobRoot: blobRoot[:], + KzgCommitment: make([]byte, fieldparams.BLSPubkeyLength), + KzgProof: make([]byte, fieldparams.BLSPubkeyLength), + }, + }, + SigningSlot: 0, + } default: fmt.Printf("Web3signer sign request type: %v not found", t) return nil @@ -606,6 +669,30 @@ func MockValidatorRegistrationSignRequest() *v1.ValidatorRegistrationSignRequest } } +// MockBlobSidecarSignRequest is a mock implementation of the BlobSidecarSignRequest. +func MockBlobSidecarSignRequest() *v1.BlobSidecarSignRequest { + blobRoot, err := ssz.ByteSliceRoot(make([]byte, fieldparams.BlobLength), fieldparams.BlobLength) + if err != nil { + log.Error(err) + return nil + } + return &v1.BlobSidecarSignRequest{ + Type: "BLOB_SIDECAR", + ForkInfo: MockForkInfo(), + SigningRoot: make([]byte, fieldparams.RootLength), + BlobSidecar: &v1.BlobSidecar{ + BlockRoot: make([]byte, fieldparams.RootLength), + Index: fmt.Sprint(0), + Slot: fmt.Sprint(0), + BlockParentRoot: make([]byte, fieldparams.RootLength), + ProposerIndex: fmt.Sprint(0), + BlobRoot: blobRoot[:], + KzgCommitment: make([]byte, fieldparams.BLSPubkeyLength), + KzgProof: make([]byte, fieldparams.BLSPubkeyLength), + }, + } +} + ///////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/validator/keymanager/remote-web3signer/v1/requests.go b/validator/keymanager/remote-web3signer/v1/requests.go index 7c55f05328..bade0c5986 100644 --- a/validator/keymanager/remote-web3signer/v1/requests.go +++ b/validator/keymanager/remote-web3signer/v1/requests.go @@ -4,8 +4,10 @@ import ( "fmt" "github.com/pkg/errors" + fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v4/encoding/ssz" validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client" ) @@ -271,8 +273,8 @@ func GetSyncCommitteeContributionAndProofSignRequest(request *validatorpb.SignRe }, nil } -// GetBlockV2BlindedSignRequest maps the request for signing types -// Supports Bellatrix and Capella +// GetBlockV2BlindedSignRequest maps the request for signing types (GetBlockV2 id defined by the remote signer interface and not the beacon APIs) +// Supports Bellatrix, Capella, Deneb func GetBlockV2BlindedSignRequest(request *validatorpb.SignRequest, genesisValidatorsRoot []byte) (*BlockV2BlindedSignRequest, error) { if request == nil { return nil, errors.New("nil sign request provided") @@ -337,6 +339,34 @@ func GetBlockV2BlindedSignRequest(request *validatorpb.SignRequest, genesisValid return nil, err } b = beaconBlock + case *validatorpb.SignRequest_BlockDeneb: + version = "DENEB" + blockDeneb, ok := request.Object.(*validatorpb.SignRequest_BlockDeneb) + if !ok { + return nil, errors.New("failed to cast request object to deneb block") + } + if blockDeneb == nil { + return nil, errors.New("invalid sign request: deneb block is nil") + } + beaconBlock, err := blocks.NewBeaconBlock(blockDeneb.BlockDeneb) + if err != nil { + return nil, err + } + b = beaconBlock + case *validatorpb.SignRequest_BlindedBlockDeneb: + version = "DENEB" + blindedBlockDeneb, ok := request.Object.(*validatorpb.SignRequest_BlindedBlockDeneb) + if !ok { + return nil, errors.New("failed to cast request object to blinded deneb block") + } + if blindedBlockDeneb == nil { + return nil, errors.New("invalid sign request: blinded deneb block is nil") + } + beaconBlock, err := blocks.NewBeaconBlock(blindedBlockDeneb.BlindedBlockDeneb) + if err != nil { + return nil, err + } + b = beaconBlock default: return nil, errors.New("invalid sign request - invalid object type") } @@ -386,3 +416,66 @@ func GetValidatorRegistrationSignRequest(request *validatorpb.SignRequest) (*Val }, }, nil } + +// GetBlobSignRequest maps the request for signing type BLOB_SIDECAR +func GetBlobSignRequest(request *validatorpb.SignRequest, genesisValidatorsRoot []byte) (*BlobSidecarSignRequest, error) { + if request == nil { + return nil, errors.New("nil sign request provided") + } + fork, err := MapForkInfo(request.SigningSlot, genesisValidatorsRoot) + if err != nil { + return nil, err + } + var blobSidecar *BlobSidecar + switch request.Object.(type) { + case *validatorpb.SignRequest_Blob: + blob, ok := request.Object.(*validatorpb.SignRequest_Blob) + if !ok { + return nil, errors.New("failed to cast request object to blob sidecar") + } + if blob == nil || blob.Blob == nil { + return nil, errors.New("invalid sign request: blob sidecar is nil") + } + blobRoot, err := ssz.ByteSliceRoot(blob.Blob.Blob, fieldparams.BlobLength) + if err != nil { + return nil, errors.Wrap(err, "unable to get blob root from ssz roots") + } + blobSidecar = &BlobSidecar{ + BlockRoot: blob.Blob.BlockRoot, + Index: fmt.Sprint(blob.Blob.Index), + Slot: fmt.Sprint(blob.Blob.Slot), + BlockParentRoot: blob.Blob.BlockParentRoot, + ProposerIndex: fmt.Sprint(blob.Blob.ProposerIndex), + BlobRoot: blobRoot[:], + KzgCommitment: blob.Blob.KzgCommitment, + KzgProof: blob.Blob.KzgProof, + } + case *validatorpb.SignRequest_BlindedBlob: + blindedBlob, ok := request.Object.(*validatorpb.SignRequest_BlindedBlob) + if !ok { + return nil, errors.New("failed to cast request object to blinded blob sidecar") + } + if blindedBlob == nil || blindedBlob.BlindedBlob == nil { + return nil, errors.New("invalid sign request: blinded blob sidecar is nil") + } + blobSidecar = &BlobSidecar{ + BlockRoot: blindedBlob.BlindedBlob.BlockRoot, + Index: fmt.Sprint(blindedBlob.BlindedBlob.Index), + Slot: fmt.Sprint(blindedBlob.BlindedBlob.Slot), + BlockParentRoot: blindedBlob.BlindedBlob.BlockParentRoot, + ProposerIndex: fmt.Sprint(blindedBlob.BlindedBlob.ProposerIndex), + BlobRoot: blindedBlob.BlindedBlob.BlobRoot, + KzgCommitment: blindedBlob.BlindedBlob.KzgCommitment, + KzgProof: blindedBlob.BlindedBlob.KzgProof, + } + default: + return nil, errors.New("invalid sign request: invalid object type") + } + + return &BlobSidecarSignRequest{ + Type: "BLOB_SIDECAR", + ForkInfo: fork, + SigningRoot: request.SigningRoot, + BlobSidecar: blobSidecar, + }, nil +} diff --git a/validator/keymanager/remote-web3signer/v1/requests_test.go b/validator/keymanager/remote-web3signer/v1/requests_test.go index 521ab4af1e..1ea3275f4a 100644 --- a/validator/keymanager/remote-web3signer/v1/requests_test.go +++ b/validator/keymanager/remote-web3signer/v1/requests_test.go @@ -424,6 +424,32 @@ func TestGetBlockV2BlindedSignRequest(t *testing.T) { }(t), "CAPELLA"), wantErr: false, }, + { + name: "Happy Path Test non blinded Deneb", + args: args{ + request: mock.GetMockSignRequest("BLOCK_V2_DENEB"), + genesisValidatorsRoot: make([]byte, fieldparams.RootLength), + }, + want: mock.MockBlockV2BlindedSignRequest(func(t *testing.T) []byte { + bytevalue, err := hexutil.Decode("0xbce73ee2c617851846af2b3ea2287e3b686098e18ae508c7271aaa06ab1d06cd") + require.NoError(t, err) + return bytevalue + }(t), "DENEB"), + wantErr: false, + }, + { + name: "Happy Path Test blinded Deneb", + args: args{ + request: mock.GetMockSignRequest("BLOCK_V2_BLINDED_DENEB"), + genesisValidatorsRoot: make([]byte, fieldparams.RootLength), + }, + want: mock.MockBlockV2BlindedSignRequest(func(t *testing.T) []byte { + bytevalue, err := hexutil.Decode("0xfeb1f7e4f704e72544f4f097b36cb3f3af83043765ad9ad3c3a6cd7fac605055") + require.NoError(t, err) + return bytevalue + }(t), "DENEB"), + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -439,6 +465,47 @@ func TestGetBlockV2BlindedSignRequest(t *testing.T) { } } +func TestGetBlobSignRequest(t *testing.T) { + type args struct { + request *validatorpb.SignRequest + } + tests := []struct { + name string + args args + want *v1.BlobSidecarSignRequest + wantErr bool + }{ + { + name: "Happy Path Test", + args: args{ + request: mock.GetMockSignRequest("BLOB_SIDECAR"), + }, + want: mock.MockBlobSidecarSignRequest(), + wantErr: false, + }, + { + name: "Happy Path Test Blinded", + args: args{ + request: mock.GetMockSignRequest("BLINDED_BLOB_SIDECAR"), + }, + want: mock.MockBlobSidecarSignRequest(), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := v1.GetBlobSignRequest(tt.args.request, make([]byte, fieldparams.RootLength)) + if (err != nil) != tt.wantErr { + t.Errorf("GetBlobSignRequest() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetBlobSignRequest() got = %v, want %v", got, tt.want) + } + }) + } +} + func TestGetValidatorRegistrationSignRequest(t *testing.T) { type args struct { request *validatorpb.SignRequest diff --git a/validator/keymanager/remote-web3signer/v1/web3signer_types.go b/validator/keymanager/remote-web3signer/v1/web3signer_types.go index 0752046773..c697653f1b 100644 --- a/validator/keymanager/remote-web3signer/v1/web3signer_types.go +++ b/validator/keymanager/remote-web3signer/v1/web3signer_types.go @@ -105,6 +105,14 @@ type ValidatorRegistrationSignRequest struct { ValidatorRegistration *ValidatorRegistration `json:"validator_registration" validate:"required"` } +// BlobSidecarSignRequest a request object for web3signer sign api. +type BlobSidecarSignRequest struct { + Type string `json:"type" validate:"required"` + ForkInfo *ForkInfo `json:"fork_info" validate:"required"` + SigningRoot hexutil.Bytes `json:"signingRoot"` + BlobSidecar *BlobSidecar `json:"blob_sidecar" validate:"required,dive"` +} + //////////////////////////////////////////////////////////////////////////////// // sub properties of Sign Requests ///////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -337,6 +345,18 @@ type ValidatorRegistration struct { Pubkey hexutil.Bytes `json:"pubkey" validate:"required"` /* bls hexadecimal string */ } +// BlobSidecar a sub property of BlobSidecarSignRequest +type BlobSidecar struct { + BlockRoot hexutil.Bytes `json:"block_root" validate:"required"` /* 32 hexadecimal string */ + Index string `json:"index" validate:"required"` /* uint64 */ + Slot string `json:"slot" validate:"required"` /* uint64 */ + BlockParentRoot hexutil.Bytes `json:"block_parent_root" validate:"required"` /* 32 hexadecimal string */ + ProposerIndex string `json:"proposer_index" validate:"required"` /* uint64 */ + BlobRoot hexutil.Bytes `json:"blob_root" validate:"required"` /* 32 hexadecimal string */ + KzgCommitment hexutil.Bytes `json:"kzg_commitment" validate:"required"` // pattern: "^0x[a-fA-F0-9]{96}$" ssz-size:"48" + KzgProof hexutil.Bytes `json:"kzg_proof" validate:"required"` // pattern: "^0x[a-fA-F0-9]{96}$" ssz-size:"48" +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////