Skip to content

Commit

Permalink
some basic validation of ethereum deposit data file
Browse files Browse the repository at this point in the history
  • Loading branch information
CluEleSsUK committed Jul 25, 2024
1 parent cd8ee94 commit 3978606
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 14 deletions.
29 changes: 19 additions & 10 deletions cli/internal/cmd/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package cmd

import (
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"os"

"github.com/randa-mu/ssv-dkg/cli"
"github.com/randa-mu/ssv-dkg/shared"
"github.com/randa-mu/ssv-dkg/shared/api"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -44,41 +45,49 @@ func Sign(cmd *cobra.Command, _ []string) {
}

log := shared.QuietLogger{Quiet: shortFlag}
signingOutput, err := cli.Sign(shared.Uniq(append(args, operatorFlag...)), depositData, log)
// TODO: this should probably sign something more than just the deposit data root
signingOutput, err := cli.Sign(shared.Uniq(append(args, operatorFlag...)), depositData.DepositDataRoot, log)
if err != nil {
shared.Exit(fmt.Sprintf("%v", err))
}

log.MaybeLog(fmt.Sprintf("✅ received signed deposit data! sessionID: %s", hex.EncodeToString(signingOutput.SessionID)))
path := cli.CreateFilename(stateDirectory, signingOutput)

log.MaybeLog(fmt.Sprintf("✅ received signed deposit data! stored state in %s", path))
log.Log(base64.StdEncoding.EncodeToString(signingOutput.GroupSignature))

path := cli.CreateFilename(stateDirectory, signingOutput)
bytes, err := cli.StoreStateIfNotExists(path, signingOutput)
if err != nil {
log.Log(fmt.Sprintf("⚠️ there was an error storing the state; you should store it somewhere for resharing. Error: %v", err))
log.Log(string(bytes))
}
}

func verifyAndGetArgs(cmd *cobra.Command) ([]string, []byte, error) {
func verifyAndGetArgs(cmd *cobra.Command) ([]string, api.UnsignedDepositData, error) {
// if the operator flag isn't passed, we consume operator addresses from stdin
operators, err := arrayOrReader(operatorFlag, cmd.InOrStdin())
if err != nil {
return nil, nil, errors.New("you must provider either the --operator flag or operators via stdin")
return nil, api.UnsignedDepositData{}, errors.New("you must provider either the --operator flag or operators via stdin")
}

if inputPathFlag == "" {
return nil, nil, errors.New("input path cannot be empty")
return nil, api.UnsignedDepositData{}, errors.New("input path cannot be empty")
}

// there is a default value, so this shouldn't really happen
if stateDirectory == "" {
return nil, nil, errors.New("you must provide a state directory")
return nil, api.UnsignedDepositData{}, errors.New("you must provide a state directory")
}

depositBytes, err := os.ReadFile(inputPathFlag)
if err != nil {
return nil, api.UnsignedDepositData{}, fmt.Errorf("error reading the deposit data file: %v", err)
}

depositData, err := os.ReadFile(inputPathFlag)
var depositData api.UnsignedDepositData
err = json.Unmarshal(depositBytes, &depositData)
if err != nil {
return nil, nil, fmt.Errorf("error reading the deposit data file: %v", err)
return nil, api.UnsignedDepositData{}, err
}

return operators, depositData, nil
Expand Down
21 changes: 18 additions & 3 deletions cli/internal/cmd/sign_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package cmd

import (
"encoding/json"
"math/big"
"os"
"path"
"strings"
"testing"

"github.com/randa-mu/ssv-dkg/shared/api"
"github.com/stretchr/testify/require"
)

func TestSignCommand(t *testing.T) {
tmp := t.TempDir()
filepath := path.Join(tmp, "testfile")
createJunkFile(t, filepath)
createdUnsignedDepositData(t, filepath)

tests := []struct {
name string
Expand Down Expand Up @@ -96,10 +99,22 @@ func TestSignCommand(t *testing.T) {
}
}

func createJunkFile(t *testing.T, filepath string) {
func createdUnsignedDepositData(t *testing.T, filepath string) {
data := api.UnsignedDepositData{
WithdrawalCredentials: []byte("hello world"),
DepositDataRoot: []byte("hello world"),
DepositMessageRoot: []byte("hello world"),
Amount: api.BigInt{Int: *big.NewInt(1)},
ForkVersion: "somefork",
NetworkName: "somenetwork",
DepositCLIVersion: "somecli",
}

bytes, err := json.Marshal(data)
require.NoError(t, err)
file, err := os.Create(filepath)
require.NoError(t, err)
_, err = file.Write([]byte("hello"))
_, err = file.Write(bytes)
require.NoError(t, err)
err = file.Close()
require.NoError(t, err)
Expand Down
45 changes: 44 additions & 1 deletion shared/api/cli.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
package api

import "github.com/randa-mu/ssv-dkg/shared/crypto"
import (
"fmt"
"math/big"

"github.com/randa-mu/ssv-dkg/shared/crypto"
)

type UnsignedDepositData struct {
WithdrawalCredentials []byte `json:"withdrawal_credentials"`
DepositDataRoot []byte `json:"deposit_data_root"`
DepositMessageRoot []byte `json:"deposit_message_root,omitempty"`
Amount BigInt `json:"amount,omitempty"`
ForkVersion string `json:"fork_version,omitempty"`
NetworkName string `json:"network_name,omitempty"`
DepositCLIVersion string `json:"deposit_cli_version,omitempty"`
}

type SignedDepositData struct {
UnsignedDepositData
PubKey []byte `json:"pubkey"`
Signature []byte `json:"signature"`
}

type SigningOutput struct {
SessionID []byte `json:"session_id"`
Expand All @@ -18,3 +39,25 @@ type OperatorResponse struct {
Identity crypto.Identity
Response SignResponse
}

type BigInt struct {
big.Int
}

// MarshalJSON intentionally uses a value pointer or things go wrong
func (b BigInt) MarshalJSON() ([]byte, error) {
return []byte(b.String()), nil
}

func (b *BigInt) UnmarshalJSON(p []byte) error {
if string(p) == "null" {
return nil
}
var z big.Int
_, ok := z.SetString(string(p), 10)
if !ok {
return fmt.Errorf("not a valid big integer: %s", p)
}
b.Int = z
return nil
}

0 comments on commit 3978606

Please sign in to comment.