diff --git a/cli/cmd/flags.go b/cli/cmd/flags.go index 2686ea01..884bc72e 100644 --- a/cli/cmd/flags.go +++ b/cli/cmd/flags.go @@ -55,12 +55,12 @@ func GetNetworkFlagValue(c *cobra.Command) (core.Network, error) { return "", err } - ret := core.NetworkFromString(networkValue) - if len(ret) == 0 { - return "", errors.New("unknown network") + network, err := core.NetworkFromString(networkValue) + if err != nil { + return "", errors.Wrap(err, "failed to parse network") } - return ret, nil + return network, nil } // AddAccumulateFlag adds the accumulate flag to the command diff --git a/cli/cmd/wallet/cmd/account/create_test.go b/cli/cmd/wallet/cmd/account/create_test.go index b906f71a..b741452f 100644 --- a/cli/cmd/wallet/cmd/account/create_test.go +++ b/cli/cmd/wallet/cmd/account/create_test.go @@ -71,7 +71,7 @@ func TestAccountCreate(t *testing.T) { err := cmd.RootCmd.Execute() actualOutput := output.String() require.EqualValues(t, actualOutput, "") - require.EqualError(t, err, "failed to collect account flags: failed to retrieve the network flag value: unknown network") + require.EqualError(t, err, "failed to collect account flags: failed to retrieve the network flag value: failed to parse network: undefined network") }) t.Run("Successfully create account at specific index and return as storage", func(t *testing.T) { diff --git a/cli/cmd/wallet/cmd/account/credentials_test.go b/cli/cmd/wallet/cmd/account/credentials_test.go index ef847ffa..e5aadf08 100644 --- a/cli/cmd/wallet/cmd/account/credentials_test.go +++ b/cli/cmd/wallet/cmd/account/credentials_test.go @@ -32,10 +32,77 @@ func TestAccountCredentials(t *testing.T) { require.NoError(t, err) }) - t.Run("Successfully handle accumulated credentials change", func(t *testing.T) { + // The signatures in this test were verified with Prysm's libraries, using the following code: + // + // func TestVerifyBLSChangeSignature(t *testing.T) { + // params.SetActive(params.MainnetConfig()) + // change := ðpb.SignedBLSToExecutionChange{ + // Message: ðpb.BLSToExecutionChange{ + // ValidatorIndex: 273230, + // FromBlsPubkey: hexutil.MustDecode("0x8c02c584a9265f6ff2a2119c4eaee0385fb4320aa6ddb14ad98050af7bc3e250aadafd8d4733f980408e8a595583db6e"), + // ToExecutionAddress: hexutil.MustDecode("0x3e6935b8250cf9a777862871649e5594be08779e"), + // }, + // Signature: hexutil.MustDecode("0xb0bd98cfe89b8439a8e787e25fb25f6999db397bfd47d34eca9e4a85bca6b0c529fa83fc8705fcbba95ce7623713a60610a7b0ba14c6816fe74f20f00c3226192a064529047ae5e4009cfa62273e9f9de5d03806ff6019443c10fc10a7fb0d11"), + // } + // spb := ðpb.BeaconStateCapella{ + // Fork: ðpb.Fork{ + // CurrentVersion: params.BeaconConfig().CapellaForkVersion, + // PreviousVersion: params.BeaconConfig().GenesisForkVersion, + // Epoch: params.BeaconConfig().CapellaForkEpoch, + // }, + // GenesisValidatorsRoot: hexutil.MustDecode("0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"), + // } + // st, err := state_native.InitializeFromProtoCapella(spb) + // require.NoError(t, err) + // changeV2 := migration.V1Alpha1SignedBLSToExecChangeToV2(change) + // require.NoError(t, blocks.VerifyBLSChangeSignature(st, changeV2)) + // } + t.Run("Successfully handle accumulated credentials change (mainnet)", func(t *testing.T) { + input := []string{ + "wallet", + "account", + "credentials", + "--seed=847d135b3aecac8ae77c3fdfd46dc5849ad3b5bacd30a1b9082b6ff53c77357e923b12fcdc3d02728fd35c3685de1fe1e9c052c48f0d83566b1b2287cf0e54c3", + "--index=1", + "--accumulate=true", + "--validator-indices=273230,273407", + "--validator-public-keys=0xb2dc1daa8c9cd104d4503028639e41a41e4f06ee5cc90ebfaeab3c41f43a148ce9afa4ebd1b8be3f54e4d6c15e870c7c,0xa1a593775967bf88bb6c14ac109c12e52dc836fa139bd1ba6ca873d65fe91bb7a0fc79c7b2a7315482a81f31e6b1018a", + "--withdrawal-credentials=0x00d9cdf17e3a79317a4e5cd18580b1d10b1df360bbca5c5f8ac5b79b45c29d15,0x00202f88c6116d27f5de06eeda3b801d3a4eeab8eb09f879848445fffc8948a5", + "--to-execution-address=0x3e6935b8250Cf9A777862871649E5594bE08779e,0x3e6935b8250Cf9A777862871649E5594bE08779e", + "--network=mainnet", + } + expectedOutput := `[ + { + "message": { + "validator_index": "273230", + "from_bls_pubkey": "0x8c02c584a9265f6ff2a2119c4eaee0385fb4320aa6ddb14ad98050af7bc3e250aadafd8d4733f980408e8a595583db6e", + "to_execution_address": "0x3e6935b8250cf9a777862871649e5594be08779e" + }, + "signature": "0xb0bd98cfe89b8439a8e787e25fb25f6999db397bfd47d34eca9e4a85bca6b0c529fa83fc8705fcbba95ce7623713a60610a7b0ba14c6816fe74f20f00c3226192a064529047ae5e4009cfa62273e9f9de5d03806ff6019443c10fc10a7fb0d11" + }, + { + "message": { + "validator_index": "273407", + "from_bls_pubkey": "0x862418bfdd18e1147e6fb62c9c7cddc638cc74819d7fbecb947a571145e7782bbb44f8ef9fa833410ef4e9dae2903756", + "to_execution_address": "0x3e6935b8250cf9a777862871649e5594be08779e" + }, + "signature": "0x8547adbba39a4c600c8308109ddc1a4705b34ba3b419fd52570b00a1d0ef811149620c7a7e85390f8a920d1458773b5b0cfc9b52d7c2421e0cd36119e6ce156276c906504b4ba4a8431e9fe717b30484666f9607cacdcf8eaa1830902c678721" + } + ]` + var output bytes.Buffer cmd.ResultPrinter = printer.New(&output) - cmd.RootCmd.SetArgs([]string{ + cmd.RootCmd.SetArgs(input) + err := cmd.RootCmd.Execute() + actualOutput := output.String() + require.NotNil(t, actualOutput) + require.NoError(t, err) + + require.JSONEq(t, expectedOutput, actualOutput) + }) + + t.Run("Successfully handle accumulated credentials change (prater)", func(t *testing.T) { + input := []string{ "wallet", "account", "credentials", @@ -47,11 +114,35 @@ func TestAccountCredentials(t *testing.T) { "--withdrawal-credentials=0x00d9cdf17e3a79317a4e5cd18580b1d10b1df360bbca5c5f8ac5b79b45c29d15,0x00202f88c6116d27f5de06eeda3b801d3a4eeab8eb09f879848445fffc8948a5", "--to-execution-address=0x3e6935b8250Cf9A777862871649E5594bE08779e,0x3e6935b8250Cf9A777862871649E5594bE08779e", "--network=prater", - }) + } + expectedOutput := `[ + { + "message": { + "validator_index": "273230", + "from_bls_pubkey": "0x8c02c584a9265f6ff2a2119c4eaee0385fb4320aa6ddb14ad98050af7bc3e250aadafd8d4733f980408e8a595583db6e", + "to_execution_address": "0x3e6935b8250cf9a777862871649e5594be08779e" + }, + "signature": "0x8265248c611cfd8202d82c42a222466051d034a01e5bd48c3c29ff47c7e557f5cbcb32713cf205ca61bcad5f59ea7df4018ff863d4318b53ea3b2383737149c16a24bea61784de5deb5ba9f5ea78f4ef7950b47e5aafa6805f238d20b80b7de7" + }, + { + "message": { + "validator_index": "273407", + "from_bls_pubkey": "0x862418bfdd18e1147e6fb62c9c7cddc638cc74819d7fbecb947a571145e7782bbb44f8ef9fa833410ef4e9dae2903756", + "to_execution_address": "0x3e6935b8250cf9a777862871649e5594be08779e" + }, + "signature": "0x969693dc21fd9b05fb9737d16909ec1c9b3f5c8b29f1d4c75b1e96609fa20b926ece5a9d8a1be4a2601bac0d514b523d0affd2f8e576c42718f08ddbcb806dfcb6becf832f1cb31dd8e474a0d9d5838564f43a64fcf54d46b409aa94de32195f" + } + ]` + + var output bytes.Buffer + cmd.ResultPrinter = printer.New(&output) + cmd.RootCmd.SetArgs(input) err := cmd.RootCmd.Execute() actualOutput := output.String() require.NotNil(t, actualOutput) require.NoError(t, err) + + require.JSONEq(t, expectedOutput, actualOutput) }) t.Run("Only one validator can be specified if accumulate is false", func(t *testing.T) { diff --git a/cli/cmd/wallet/cmd/account/handler/handler_credentials.go b/cli/cmd/wallet/cmd/account/handler/handler_credentials.go index 9ed87170..824f069f 100644 --- a/cli/cmd/wallet/cmd/account/handler/handler_credentials.go +++ b/cli/cmd/wallet/cmd/account/handler/handler_credentials.go @@ -65,7 +65,10 @@ func (h *Account) Credentials(cmd *cobra.Command, args []string) error { }) // Compute domain - genesisValidatorsRoot := store.Network().GenesisValidatorsRoot() + genesisValidatorsRoot, err := store.Network().GenesisValidatorsRoot() + if err != nil { + return errors.Wrap(err, "failed to get genesis validators root") + } genesisForkVersion := store.Network().GenesisForkVersion() domainBytes, err := types.ComputeDomain(domainBlsToExecutionChange, genesisForkVersion[:], genesisValidatorsRoot[:]) if err != nil { diff --git a/cli/cmd/wallet/cmd/account/handler/handler_voluntary_exit.go b/cli/cmd/wallet/cmd/account/handler/handler_voluntary_exit.go index 0ecc5dba..3e2389f3 100644 --- a/cli/cmd/wallet/cmd/account/handler/handler_voluntary_exit.go +++ b/cli/cmd/wallet/cmd/account/handler/handler_voluntary_exit.go @@ -66,7 +66,10 @@ func (h *Account) VoluntaryExit(cmd *cobra.Command, args []string) error { } // Compute domain - genesisValidatorsRoot := store.Network().GenesisValidatorsRoot() + genesisValidatorsRoot, err := store.Network().GenesisValidatorsRoot() + if err != nil { + return errors.Wrap(err, "failed to get genesis validators root") + } domainBytes, err := types.ComputeDomain(types.DomainVoluntaryExit, voluntaryExitFlags.currentForkVersion[:], genesisValidatorsRoot[:]) if err != nil { return errors.Wrap(err, "failed to calculate domain") diff --git a/core/networks.go b/core/networks.go index cd6c79c2..3dc7b147 100644 --- a/core/networks.go +++ b/core/networks.go @@ -5,6 +5,7 @@ import ( "time" "github.com/attestantio/go-eth2-client/spec/phase0" + "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -12,16 +13,16 @@ import ( type Network string // NetworkFromString returns network from the given string value -func NetworkFromString(n string) Network { +func NetworkFromString(n string) (Network, error) { switch n { case string(PyrmontNetwork): - return PyrmontNetwork + return PyrmontNetwork, nil case string(PraterNetwork): - return PraterNetwork + return PraterNetwork, nil case string(MainNetwork): - return MainNetwork + return MainNetwork, nil default: - return "" + return "", errors.New("undefined network") } } @@ -41,19 +42,26 @@ func (n Network) GenesisForkVersion() phase0.Version { } // GenesisValidatorsRoot returns the genesis validators root of the network. -func (n Network) GenesisValidatorsRoot() phase0.Root { +func (n Network) GenesisValidatorsRoot() (phase0.Root, error) { var genValidatorsRoot phase0.Root switch n { case PraterNetwork: - rootBytes, _ := hex.DecodeString("043db0d9a83813551ee2f33450d23797757d430911a9320530ad8a0eabc43efb") + rootBytes, err := hex.DecodeString("043db0d9a83813551ee2f33450d23797757d430911a9320530ad8a0eabc43efb") + if err != nil { + return phase0.Root{}, err + } copy(genValidatorsRoot[:], rootBytes) case MainNetwork: - rootBytes, _ := hex.DecodeString("4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95") + rootBytes, err := hex.DecodeString("4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95") + if err != nil { + return phase0.Root{}, err + } copy(genValidatorsRoot[:], rootBytes) default: logrus.WithField("network", n).Fatal("undefined network") + return phase0.Root{}, errors.New("undefined network") } - return genValidatorsRoot + return genValidatorsRoot, nil } // DepositContractAddress returns the deposit contract address of the network. diff --git a/core/networks_test.go b/core/networks_test.go index beef15f0..f3e7164e 100644 --- a/core/networks_test.go +++ b/core/networks_test.go @@ -9,11 +9,12 @@ import ( ) func TestNetworkMainnet(t *testing.T) { - net := NetworkFromString(string(MainNetwork)) + network, err := NetworkFromString(string(MainNetwork)) + require.NoError(t, err) secondsPassedSinceGenesis := time.Now().Unix() - 1606824023 - require.EqualValues(t, phase0.Epoch(secondsPassedSinceGenesis/(12*32)), net.EstimatedCurrentEpoch()) - require.EqualValues(t, phase0.Epoch(secondsPassedSinceGenesis/12), net.EstimatedCurrentSlot()) - require.EqualValues(t, phase0.Epoch(secondsPassedSinceGenesis/12), net.EstimatedSlotAtTime(time.Now().Unix())) - require.EqualValues(t, phase0.Epoch(101010/32), net.EstimatedEpochAtSlot(phase0.Slot(101010))) + require.EqualValues(t, phase0.Epoch(secondsPassedSinceGenesis/(12*32)), network.EstimatedCurrentEpoch()) + require.EqualValues(t, phase0.Epoch(secondsPassedSinceGenesis/12), network.EstimatedCurrentSlot()) + require.EqualValues(t, phase0.Epoch(secondsPassedSinceGenesis/12), network.EstimatedSlotAtTime(time.Now().Unix())) + require.EqualValues(t, phase0.Epoch(101010/32), network.EstimatedEpochAtSlot(phase0.Slot(101010))) } diff --git a/signer/sign_blinded_beacon_block_test.go b/signer/sign_blinded_beacon_block_test.go index 593bf210..0a295cff 100644 --- a/signer/sign_blinded_beacon_block_test.go +++ b/signer/sign_blinded_beacon_block_test.go @@ -12,6 +12,7 @@ import ( apiv1capella "github.com/attestantio/go-eth2-client/api/v1/capella" "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/bellatrix" + "github.com/attestantio/go-eth2-client/spec/capella" "github.com/stretchr/testify/require" eth2keymanager "github.com/bloxapp/eth2-key-manager" @@ -238,3 +239,65 @@ func TestDoubleProposalsSigning_Blinded_Regular(t *testing.T) { require.Error(t, err) require.EqualError(t, err, "slashable proposal (HighestProposalVote), not signing") } + +// Test slashing by signing first beacon block and then blinded beacon block +func TestDoubleProposalsSigning_Regular_Blinded_Capella(t *testing.T) { + require.NoError(t, core.InitBLS()) + + // fixture + sk := "17f8b2dbb824318970a9c82b4f5456d598342dac248f89c252dd30bb9e85e43c" + pk := "81d6fc2f01633e8eab3ba4d72588e14f45b00e68ab887bdd4ec5e8558965db21189310df973837106216777b07fc0805" + domain := "0000000047eb72b3be36f08feffcaba760f0a2ed78c1a85f0654941a0d19d0fa" + blkJSON := []byte(`{"slot":"1861337","proposer_index":"1610","parent_root":"0x353f35e506b07b6a20dd5d24c92b6dfda1b9e221848963d7a40cb7fe4e23c35a","state_root":"0x8e9cfedb909c4c9bbc52ca4174b279d31ffe40a667077c7b31a66bbd1a66d0be","body":{"randao_reveal":"0xb019a2ef4b7763c7bd5a9b3dbe00ba38cdfb6ee0fcecfe4a7301687973717f7c193072a3ebd70de3aed153f960b11fc40037b8164542e1364a31489ff7a0a1119ef46bc2ea099886446cba3acc4721a2534c292f6eeb650719f32477707aab3e","eth1_data":{"deposit_root":"0x9df92d765b5aa041fd4bbe8d5878eb89290efa78e444c1a603eecfae2ea05fa4","deposit_count":"403","block_hash":"0x1ee29c95ea816db342e04fbd1f00cb14940a45d025d2d14bf0d33187d8f4d5ea"},"graffiti":"0x626c6f787374616b696e672e636f6d0000000000000000000000000000000000","proposer_slashings":[],"attester_slashings":[],"attestations":[{"aggregation_bits":"0xffffffffffffff37","data":{"slot":"1861336","index":"0","beacon_block_root":"0x353f35e506b07b6a20dd5d24c92b6dfda1b9e221848963d7a40cb7fe4e23c35a","source":{"epoch":"58165","root":"0x5c0a59daecb2f509e0d5a038da44c55ef5827b0b979e6e397cc7f5846f9f3f4c"},"target":{"epoch":"58166","root":"0x835469d3b4348c2f5c2964afaac731acc0117eb0f5cec64bf166ab26847f77a8"}},"signature":"0x991b97e124a8dc672d135c167f030ceff9ab500dfd9a8bb79e199a303bfa54cebc205e396a16466e51d54cb7e0d981eb0eb03295bdb39b69d9559421aeea22838d22732d66ea79d3bebb8a8a335679491b60ad6d815318cbfd92a1a867c70255"}],"deposits":[],"voluntary_exits":[],"sync_aggregate":{"sync_committee_bits":"0xfffffbfffffffffffffffcffffdfffffffffffffffefffffffffffff7ffdffffbfffffffffffefffffebfffffffffffffffffffdff7fffffffffffffffffffff","sync_committee_signature":"0x91713624034f3c1e37baa3de1d082883c6e44cc830f4ecf0ca58cc06153aba97ca4539edfdb0f49a0d18b354f585422e114feb07b689db0a47ee72231d8e6fb2970663f518ca0a3fda0e701cd4662405c4f2fa9fdac0533c790f92404240432e"},"execution_payload":{"parent_hash":"0x4b37c3a4f001b91cfcac61b7f6bdfd2218525e4f421a4ab52fa513b00e76ab6f","fee_recipient":"0x0f35b0753e261375c9a6cb44316b4bdc7e765509","state_root":"0xc9d0b31cc38141d01998220dcc0e7830994e6a1d11fa3a26d7d113df82c1a53a","receipts_root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logs_bloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prev_randao":"0x251fdfd6ebef77085f24016900debbd334e67cf51ee48d959f01ef12698a49a5","block_number":"3031542","gas_limit":"30000000","gas_used":"0","timestamp":"1678069644","extra_data":"0xd883010b02846765746888676f312e32302e31856c696e7578","base_fee_per_gas":"7","block_hash":"0x4cb1ca5a2947972cb018416fe4489b9daf674d5be97fd2ebb6de1a1608226733","transactions":[],"withdrawals":[{"index":"645759","validator_index":"425","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"2886"},{"index":"645760","validator_index":"428","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"2886"},{"index":"645761","validator_index":"429","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"2886"},{"index":"645762","validator_index":"431","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"2886"},{"index":"645763","validator_index":"434","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"2886"},{"index":"645764","validator_index":"437","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"2886"},{"index":"645765","validator_index":"440","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"1924"},{"index":"645766","validator_index":"441","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"1924"},{"index":"645767","validator_index":"448","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"1924"},{"index":"645768","validator_index":"450","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"1924"},{"index":"645769","validator_index":"451","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"1924"},{"index":"645770","validator_index":"456","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"1924"},{"index":"645771","validator_index":"458","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"1924"},{"index":"645772","validator_index":"465","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"1924"},{"index":"645773","validator_index":"467","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"1924"},{"index":"645774","validator_index":"468","address":"0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b","amount":"1924"}]},"bls_to_execution_changes":[]}}`) + blindedBlockJSON := []byte(`{"slot":"1861337","proposer_index":"1610","parent_root":"0x353f35e506b07b6a20dd5d24c92b6dfda1b9e221848963d7a40cb7fe4e23c35a","state_root":"0x8e9cfedb909c4c9bbc52ca4174b279d31ffe40a667077c7b31a66bbd1a66d0be","body":{"randao_reveal":"0xb019a2ef4b7763c7bd5a9b3dbe00ba38cdfb6ee0fcecfe4a7301687973717f7c193072a3ebd70de3aed153f960b11fc40037b8164542e1364a31489ff7a0a1119ef46bc2ea099886446cba3acc4721a2534c292f6eeb650719f32477707aab3e","eth1_data":{"deposit_root":"0x9df92d765b5aa041fd4bbe8d5878eb89290efa78e444c1a603eecfae2ea05fa4","deposit_count":"403","block_hash":"0x1ee29c95ea816db342e04fbd1f00cb14940a45d025d2d14bf0d33187d8f4d5ea"},"graffiti":"0x626c6f787374616b696e672e636f6d0000000000000000000000000000000000","proposer_slashings":[],"attester_slashings":[],"attestations":[{"aggregation_bits":"0xffffffffffffff37","data":{"slot":"1861336","index":"0","beacon_block_root":"0x353f35e506b07b6a20dd5d24c92b6dfda1b9e221848963d7a40cb7fe4e23c35a","source":{"epoch":"58165","root":"0x5c0a59daecb2f509e0d5a038da44c55ef5827b0b979e6e397cc7f5846f9f3f4c"},"target":{"epoch":"58166","root":"0x835469d3b4348c2f5c2964afaac731acc0117eb0f5cec64bf166ab26847f77a8"}},"signature":"0x991b97e124a8dc672d135c167f030ceff9ab500dfd9a8bb79e199a303bfa54cebc205e396a16466e51d54cb7e0d981eb0eb03295bdb39b69d9559421aeea22838d22732d66ea79d3bebb8a8a335679491b60ad6d815318cbfd92a1a867c70255"}],"deposits":[],"voluntary_exits":[],"sync_aggregate":{"sync_committee_bits":"0xfffffbfffffffffffffffcffffdfffffffffffffffefffffffffffff7ffdffffbfffffffffffefffffebfffffffffffffffffffdff7fffffffffffffffffffff","sync_committee_signature":"0x91713624034f3c1e37baa3de1d082883c6e44cc830f4ecf0ca58cc06153aba97ca4539edfdb0f49a0d18b354f585422e114feb07b689db0a47ee72231d8e6fb2970663f518ca0a3fda0e701cd4662405c4f2fa9fdac0533c790f92404240432e"},"execution_payload_header":{"parent_hash":"0x4b37c3a4f001b91cfcac61b7f6bdfd2218525e4f421a4ab52fa513b00e76ab6f","fee_recipient":"0x0f35b0753e261375c9a6cb44316b4bdc7e765509","state_root":"0xc9d0b31cc38141d01998220dcc0e7830994e6a1d11fa3a26d7d113df82c1a53a","receipts_root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logs_bloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prev_randao":"0x251fdfd6ebef77085f24016900debbd334e67cf51ee48d959f01ef12698a49a5","block_number":"3031542","gas_limit":"30000000","gas_used":"0","timestamp":"1678069644","extra_data":"0xd883010b02846765746888676f312e32302e31856c696e7578","base_fee_per_gas":"7","block_hash":"0x4cb1ca5a2947972cb018416fe4489b9daf674d5be97fd2ebb6de1a1608226733","transactions_root":"0x7ffe241ea60187fdb0187bfa22de35d1f9bed7ab061d9401fd47e34a54fbede1","withdrawals_root":"0xb8edfc6f0dc2564cff3102471bef1e02db94346c692eb81decf0dec63c1c69f5"},"bls_to_execution_changes":[]}}`) + sigByts := "9321eb1d373e75bb0b746a8c4b6f62285cccb17f2105a1f4f968534902131a29fffd5b54a0012c34c8600639609c46ab05a23fe8f89cdd252df680883ccb94073d9b852680bba6c5f5166edcd6024c9ef489c555d1cde994fdd7010fb394e45d" + + // setup KeyVault + store := inmemStorage() + options := ð2keymanager.KeyVaultOptions{} + options.SetStorage(store) + + protector := prot.NewNormalProtection(store) + + options.SetWalletType(core.NDWallet) + vault, err := eth2keymanager.NewKeyVault(options) + require.NoError(t, err) + wallet, err := vault.Wallet() + require.NoError(t, err) + k, err := core.NewHDKeyFromPrivateKey(_byteArray(sk), "") + require.NoError(t, err) + acc := wallets.NewValidatorAccount("1", k, nil, "", vault.Context) + require.NoError(t, wallet.AddValidatorAccount(acc)) + + // setup signer + signer := NewSimpleSigner(wallet, protector, core.PraterNetwork) + + // decode block + blk := &capella.BeaconBlock{} + require.NoError(t, json.Unmarshal(blkJSON, blk)) + + // minimal slashing protection + require.NoError(t, protector.UpdateHighestProposal(_byteArray(pk), blk.Slot-1)) + + versionedBeaconBlock := &spec.VersionedBeaconBlock{ + Version: spec.DataVersionCapella, + Capella: blk, + } + + // decode blinded block + blindedBlk := &apiv1capella.BlindedBeaconBlock{} + require.NoError(t, json.Unmarshal(blindedBlockJSON, blindedBlk)) + + versionedBlindedBeaconBlock := &api.VersionedBlindedBeaconBlock{ + Version: spec.DataVersionCapella, + Capella: blindedBlk, + } + + sig, _, err := signer.SignBeaconBlock(versionedBeaconBlock, _byteArray32(domain), _byteArray(pk)) + require.NoError(t, err) + require.EqualValues(t, _byteArray(sigByts), sig) + + _, _, err = signer.SignBlindedBeaconBlock(versionedBlindedBeaconBlock, _byteArray32(domain), _byteArray(pk)) + require.Error(t, err) + require.EqualError(t, err, "slashable proposal (HighestProposalVote), not signing") +} diff --git a/signer/sign_registration_test.go b/signer/sign_registration_test.go index f943b209..4e35293f 100644 --- a/signer/sign_registration_test.go +++ b/signer/sign_registration_test.go @@ -18,10 +18,10 @@ func TestSimpleSigner_SignRegistration(t *testing.T) { valRegistrationMock := &apiv1.ValidatorRegistration{ GasLimit: 123456, - Timestamp: time.UnixMilli(1658313712), + Timestamp: time.Unix(1658313712, 0), } - copy(valRegistrationMock.FeeRecipient[:], "9831EeF7A86C19E32bEcDad091c1DbC974cf452a") - copy(valRegistrationMock.Pubkey[:], "a27c45f7afe6c63363acf886cdad282539fb2cf58b304f2caa95f2ea53048b65a5d41d926c3562e3f18b8b61871375af") + copy(valRegistrationMock.FeeRecipient[:], _byteArray("9831EeF7A86C19E32bEcDad091c1DbC974cf452a")) + copy(valRegistrationMock.Pubkey[:], _byteArray("a27c45f7afe6c63363acf886cdad282539fb2cf58b304f2caa95f2ea53048b65a5d41d926c3562e3f18b8b61871375af")) registrationMock := &api.VersionedValidatorRegistration{ Version: 0, @@ -42,7 +42,7 @@ func TestSimpleSigner_SignRegistration(t *testing.T) { pubKey: _byteArray("a27c45f7afe6c63363acf886cdad282539fb2cf58b304f2caa95f2ea53048b65a5d41d926c3562e3f18b8b61871375af"), domain: _byteArray32("00000001d7a9bca8823e555db65bb772e1496a26e1a8c5b1c0c7def9c9eaf7f6"), expectedError: nil, - sig: _byteArray("800a93d4361eda08cd00d4d9fd22c296d9e8253500d3702ede2516abfe5b6a89cfc23d27ce28f0c95828878880494cb815c74b203846d91c29010c6111c3b245f4e270e5f1f9ee40dec985f6e7b733059d88a662f4d1341b0f015fbd5ed829a4"), + sig: _byteArray("b088d9d27c783f3d5eb57a0df1e99f030e035ebcfdeb745da95400ab46a0c461f05f61533379d3bc56c5e94dfdf8560d0a31cfb9162f11ba9a82522f4043764a02008f6fef3b0167cbf2db9a749095343412a38568fe39d14c3ebcdddad7ee36"), }, { name: "nil data", diff --git a/stores/inmemory/marshalable.go b/stores/inmemory/marshalable.go index 4ec12677..95a9a1d0 100644 --- a/stores/inmemory/marshalable.go +++ b/stores/inmemory/marshalable.go @@ -62,7 +62,11 @@ func (store *InMemStore) UnmarshalJSON(data []byte) error { return err } - store.network = core.NetworkFromString(string(byts)) + network, err := core.NetworkFromString(string(byts)) + if err != nil { + return errors.Wrap(err, "failed to parse network") + } + store.network = network } else { return errors.New("could not find var: network") }