From 1a9935d6160af3eb970f3e30502cdba0cb5a57ab Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Mon, 8 Jan 2024 23:57:17 +0400 Subject: [PATCH 01/11] Add submit cmd to the deposit cli --- cmd/staking-deposit-cli/deposit/BUILD.bazel | 1 + .../deposit/flags/BUILD.bazel | 12 ++ .../deposit/flags/flags.go | 51 ++++++ cmd/staking-deposit-cli/deposit/main.go | 3 + .../deposit/submit/BUILD.bazel | 31 ++++ cmd/staking-deposit-cli/deposit/submit/cmd.go | 25 +++ .../deposit/submit/deposit.go | 147 ++++++++++++++++++ .../deposit/submit/deposit_test.go | 11 ++ 8 files changed, 281 insertions(+) create mode 100644 cmd/staking-deposit-cli/deposit/flags/BUILD.bazel create mode 100644 cmd/staking-deposit-cli/deposit/flags/flags.go create mode 100644 cmd/staking-deposit-cli/deposit/submit/BUILD.bazel create mode 100644 cmd/staking-deposit-cli/deposit/submit/cmd.go create mode 100644 cmd/staking-deposit-cli/deposit/submit/deposit.go create mode 100644 cmd/staking-deposit-cli/deposit/submit/deposit_test.go diff --git a/cmd/staking-deposit-cli/deposit/BUILD.bazel b/cmd/staking-deposit-cli/deposit/BUILD.bazel index f4190645e..fc457e0af 100644 --- a/cmd/staking-deposit-cli/deposit/BUILD.bazel +++ b/cmd/staking-deposit-cli/deposit/BUILD.bazel @@ -10,6 +10,7 @@ go_library( "//cmd/staking-deposit-cli/deposit/existingseed:go_default_library", "//cmd/staking-deposit-cli/deposit/generatedilithiumtoexecutionchange:go_default_library", "//cmd/staking-deposit-cli/deposit/newseed:go_default_library", + "//cmd/staking-deposit-cli/deposit/submit:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_urfave_cli_v2//:go_default_library", ], diff --git a/cmd/staking-deposit-cli/deposit/flags/BUILD.bazel b/cmd/staking-deposit-cli/deposit/flags/BUILD.bazel new file mode 100644 index 000000000..ad51ca4eb --- /dev/null +++ b/cmd/staking-deposit-cli/deposit/flags/BUILD.bazel @@ -0,0 +1,12 @@ +load("@qrysm//tools/go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["flags.go"], + importpath = "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/deposit/flags", + visibility = ["//visibility:public"], + deps = [ + "//config/params:go_default_library", + "@com_github_urfave_cli_v2//:go_default_library", + ], +) diff --git a/cmd/staking-deposit-cli/deposit/flags/flags.go b/cmd/staking-deposit-cli/deposit/flags/flags.go new file mode 100644 index 000000000..e67c2fbea --- /dev/null +++ b/cmd/staking-deposit-cli/deposit/flags/flags.go @@ -0,0 +1,51 @@ +package flags + +import ( + "github.com/theQRL/qrysm/v4/config/params" + "github.com/urfave/cli/v2" +) + +// ValidatorKeysDefaultDirName for validator_keys. +const ValidatorKeysDefaultDirName = "validator_keys" + +var ( + // ValidatorKeysDir defines the path to the validator keys directory. + ValidatorKeysDirFlag = &cli.StringFlag{ + Name: "validator-keys-dir", + Usage: "Path to a wallet directory on-disk for validator keys", + // Value: filepath.Join(DefaultValidatorKeysDir(), ValidatorKeysDefaultDirName), + Value: ValidatorKeysDefaultDirName, + } + // ZondSeedFileFlag for transaction signing. + ZondSeedFileFlag = &cli.StringFlag{ + Name: "zond-seed-file", + Usage: "File containing a seed for sending deposit transactions from zond", + Value: "", + Required: true, + } + // HTTPWeb3ProviderFlag provides an HTTP access endpoint to an ETH 1.0 RPC. + HTTPWeb3ProviderFlag = &cli.StringFlag{ + Name: "http-web3provider", + Usage: "A zond web3 provider string http endpoint", + Value: "http://localhost:8545", + } + // DepositContractAddressFlag for the validator deposit contract on eth1. + DepositContractAddressFlag = &cli.StringFlag{ + Name: "deposit-contract", + Usage: "Address of the deposit contract", + Value: params.MainnetConfig().DepositContractAddress, + } + /* + // SkipDepositConfirmationFlag skips the y/n confirmation prompt for sending a deposit to the deposit contract. + SkipDepositConfirmationFlag = &cli.BoolFlag{ + Name: "skip-deposit-confirmation", + Usage: "Skips the y/n confirmation prompt for sending a deposit to the deposit contract", + } + // DepositDelaySecondsFlag to delay sending deposit transactions by a fixed interval. + DepositDelaySecondsFlag = &cli.Int64Flag{ + Name: "deposit-delay-seconds", + Usage: "The time delay between sending the deposits to the contract (in seconds)", + Value: 5, + } + */ +) diff --git a/cmd/staking-deposit-cli/deposit/main.go b/cmd/staking-deposit-cli/deposit/main.go index f1ab571c5..a79f69811 100644 --- a/cmd/staking-deposit-cli/deposit/main.go +++ b/cmd/staking-deposit-cli/deposit/main.go @@ -7,6 +7,7 @@ import ( "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/deposit/existingseed" "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/deposit/generatedilithiumtoexecutionchange" "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/deposit/newseed" + "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/deposit/submit" "github.com/urfave/cli/v2" ) @@ -26,4 +27,6 @@ func init() { depositCommands = append(depositCommands, existingseed.Commands...) depositCommands = append(depositCommands, newseed.Commands...) depositCommands = append(depositCommands, generatedilithiumtoexecutionchange.Commands...) + depositCommands = append(depositCommands, generatedilithiumtoexecutionchange.Commands...) + depositCommands = append(depositCommands, submit.Command) } diff --git a/cmd/staking-deposit-cli/deposit/submit/BUILD.bazel b/cmd/staking-deposit-cli/deposit/submit/BUILD.bazel new file mode 100644 index 000000000..0b367b96d --- /dev/null +++ b/cmd/staking-deposit-cli/deposit/submit/BUILD.bazel @@ -0,0 +1,31 @@ +load("@qrysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "cmd.go", + "deposit.go", + ], + importpath = "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/deposit/submit", + visibility = ["//visibility:public"], + deps = [ + "//cmd/staking-deposit-cli/deposit/flags:go_default_library", + "//cmd/staking-deposit-cli/misc:go_default_library", + "//cmd/staking-deposit-cli/stakingdeposit:go_default_library", + "//contracts/deposit:go_default_library", + "//encoding/bytesutil:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + "@com_github_theqrl_go_qrllib//dilithium:go_default_library", + "@com_github_theqrl_go_zond//accounts/abi/bind:go_default_library", + "@com_github_theqrl_go_zond//common:go_default_library", + "@com_github_theqrl_go_zond//core/types:go_default_library", + "@com_github_theqrl_go_zond//rpc:go_default_library", + "@com_github_theqrl_go_zond//zondclient:go_default_library", + "@com_github_urfave_cli_v2//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["deposit_test.go"], +) diff --git a/cmd/staking-deposit-cli/deposit/submit/cmd.go b/cmd/staking-deposit-cli/deposit/submit/cmd.go new file mode 100644 index 000000000..8634350fd --- /dev/null +++ b/cmd/staking-deposit-cli/deposit/submit/cmd.go @@ -0,0 +1,25 @@ +package submit + +import ( + "github.com/sirupsen/logrus" + "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/deposit/flags" + "github.com/urfave/cli/v2" +) + +var log = logrus.WithField("prefix", "submit") + +var Command = &cli.Command{ + Name: "submit", + Description: "Submits deposits to the zond deposit contract for a set of validators by connecting " + + "to a zond endpoint to submit the transactions. Requires signing the transactions with a zond private key", + Usage: "", + Action: func(cliCtx *cli.Context) error { + return submitDeposits(cliCtx) + }, + Flags: []cli.Flag{ + flags.ValidatorKeysDirFlag, + flags.ZondSeedFileFlag, + flags.DepositContractAddressFlag, + flags.HTTPWeb3ProviderFlag, + }, +} diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit.go b/cmd/staking-deposit-cli/deposit/submit/deposit.go new file mode 100644 index 000000000..0d134e0e2 --- /dev/null +++ b/cmd/staking-deposit-cli/deposit/submit/deposit.go @@ -0,0 +1,147 @@ +package submit + +import ( + "encoding/json" + "fmt" + "math/big" + "os" + "path/filepath" + "strings" + + "github.com/sirupsen/logrus" + dilithiumlib "github.com/theQRL/go-qrllib/dilithium" + "github.com/theQRL/go-zond/accounts/abi/bind" + "github.com/theQRL/go-zond/common" + "github.com/theQRL/go-zond/core/types" + "github.com/theQRL/go-zond/rpc" + "github.com/theQRL/go-zond/zondclient" + "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/deposit/flags" + "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/misc" + "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/stakingdeposit" + "github.com/theQRL/qrysm/v4/contracts/deposit" + "github.com/theQRL/qrysm/v4/encoding/bytesutil" + "github.com/urfave/cli/v2" +) + +// TODO(rgeraldes24): value validation? +// TODO(rgeraldes24): operation timeout +// TODO(rgeraldes24): gas fees +// TODO(rgeraldes24): check if the deposit already exists? +// TODO(rgeraldes24): wait for tx confirmation option? +// TODO(rgeraldes24): delay between transactions? + +const depositDataFilePrefix = "deposit_data-" + +func submitDeposits(cliCtx *cli.Context) error { + + web3Provider := cliCtx.String(flags.HTTPWeb3ProviderFlag.Name) + rpcClient, err := rpc.Dial(web3Provider) + if err != nil { + return fmt.Errorf("failed to connect to the zond provider. reason: %v", err) + } + zondCli := zondclient.NewClient(rpcClient) + chainID, err := zondCli.ChainID(cliCtx.Context) + if err != nil { + return fmt.Errorf("failed to retrieve the chain ID. reason: %v", err) + } + contractAddr := cliCtx.String(flags.DepositContractAddressFlag.Name) + contract, err := deposit.NewDepositContract(common.HexToAddress(contractAddr), zondCli) + if err != nil { + return fmt.Errorf("failed to create a new instance of the deposit contract. reason: %v", err) + } + + validatorKeysDir := cliCtx.String(flags.HTTPWeb3ProviderFlag.Name) + depositDataList, err := importDepositDataJSON(validatorKeysDir) + if err != nil { + return fmt.Errorf("failed to read deposit data. reason: %v", err) + } + + signingSeedFile := cliCtx.String(flags.ZondSeedFileFlag.Name) + binSigningSeed, err := os.ReadFile(signingSeedFile) + if err != nil { + return fmt.Errorf("failed to read seed file. reason: %v", err) + } + depositKey, err := dilithiumlib.NewDilithiumFromSeed(bytesutil.ToBytes48(binSigningSeed)) + if err != nil { + return fmt.Errorf("failed to generate the deposit key from the signing seed. reason: %v", err) + } + + for _, depositData := range depositDataList { + tx, err := sendDepositTx(contract, depositKey, depositData, chainID) + if err != nil { + return fmt.Errorf("failed to submit deposit transaction. reason: %v", err) + } + + log.WithFields(logrus.Fields{ + "Transaction Hash": fmt.Sprintf("%#x", tx.Hash()), + }).Infof( + "Deposit sent to contract address %v for validator with a public key %#x", + contractAddr, + depositData.PubKey, + ) + } + + return nil +} + +func sendDepositTx( + contract *deposit.DepositContract, + key *dilithiumlib.Dilithium, + data *stakingdeposit.DepositData, + chainID *big.Int, +) (*types.Transaction, error) { + txOpts, err := bind.NewKeyedTransactorWithChainID(key, chainID) + if err != nil { + return nil, err + } + + txOpts.Value = new(big.Int).Mul(big.NewInt(int64(data.Amount)), big.NewInt(1e9)) // value in wei + txOpts.GasLimit = 500000 + txOpts.GasFeeCap = new(big.Int).SetUint64(50000) + txOpts.GasTipCap = new(big.Int).SetUint64(50000) + + tx, err := contract.Deposit( + txOpts, + misc.DecodeHex(data.PubKey), + misc.DecodeHex(data.WithdrawalCredentials), + misc.DecodeHex(data.Signature), + bytesutil.ToBytes32(misc.DecodeHex(data.DepositDataRoot)), + ) + if err != nil { + return nil, err + } + + return tx, nil +} + +func importDepositDataJSON(folder string) ([]*stakingdeposit.DepositData, error) { + entries, err := os.ReadDir(folder) + if err != nil { + return nil, err + } + + var file string + for _, entry := range entries { + if !entry.IsDir() && strings.HasPrefix(depositDataFilePrefix, entry.Name()) { + file = entry.Name() + break + } + } + + if file == "" { + return nil, fmt.Errorf("deposit data file not found. dir: %s", folder) + } + + fileFolder := filepath.Join(folder, file) + data, err := os.ReadFile(fileFolder) + if err != nil { + return nil, err + } + + var depositDataList []*stakingdeposit.DepositData + if err := json.Unmarshal(data, &depositDataList); err != nil { + return nil, fmt.Errorf("failed to read deposit data list. reason: %v", err) + } + + return depositDataList, nil +} diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit_test.go b/cmd/staking-deposit-cli/deposit/submit/deposit_test.go new file mode 100644 index 000000000..9c162a8ac --- /dev/null +++ b/cmd/staking-deposit-cli/deposit/submit/deposit_test.go @@ -0,0 +1,11 @@ +package submit_test + +import "testing" + +func TestImportDepositDataJSON(t *testing.T) { + // TODO(rgeraldes24) +} + +func TestSendDepositTx(t *testing.T) { + // TODO(rgeraldes24) +} From abf1f2697d0d649027c7d59e6521d872ed37b6b1 Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Wed, 10 Jan 2024 13:15:14 +0400 Subject: [PATCH 02/11] Add missing pieces --- .../deposit/flags/flags.go | 25 ++-- cmd/staking-deposit-cli/deposit/submit/cmd.go | 2 + .../deposit/submit/deposit.go | 109 +++++++++++++----- 3 files changed, 92 insertions(+), 44 deletions(-) diff --git a/cmd/staking-deposit-cli/deposit/flags/flags.go b/cmd/staking-deposit-cli/deposit/flags/flags.go index e67c2fbea..a0e8d1298 100644 --- a/cmd/staking-deposit-cli/deposit/flags/flags.go +++ b/cmd/staking-deposit-cli/deposit/flags/flags.go @@ -35,17 +35,16 @@ var ( Usage: "Address of the deposit contract", Value: params.MainnetConfig().DepositContractAddress, } - /* - // SkipDepositConfirmationFlag skips the y/n confirmation prompt for sending a deposit to the deposit contract. - SkipDepositConfirmationFlag = &cli.BoolFlag{ - Name: "skip-deposit-confirmation", - Usage: "Skips the y/n confirmation prompt for sending a deposit to the deposit contract", - } - // DepositDelaySecondsFlag to delay sending deposit transactions by a fixed interval. - DepositDelaySecondsFlag = &cli.Int64Flag{ - Name: "deposit-delay-seconds", - Usage: "The time delay between sending the deposits to the contract (in seconds)", - Value: 5, - } - */ + // SkipDepositConfirmationFlag skips the y/n confirmation prompt for sending a deposit to the deposit contract. + SkipDepositConfirmationFlag = &cli.BoolFlag{ + Name: "skip-deposit-confirmation", + Usage: "Skips the y/n confirmation prompt for sending a deposit to the deposit contract", + Value: false, + } + // DepositDelaySecondsFlag to delay sending deposit transactions by a fixed interval. + DepositDelaySecondsFlag = &cli.Int64Flag{ + Name: "deposit-delay-seconds", + Usage: "The time delay between sending the deposits to the contract (in seconds)", + Value: 5, + } ) diff --git a/cmd/staking-deposit-cli/deposit/submit/cmd.go b/cmd/staking-deposit-cli/deposit/submit/cmd.go index 8634350fd..b4bdc354d 100644 --- a/cmd/staking-deposit-cli/deposit/submit/cmd.go +++ b/cmd/staking-deposit-cli/deposit/submit/cmd.go @@ -21,5 +21,7 @@ var Command = &cli.Command{ flags.ZondSeedFileFlag, flags.DepositContractAddressFlag, flags.HTTPWeb3ProviderFlag, + flags.DepositDelaySecondsFlag, + flags.SkipDepositConfirmationFlag, }, } diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit.go b/cmd/staking-deposit-cli/deposit/submit/deposit.go index 0d134e0e2..050be6b65 100644 --- a/cmd/staking-deposit-cli/deposit/submit/deposit.go +++ b/cmd/staking-deposit-cli/deposit/submit/deposit.go @@ -7,17 +7,21 @@ import ( "os" "path/filepath" "strings" + "time" + "github.com/k0kubun/go-ansi" + "github.com/schollz/progressbar/v3" "github.com/sirupsen/logrus" dilithiumlib "github.com/theQRL/go-qrllib/dilithium" "github.com/theQRL/go-zond/accounts/abi/bind" "github.com/theQRL/go-zond/common" - "github.com/theQRL/go-zond/core/types" "github.com/theQRL/go-zond/rpc" "github.com/theQRL/go-zond/zondclient" + "github.com/theQRL/qrysm/v4/cmd" "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/deposit/flags" "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/misc" "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/stakingdeposit" + "github.com/theQRL/qrysm/v4/config/params" "github.com/theQRL/qrysm/v4/contracts/deposit" "github.com/theQRL/qrysm/v4/encoding/bytesutil" "github.com/urfave/cli/v2" @@ -33,6 +37,27 @@ import ( const depositDataFilePrefix = "deposit_data-" func submitDeposits(cliCtx *cli.Context) error { + validatorKeysDir := cliCtx.String(flags.HTTPWeb3ProviderFlag.Name) + depositDataList, err := importDepositDataJSON(validatorKeysDir) + if err != nil { + return fmt.Errorf("failed to read deposit data. reason: %v", err) + } + + contractAddr := cliCtx.String(flags.DepositContractAddressFlag.Name) + if !cliCtx.Bool(flags.SkipDepositConfirmationFlag.Name) { + qrlDepositTotal := uint64(len(depositDataList)) * params.BeaconConfig().MaxEffectiveBalance / params.BeaconConfig().GweiPerEth + actionText := "This will submit the deposits stored in your deposit data directory. " + + fmt.Sprintf("A total of %d QRL will be sent to contract address %s for %d validator accounts.", qrlDepositTotal, contractAddr, len(depositDataList)) + + "Do you want to proceed? (Y/N)" + deniedText := "Deposits will not be submitted. No changes have been made." + submitConfirmed, err := cmd.ConfirmAction(actionText, deniedText) + if err != nil { + return err + } + if !submitConfirmed { + return nil + } + } web3Provider := cliCtx.String(flags.HTTPWeb3ProviderFlag.Name) rpcClient, err := rpc.Dial(web3Provider) @@ -44,18 +69,11 @@ func submitDeposits(cliCtx *cli.Context) error { if err != nil { return fmt.Errorf("failed to retrieve the chain ID. reason: %v", err) } - contractAddr := cliCtx.String(flags.DepositContractAddressFlag.Name) contract, err := deposit.NewDepositContract(common.HexToAddress(contractAddr), zondCli) if err != nil { return fmt.Errorf("failed to create a new instance of the deposit contract. reason: %v", err) } - validatorKeysDir := cliCtx.String(flags.HTTPWeb3ProviderFlag.Name) - depositDataList, err := importDepositDataJSON(validatorKeysDir) - if err != nil { - return fmt.Errorf("failed to read deposit data. reason: %v", err) - } - signingSeedFile := cliCtx.String(flags.ZondSeedFileFlag.Name) binSigningSeed, err := os.ReadFile(signingSeedFile) if err != nil { @@ -66,21 +84,33 @@ func submitDeposits(cliCtx *cli.Context) error { return fmt.Errorf("failed to generate the deposit key from the signing seed. reason: %v", err) } - for _, depositData := range depositDataList { - tx, err := sendDepositTx(contract, depositKey, depositData, chainID) - if err != nil { - return fmt.Errorf("failed to submit deposit transaction. reason: %v", err) + txOpts, err := bind.NewKeyedTransactorWithChainID(depositKey, chainID) + if err != nil { + return err + } + txOpts.GasLimit = 500000 + txOpts.GasFeeCap = new(big.Int).SetUint64(50000) + txOpts.GasTipCap = new(big.Int).SetUint64(50000) + txOpts.Value = new(big.Int).Mul(big.NewInt(int64(params.BeaconConfig().MaxEffectiveBalance)), big.NewInt(1e9)) // value in wei + + depositDelaySeconds := cliCtx.Int(flags.DepositDelaySecondsFlag.Name) + depositDelay := time.Duration(depositDelaySeconds) * time.Second + bar := initializeProgressBar(len(depositDataList), "Sending deposit transactions...") + for i, depositData := range depositDataList { + if err := sendDepositTx(contract, depositKey, depositData, chainID, txOpts); err != nil { + log.Errorf("Unable to send transaction to contract: %v | deposit data index: %d", err, i) + continue } - log.WithFields(logrus.Fields{ - "Transaction Hash": fmt.Sprintf("%#x", tx.Hash()), - }).Infof( - "Deposit sent to contract address %v for validator with a public key %#x", - contractAddr, - depositData.PubKey, - ) + log.Infof("Waiting for a short delay of %v seconds...", depositDelaySeconds) + if err := bar.Add(1); err != nil { + log.Errorf("Could not increase progress bar percentage: %v", err) + } + time.Sleep(depositDelay) } + log.Infof("Successfully sent all validator deposits!") + return nil } @@ -89,16 +119,8 @@ func sendDepositTx( key *dilithiumlib.Dilithium, data *stakingdeposit.DepositData, chainID *big.Int, -) (*types.Transaction, error) { - txOpts, err := bind.NewKeyedTransactorWithChainID(key, chainID) - if err != nil { - return nil, err - } - - txOpts.Value = new(big.Int).Mul(big.NewInt(int64(data.Amount)), big.NewInt(1e9)) // value in wei - txOpts.GasLimit = 500000 - txOpts.GasFeeCap = new(big.Int).SetUint64(50000) - txOpts.GasTipCap = new(big.Int).SetUint64(50000) + txOpts *bind.TransactOpts, +) error { tx, err := contract.Deposit( txOpts, @@ -108,10 +130,17 @@ func sendDepositTx( bytesutil.ToBytes32(misc.DecodeHex(data.DepositDataRoot)), ) if err != nil { - return nil, err + return err } - return tx, nil + log.WithFields(logrus.Fields{ + "Transaction Hash": fmt.Sprintf("%#x", tx.Hash()), + }).Infof( + "Deposit sent for validator with a public key %#x", + data.PubKey, + ) + + return nil } func importDepositDataJSON(folder string) ([]*stakingdeposit.DepositData, error) { @@ -145,3 +174,21 @@ func importDepositDataJSON(folder string) ([]*stakingdeposit.DepositData, error) return depositDataList, nil } + +func initializeProgressBar(numItems int, msg string) *progressbar.ProgressBar { + return progressbar.NewOptions( + numItems, + progressbar.OptionFullWidth(), + progressbar.OptionSetWriter(ansi.NewAnsiStdout()), + progressbar.OptionEnableColorCodes(true), + progressbar.OptionSetTheme(progressbar.Theme{ + Saucer: "[green]=[reset]", + SaucerHead: "[green]>[reset]", + SaucerPadding: " ", + BarStart: "[", + BarEnd: "]", + }), + progressbar.OptionOnCompletion(func() { fmt.Println() }), + progressbar.OptionSetDescription(msg), + ) +} From d5c91228681dea62640e93c68568b4e9d2ca4f8f Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Wed, 10 Jan 2024 14:01:45 +0400 Subject: [PATCH 03/11] Review gas fees --- .../deposit/submit/deposit.go | 17 +++++++---------- .../deposit/submit/deposit_test.go | 11 ----------- 2 files changed, 7 insertions(+), 21 deletions(-) delete mode 100644 cmd/staking-deposit-cli/deposit/submit/deposit_test.go diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit.go b/cmd/staking-deposit-cli/deposit/submit/deposit.go index 050be6b65..a2f55bcba 100644 --- a/cmd/staking-deposit-cli/deposit/submit/deposit.go +++ b/cmd/staking-deposit-cli/deposit/submit/deposit.go @@ -27,13 +27,6 @@ import ( "github.com/urfave/cli/v2" ) -// TODO(rgeraldes24): value validation? -// TODO(rgeraldes24): operation timeout -// TODO(rgeraldes24): gas fees -// TODO(rgeraldes24): check if the deposit already exists? -// TODO(rgeraldes24): wait for tx confirmation option? -// TODO(rgeraldes24): delay between transactions? - const depositDataFilePrefix = "deposit_data-" func submitDeposits(cliCtx *cli.Context) error { @@ -84,13 +77,18 @@ func submitDeposits(cliCtx *cli.Context) error { return fmt.Errorf("failed to generate the deposit key from the signing seed. reason: %v", err) } + gasTip, err := zondCli.SuggestGasTipCap(cliCtx.Context) + if err != nil { + return fmt.Errorf("failed to get gas tip suggestion. reason: %v", err) + } + txOpts, err := bind.NewKeyedTransactorWithChainID(depositKey, chainID) if err != nil { return err } txOpts.GasLimit = 500000 - txOpts.GasFeeCap = new(big.Int).SetUint64(50000) - txOpts.GasTipCap = new(big.Int).SetUint64(50000) + txOpts.GasFeeCap = nil + txOpts.GasTipCap = gasTip txOpts.Value = new(big.Int).Mul(big.NewInt(int64(params.BeaconConfig().MaxEffectiveBalance)), big.NewInt(1e9)) // value in wei depositDelaySeconds := cliCtx.Int(flags.DepositDelaySecondsFlag.Name) @@ -121,7 +119,6 @@ func sendDepositTx( chainID *big.Int, txOpts *bind.TransactOpts, ) error { - tx, err := contract.Deposit( txOpts, misc.DecodeHex(data.PubKey), diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit_test.go b/cmd/staking-deposit-cli/deposit/submit/deposit_test.go deleted file mode 100644 index 9c162a8ac..000000000 --- a/cmd/staking-deposit-cli/deposit/submit/deposit_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package submit_test - -import "testing" - -func TestImportDepositDataJSON(t *testing.T) { - // TODO(rgeraldes24) -} - -func TestSendDepositTx(t *testing.T) { - // TODO(rgeraldes24) -} From 105d50c82540d31dbaf05e3e62d819cec1e7a8e2 Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Wed, 10 Jan 2024 14:56:03 +0400 Subject: [PATCH 04/11] Review desc and fix deposit flag --- cmd/staking-deposit-cli/deposit/flags/flags.go | 4 ++-- cmd/staking-deposit-cli/deposit/submit/deposit.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/staking-deposit-cli/deposit/flags/flags.go b/cmd/staking-deposit-cli/deposit/flags/flags.go index a0e8d1298..c3115b942 100644 --- a/cmd/staking-deposit-cli/deposit/flags/flags.go +++ b/cmd/staking-deposit-cli/deposit/flags/flags.go @@ -23,13 +23,13 @@ var ( Value: "", Required: true, } - // HTTPWeb3ProviderFlag provides an HTTP access endpoint to an ETH 1.0 RPC. + // HTTPWeb3ProviderFlag provides an HTTP access endpoint to a ZOND RPC. HTTPWeb3ProviderFlag = &cli.StringFlag{ Name: "http-web3provider", Usage: "A zond web3 provider string http endpoint", Value: "http://localhost:8545", } - // DepositContractAddressFlag for the validator deposit contract on eth1. + // DepositContractAddressFlag for the validator deposit contract on zond. DepositContractAddressFlag = &cli.StringFlag{ Name: "deposit-contract", Usage: "Address of the deposit contract", diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit.go b/cmd/staking-deposit-cli/deposit/submit/deposit.go index a2f55bcba..06d9deb96 100644 --- a/cmd/staking-deposit-cli/deposit/submit/deposit.go +++ b/cmd/staking-deposit-cli/deposit/submit/deposit.go @@ -30,7 +30,7 @@ import ( const depositDataFilePrefix = "deposit_data-" func submitDeposits(cliCtx *cli.Context) error { - validatorKeysDir := cliCtx.String(flags.HTTPWeb3ProviderFlag.Name) + validatorKeysDir := cliCtx.String(flags.ValidatorKeysDirFlag.Name) depositDataList, err := importDepositDataJSON(validatorKeysDir) if err != nil { return fmt.Errorf("failed to read deposit data. reason: %v", err) From df6c354452297612cdbd0f96da6804c31f95cf75 Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Wed, 10 Jan 2024 14:58:49 +0400 Subject: [PATCH 05/11] cmd/staking-deposit-cli/deposit/submit/deposit.go: fix args order --- cmd/staking-deposit-cli/deposit/submit/deposit.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit.go b/cmd/staking-deposit-cli/deposit/submit/deposit.go index 06d9deb96..45b823c01 100644 --- a/cmd/staking-deposit-cli/deposit/submit/deposit.go +++ b/cmd/staking-deposit-cli/deposit/submit/deposit.go @@ -148,7 +148,8 @@ func importDepositDataJSON(folder string) ([]*stakingdeposit.DepositData, error) var file string for _, entry := range entries { - if !entry.IsDir() && strings.HasPrefix(depositDataFilePrefix, entry.Name()) { + fmt.Println(entry.Name()) + if !entry.IsDir() && strings.HasPrefix(entry.Name(), depositDataFilePrefix) { file = entry.Name() break } From 909cce67084a8882b687a2587fc1da28254595cc Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Wed, 10 Jan 2024 15:21:49 +0400 Subject: [PATCH 06/11] Fix several issues around the hex formats --- cmd/helpers.go | 2 +- cmd/staking-deposit-cli/deposit/submit/cmd.go | 2 +- .../deposit/submit/deposit.go | 37 +++++++++++++++---- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/cmd/helpers.go b/cmd/helpers.go index a352e649c..8120d2d86 100644 --- a/cmd/helpers.go +++ b/cmd/helpers.go @@ -13,7 +13,7 @@ import ( "github.com/urfave/cli/v2" ) -var log = logrus.WithField("prefix", "node") +var log = logrus.WithField("prefix", "cmd") // ConfirmAction uses the passed in actionText as the confirmation text displayed in the terminal. // The user must enter Y or N to indicate whether they confirm the action detailed in the warning text. diff --git a/cmd/staking-deposit-cli/deposit/submit/cmd.go b/cmd/staking-deposit-cli/deposit/submit/cmd.go index b4bdc354d..7214f3308 100644 --- a/cmd/staking-deposit-cli/deposit/submit/cmd.go +++ b/cmd/staking-deposit-cli/deposit/submit/cmd.go @@ -6,7 +6,7 @@ import ( "github.com/urfave/cli/v2" ) -var log = logrus.WithField("prefix", "submit") +var log = logrus.WithField("prefix2", "deposit") var Command = &cli.Command{ Name: "submit", diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit.go b/cmd/staking-deposit-cli/deposit/submit/deposit.go index 45b823c01..cce8242ea 100644 --- a/cmd/staking-deposit-cli/deposit/submit/deposit.go +++ b/cmd/staking-deposit-cli/deposit/submit/deposit.go @@ -1,6 +1,7 @@ package submit import ( + "encoding/hex" "encoding/json" "fmt" "math/big" @@ -19,7 +20,6 @@ import ( "github.com/theQRL/go-zond/zondclient" "github.com/theQRL/qrysm/v4/cmd" "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/deposit/flags" - "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/misc" "github.com/theQRL/qrysm/v4/cmd/staking-deposit-cli/stakingdeposit" "github.com/theQRL/qrysm/v4/config/params" "github.com/theQRL/qrysm/v4/contracts/deposit" @@ -68,11 +68,17 @@ func submitDeposits(cliCtx *cli.Context) error { } signingSeedFile := cliCtx.String(flags.ZondSeedFileFlag.Name) - binSigningSeed, err := os.ReadFile(signingSeedFile) + signingSeedHex, err := os.ReadFile(signingSeedFile) if err != nil { return fmt.Errorf("failed to read seed file. reason: %v", err) } - depositKey, err := dilithiumlib.NewDilithiumFromSeed(bytesutil.ToBytes48(binSigningSeed)) + signingSeed := make([]byte, hex.DecodedLen(len(signingSeedHex))) + _, err = hex.Decode(signingSeed, signingSeedHex) + if err != nil { + return fmt.Errorf("failed to read seed. reason: %v", err) + } + + depositKey, err := dilithiumlib.NewDilithiumFromSeed(bytesutil.ToBytes48(signingSeed)) if err != nil { return fmt.Errorf("failed to generate the deposit key from the signing seed. reason: %v", err) } @@ -119,12 +125,29 @@ func sendDepositTx( chainID *big.Int, txOpts *bind.TransactOpts, ) error { + pubKeyBytes, err := hex.DecodeString(data.PubKey) + if err != nil { + return err + } + credsBytes, err := hex.DecodeString(data.WithdrawalCredentials) + if err != nil { + return err + } + sigBytes, err := hex.DecodeString(data.Signature) + if err != nil { + return err + } + depDataRootBytes, err := hex.DecodeString(data.Signature) + if err != nil { + return err + } + tx, err := contract.Deposit( txOpts, - misc.DecodeHex(data.PubKey), - misc.DecodeHex(data.WithdrawalCredentials), - misc.DecodeHex(data.Signature), - bytesutil.ToBytes32(misc.DecodeHex(data.DepositDataRoot)), + pubKeyBytes, + credsBytes, + sigBytes, + bytesutil.ToBytes32(depDataRootBytes), ) if err != nil { return err From 59b9d47b8030608169f57e0467d38c89aa3511d1 Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Wed, 10 Jan 2024 15:30:50 +0400 Subject: [PATCH 07/11] Fix several issues around the hex formats --- cmd/staking-deposit-cli/deposit/submit/cmd.go | 2 +- cmd/staking-deposit-cli/deposit/submit/deposit.go | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/cmd/staking-deposit-cli/deposit/submit/cmd.go b/cmd/staking-deposit-cli/deposit/submit/cmd.go index 7214f3308..3a67a4c58 100644 --- a/cmd/staking-deposit-cli/deposit/submit/cmd.go +++ b/cmd/staking-deposit-cli/deposit/submit/cmd.go @@ -6,7 +6,7 @@ import ( "github.com/urfave/cli/v2" ) -var log = logrus.WithField("prefix2", "deposit") +var log = logrus.WithField("prefix", "deposit") var Command = &cli.Command{ Name: "submit", diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit.go b/cmd/staking-deposit-cli/deposit/submit/deposit.go index cce8242ea..8643ffc0d 100644 --- a/cmd/staking-deposit-cli/deposit/submit/deposit.go +++ b/cmd/staking-deposit-cli/deposit/submit/deposit.go @@ -40,7 +40,7 @@ func submitDeposits(cliCtx *cli.Context) error { if !cliCtx.Bool(flags.SkipDepositConfirmationFlag.Name) { qrlDepositTotal := uint64(len(depositDataList)) * params.BeaconConfig().MaxEffectiveBalance / params.BeaconConfig().GweiPerEth actionText := "This will submit the deposits stored in your deposit data directory. " + - fmt.Sprintf("A total of %d QRL will be sent to contract address %s for %d validator accounts.", qrlDepositTotal, contractAddr, len(depositDataList)) + + fmt.Sprintf("A total of %d QRL will be sent to contract address %s for %d validator accounts. ", qrlDepositTotal, contractAddr, len(depositDataList)) + "Do you want to proceed? (Y/N)" deniedText := "Deposits will not be submitted. No changes have been made." submitConfirmed, err := cmd.ConfirmAction(actionText, deniedText) @@ -155,10 +155,7 @@ func sendDepositTx( log.WithFields(logrus.Fields{ "Transaction Hash": fmt.Sprintf("%#x", tx.Hash()), - }).Infof( - "Deposit sent for validator with a public key %#x", - data.PubKey, - ) + }).Info("Deposit sent for validator") return nil } From a378ef66657f8473cfa277cb60f779e999732a81 Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Wed, 10 Jan 2024 15:33:37 +0400 Subject: [PATCH 08/11] cmd/staking-deposit-cli/deposit/main.go: remove duplicate --- cmd/staking-deposit-cli/deposit/main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/staking-deposit-cli/deposit/main.go b/cmd/staking-deposit-cli/deposit/main.go index a79f69811..7a198789a 100644 --- a/cmd/staking-deposit-cli/deposit/main.go +++ b/cmd/staking-deposit-cli/deposit/main.go @@ -27,6 +27,5 @@ func init() { depositCommands = append(depositCommands, existingseed.Commands...) depositCommands = append(depositCommands, newseed.Commands...) depositCommands = append(depositCommands, generatedilithiumtoexecutionchange.Commands...) - depositCommands = append(depositCommands, generatedilithiumtoexecutionchange.Commands...) depositCommands = append(depositCommands, submit.Command) } From 8719ecc8938698417c82f2778a2b392e15fd31b4 Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Wed, 10 Jan 2024 15:41:26 +0400 Subject: [PATCH 09/11] cmd/staking-deposit-cli/deposit/main.go: remove deprecated arg --- cmd/staking-deposit-cli/deposit/submit/deposit.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit.go b/cmd/staking-deposit-cli/deposit/submit/deposit.go index 8643ffc0d..6cc870d92 100644 --- a/cmd/staking-deposit-cli/deposit/submit/deposit.go +++ b/cmd/staking-deposit-cli/deposit/submit/deposit.go @@ -101,7 +101,7 @@ func submitDeposits(cliCtx *cli.Context) error { depositDelay := time.Duration(depositDelaySeconds) * time.Second bar := initializeProgressBar(len(depositDataList), "Sending deposit transactions...") for i, depositData := range depositDataList { - if err := sendDepositTx(contract, depositKey, depositData, chainID, txOpts); err != nil { + if err := sendDepositTx(contract, depositData, chainID, txOpts); err != nil { log.Errorf("Unable to send transaction to contract: %v | deposit data index: %d", err, i) continue } @@ -120,7 +120,6 @@ func submitDeposits(cliCtx *cli.Context) error { func sendDepositTx( contract *deposit.DepositContract, - key *dilithiumlib.Dilithium, data *stakingdeposit.DepositData, chainID *big.Int, txOpts *bind.TransactOpts, From 70a4485c4f06965ddc6b57c4d7ceeae131190802 Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Wed, 10 Jan 2024 15:49:13 +0400 Subject: [PATCH 10/11] cmd/staking-deposit-cli/deposit/main.go: add correct deposit data root field and reviewed tx opts value --- cmd/staking-deposit-cli/deposit/submit/deposit.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit.go b/cmd/staking-deposit-cli/deposit/submit/deposit.go index 6cc870d92..68c1ec339 100644 --- a/cmd/staking-deposit-cli/deposit/submit/deposit.go +++ b/cmd/staking-deposit-cli/deposit/submit/deposit.go @@ -95,12 +95,13 @@ func submitDeposits(cliCtx *cli.Context) error { txOpts.GasLimit = 500000 txOpts.GasFeeCap = nil txOpts.GasTipCap = gasTip - txOpts.Value = new(big.Int).Mul(big.NewInt(int64(params.BeaconConfig().MaxEffectiveBalance)), big.NewInt(1e9)) // value in wei depositDelaySeconds := cliCtx.Int(flags.DepositDelaySecondsFlag.Name) depositDelay := time.Duration(depositDelaySeconds) * time.Second bar := initializeProgressBar(len(depositDataList), "Sending deposit transactions...") for i, depositData := range depositDataList { + txOpts.Value = new(big.Int).Mul(new(big.Int).SetUint64(depositData.Amount), big.NewInt(1e9)) // value in wei + if err := sendDepositTx(contract, depositData, chainID, txOpts); err != nil { log.Errorf("Unable to send transaction to contract: %v | deposit data index: %d", err, i) continue @@ -136,7 +137,7 @@ func sendDepositTx( if err != nil { return err } - depDataRootBytes, err := hex.DecodeString(data.Signature) + depDataRootBytes, err := hex.DecodeString(data.DepositDataRoot) if err != nil { return err } From a90516d836f78a79da53725f0c06abbf693fc635 Mon Sep 17 00:00:00 2001 From: rgeraldes24 Date: Wed, 10 Jan 2024 15:51:05 +0400 Subject: [PATCH 11/11] cmd/staking-deposit-cli/deposit/main.go: remove println --- cmd/staking-deposit-cli/deposit/submit/deposit.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/staking-deposit-cli/deposit/submit/deposit.go b/cmd/staking-deposit-cli/deposit/submit/deposit.go index 68c1ec339..19dcb25f1 100644 --- a/cmd/staking-deposit-cli/deposit/submit/deposit.go +++ b/cmd/staking-deposit-cli/deposit/submit/deposit.go @@ -168,7 +168,6 @@ func importDepositDataJSON(folder string) ([]*stakingdeposit.DepositData, error) var file string for _, entry := range entries { - fmt.Println(entry.Name()) if !entry.IsDir() && strings.HasPrefix(entry.Name(), depositDataFilePrefix) { file = entry.Name() break