Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 41 additions & 28 deletions rocketpool-cli/node/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,42 +60,55 @@ func getSyncProgress() error {
return err
}

// Make sure ETH2 is on the correct chain
depositContractInfo, err := rp.DepositContractInfo()
if err != nil {
return err
}
if !depositContractInfo.SufficientSync {
color.YellowPrintln("Your execution client hasn't synced enough to determine if your execution and consensus clients are on the same network.")
color.YellowPrintln("To run this safety check, try again later when the execution client has made more sync progress.")
fmt.Println()
return nil
}
if depositContractInfo.RPNetwork != depositContractInfo.BeaconNetwork ||
depositContractInfo.RPDepositContract != depositContractInfo.BeaconDepositContract {
cliutils.PrintDepositMismatchError(
depositContractInfo.RPNetwork,
depositContractInfo.BeaconNetwork,
depositContractInfo.RPDepositContract,
depositContractInfo.BeaconDepositContract)
return nil
}
fmt.Println("Your consensus client is on the correct network.")
fmt.Println()

// Get node status
// Report progress before checking contracts. The deposit-contract endpoint
// requires a synced EC and can wait behind the daemon's background sync loop.
status, err := rp.NodeSync()
if err != nil {
return err
}

// Print EC status
printSyncProgress(&status.EcStatus, "execution")

// Print CC status
printSyncProgress(&status.BcStatus, "consensus")
fmt.Println()

if cfg.HasRocketPoolContracts() {
if !hasSyncedExecutionClient(&status.EcStatus) {
color.YellowPrintln("The deposit contract network check is unavailable until an execution client is synced and ready.")
return nil
}
// Make sure ETH2 is on the correct chain using Rocket Pool's deposit contract.
depositContractInfo, err := rp.DepositContractInfo()
if err != nil {
return err
}
if !depositContractInfo.SufficientSync {
color.YellowPrintln("Your execution client hasn't synced enough to determine if your execution and consensus clients are on the same network.")
color.YellowPrintln("To run this safety check, try again later when the execution client has made more sync progress.")
fmt.Println()
return nil
}
if depositContractInfo.RPNetwork != depositContractInfo.BeaconNetwork ||
depositContractInfo.RPDepositContract != depositContractInfo.BeaconDepositContract {
cliutils.PrintDepositMismatchError(
depositContractInfo.RPNetwork,
depositContractInfo.BeaconNetwork,
depositContractInfo.RPDepositContract,
depositContractInfo.BeaconDepositContract)
return nil
}
fmt.Println("Your consensus client is on the correct network.")
} else {
fmt.Println("Rocket Pool contracts are not configured; skipping the deposit contract network check.")
}
fmt.Println()

// Return
return nil

}

func hasSyncedExecutionClient(status *api.ClientManagerStatus) bool {
ready := func(client api.ClientStatus) bool {
return client.IsWorking && client.IsSynced && client.Error == ""
}
return ready(status.PrimaryClientStatus) || (status.FallbackEnabled && ready(status.FallbackClientStatus))
}
5 changes: 5 additions & 0 deletions rocketpool-cli/service/config/choice-wizard-step.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type choiceWizardStep struct {
wiz *wizard
modal *choiceModalLayout
showImpl func(*choiceModalLayout)
rebuild func() *choiceWizardStep
}

func newChoiceStep(wiz *wizard, currentStep int, totalSteps int, helperText string, names []string, descriptions []string, width int, title string, direction int, showImpl func(*choiceModalLayout), done func(int, string), back func(), pageID string) *choiceWizardStep {
Expand Down Expand Up @@ -40,5 +41,9 @@ func newChoiceStep(wiz *wizard, currentStep int, totalSteps int, helperText stri
}

func (step *choiceWizardStep) show() {
// Client choices depend on the network selected since the wizard was built.
if step.rebuild != nil {
*step = *step.rebuild()
}
step.showImpl(step.modal)
}
12 changes: 6 additions & 6 deletions rocketpool-cli/service/config/config-form.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,20 @@ func createParameterizedStringField(param *cfgtypes.Parameter) *parameterizedFor
func createParameterizedDropDown(param *cfgtypes.Parameter, descriptionBox *tview.TextView) *parameterizedFormItem {
// Create the list of options
options := []string{}
descriptions := []string{}
values := []interface{}{}
for _, option := range param.Options {
options = append(options, option.Name)
descriptions = append(descriptions, option.Description)
values = append(values, option.Value)
}
item := NewDropDown().
SetLabel(param.Name).
SetOptions(options, func(text string, index int) {
param.Value = values[index]
if index >= 0 && index < len(param.Options) {
param.Value = param.Options[index].Value
}
}).
SetChangedFunc(func(index int, mainText, secondaryText string, shortcut rune) {
descriptionBox.SetText(descriptions[index])
if index >= 0 && index < len(param.Options) {
descriptionBox.SetText(param.Options[index].Description)
}
})
item.SetTextOptions(" ", " ", "", "", "")
list := item.GetList()
Expand Down
4 changes: 2 additions & 2 deletions rocketpool-cli/service/config/settings-home.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,11 @@ func (home *settingsHome) refresh() {
}

if home.ecPage != nil {
home.ecPage.layout.refresh()
home.ecPage.handleLayoutChanged()
}

if home.ccPage != nil {
home.ccPage.layout.refresh()
home.ccPage.handleLayoutChanged()
}

if home.fallbackPage != nil {
Expand Down
16 changes: 16 additions & 0 deletions rocketpool-cli/service/config/standard-layout.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,22 @@ func (layout *standardLayout) refresh() {
formItem.(*tview.InputField).SetText(fmt.Sprint(param.Value))

case cfgtypes.ParameterType_Choice:
dropDown := formItem.(*DropDown)
optionsChanged := len(dropDown.options) != len(param.Options)
for i, option := range param.Options {
if i >= len(dropDown.options) || dropDown.options[i].Text != option.Name {
optionsChanged = true
break
}
}
if optionsChanged {
names := make([]string, len(param.Options))
for i, option := range param.Options {
names[i] = option.Name
}
dropDown.SetOptions(names, dropDown.selected)
dropDown.currentOption = -1
}
for i := 0; i < len(param.Options); i++ {
if param.Options[i].Value == param.Value {
formItem.(*DropDown).SetCurrentOption(i)
Expand Down
4 changes: 3 additions & 1 deletion rocketpool-cli/service/config/step-external-cc.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func createExternalCcStep(wiz *wizard, currentStep int, totalSteps int) *choiceW
wiz.modeModal.show()
}

return newChoiceStep(
step := newChoiceStep(
wiz,
currentStep,
totalSteps,
Expand All @@ -63,5 +63,7 @@ func createExternalCcStep(wiz *wizard, currentStep int, totalSteps int) *choiceW
back,
"step-external-cc",
)
step.rebuild = func() *choiceWizardStep { return createExternalCcStep(wiz, currentStep, totalSteps) }
return step

}
4 changes: 3 additions & 1 deletion rocketpool-cli/service/config/step-local-cc.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func createLocalCcStep(wiz *wizard, currentStep int, totalSteps int) *choiceWiza
wiz.modeModal.show()
}

return newChoiceStep(
step := newChoiceStep(
wiz,
currentStep,
totalSteps,
Expand All @@ -101,6 +101,8 @@ func createLocalCcStep(wiz *wizard, currentStep int, totalSteps int) *choiceWiza
back,
localCcStepID,
)
step.rebuild = func() *choiceWizardStep { return createLocalCcStep(wiz, currentStep, totalSteps) }
return step

}

Expand Down
4 changes: 3 additions & 1 deletion rocketpool-cli/service/config/step-local-ec.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func createLocalEcStep(wiz *wizard, currentStep int, totalSteps int) *choiceWiza
wiz.modeModal.show()
}

return newChoiceStep(
step := newChoiceStep(
wiz,
currentStep,
totalSteps,
Expand All @@ -94,6 +94,8 @@ func createLocalEcStep(wiz *wizard, currentStep int, totalSteps int) *choiceWiza
back,
"step-ec-local",
)
step.rebuild = func() *choiceWizardStep { return createLocalEcStep(wiz, currentStep, totalSteps) }
return step
}

// Get a random execution client
Expand Down
4 changes: 3 additions & 1 deletion rocketpool-cli/service/config/step-native-cc.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func createNativeCcStep(wiz *wizard, currentStep int, totalSteps int) *choiceWiz
wiz.nativeEcModal.show()
}

return newChoiceStep(
step := newChoiceStep(
wiz,
currentStep,
totalSteps,
Expand All @@ -56,5 +56,7 @@ func createNativeCcStep(wiz *wizard, currentStep int, totalSteps int) *choiceWiz
back,
"step-native-cc",
)
step.rebuild = func() *choiceWizardStep { return createNativeCcStep(wiz, currentStep, totalSteps) }
return step

}
47 changes: 41 additions & 6 deletions rocketpool-cli/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,30 @@ func configureServiceHeadless(c *cli.Command) error {
if err != nil {
return err
}
if err := updateConfigFromCliArgs(c, cfg); err != nil {
return err
}
return rp.SaveConfig(cfg)
}

func updateConfigFromCliArgs(c *cli.Command, cfg *config.RocketPoolConfig) error {
// The selected network determines valid client choices and their defaults.
// Apply it before client arguments, independently of subconfig map order.
if c.IsSet("smartnode-network") {
network := cfgtypes.Network(c.String("smartnode-network"))
if cfg.LoadedNetworks().GetNetwork(network) == nil {
return fmt.Errorf("unknown network %q", network)
}
// Match the TUI: a checkpoint URL from the previous chain must not be
// kept. Flags are applied after this, so an explicit URL still wins.
changed := cfg.GetNetwork() != network
cfg.ChangeNetwork(network)
if changed {
if err := cfg.ConsensusCommon.CheckpointSyncProvider.SetToDefault(network); err != nil {
return err
}
}
}

// Root params
for _, param := range cfg.GetParameters() {
Expand All @@ -247,7 +271,7 @@ func configureServiceHeadless(c *cli.Command) error {
}
}

return rp.SaveConfig(cfg)
return cfg.ValidateNetworkClients()
}

// Configure the service
Expand Down Expand Up @@ -285,6 +309,10 @@ func configureService(configPath string, isNative, yes bool, composeFiles []stri
return fmt.Errorf("error saving config: %w", err)
}
fmt.Println("Your changes have been saved!")
if err := md.Config.ValidateNetworkForStart(); err != nil {
fmt.Println(err)
return nil
}

// Exit immediately if we're in native mode
if isNative {
Expand All @@ -295,16 +323,18 @@ func configureService(configPath string, isNative, yes bool, composeFiles []stri
// Handle network changes
prefix := fmt.Sprint(md.PreviousConfig.Smartnode.ProjectName.Value)
if md.ChangeNetworks {
// Remove the checkpoint sync provider
md.Config.ConsensusCommon.CheckpointSyncProvider.Value = ""
// Use a checkpoint provider for the new network, never the old chain.
if err := md.Config.ConsensusCommon.CheckpointSyncProvider.SetToDefault(md.Config.GetNetwork()); err != nil {
return err
}
err = rp.SaveConfig(md.Config)
if err != nil {
return fmt.Errorf("error saving config: %w", err)
}

color.YellowPrintln("WARNING: You have requested to change networks.")
fmt.Println()
color.YellowPrintln("All of your existing chain data, your node wallet, and your validator keys will be removed. If you had a Checkpoint Sync URL provided for your Consensus client, it will be removed and you will need to specify a different one that supports the new network.")
color.YellowPrintln("All of your existing chain data, your node wallet, and your validator keys will be removed. Your Checkpoint Sync URL will be reset to the new network's default.")
fmt.Println()
color.YellowPrintln("Please confirm you have backed up everything you want to keep, because it will be deleted if you answer `y` to the prompt below.")
fmt.Println()
Expand Down Expand Up @@ -632,6 +662,9 @@ func startService(params startServiceParams) error {
if isNew {
return fmt.Errorf("No configuration detected. Please run `rocketpool service config` to set up your Smart Node before running it.")
}
if err := cfg.ValidateNetworkForStart(); err != nil {
return err
}

// Warn if IPv6 is enabled but no public IPv6 address is available
if cfg.IsIPv6Enabled() && cfg.GetExternalIpv6() == "" {
Expand Down Expand Up @@ -691,7 +724,9 @@ func startService(params startServiceParams) error {
return nil
}

if !params.ignoreSlashTimer {
if !cfg.HasRocketPoolContracts() {
fmt.Println("Rocket Pool contracts are not configured. Starting configured services; validator and watchtower services are disabled.")
} else if !params.ignoreSlashTimer {
// Do the client swap check
err := checkForValidatorChange(rp, cfg)
if err != nil {
Expand Down Expand Up @@ -745,7 +780,7 @@ func startService(params startServiceParams) error {
color.YellowPrintf("Couldn't check if you have Doppelganger Protection enabled: %s\n", err.Error())
color.YellowPrintln("If you do, your validator will miss up to 3 attestations when it starts.")
color.YellowPrintln("This is *intentional* and does not indicate a problem with your node.")
} else if doppelgangerEnabled {
} else if cfg.HasRocketPoolContracts() && doppelgangerEnabled {
color.YellowPrintln("NOTE: You currently have Doppelganger Protection enabled.")
color.YellowPrintln("Your validator will miss up to 3 attestations when it starts.")
color.YellowPrintln("This is *intentional* and does not indicate a problem with your node.")
Expand Down
6 changes: 1 addition & 5 deletions rocketpool/api/node/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"github.com/rocket-pool/smartnode/shared/services"
"github.com/rocket-pool/smartnode/shared/services/beacon"
"github.com/rocket-pool/smartnode/shared/types/api"
cfgtypes "github.com/rocket-pool/smartnode/shared/types/config"
)

func getStatus(c *cli.Command) (*api.NodeStatusResponse, error) {
Expand Down Expand Up @@ -66,9 +65,6 @@ func getStatus(c *cli.Command) (*api.NodeStatusResponse, error) {
if err != nil {
return nil, err
}
if reg == nil {
return nil, fmt.Errorf("Error getting the signer registry on network [%v].", cfg.Smartnode.Network.Value.(cfgtypes.Network))
}

// Response
response := api.NodeStatusResponse{}
Expand Down Expand Up @@ -288,7 +284,7 @@ func getStatus(c *cli.Command) (*api.NodeStatusResponse, error) {
return err
})

// Get RocketDash proposals and votes, but treat errors as non-fatal
// Get RocketDash proposals and votes when a signer registry is configured, but treat errors as non-fatal
if reg != nil {
wg.Go(func() error {
var err error
Expand Down
Loading
Loading