Skip to content

Commit

Permalink
Capella withdrawals (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
olegshmuelov committed Mar 28, 2023
1 parent 8d1395f commit ccd30ae
Show file tree
Hide file tree
Showing 31 changed files with 1,541 additions and 174 deletions.
79 changes: 77 additions & 2 deletions cli/cmd/flags.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
package cmd

import (
"fmt"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/bloxapp/eth2-key-manager/cli/util/cliflag"
"github.com/bloxapp/eth2-key-manager/core"
)

// ResponseType represents the network.
type ResponseType string

// Available response types.
const (
// StorageResponseType represents the storage response type.
StorageResponseType ResponseType = "storage"

// ObjectResponseType represents the storage response type.
ObjectResponseType ResponseType = "object"
)

// ResponseTypeFromString returns response type from the given string value
func ResponseTypeFromString(n string) ResponseType {
switch n {
case string(StorageResponseType):
return StorageResponseType
case string(ObjectResponseType):
return ObjectResponseType
default:
panic(fmt.Sprintf("undefined response type %s", n))
}
}

// Flag names.
const (
networkFlag = "network"
networkFlag = "network"
accumulateFlag = "accumulate"
seedFlag = "seed"
indexFlag = "index"
responseTypeFlag = "response-type"
)

// AddNetworkFlag adds the network flag to the command
func AddNetworkFlag(c *cobra.Command) {
cliflag.AddPersistentStringFlag(c, networkFlag, "", "Ethereum network", false)
cliflag.AddPersistentStringFlag(c, networkFlag, "", "Ethereum network", true)
}

// GetNetworkFlagValue gets the network flag from the command
Expand All @@ -32,3 +62,48 @@ func GetNetworkFlagValue(c *cobra.Command) (core.Network, error) {

return ret, nil
}

// AddAccumulateFlag adds the accumulate flag to the command
func AddAccumulateFlag(c *cobra.Command) {
cliflag.AddPersistentBoolFlag(c, accumulateFlag, false, "accumulate accounts", false)
}

// GetAccumulateFlagValue gets the accumulate flag from the command
func GetAccumulateFlagValue(c *cobra.Command) (bool, error) {
return c.Flags().GetBool(accumulateFlag)
}

// AddSeedFlag adds the seed flag to the command
func AddSeedFlag(c *cobra.Command) {
cliflag.AddPersistentStringFlag(c, seedFlag, "", "seed", false)
}

// GetSeedFlagValue gets the seed flag from the command
func GetSeedFlagValue(c *cobra.Command) (string, error) {
return c.Flags().GetString(seedFlag)
}

// AddIndexFlag adds the index flag to the command
func AddIndexFlag(c *cobra.Command) {
cliflag.AddPersistentIntFlag(c, indexFlag, 0, "public key index", true)
}

// GetIndexFlagValue gets the index flag from the command
func GetIndexFlagValue(c *cobra.Command) (int, error) {
return c.Flags().GetInt(indexFlag)
}

// AddResponseTypeFlag adds the response-type flag to the command
func AddResponseTypeFlag(c *cobra.Command) {
cliflag.AddPersistentStringFlag(c, responseTypeFlag, string(StorageResponseType), "response type", false)
}

// GetResponseTypeFlagValue gets the response-type flag from the command
func GetResponseTypeFlagValue(c *cobra.Command) (ResponseType, error) {
responseTypeValue, err := c.Flags().GetString(responseTypeFlag)
if err != nil {
return "", err
}

return ResponseTypeFromString(responseTypeValue), nil
}
10 changes: 5 additions & 5 deletions cli/cmd/wallet/cmd/account/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ var createCmd = &cobra.Command{

func init() {
// Define flags for the command.
flag.AddIndexFlag(createCmd)
flag.AddSeedFlag(createCmd)
rootcmd.AddNetworkFlag(createCmd)
rootcmd.AddSeedFlag(createCmd)
rootcmd.AddIndexFlag(createCmd)
rootcmd.AddAccumulateFlag(createCmd)
rootcmd.AddResponseTypeFlag(createCmd)
flag.AddPrivateKeyFlag(createCmd)
flag.AddAccumulateFlag(createCmd)
flag.AddResponseTypeFlag(createCmd)
flag.AddHighestSourceFlag(createCmd)
flag.AddHighestTargetFlag(createCmd)
flag.AddHighestProposalFlag(createCmd)
rootcmd.AddNetworkFlag(createCmd)

Command.AddCommand(createCmd)
}
34 changes: 34 additions & 0 deletions cli/cmd/wallet/cmd/account/credentials.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package account

import (
"github.com/spf13/cobra"

rootcmd "github.com/bloxapp/eth2-key-manager/cli/cmd"
"github.com/bloxapp/eth2-key-manager/cli/cmd/wallet/cmd/account/flag"
"github.com/bloxapp/eth2-key-manager/cli/cmd/wallet/cmd/account/handler"
)

// credentialsCmd represents the credentials account command.
var credentialsCmd = &cobra.Command{
Use: "credentials",
Short: "Sign BLS to execution message",
Long: `This command signing BLS to execution change using seed`,
RunE: func(cmd *cobra.Command, args []string) error {
handler := handler.New(rootcmd.ResultPrinter)
return handler.Credentials(cmd, args)
},
}

func init() {
// Define flags for the command.
rootcmd.AddNetworkFlag(credentialsCmd)
rootcmd.AddSeedFlag(credentialsCmd)
rootcmd.AddIndexFlag(credentialsCmd)
rootcmd.AddAccumulateFlag(credentialsCmd)
flag.AddValidatorIndicesFlag(credentialsCmd)
flag.AddValidatorPublicKeysFlag(credentialsCmd)
flag.AddWithdrawalCredentialsFlag(credentialsCmd)
flag.AddToExecutionAddressFlag(credentialsCmd)

Command.AddCommand(credentialsCmd)
}
217 changes: 217 additions & 0 deletions cli/cmd/wallet/cmd/account/credentials_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
package account_test

import (
"bytes"
"testing"

"github.com/stretchr/testify/require"

"github.com/bloxapp/eth2-key-manager/cli/cmd"
"github.com/bloxapp/eth2-key-manager/cli/util/printer"
)

func TestAccountCredentials(t *testing.T) {
t.Run("Successfully handle credentials change at specific index", func(t *testing.T) {
var output bytes.Buffer
cmd.ResultPrinter = printer.New(&output)
cmd.RootCmd.SetArgs([]string{
"wallet",
"account",
"credentials",
"--seed=847d135b3aecac8ae77c3fdfd46dc5849ad3b5bacd30a1b9082b6ff53c77357e923b12fcdc3d02728fd35c3685de1fe1e9c052c48f0d83566b1b2287cf0e54c3",
"--index=1",
"--validator-indices=273230",
"--validator-public-keys=0xa1a593775967bf88bb6c14ac109c12e52dc836fa139bd1ba6ca873d65fe91bb7a0fc79c7b2a7315482a81f31e6b1018a",
"--withdrawal-credentials=0x00202f88c6116d27f5de06eeda3b801d3a4eeab8eb09f879848445fffc8948a5",
"--to-execution-address=0x3e6935b8250Cf9A777862871649E5594bE08779e",
"--network=prater",
})
err := cmd.RootCmd.Execute()
actualOutput := output.String()
require.NotNil(t, actualOutput)
require.NoError(t, err)
})

t.Run("Successfully handle accumulated credentials change", func(t *testing.T) {
var output bytes.Buffer
cmd.ResultPrinter = printer.New(&output)
cmd.RootCmd.SetArgs([]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=prater",
})
err := cmd.RootCmd.Execute()
actualOutput := output.String()
require.NotNil(t, actualOutput)
require.NoError(t, err)
})

t.Run("Only one validator can be specified if accumulate is false", func(t *testing.T) {
var output bytes.Buffer
cmd.ResultPrinter = printer.New(&output)
cmd.RootCmd.SetArgs([]string{
"wallet",
"account",
"credentials",
"--seed=847d135b3aecac8ae77c3fdfd46dc5849ad3b5bacd30a1b9082b6ff53c77357e923b12fcdc3d02728fd35c3685de1fe1e9c052c48f0d83566b1b2287cf0e54c3",
"--index=1",
"--accumulate=false",
"--validator-indices=273230,273407",
"--validator-public-keys=0xb2dc1daa8c9cd104d4503028639e41a41e4f06ee5cc90ebfaeab3c41f43a148ce9afa4ebd1b8be3f54e4d6c15e870c7c,0xa1a593775967bf88bb6c14ac109c12e52dc836fa139bd1ba6ca873d65fe91bb7a0fc79c7b2a7315482a81f31e6b1018a",
"--withdrawal-credentials=0x00d9cdf17e3a79317a4e5cd18580b1d10b1df360bbca5c5f8ac5b79b45c29d15,0x00202f88c6116d27f5de06eeda3b801d3a4eeab8eb09f879848445fffc8948a5",
"--to-execution-address=0x3e6935b8250Cf9A777862871649E5594bE08779e,0x3e6935b8250Cf9A777862871649E5594bE08779e",
"--network=prater",
})
err := cmd.RootCmd.Execute()
actualOutput := output.String()
require.EqualValues(t, actualOutput, "")
require.Error(t, err)
require.EqualError(t, err, "failed to collect credentials flags: only one validator can be specified if accumulate is false")
})

t.Run("Not equal length - should be 2 validator indices", func(t *testing.T) {
var output bytes.Buffer
cmd.ResultPrinter = printer.New(&output)
cmd.RootCmd.SetArgs([]string{
"wallet",
"account",
"credentials",
"--seed=847d135b3aecac8ae77c3fdfd46dc5849ad3b5bacd30a1b9082b6ff53c77357e923b12fcdc3d02728fd35c3685de1fe1e9c052c48f0d83566b1b2287cf0e54c3",
"--index=1",
"--accumulate=true",
"--validator-indices=273230,273407,273407",
"--validator-public-keys=0xb2dc1daa8c9cd104d4503028639e41a41e4f06ee5cc90ebfaeab3c41f43a148ce9afa4ebd1b8be3f54e4d6c15e870c7c,0xa1a593775967bf88bb6c14ac109c12e52dc836fa139bd1ba6ca873d65fe91bb7a0fc79c7b2a7315482a81f31e6b1018a",
"--withdrawal-credentials=0x00d9cdf17e3a79317a4e5cd18580b1d10b1df360bbca5c5f8ac5b79b45c29d15,0x00202f88c6116d27f5de06eeda3b801d3a4eeab8eb09f879848445fffc8948a5",
"--to-execution-address=0x3e6935b8250Cf9A777862871649E5594bE08779e,0x3e6935b8250Cf9A777862871649E5594bE08779e",
"--network=prater",
})
err := cmd.RootCmd.Execute()
actualOutput := output.String()
require.EqualValues(t, actualOutput, "")
require.Error(t, err)
require.EqualError(t, err, "failed to collect credentials flags: validator indices, public keys, withdrawal credentials and to execution addresses must be of equal length")
})

t.Run("Not equal length - should be two public keys", func(t *testing.T) {
var output bytes.Buffer
cmd.ResultPrinter = printer.New(&output)
cmd.RootCmd.SetArgs([]string{
"wallet",
"account",
"credentials",
"--seed=847d135b3aecac8ae77c3fdfd46dc5849ad3b5bacd30a1b9082b6ff53c77357e923b12fcdc3d02728fd35c3685de1fe1e9c052c48f0d83566b1b2287cf0e54c3",
"--index=1",
"--accumulate=true",
"--validator-indices=273230,273407",
"--validator-public-keys=0xa1a593775967bf88bb6c14ac109c12e52dc836fa139bd1ba6ca873d65fe91bb7a0fc79c7b2a7315482a81f31e6b1018a",
"--withdrawal-credentials=0x00d9cdf17e3a79317a4e5cd18580b1d10b1df360bbca5c5f8ac5b79b45c29d15,0x00202f88c6116d27f5de06eeda3b801d3a4eeab8eb09f879848445fffc8948a5",
"--to-execution-address=0x3e6935b8250Cf9A777862871649E5594bE08779e,0x3e6935b8250Cf9A777862871649E5594bE08779e",
"--network=prater",
})
err := cmd.RootCmd.Execute()
actualOutput := output.String()
require.EqualValues(t, actualOutput, "")
require.Error(t, err)
require.EqualError(t, err, "failed to collect credentials flags: validator indices, public keys, withdrawal credentials and to execution addresses must be of equal length")
})

t.Run("Not equal length - should be two withdrawal credentials", func(t *testing.T) {
var output bytes.Buffer
cmd.ResultPrinter = printer.New(&output)
cmd.RootCmd.SetArgs([]string{
"wallet",
"account",
"credentials",
"--seed=847d135b3aecac8ae77c3fdfd46dc5849ad3b5bacd30a1b9082b6ff53c77357e923b12fcdc3d02728fd35c3685de1fe1e9c052c48f0d83566b1b2287cf0e54c3",
"--index=1",
"--accumulate=true",
"--validator-indices=273230,273407",
"--validator-public-keys=0xb2dc1daa8c9cd104d4503028639e41a41e4f06ee5cc90ebfaeab3c41f43a148ce9afa4ebd1b8be3f54e4d6c15e870c7c,0xa1a593775967bf88bb6c14ac109c12e52dc836fa139bd1ba6ca873d65fe91bb7a0fc79c7b2a7315482a81f31e6b1018a",
"--withdrawal-credentials=0x00202f88c6116d27f5de06eeda3b801d3a4eeab8eb09f879848445fffc8948a5",
"--to-execution-address=0x3e6935b8250Cf9A777862871649E5594bE08779e,0x3e6935b8250Cf9A777862871649E5594bE08779e",
"--network=prater",
})
err := cmd.RootCmd.Execute()
actualOutput := output.String()
require.EqualValues(t, actualOutput, "")
require.Error(t, err)
require.EqualError(t, err, "failed to collect credentials flags: validator indices, public keys, withdrawal credentials and to execution addresses must be of equal length")
})

t.Run("Not equal length - should be two to execution addresses", func(t *testing.T) {
var output bytes.Buffer
cmd.ResultPrinter = printer.New(&output)
cmd.RootCmd.SetArgs([]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",
"--network=prater",
})
err := cmd.RootCmd.Execute()
actualOutput := output.String()
require.EqualValues(t, actualOutput, "")
require.Error(t, err)
require.EqualError(t, err, "failed to collect credentials flags: validator indices, public keys, withdrawal credentials and to execution addresses must be of equal length")
})

t.Run("Derived pub key does not match with the provided", func(t *testing.T) {
var output bytes.Buffer
cmd.ResultPrinter = printer.New(&output)
cmd.RootCmd.SetArgs([]string{
"wallet",
"account",
"credentials",
"--seed=847d135b3aecac8ae77c3fdfd46dc5849ad3b5bacd30a1b9082b6ff53c77357e923b12fcdc3d02728fd35c3685de1fe1e9c052c48f0d83566b1b2287cf0e54c3",
"--index=1",
"--accumulate=true",
"--validator-indices=273230,273407",
"--validator-public-keys=0xb2dc1daa8c9cd104d4503028639e41a41e4f06ee5cc90ebfaeab3c41f43a148ce9afa4ebd1b8be3f54e4d6c15e870c7a,0xa1a593775967bf88bb6c14ac109c12e52dc836fa139bd1ba6ca873d65fe91bb7a0fc79c7b2a7315482a81f31e6b1018a",
"--withdrawal-credentials=0x00d9cdf17e3a79317a4e5cd18580b1d10b1df360bbca5c5f8ac5b79b45c29d15,0x00202f88c6116d27f5de06eeda3b801d3a4eeab8eb09f879848445fffc8948a5",
"--to-execution-address=0x3e6935b8250Cf9A777862871649E5594bE08779e,0x3e6935b8250Cf9A777862871649E5594bE08779e",
"--network=prater",
})
err := cmd.RootCmd.Execute()
actualOutput := output.String()
require.EqualValues(t, actualOutput, "")
require.Error(t, err)
require.EqualError(t, err, "derived validator public key: 0xb2dc1daa8c9cd104d4503028639e41a41e4f06ee5cc90ebfaeab3c41f43a148ce9afa4ebd1b8be3f54e4d6c15e870c7c, does not match with the provided one: 0xb2dc1daa8c9cd104d4503028639e41a41e4f06ee5cc90ebfaeab3c41f43a148ce9afa4ebd1b8be3f54e4d6c15e870c7a")
})

t.Run("Derived withdrawal credentials does not match with the provided", func(t *testing.T) {
var output bytes.Buffer
cmd.ResultPrinter = printer.New(&output)
cmd.RootCmd.SetArgs([]string{
"wallet",
"account",
"credentials",
"--seed=847d135b3aecac8ae77c3fdfd46dc5849ad3b5bacd30a1b9082b6ff53c77357e923b12fcdc3d02728fd35c3685de1fe1e9c052c48f0d83566b1b2287cf0e54c3",
"--index=1",
"--accumulate=true",
"--validator-indices=273230,273407",
"--validator-public-keys=0xb2dc1daa8c9cd104d4503028639e41a41e4f06ee5cc90ebfaeab3c41f43a148ce9afa4ebd1b8be3f54e4d6c15e870c7c,0xa1a593775967bf88bb6c14ac109c12e52dc836fa139bd1ba6ca873d65fe91bb7a0fc79c7b2a7315482a81f31e6b1018a",
"--withdrawal-credentials=0x00d9cdf17e3a79317a4e5cd18580b1d10b1df360bbca5c5f8ac5b79b45c29d14,0x00202f88c6116d27f5de06eeda3b801d3a4eeab8eb09f879848445fffc8948a5",
"--to-execution-address=0x3e6935b8250Cf9A777862871649E5594bE08779e,0x3e6935b8250Cf9A777862871649E5594bE08779e",
"--network=prater",
})
err := cmd.RootCmd.Execute()
actualOutput := output.String()
require.EqualValues(t, actualOutput, "")
require.Error(t, err)
require.EqualError(t, err, "derived withdrawal credentials: 0x00d9cdf17e3a79317a4e5cd18580b1d10b1df360bbca5c5f8ac5b79b45c29d15, does not match with the provided one: 0x00d9cdf17e3a79317a4e5cd18580b1d10b1df360bbca5c5f8ac5b79b45c29d14")
})
}
6 changes: 3 additions & 3 deletions cli/cmd/wallet/cmd/account/deposit-data.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ var depositDataCmd = &cobra.Command{

func init() {
// Define flags for the command.
flag.AddIndexFlag(depositDataCmd)
flag.AddSeedFlag(depositDataCmd)
flag.AddPublicKeyFlag(depositDataCmd)
rootcmd.AddNetworkFlag(depositDataCmd)
rootcmd.AddSeedFlag(depositDataCmd)
rootcmd.AddIndexFlag(depositDataCmd)
flag.AddPublicKeyFlag(depositDataCmd)

Command.AddCommand(depositDataCmd)
}
Loading

0 comments on commit ccd30ae

Please sign in to comment.