diff --git a/shared/services/beacon/client/std-http-client.go b/shared/services/beacon/client/std-http-client.go index f6a94db29..250b756a8 100644 --- a/shared/services/beacon/client/std-http-client.go +++ b/shared/services/beacon/client/std-http-client.go @@ -25,6 +25,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net/http" "strconv" "strings" diff --git a/shared/services/config/config-legacy.go b/shared/services/config/config-legacy.go index 7d693384a..f37abdf97 100644 --- a/shared/services/config/config-legacy.go +++ b/shared/services/config/config-legacy.go @@ -21,7 +21,7 @@ package config import ( "fmt" - "io/ioutil" + "math/big" "os" "strconv" @@ -301,7 +301,7 @@ func Load(c *cli.Context) (LegacyStaderConfig, error) { func loadFile(path string, required bool) (LegacyStaderConfig, error) { // Read file; squelch not found errors if file is optional - bytes, err := ioutil.ReadFile(path) + bytes, err := os.ReadFile(path) if err != nil { if required { return LegacyStaderConfig{}, fmt.Errorf("Could not find config file at %s: %w", path, err) diff --git a/shared/services/config/stader-config.go b/shared/services/config/stader-config.go index 999f2d3ef..5f6d5e5b8 100644 --- a/shared/services/config/stader-config.go +++ b/shared/services/config/stader-config.go @@ -21,7 +21,7 @@ package config import ( "fmt" - "io/ioutil" + "net/url" "os" "path/filepath" @@ -149,7 +149,7 @@ func LoadFromFile(path string) (*StaderConfig, error) { } // Read the file - configBytes, err := ioutil.ReadFile(path) + configBytes, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("could not read Stader settings file at %s: %w", shellescape.Quote(path), err) } diff --git a/shared/services/config/stadernode-config.go b/shared/services/config/stadernode-config.go index aadcfcbc8..83fdc1835 100644 --- a/shared/services/config/stadernode-config.go +++ b/shared/services/config/stadernode-config.go @@ -98,6 +98,9 @@ type StaderNodeConfig struct { // URL for an EC with archive mode, for manual rewards tree generation ArchiveECUrl config.Parameter `yaml:"archiveEcUrl,omitempty"` + // The path of the data folder where everything is stored + SsvMigration config.Parameter `yaml:"ssvMigration,omitempty"` + /////////////////////////// // Non-editable settings // /////////////////////////// @@ -231,6 +234,18 @@ func NewStadernodeConfig(cfg *StaderConfig) *StaderNodeConfig { OverwriteOnUpgrade: false, }, + SsvMigration: config.Parameter{ + ID: "ssvMigration", + Name: "Enable Ssv migration mode", + Description: "Enable this for failsafe mechanisms during Migration to SSV", + Type: config.ParameterType_Bool, + Default: map[config.Network]interface{}{config.Network_All: false}, + AffectsContainers: []config.ContainerID{config.ContainerID_Validator}, + EnvironmentVariables: []string{}, + CanBeBlank: true, + OverwriteOnUpgrade: false, + }, + beaconChainUrl: map[config.Network]string{ config.Network_Mainnet: "https://beaconcha.in", config.Network_Holesky: "https://holesky.beaconcha.in", @@ -278,6 +293,7 @@ func (cfg *StaderNodeConfig) GetParameters() []*config.Parameter { &cfg.PriorityFee, &cfg.TxFeeCap, &cfg.ArchiveECUrl, + &cfg.SsvMigration, } } @@ -356,6 +372,14 @@ func (cfg *StaderNodeConfig) GetValidatorKeychainPath() string { return filepath.Join(DaemonDataPath, "validators") } +func (cfg *StaderNodeConfig) GetPresignKeychainPath() string { + if cfg.parent.IsNativeMode { + return filepath.Join(cfg.DataPath.Value.(string), "presign") + } + + return filepath.Join(DaemonDataPath, "presign") +} + func (cfg *StaderNodeConfig) GetWalletPathInCLI() string { return filepath.Join(cfg.DataPath.Value.(string), "wallet") } diff --git a/shared/services/gas/etherchain/etherchain.go b/shared/services/gas/etherchain/etherchain.go index f2d407b86..4e4a0050b 100644 --- a/shared/services/gas/etherchain/etherchain.go +++ b/shared/services/gas/etherchain/etherchain.go @@ -23,6 +23,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "math/big" "net/http" ) diff --git a/shared/services/gas/etherscan/etherscan.go b/shared/services/gas/etherscan/etherscan.go index e720de8e9..41e00b93b 100644 --- a/shared/services/gas/etherscan/etherscan.go +++ b/shared/services/gas/etherscan/etherscan.go @@ -23,6 +23,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net/http" "strconv" ) diff --git a/shared/services/passwords/manager.go b/shared/services/passwords/manager.go index 48ede9a3f..5ac995464 100644 --- a/shared/services/passwords/manager.go +++ b/shared/services/passwords/manager.go @@ -22,7 +22,7 @@ package passwords import ( "errors" "fmt" - "io/ioutil" + "os" ) @@ -46,7 +46,7 @@ func NewPasswordManager(passwordPath string) *PasswordManager { // Check if the password has been set func (pm *PasswordManager) IsPasswordSet() bool { - _, err := ioutil.ReadFile(pm.passwordPath) + _, err := os.ReadFile(pm.passwordPath) return (err == nil) } @@ -54,7 +54,7 @@ func (pm *PasswordManager) IsPasswordSet() bool { func (pm *PasswordManager) GetPassword() (string, error) { // Read from disk - password, err := ioutil.ReadFile(pm.passwordPath) + password, err := os.ReadFile(pm.passwordPath) if err != nil { return "", fmt.Errorf("Could not read password from disk: %w", err) } @@ -78,7 +78,7 @@ func (pm *PasswordManager) SetPassword(password string) error { } // Write to disk - if err := ioutil.WriteFile(pm.passwordPath, []byte(password), FileMode); err != nil { + if err := os.WriteFile(pm.passwordPath, []byte(password), FileMode); err != nil { return fmt.Errorf("Could not write password to disk: %w", err) } diff --git a/shared/services/services.go b/shared/services/services.go index 60b943869..3824d8d17 100644 --- a/shared/services/services.go +++ b/shared/services/services.go @@ -513,17 +513,35 @@ func getWallet(c *cli.Context, cfg *config.StaderConfig, pm *passwords.PasswordM return } - // Keystores - lighthouseKeystore := lhkeystore.NewKeystore(os.ExpandEnv(cfg.StaderNode.GetValidatorKeychainPath()), pm) - nimbusKeystore := nmkeystore.NewKeystore(os.ExpandEnv(cfg.StaderNode.GetValidatorKeychainPath()), pm) - prysmKeystore := prkeystore.NewKeystore(os.ExpandEnv(cfg.StaderNode.GetValidatorKeychainPath()), pm) - tekuKeystore := tkkeystore.NewKeystore(os.ExpandEnv(cfg.StaderNode.GetValidatorKeychainPath()), pm) - lodestarKeystore := lokeystore.NewKeystore(os.ExpandEnv(cfg.StaderNode.GetValidatorKeychainPath()), pm) + validatorPath := os.ExpandEnv(cfg.StaderNode.GetValidatorKeychainPath()) + + // Keystores in validator + lighthouseKeystore := lhkeystore.NewKeystore(validatorPath, pm) + nimbusKeystore := nmkeystore.NewKeystore(validatorPath, pm) + prysmKeystore := prkeystore.NewKeystore(validatorPath, pm) + tekuKeystore := tkkeystore.NewKeystore(validatorPath, pm) + lodestarKeystore := lokeystore.NewKeystore(validatorPath, pm) + nodeWallet.AddKeystore("lighthouse", lighthouseKeystore) nodeWallet.AddKeystore("nimbus", nimbusKeystore) nodeWallet.AddKeystore("prysm", prysmKeystore) nodeWallet.AddKeystore("teku", tekuKeystore) nodeWallet.AddKeystore("lodestar", lodestarKeystore) + + presignPath := os.ExpandEnv(cfg.StaderNode.GetPresignKeychainPath()) + + // Keystores in presign + lighthousePresignKeystore := lhkeystore.NewKeystore(presignPath, pm) + nimbusPresignKeystore := nmkeystore.NewKeystore(presignPath, pm) + prysmPresignKeystore := prkeystore.NewKeystore(presignPath, pm) + tekuPresignKeystore := tkkeystore.NewKeystore(presignPath, pm) + lodestarPresignKeystore := lokeystore.NewKeystore(presignPath, pm) + + nodeWallet.AddPresignKeystore("lighthouse", lighthousePresignKeystore) + nodeWallet.AddPresignKeystore("nimbus", nimbusPresignKeystore) + nodeWallet.AddPresignKeystore("prysm", prysmPresignKeystore) + nodeWallet.AddPresignKeystore("teku", tekuPresignKeystore) + nodeWallet.AddPresignKeystore("lodestar", lodestarPresignKeystore) }) return nodeWallet, err } diff --git a/shared/services/stader/client.go b/shared/services/stader/client.go index 8920cf4af..ce5eed6da 100644 --- a/shared/services/stader/client.go +++ b/shared/services/stader/client.go @@ -24,7 +24,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "log" "math/big" "net" @@ -292,7 +291,7 @@ func (c *Client) UpdatePrometheusConfiguration(settings map[string]string) error } // Write the actual Prometheus config file - err = ioutil.WriteFile(prometheusConfigPath, contents, 0664) + err = os.WriteFile(prometheusConfigPath, contents, 0664) if err != nil { return fmt.Errorf("Could not write Prometheus config file to %s: %w", shellescape.Quote(prometheusConfigPath), err) } @@ -1421,7 +1420,7 @@ func (c *Client) deployTemplates(cfg *config.StaderConfig, staderDir string, set return []string{}, fmt.Errorf("error reading and substituting API container template: %w", err) } apiComposePath := filepath.Join(runtimeFolder, config.ApiContainerName+composeFileSuffix) - err = ioutil.WriteFile(apiComposePath, contents, 0664) + err = os.WriteFile(apiComposePath, contents, 0664) if err != nil { return []string{}, fmt.Errorf("could not write API container file to %s: %w", apiComposePath, err) } @@ -1434,7 +1433,7 @@ func (c *Client) deployTemplates(cfg *config.StaderConfig, staderDir string, set return []string{}, fmt.Errorf("error reading and substituting node container template: %w", err) } nodeComposePath := filepath.Join(runtimeFolder, config.NodeContainerName+composeFileSuffix) - err = ioutil.WriteFile(nodeComposePath, contents, 0664) + err = os.WriteFile(nodeComposePath, contents, 0664) if err != nil { return []string{}, fmt.Errorf("could not write node container file to %s: %w", nodeComposePath, err) } @@ -1447,7 +1446,7 @@ func (c *Client) deployTemplates(cfg *config.StaderConfig, staderDir string, set return []string{}, fmt.Errorf("error reading and substituting guardian container template: %w", err) } guardianComposePath := filepath.Join(runtimeFolder, config.GuardianContainerName+composeFileSuffix) - err = ioutil.WriteFile(guardianComposePath, contents, 0664) + err = os.WriteFile(guardianComposePath, contents, 0664) if err != nil { return []string{}, fmt.Errorf("could not write guardian container file to %s: %w", guardianComposePath, err) } @@ -1455,17 +1454,21 @@ func (c *Client) deployTemplates(cfg *config.StaderConfig, staderDir string, set deployedContainers = append(deployedContainers, filepath.Join(overrideFolder, config.GuardianContainerName+composeFileSuffix)) // Validator - contents, err = envsubst.ReadFile(filepath.Join(templatesFolder, config.ValidatorContainerName+templateSuffix)) - if err != nil { - return []string{}, fmt.Errorf("error reading and substituting validator container template: %w", err) - } - validatorComposePath := filepath.Join(runtimeFolder, config.ValidatorContainerName+composeFileSuffix) - err = ioutil.WriteFile(validatorComposePath, contents, 0664) - if err != nil { - return []string{}, fmt.Errorf("could not write validator container file to %s: %w", validatorComposePath, err) + + ssvMigration, _ := cfg.StaderNode.SsvMigration.Value.(bool) + if !ssvMigration { + contents, err = envsubst.ReadFile(filepath.Join(templatesFolder, config.ValidatorContainerName+templateSuffix)) + if err != nil { + return []string{}, fmt.Errorf("error reading and substituting validator container template: %w", err) + } + validatorComposePath := filepath.Join(runtimeFolder, config.ValidatorContainerName+composeFileSuffix) + err = os.WriteFile(validatorComposePath, contents, 0664) + if err != nil { + return []string{}, fmt.Errorf("could not write validator container file to %s: %w", validatorComposePath, err) + } + deployedContainers = append(deployedContainers, validatorComposePath) + deployedContainers = append(deployedContainers, filepath.Join(overrideFolder, config.ValidatorContainerName+composeFileSuffix)) } - deployedContainers = append(deployedContainers, validatorComposePath) - deployedContainers = append(deployedContainers, filepath.Join(overrideFolder, config.ValidatorContainerName+composeFileSuffix)) // Check the EC mode to see if it needs to be deployed if cfg.ExecutionClientMode.Value.(cfgtypes.Mode) == cfgtypes.Mode_Local { @@ -1474,7 +1477,7 @@ func (c *Client) deployTemplates(cfg *config.StaderConfig, staderDir string, set return []string{}, fmt.Errorf("error reading and substituting execution client container template: %w", err) } eth1ComposePath := filepath.Join(runtimeFolder, config.Eth1ContainerName+composeFileSuffix) - err = ioutil.WriteFile(eth1ComposePath, contents, 0664) + err = os.WriteFile(eth1ComposePath, contents, 0664) if err != nil { return []string{}, fmt.Errorf("could not write execution client container file to %s: %w", eth1ComposePath, err) } @@ -1489,7 +1492,7 @@ func (c *Client) deployTemplates(cfg *config.StaderConfig, staderDir string, set return []string{}, fmt.Errorf("error reading and substituting consensus client container template: %w", err) } eth2ComposePath := filepath.Join(runtimeFolder, config.Eth2ContainerName+composeFileSuffix) - err = ioutil.WriteFile(eth2ComposePath, contents, 0664) + err = os.WriteFile(eth2ComposePath, contents, 0664) if err != nil { return []string{}, fmt.Errorf("could not write consensus client container file to %s: %w", eth2ComposePath, err) } @@ -1505,7 +1508,7 @@ func (c *Client) deployTemplates(cfg *config.StaderConfig, staderDir string, set return []string{}, fmt.Errorf("error reading and substituting Grafana container template: %w", err) } grafanaComposePath := filepath.Join(runtimeFolder, config.GrafanaContainerName+composeFileSuffix) - err = ioutil.WriteFile(grafanaComposePath, contents, 0664) + err = os.WriteFile(grafanaComposePath, contents, 0664) if err != nil { return []string{}, fmt.Errorf("could not write Grafana container file to %s: %w", grafanaComposePath, err) } @@ -1517,7 +1520,7 @@ func (c *Client) deployTemplates(cfg *config.StaderConfig, staderDir string, set return []string{}, fmt.Errorf("error reading and substituting Node Exporter container template: %w", err) } exporterComposePath := filepath.Join(runtimeFolder, config.ExporterContainerName+composeFileSuffix) - err = ioutil.WriteFile(exporterComposePath, contents, 0664) + err = os.WriteFile(exporterComposePath, contents, 0664) if err != nil { return []string{}, fmt.Errorf("could not write Node Exporter container file to %s: %w", exporterComposePath, err) } @@ -1530,7 +1533,7 @@ func (c *Client) deployTemplates(cfg *config.StaderConfig, staderDir string, set return []string{}, fmt.Errorf("error reading and substituting Prometheus container template: %w", err) } prometheusComposePath := filepath.Join(runtimeFolder, config.PrometheusContainerName+composeFileSuffix) - err = ioutil.WriteFile(prometheusComposePath, contents, 0664) + err = os.WriteFile(prometheusComposePath, contents, 0664) if err != nil { return []string{}, fmt.Errorf("could not write Prometheus container file to %s: %w", prometheusComposePath, err) } @@ -1545,7 +1548,7 @@ func (c *Client) deployTemplates(cfg *config.StaderConfig, staderDir string, set return []string{}, fmt.Errorf("error reading and substituting MEV-Boost container template: %w", err) } mevBoostComposePath := filepath.Join(runtimeFolder, config.MevBoostContainerName+composeFileSuffix) - err = ioutil.WriteFile(mevBoostComposePath, contents, 0664) + err = os.WriteFile(mevBoostComposePath, contents, 0664) if err != nil { return []string{}, fmt.Errorf("could not write MEV-Boost container file to %s: %w", mevBoostComposePath, err) } diff --git a/shared/services/stader/fee-recipient.go b/shared/services/stader/fee-recipient.go index 67c3d0436..96cace6c0 100644 --- a/shared/services/stader/fee-recipient.go +++ b/shared/services/stader/fee-recipient.go @@ -22,7 +22,7 @@ package stader import ( "fmt" "io/fs" - "io/ioutil" + "os" "github.com/ethereum/go-ethereum/common" @@ -49,7 +49,7 @@ func CheckFeeRecipientFile(feeRecipient common.Address, cfg *config.StaderConfig // Compare the file contents with the expected string expectedString := getFeeRecipientFileContents(feeRecipient, cfg) - bytes, err := ioutil.ReadFile(path) + bytes, err := os.ReadFile(path) if err != nil { return false, false, fmt.Errorf("error reading fee recipient file: %w", err) } @@ -72,7 +72,7 @@ func UpdateFeeRecipientFile(feeRecipient common.Address, cfg *config.StaderConfi // Write the file path := cfg.StaderNode.GetFeeRecipientFilePath() - err := ioutil.WriteFile(path, bytes, FileMode) + err := os.WriteFile(path, bytes, FileMode) if err != nil { return fmt.Errorf("error writing fee recipient file: %w", err) } diff --git a/shared/services/stader/legacy-client.go b/shared/services/stader/legacy-client.go index 0da09ad05..d5dc860bc 100644 --- a/shared/services/stader/legacy-client.go +++ b/shared/services/stader/legacy-client.go @@ -21,7 +21,7 @@ package stader import ( "fmt" - "io/ioutil" + "os" "github.com/alessio/shellescape" "github.com/mitchellh/go-homedir" @@ -66,7 +66,7 @@ func (c *Client) loadConfig_Legacy(path string) (config.LegacyStaderConfig, erro if err != nil { return config.LegacyStaderConfig{}, err } - configBytes, err := ioutil.ReadFile(expandedPath) + configBytes, err := os.ReadFile(expandedPath) if err != nil { return config.LegacyStaderConfig{}, fmt.Errorf("Could not read Stader config at %s: %w", shellescape.Quote(path), err) } diff --git a/shared/services/wallet/keystore/lighthouse/keystore.go b/shared/services/wallet/keystore/lighthouse/keystore.go index 41768ed3b..76b8d2d5e 100644 --- a/shared/services/wallet/keystore/lighthouse/keystore.go +++ b/shared/services/wallet/keystore/lighthouse/keystore.go @@ -22,7 +22,6 @@ package lighthouse import ( "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" @@ -118,7 +117,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write secret to disk - if err := ioutil.WriteFile(secretFilePath, []byte(password), FileMode); err != nil { + if err := os.WriteFile(secretFilePath, []byte(password), FileMode); err != nil { return fmt.Errorf("Could not write validator secret to disk: %w", err) } @@ -131,7 +130,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write key store to disk - if err := ioutil.WriteFile(keyFilePath, keyStoreBytes, FileMode); err != nil { + if err := os.WriteFile(keyFilePath, keyStoreBytes, FileMode); err != nil { return fmt.Errorf("Could not write validator key to disk: %w", err) } diff --git a/shared/services/wallet/keystore/lodestar/keystore.go b/shared/services/wallet/keystore/lodestar/keystore.go index 92f15ef41..dc8261634 100644 --- a/shared/services/wallet/keystore/lodestar/keystore.go +++ b/shared/services/wallet/keystore/lodestar/keystore.go @@ -3,7 +3,6 @@ package lodestar import ( "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" @@ -99,7 +98,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write secret to disk - if err := ioutil.WriteFile(secretFilePath, []byte(password), FileMode); err != nil { + if err := os.WriteFile(secretFilePath, []byte(password), FileMode); err != nil { return fmt.Errorf("Could not write validator secret to disk: %w", err) } @@ -112,7 +111,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write key store to disk - if err := ioutil.WriteFile(keyFilePath, keyStoreBytes, FileMode); err != nil { + if err := os.WriteFile(keyFilePath, keyStoreBytes, FileMode); err != nil { return fmt.Errorf("Could not write validator key to disk: %w", err) } diff --git a/shared/services/wallet/keystore/nimbus/keystore.go b/shared/services/wallet/keystore/nimbus/keystore.go index b1b13ad43..2c698c7d7 100644 --- a/shared/services/wallet/keystore/nimbus/keystore.go +++ b/shared/services/wallet/keystore/nimbus/keystore.go @@ -22,7 +22,6 @@ package nimbus import ( "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" @@ -118,7 +117,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write secret to disk - if err := ioutil.WriteFile(secretFilePath, []byte(password), FileMode); err != nil { + if err := os.WriteFile(secretFilePath, []byte(password), FileMode); err != nil { return fmt.Errorf("Could not write validator secret to disk: %w", err) } @@ -131,7 +130,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write key store to disk - if err := ioutil.WriteFile(keyFilePath, keyStoreBytes, FileMode); err != nil { + if err := os.WriteFile(keyFilePath, keyStoreBytes, FileMode); err != nil { return fmt.Errorf("Could not write validator key to disk: %w", err) } diff --git a/shared/services/wallet/keystore/prysm/keystore.go b/shared/services/wallet/keystore/prysm/keystore.go index b9843e8de..05c23d35e 100644 --- a/shared/services/wallet/keystore/prysm/keystore.go +++ b/shared/services/wallet/keystore/prysm/keystore.go @@ -24,7 +24,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "os" "path/filepath" @@ -117,7 +117,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa // Get the keystore account password passwordFilePath := filepath.Join(ks.keystorePath, KeystoreDir, WalletDir, AccountsDir, KeystorePasswordFileName) - passwordBytes, err := ioutil.ReadFile(passwordFilePath) + passwordBytes, err := os.ReadFile(passwordFilePath) if err != nil { return fmt.Errorf("Error reading account password file: %w", err) } @@ -153,7 +153,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write keystore to disk - if err := ioutil.WriteFile(keystoreFilePath, ksBytes, FileMode); err != nil { + if err := os.WriteFile(keystoreFilePath, ksBytes, FileMode); err != nil { return fmt.Errorf("Could not write keystore to disk: %w", err) } @@ -171,7 +171,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write wallet config to disk - if err := ioutil.WriteFile(configFilePath, configBytes, FileMode); err != nil { + if err := os.WriteFile(configFilePath, configBytes, FileMode); err != nil { return fmt.Errorf("Could not write wallet config to disk: %w", err) } @@ -207,21 +207,21 @@ func (ks *Keystore) initialize() error { if err != nil { return fmt.Errorf("Error creating account password directory: %w", err) } - err = ioutil.WriteFile(passwordFilePath, passwordBytes, FileMode) + err = os.WriteFile(passwordFilePath, passwordBytes, FileMode) if err != nil { return fmt.Errorf("Error writing account password file: %w", err) } } // Get the random keystore password - passwordBytes, err := ioutil.ReadFile(passwordFilePath) + passwordBytes, err := os.ReadFile(passwordFilePath) if err != nil { return fmt.Errorf("Error opening account password file: %w", err) } password = string(passwordBytes) // Read keystore file; initialize empty account store if it doesn't exist - ksBytes, err := ioutil.ReadFile(filepath.Join(ks.keystorePath, KeystoreDir, WalletDir, AccountsDir, KeystoreFileName)) + ksBytes, err := os.ReadFile(filepath.Join(ks.keystorePath, KeystoreDir, WalletDir, AccountsDir, KeystoreFileName)) if err != nil { ks.as = &accountStore{} return nil diff --git a/shared/services/wallet/keystore/teku/keystore.go b/shared/services/wallet/keystore/teku/keystore.go index 4433e8efb..6da803a05 100644 --- a/shared/services/wallet/keystore/teku/keystore.go +++ b/shared/services/wallet/keystore/teku/keystore.go @@ -22,7 +22,6 @@ package teku import ( "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" @@ -117,7 +116,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write secret to disk - if err := ioutil.WriteFile(secretFilePath, []byte(password), FileMode); err != nil { + if err := os.WriteFile(secretFilePath, []byte(password), FileMode); err != nil { return fmt.Errorf("Could not write validator secret to disk: %w", err) } @@ -130,7 +129,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write key store to disk - if err := ioutil.WriteFile(keyFilePath, keyStoreBytes, FileMode); err != nil { + if err := os.WriteFile(keyFilePath, keyStoreBytes, FileMode); err != nil { return fmt.Errorf("Could not write validator key to disk: %w", err) } diff --git a/shared/services/wallet/validator.go b/shared/services/wallet/validator.go index 404db856d..fd6a4dd93 100644 --- a/shared/services/wallet/validator.go +++ b/shared/services/wallet/validator.go @@ -135,7 +135,7 @@ func (w *Wallet) CreateValidatorKeyFromIndex(index uint) (*eth2types.BLSPrivateK } // Create a new validator key -func (w *Wallet) CreateValidatorKey() (*eth2types.BLSPrivateKey, error) { +func (w *Wallet) CreateValidatorKey(ssvMigrate bool) (*eth2types.BLSPrivateKey, error) { // Check wallet is initialized if !w.IsInitialized() { @@ -153,9 +153,17 @@ func (w *Wallet) CreateValidatorKey() (*eth2types.BLSPrivateKey, error) { } // Update keystores - err = w.StoreValidatorKey(key, path) - if err != nil { - return nil, err + + if ssvMigrate { + err = w.StoreValidatorPresignKey(key, path) + if err != nil { + return nil, err + } + } else { + err = w.StoreValidatorKey(key, path) + if err != nil { + return nil, err + } } // Return validator key @@ -177,6 +185,20 @@ func (w *Wallet) StoreValidatorKey(key *eth2types.BLSPrivateKey, path string) er } +func (w *Wallet) StoreValidatorPresignKey(key *eth2types.BLSPrivateKey, path string) error { + + for name := range w.keystores { + // Update the keystore in the wallet - using an iterator variable only runs it on the local copy + if err := w.keystoresPresign[name].StoreValidatorKey(key, path); err != nil { + return fmt.Errorf("Could not store %s presign key for : %w", name, err) + } + } + + // Return validator key + return nil + +} + // Deletes all of the keystore directories and persistent VC storage func (w *Wallet) DeleteValidatorStores() error { diff --git a/shared/services/wallet/wallet.go b/shared/services/wallet/wallet.go index 37a21143a..99fd23485 100644 --- a/shared/services/wallet/wallet.go +++ b/shared/services/wallet/wallet.go @@ -24,7 +24,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "math/big" "os" @@ -78,6 +78,8 @@ type Wallet struct { // Keystores keystores map[string]keystore.Keystore + keystoresPresign map[string]keystore.Keystore + // Desired gas price & limit from config maxFee *big.Int maxPriorityFee *big.Int @@ -107,6 +109,7 @@ func NewWallet(walletPath string, chainId uint, maxFee *big.Int, maxPriorityFee validatorKeys: map[uint]*eth2types.BLSPrivateKey{}, validatorKeyIndices: map[string]uint{}, keystores: map[string]keystore.Keystore{}, + keystoresPresign: map[string]keystore.Keystore{}, maxFee: maxFee, maxPriorityFee: maxPriorityFee, gasLimit: gasLimit, @@ -133,6 +136,11 @@ func (w *Wallet) AddKeystore(name string, ks keystore.Keystore) { w.keystores[name] = ks } +// Add a keystore to the wallet +func (w *Wallet) AddPresignKeystore(name string, ks keystore.Keystore) { + w.keystoresPresign[name] = ks +} + // Check if the wallet has been initialized func (w *Wallet) IsInitialized() bool { return (w.ws != nil && w.seed != nil && w.mk != nil) @@ -266,7 +274,7 @@ func (w *Wallet) Save() error { } // Write wallet store to disk - if err := ioutil.WriteFile(w.walletPath, wsBytes, FileMode); err != nil { + if err := os.WriteFile(w.walletPath, wsBytes, FileMode); err != nil { return fmt.Errorf("Could not write wallet to disk: %w", err) } @@ -349,7 +357,7 @@ func (w *Wallet) Reload() error { func (w *Wallet) loadStore() (bool, error) { // Read wallet store from disk; cancel if not found - wsBytes, err := ioutil.ReadFile(w.walletPath) + wsBytes, err := os.ReadFile(w.walletPath) if err != nil { return false, nil } diff --git a/shared/utils/stdr/config.go b/shared/utils/stdr/config.go index d2ed6c2dd..82bfa2aac 100644 --- a/shared/utils/stdr/config.go +++ b/shared/utils/stdr/config.go @@ -21,7 +21,6 @@ package stdr import ( "fmt" - "io/ioutil" "os" "path/filepath" @@ -58,7 +57,7 @@ func SaveConfig(cfg *config.StaderConfig, path string) error { return fmt.Errorf("could not serialize settings file: %w", err) } - if err := ioutil.WriteFile(path, configBytes, 0664); err != nil { + if err := os.WriteFile(path, configBytes, 0664); err != nil { return fmt.Errorf("could not write Stader config to %s: %w", shellescape.Quote(path), err) } diff --git a/stader-cli/wallet/utils.go b/stader-cli/wallet/utils.go index dc4f9b6aa..1c7ff0709 100644 --- a/stader-cli/wallet/utils.go +++ b/stader-cli/wallet/utils.go @@ -23,6 +23,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "os" "path/filepath" "strconv" @@ -157,7 +158,7 @@ func promptForCustomKeyPasswords(sd *stader.Client, cfg *config.StaderConfig, te customPubkeys := []types.ValidatorPubkey{} for _, file := range files { // Read the file - bytes, err := ioutil.ReadFile(filepath.Join(customKeyDir, file.Name())) + bytes, err := os.ReadFile(filepath.Join(customKeyDir, file.Name())) if err != nil { return "", fmt.Errorf("error reading custom keystore %s: %w", file.Name(), err) } @@ -194,7 +195,7 @@ func promptForCustomKeyPasswords(sd *stader.Client, cfg *config.StaderConfig, te return "", fmt.Errorf("error serializing keystore passwords file: %w", err) } passwordFile := filepath.Join(datapath, "custom-key-passwords") - err = ioutil.WriteFile(passwordFile, fileBytes, 0600) + err = os.WriteFile(passwordFile, fileBytes, 0600) if err != nil { return "", fmt.Errorf("error writing keystore passwords file: %w", err) } diff --git a/stader/api/validator/deposit.go b/stader/api/validator/deposit.go index bad76ea18..eff7c0d36 100644 --- a/stader/api/validator/deposit.go +++ b/stader/api/validator/deposit.go @@ -296,6 +296,7 @@ func canNodeDeposit(c *cli.Context, baseAmountWei, utilityAmountWei, numValidato } func nodeDeposit(c *cli.Context, baseAmountWei, utilityAmountWei, numValidators *big.Int, reloadKeys bool) (*api.NodeDepositResponse, error) { + cfg, err := services.GetConfig(c) if err != nil { return nil, err @@ -304,6 +305,8 @@ func nodeDeposit(c *cli.Context, baseAmountWei, utilityAmountWei, numValidators if err != nil { return nil, err } + + ssvMigration, _ := cfg.StaderNode.SsvMigration.Value.(bool) prn, err := services.GetPermissionlessNodeRegistry(c) if err != nil { return nil, err @@ -365,7 +368,7 @@ func nodeDeposit(c *cli.Context, baseAmountWei, utilityAmountWei, numValidators for i := int64(0); i < numValidators.Int64(); i++ { // Create and save a new validator key - validatorKey, err := w.CreateValidatorKey() + validatorKey, err := w.CreateValidatorKey(ssvMigration) if err != nil { return nil, err } @@ -416,7 +419,7 @@ func nodeDeposit(c *cli.Context, baseAmountWei, utilityAmountWei, numValidators newValidatorKey = validatorKeyCount.Add(validatorKeyCount, big.NewInt(1)) } - if reloadKeys { + if reloadKeys && !ssvMigration { d, err := services.GetDocker(c) if err != nil { return nil, err diff --git a/stader/node/node.go b/stader/node/node.go index 524b081de..b15942d73 100644 --- a/stader/node/node.go +++ b/stader/node/node.go @@ -25,7 +25,6 @@ import ( "encoding/hex" "encoding/json" "fmt" - "io/ioutil" "net/http" "os" "path/filepath" @@ -622,7 +621,7 @@ func deployDefaultFeeRecipientFile(c *cli.Context) error { // Docker and Hybrid just need the address itself defaultFeeRecipientFileContents = cfg.StaderNode.GetEthxTokenAddress().Hex() } - err := ioutil.WriteFile(feeRecipientPath, []byte(defaultFeeRecipientFileContents), 0664) + err := os.WriteFile(feeRecipientPath, []byte(defaultFeeRecipientFileContents), 0664) if err != nil { return fmt.Errorf("could not write default fee recipient file to %s: %w", feeRecipientPath, err) }