Best Gauge code snippet using execution.getParameters
rocket-pool-config.go
Source:rocket-pool-config.go
1package config2import (3 "fmt"4 "io/ioutil"5 "net/url"6 "os"7 "path/filepath"8 "reflect"9 "strconv"10 "github.com/alessio/shellescape"11 "github.com/pbnjay/memory"12 "github.com/rocket-pool/smartnode/shared"13 "github.com/rocket-pool/smartnode/shared/services/config/migration"14 "gopkg.in/yaml.v2"15)16// Constants17const (18 rootConfigName string = "root"19 ApiContainerName string = "api"20 Eth1ContainerName string = "eth1"21 Eth1FallbackContainerName string = "eth1-fallback"22 Eth2ContainerName string = "eth2"23 ExporterContainerName string = "exporter"24 GrafanaContainerName string = "grafana"25 NodeContainerName string = "node"26 PrometheusContainerName string = "prometheus"27 ValidatorContainerName string = "validator"28 WatchtowerContainerName string = "watchtower"29)30// Defaults31const defaultBnMetricsPort uint16 = 910032const defaultVcMetricsPort uint16 = 910133const defaultNodeMetricsPort uint16 = 910234const defaultExporterMetricsPort uint16 = 910335const defaultWatchtowerMetricsPort uint16 = 910436const defaultEcMetricsPort uint16 = 910537// The master configuration struct38type RocketPoolConfig struct {39 Title string `yaml:"-"`40 Version string `yaml:"-"`41 RocketPoolDirectory string `yaml:"-"`42 IsNativeMode bool `yaml:"-"`43 // Execution client settings44 ExecutionClientMode Parameter `yaml:"executionClientMode"`45 ExecutionClient Parameter `yaml:"executionClient"`46 // Fallback execution client settings47 UseFallbackExecutionClient Parameter `yaml:"useFallbackExecutionClient,omitempty"`48 FallbackExecutionClientMode Parameter `yaml:"fallbackExecutionClientMode,omitempty"`49 FallbackExecutionClient Parameter `yaml:"fallbackExecutionClient,omitempty"`50 ReconnectDelay Parameter `yaml:"reconnectDelay,omitempty"`51 // Consensus client settings52 ConsensusClientMode Parameter `yaml:"consensusClientMode,omitempty"`53 ConsensusClient Parameter `yaml:"consensusClient,omitempty"`54 ExternalConsensusClient Parameter `yaml:"externalConsensusClient,omitempty"`55 // Metrics settings56 EnableMetrics Parameter `yaml:"enableMetrics,omitempty"`57 EcMetricsPort Parameter `yaml:"ecMetricsPort,omitempty"`58 BnMetricsPort Parameter `yaml:"bnMetricsPort,omitempty"`59 VcMetricsPort Parameter `yaml:"vcMetricsPort,omitempty"`60 NodeMetricsPort Parameter `yaml:"nodeMetricsPort,omitempty"`61 ExporterMetricsPort Parameter `yaml:"exporterMetricsPort,omitempty"`62 WatchtowerMetricsPort Parameter `yaml:"watchtowerMetricsPort,omitempty"`63 EnableBitflyNodeMetrics Parameter `yaml:"enableBitflyNodeMetrics,omitempty"`64 // The Smartnode configuration65 Smartnode *SmartnodeConfig `yaml:"smartnode"`66 // Execution client configurations67 ExecutionCommon *ExecutionCommonConfig `yaml:"executionCommon,omitempty"`68 Geth *GethConfig `yaml:"geth,omitempty"`69 Nethermind *NethermindConfig `yaml:"nethermind,omitempty"`70 Besu *BesuConfig `yaml:"besu,omitempty"`71 Infura *InfuraConfig `yaml:"infura,omitempty"`72 Pocket *PocketConfig `yaml:"pocket,omitempty"`73 ExternalExecution *ExternalExecutionConfig `yaml:"externalExecution,omitempty"`74 // Fallback Execution client configurations75 FallbackExecutionCommon *ExecutionCommonConfig `yaml:"fallbackExecutionCommon,omitempty"`76 FallbackInfura *InfuraConfig `yaml:"fallbackInfura,omitempty"`77 FallbackPocket *PocketConfig `yaml:"fallbackPocket,omitempty"`78 FallbackExternalExecution *ExternalExecutionConfig `yaml:"fallbackExternalExecution,omitempty"`79 // Consensus client configurations80 ConsensusCommon *ConsensusCommonConfig `yaml:"consensusCommon,omitempty"`81 Lighthouse *LighthouseConfig `yaml:"lighthouse,omitempty"`82 Nimbus *NimbusConfig `yaml:"nimbus,omitempty"`83 Prysm *PrysmConfig `yaml:"prysm,omitempty"`84 Teku *TekuConfig `yaml:"teku,omitempty"`85 ExternalLighthouse *ExternalLighthouseConfig `yaml:"externalLighthouse,omitempty"`86 ExternalPrysm *ExternalPrysmConfig `yaml:"externalPrysm,omitempty"`87 ExternalTeku *ExternalTekuConfig `yaml:"externalTeku,omitempty"`88 // Metrics89 Grafana *GrafanaConfig `yaml:"grafana,omitempty"`90 Prometheus *PrometheusConfig `yaml:"prometheus,omitempty"`91 Exporter *ExporterConfig `yaml:"exporter,omitempty"`92 BitflyNodeMetrics *BitflyNodeMetricsConfig `yaml:"bitflyNodeMetrics,omitempty"`93 // Native mode94 Native *NativeConfig `yaml:"native,omitempty"`95}96// Load configuration settings from a file97func LoadFromFile(path string) (*RocketPoolConfig, error) {98 // Return nil if the file doesn't exist99 _, err := os.Stat(path)100 if os.IsNotExist(err) {101 return nil, nil102 }103 // Read the file104 configBytes, err := ioutil.ReadFile(path)105 if err != nil {106 return nil, fmt.Errorf("could not read Rocket Pool settings file at %s: %w", shellescape.Quote(path), err)107 }108 // Attempt to parse it out into a settings map109 var settings map[string]map[string]string110 if err := yaml.Unmarshal(configBytes, &settings); err != nil {111 return nil, fmt.Errorf("could not parse settings file: %w", err)112 }113 // Deserialize it into a config object114 cfg := NewRocketPoolConfig(filepath.Dir(path), false)115 err = cfg.Deserialize(settings)116 if err != nil {117 return nil, fmt.Errorf("could not deserialize settings file: %w", err)118 }119 return cfg, nil120}121// Creates a new Rocket Pool configuration instance122func NewRocketPoolConfig(rpDir string, isNativeMode bool) *RocketPoolConfig {123 config := &RocketPoolConfig{124 Title: "Top-level Settings",125 RocketPoolDirectory: rpDir,126 IsNativeMode: isNativeMode,127 ExecutionClientMode: Parameter{128 ID: "executionClientMode",129 Name: "Execution Client Mode",130 Description: "Choose which mode to use for your Execution client - locally managed (Docker Mode), or externally managed (Hybrid Mode).",131 Type: ParameterType_Choice,132 Default: map[Network]interface{}{},133 AffectsContainers: []ContainerID{ContainerID_Api, ContainerID_Eth1, ContainerID_Eth2, ContainerID_Node, ContainerID_Watchtower},134 EnvironmentVariables: []string{},135 CanBeBlank: false,136 OverwriteOnUpgrade: false,137 Options: []ParameterOption{{138 Name: "Locally Managed",139 Description: "Allow the Smartnode to manage an Execution client for you (Docker Mode)",140 Value: Mode_Local,141 }, {142 Name: "Externally Managed",143 Description: "Use an existing Execution client that you manage on your own (Hybrid Mode)",144 Value: Mode_External,145 }},146 },147 ExecutionClient: Parameter{148 ID: "executionClient",149 Name: "Execution Client",150 Description: "Select which Execution client you would like to run.",151 Type: ParameterType_Choice,152 Default: map[Network]interface{}{Network_All: ExecutionClient_Geth},153 AffectsContainers: []ContainerID{ContainerID_Eth1},154 EnvironmentVariables: []string{},155 CanBeBlank: false,156 OverwriteOnUpgrade: false,157 Options: []ParameterOption{{158 Name: "Geth",159 Description: "Geth is one of the three original implementations of the Ethereum protocol. It is written in Go, fully open source and licensed under the GNU LGPL v3.",160 Value: ExecutionClient_Geth,161 }, {162 Name: "Nethermind",163 Description: getAugmentedEcDescription(ExecutionClient_Nethermind, "Nethermind is a high-performance full Ethereum protocol client with very fast sync speeds. Nethermind is built with proven industrial technologies such as .NET 6 and the Kestrel web server. It is fully open source."),164 Value: ExecutionClient_Nethermind,165 }, {166 Name: "Besu",167 Description: getAugmentedEcDescription(ExecutionClient_Besu, "Hyperledger Besu is a robust full Ethereum protocol client. It uses a novel system called \"Bonsai Trees\" to store its chain data efficiently, which allows it to access block states from the past and does not require pruning. Besu is fully open source and written in Java."),168 Value: ExecutionClient_Besu,169 }, {170 Name: "*Infura",171 Description: "Use infura.io as a light client for Eth 1.0. Not recommended for use in production.\n\n[orange]*WARNING: Infura is deprecated and will NOT BE COMPATIBLE with the upcoming Ethereum Merge. It will be removed in a future version of the Smartnode. We strongly recommend you choose a Full Execution client instead.",172 Value: ExecutionClient_Infura,173 }, {174 Name: "*Pocket",175 Description: "Use Pocket Network as a decentralized light client for Eth 1.0. Suitable for use in production.\n\n[orange]*WARNING: Pocket is deprecated and will NOT BE COMPATIBLE with the upcoming Ethereum Merge. It will be removed in a future version of the Smartnode. We strongly recommend you choose a Full Execution client instead.",176 Value: ExecutionClient_Pocket,177 }},178 },179 UseFallbackExecutionClient: Parameter{180 ID: "useFallbackExecutionClient",181 Name: "Use Fallback Execution Client",182 Description: "Enable this if you would like to specify a fallback Execution client, which will temporarily be used by the Smartnode and your Consensus client if your primary Execution client ever goes offline.",183 Type: ParameterType_Bool,184 Default: map[Network]interface{}{Network_All: false},185 AffectsContainers: []ContainerID{ContainerID_Api, ContainerID_Eth1Fallback, ContainerID_Eth2, ContainerID_Node, ContainerID_Watchtower},186 EnvironmentVariables: []string{},187 CanBeBlank: false,188 OverwriteOnUpgrade: false,189 },190 FallbackExecutionClientMode: Parameter{191 ID: "fallbackExecutionClientMode",192 Name: "Fallback Execution Client Mode",193 Description: "Choose which mode to use for your fallback Execution client - locally managed (Docker Mode), or externally managed (Hybrid Mode).",194 Type: ParameterType_Choice,195 Default: map[Network]interface{}{Network_All: nil},196 AffectsContainers: []ContainerID{ContainerID_Api, ContainerID_Eth1Fallback, ContainerID_Eth2, ContainerID_Node, ContainerID_Watchtower},197 EnvironmentVariables: []string{},198 CanBeBlank: false,199 OverwriteOnUpgrade: false,200 Options: []ParameterOption{{201 Name: "Locally Managed",202 Description: "Allow the Smartnode to manage a fallback Execution client for you (Docker Mode)",203 Value: Mode_Local,204 }, {205 Name: "Externally Managed",206 Description: "Use an existing fallback Execution client that you manage on your own (Hybrid Mode)",207 Value: Mode_External,208 }},209 },210 FallbackExecutionClient: Parameter{211 ID: "fallbackExecutionClient",212 Name: "Fallback Execution Client",213 Description: "Select which fallback Execution client you would like to run.",214 Type: ParameterType_Choice,215 Default: map[Network]interface{}{Network_All: ExecutionClient_Pocket},216 AffectsContainers: []ContainerID{ContainerID_Eth1Fallback},217 EnvironmentVariables: []string{},218 CanBeBlank: false,219 OverwriteOnUpgrade: false,220 Options: []ParameterOption{{221 Name: "*Infura",222 Description: "Use infura.io as a light client for Eth 1.0. Not recommended for use in production.\n\n[orange]*WARNING: Infura is deprecated and will NOT BE COMPATIBLE with the upcoming Ethereum Merge. It will be removed in a future version of the Smartnode. If you want to use a fallback Execution client, you will need to use an Externally Managed one that you control on a separate machine.",223 Value: ExecutionClient_Infura,224 }, {225 Name: "*Pocket",226 Description: "Use Pocket Network as a decentralized light client for Eth 1.0. Suitable for use in production.\n\n[orange]*WARNING: Pocket is deprecated and will NOT BE COMPATIBLE with the upcoming Ethereum Merge. It will be removed in a future version of the Smartnode. If you want to use a fallback Execution client, you will need to use an Externally Managed one that you control on a separate machine.",227 Value: ExecutionClient_Pocket,228 }},229 },230 ReconnectDelay: Parameter{231 ID: "reconnectDelay",232 Name: "Reconnect Delay",233 Description: "The delay to wait after the primary Execution client fails before trying to reconnect to it. An example format is \"10h20m30s\" - this would make it 10 hours, 20 minutes, and 30 seconds.",234 Type: ParameterType_String,235 Default: map[Network]interface{}{Network_All: "60s"},236 AffectsContainers: []ContainerID{ContainerID_Api, ContainerID_Node, ContainerID_Watchtower},237 EnvironmentVariables: []string{},238 CanBeBlank: false,239 OverwriteOnUpgrade: false,240 },241 ConsensusClientMode: Parameter{242 ID: "consensusClientMode",243 Name: "Consensus Client Mode",244 Description: "Choose which mode to use for your Consensus client - locally managed (Docker Mode), or externally managed (Hybrid Mode).",245 Type: ParameterType_Choice,246 Default: map[Network]interface{}{Network_All: Mode_Local},247 AffectsContainers: []ContainerID{ContainerID_Api, ContainerID_Eth2, ContainerID_Node, ContainerID_Prometheus, ContainerID_Validator, ContainerID_Watchtower},248 EnvironmentVariables: []string{},249 CanBeBlank: false,250 OverwriteOnUpgrade: false,251 Options: []ParameterOption{{252 Name: "Locally Managed",253 Description: "Allow the Smartnode to manage a Consensus client for you (Docker Mode)",254 Value: Mode_Local,255 }, {256 Name: "Externally Managed",257 Description: "Use an existing Consensus client that you manage on your own (Hybrid Mode)",258 Value: Mode_External,259 }},260 },261 ConsensusClient: Parameter{262 ID: "consensusClient",263 Name: "Consensus Client",264 Description: "Select which Consensus client you would like to use.",265 Type: ParameterType_Choice,266 Default: map[Network]interface{}{Network_All: ConsensusClient_Nimbus},267 AffectsContainers: []ContainerID{ContainerID_Api, ContainerID_Node, ContainerID_Watchtower, ContainerID_Eth2, ContainerID_Validator},268 EnvironmentVariables: []string{},269 CanBeBlank: false,270 OverwriteOnUpgrade: false,271 Options: []ParameterOption{{272 Name: "Lighthouse",273 Description: "Lighthouse is a Consensus client with a heavy focus on speed and security. The team behind it, Sigma Prime, is an information security and software engineering firm who have funded Lighthouse along with the Ethereum Foundation, Consensys, and private individuals. Lighthouse is built in Rust and offered under an Apache 2.0 License.",274 Value: ConsensusClient_Lighthouse,275 }, {276 Name: "Nimbus",277 Description: "Nimbus is a Consensus client implementation that strives to be as lightweight as possible in terms of resources used. This allows it to perform well on embedded systems, resource-restricted devices -- including Raspberry Pis and mobile devices -- and multi-purpose servers.",278 Value: ConsensusClient_Nimbus,279 }, {280 Name: "Prysm",281 Description: "Prysm is a Go implementation of Ethereum Consensus protocol with a focus on usability, security, and reliability. Prysm is developed by Prysmatic Labs, a company with the sole focus on the development of their client. Prysm is written in Go and released under a GPL-3.0 license.",282 Value: ConsensusClient_Prysm,283 }, {284 Name: "Teku",285 Description: "PegaSys Teku (formerly known as Artemis) is a Java-based Ethereum 2.0 client designed & built to meet institutional needs and security requirements. PegaSys is an arm of ConsenSys dedicated to building enterprise-ready clients and tools for interacting with the core Ethereum platform. Teku is Apache 2 licensed and written in Java, a language notable for its maturity & ubiquity.",286 Value: ConsensusClient_Teku,287 }},288 },289 ExternalConsensusClient: Parameter{290 ID: "externalConsensusClient",291 Name: "Consensus Client",292 Description: "Select which Consensus client your externally managed client is.",293 Type: ParameterType_Choice,294 Default: map[Network]interface{}{Network_All: ConsensusClient_Lighthouse},295 AffectsContainers: []ContainerID{ContainerID_Api, ContainerID_Node, ContainerID_Watchtower, ContainerID_Eth2, ContainerID_Validator},296 EnvironmentVariables: []string{},297 CanBeBlank: false,298 OverwriteOnUpgrade: false,299 Options: []ParameterOption{{300 Name: "Lighthouse",301 Description: "Select this if you will use Lighthouse as your Consensus client.",302 Value: ConsensusClient_Lighthouse,303 }, {304 Name: "Prysm",305 Description: "Select this if you will use Prysm as your Consensus client.",306 Value: ConsensusClient_Prysm,307 }, {308 Name: "Teku",309 Description: "Select this if you will use Teku as your Consensus client.",310 Value: ConsensusClient_Teku,311 }},312 },313 EnableMetrics: Parameter{314 ID: "enableMetrics",315 Name: "Enable Metrics",316 Description: "Enable the Smartnode's performance and status metrics system. This will provide you with the node operator's Grafana dashboard.",317 Type: ParameterType_Bool,318 Default: map[Network]interface{}{Network_All: true},319 AffectsContainers: []ContainerID{ContainerID_Node, ContainerID_Watchtower, ContainerID_Eth2, ContainerID_Grafana, ContainerID_Prometheus, ContainerID_Exporter},320 EnvironmentVariables: []string{"ENABLE_METRICS"},321 CanBeBlank: false,322 OverwriteOnUpgrade: false,323 },324 EnableBitflyNodeMetrics: Parameter{325 ID: "enableBitflyNodeMetrics",326 Name: "Enable Beaconcha.in Node Metrics",327 Description: "Enable the Beaconcha.in node metrics integration. This will allow you to track your node's metrics from your phone using the Beaconcha.in App.\n\nFor more information on setting up an account and the app, please visit https://beaconcha.in/mobile.",328 Type: ParameterType_Bool,329 Default: map[Network]interface{}{Network_All: false},330 AffectsContainers: []ContainerID{ContainerID_Validator, ContainerID_Eth2},331 EnvironmentVariables: []string{"ENABLE_BITFLY_NODE_METRICS"},332 CanBeBlank: false,333 OverwriteOnUpgrade: false,334 },335 EcMetricsPort: Parameter{336 ID: "ecMetricsPort",337 Name: "Execution Client Metrics Port",338 Description: "The port your Execution client should expose its metrics on.",339 Type: ParameterType_Uint16,340 Default: map[Network]interface{}{Network_All: defaultEcMetricsPort},341 AffectsContainers: []ContainerID{ContainerID_Eth1, ContainerID_Prometheus},342 EnvironmentVariables: []string{"EC_METRICS_PORT"},343 CanBeBlank: false,344 OverwriteOnUpgrade: false,345 },346 BnMetricsPort: Parameter{347 ID: "bnMetricsPort",348 Name: "Beacon Node Metrics Port",349 Description: "The port your Consensus client's Beacon Node should expose its metrics on.",350 Type: ParameterType_Uint16,351 Default: map[Network]interface{}{Network_All: defaultBnMetricsPort},352 AffectsContainers: []ContainerID{ContainerID_Eth2, ContainerID_Prometheus},353 EnvironmentVariables: []string{"BN_METRICS_PORT"},354 CanBeBlank: false,355 OverwriteOnUpgrade: false,356 },357 VcMetricsPort: Parameter{358 ID: "vcMetricsPort",359 Name: "Validator Client Metrics Port",360 Description: "The port your validator client should expose its metrics on.",361 Type: ParameterType_Uint16,362 Default: map[Network]interface{}{Network_All: defaultVcMetricsPort},363 AffectsContainers: []ContainerID{ContainerID_Validator, ContainerID_Prometheus},364 EnvironmentVariables: []string{"VC_METRICS_PORT"},365 CanBeBlank: false,366 OverwriteOnUpgrade: false,367 },368 NodeMetricsPort: Parameter{369 ID: "nodeMetricsPort",370 Name: "Node Metrics Port",371 Description: "The port your Node container should expose its metrics on.",372 Type: ParameterType_Uint16,373 Default: map[Network]interface{}{Network_All: defaultNodeMetricsPort},374 AffectsContainers: []ContainerID{ContainerID_Node, ContainerID_Prometheus},375 EnvironmentVariables: []string{"NODE_METRICS_PORT"},376 CanBeBlank: false,377 OverwriteOnUpgrade: false,378 },379 ExporterMetricsPort: Parameter{380 ID: "exporterMetricsPort",381 Name: "Exporter Metrics Port",382 Description: "The port that Prometheus's Node Exporter should expose its metrics on.",383 Type: ParameterType_Uint16,384 Default: map[Network]interface{}{Network_All: defaultExporterMetricsPort},385 AffectsContainers: []ContainerID{ContainerID_Exporter, ContainerID_Prometheus},386 EnvironmentVariables: []string{"EXPORTER_METRICS_PORT"},387 CanBeBlank: false,388 OverwriteOnUpgrade: false,389 },390 WatchtowerMetricsPort: Parameter{391 ID: "watchtowerMetricsPort",392 Name: "Watchtower Metrics Port",393 Description: "The port your Watchtower container should expose its metrics on.\nThis is only relevant for Oracle Nodes.",394 Type: ParameterType_Uint16,395 Default: map[Network]interface{}{Network_All: defaultWatchtowerMetricsPort},396 AffectsContainers: []ContainerID{ContainerID_Watchtower, ContainerID_Prometheus},397 EnvironmentVariables: []string{"WATCHTOWER_METRICS_PORT"},398 CanBeBlank: false,399 OverwriteOnUpgrade: false,400 },401 }402 // Set the defaults for choices403 config.ExecutionClientMode.Default[Network_All] = config.ExecutionClientMode.Options[0].Value404 config.FallbackExecutionClientMode.Default[Network_All] = config.FallbackExecutionClientMode.Options[0].Value405 config.ConsensusClientMode.Default[Network_All] = config.ConsensusClientMode.Options[0].Value406 config.Smartnode = NewSmartnodeConfig(config)407 config.ExecutionCommon = NewExecutionCommonConfig(config, false)408 config.Geth = NewGethConfig(config, false)409 config.Nethermind = NewNethermindConfig(config, false)410 config.Besu = NewBesuConfig(config, false)411 config.Infura = NewInfuraConfig(config, false)412 config.Pocket = NewPocketConfig(config, false)413 config.ExternalExecution = NewExternalExecutionConfig(config, false)414 config.FallbackExecutionCommon = NewExecutionCommonConfig(config, true)415 config.FallbackInfura = NewInfuraConfig(config, true)416 config.FallbackPocket = NewPocketConfig(config, true)417 config.FallbackExternalExecution = NewExternalExecutionConfig(config, true)418 config.ConsensusCommon = NewConsensusCommonConfig(config)419 config.Lighthouse = NewLighthouseConfig(config)420 config.Nimbus = NewNimbusConfig(config)421 config.Prysm = NewPrysmConfig(config)422 config.Teku = NewTekuConfig(config)423 config.ExternalLighthouse = NewExternalLighthouseConfig(config)424 config.ExternalPrysm = NewExternalPrysmConfig(config)425 config.ExternalTeku = NewExternalTekuConfig(config)426 config.Grafana = NewGrafanaConfig(config)427 config.Prometheus = NewPrometheusConfig(config)428 config.Exporter = NewExporterConfig(config)429 config.BitflyNodeMetrics = NewBitflyNodeMetricsConfig(config)430 config.Native = NewNativeConfig(config)431 // Apply the default values for mainnet432 config.Smartnode.Network.Value = config.Smartnode.Network.Options[0].Value433 config.applyAllDefaults()434 return config435}436// Get a more verbose client description, including warnings437func getAugmentedEcDescription(client ExecutionClient, originalDescription string) string {438 switch client {439 case ExecutionClient_Besu:440 totalMemoryGB := memory.TotalMemory() / 1024 / 1024 / 1024441 if totalMemoryGB < 9 {442 return fmt.Sprintf("%s\n\n[red]WARNING: Besu currently requires over 8 GB of RAM to run smoothly. We do not recommend it for your system. This may be improved in a future release.", originalDescription)443 }444 case ExecutionClient_Nethermind:445 totalMemoryGB := memory.TotalMemory() / 1024 / 1024 / 1024446 if totalMemoryGB < 9 {447 return fmt.Sprintf("%s\n\n[red]WARNING: Nethermind currently requires over 8 GB of RAM to run smoothly. We do not recommend it for your system. This may be improved in a future release.", originalDescription)448 }449 }450 return originalDescription451}452// Create a copy of this configuration.453func (config *RocketPoolConfig) CreateCopy() *RocketPoolConfig {454 newConfig := NewRocketPoolConfig(config.RocketPoolDirectory, config.IsNativeMode)455 newParams := newConfig.GetParameters()456 for i, param := range config.GetParameters() {457 newParams[i].Value = param.Value458 }459 newSubconfigs := newConfig.GetSubconfigs()460 for name, subConfig := range config.GetSubconfigs() {461 newParams := newSubconfigs[name].GetParameters()462 for i, param := range subConfig.GetParameters() {463 newParams[i].Value = param.Value464 }465 }466 return newConfig467}468// Get the parameters for this config469func (config *RocketPoolConfig) GetParameters() []*Parameter {470 return []*Parameter{471 &config.ExecutionClientMode,472 &config.ExecutionClient,473 &config.UseFallbackExecutionClient,474 &config.FallbackExecutionClientMode,475 &config.FallbackExecutionClient,476 &config.ReconnectDelay,477 &config.ConsensusClientMode,478 &config.ConsensusClient,479 &config.ExternalConsensusClient,480 &config.EnableMetrics,481 &config.EnableBitflyNodeMetrics,482 &config.EcMetricsPort,483 &config.BnMetricsPort,484 &config.VcMetricsPort,485 &config.NodeMetricsPort,486 &config.ExporterMetricsPort,487 &config.WatchtowerMetricsPort,488 }489}490// Get the subconfigurations for this config491func (config *RocketPoolConfig) GetSubconfigs() map[string]Config {492 return map[string]Config{493 "smartnode": config.Smartnode,494 "executionCommon": config.ExecutionCommon,495 "geth": config.Geth,496 "nethermind": config.Nethermind,497 "besu": config.Besu,498 "infura": config.Infura,499 "pocket": config.Pocket,500 "externalExecution": config.ExternalExecution,501 "fallbackExecutionCommon": config.FallbackExecutionCommon,502 "fallbackInfura": config.FallbackInfura,503 "fallbackPocket": config.FallbackPocket,504 "fallbackExternalExecution": config.FallbackExternalExecution,505 "consensusCommon": config.ConsensusCommon,506 "lighthouse": config.Lighthouse,507 "nimbus": config.Nimbus,508 "prysm": config.Prysm,509 "teku": config.Teku,510 "externalLighthouse": config.ExternalLighthouse,511 "externalPrysm": config.ExternalPrysm,512 "externalTeku": config.ExternalTeku,513 "grafana": config.Grafana,514 "prometheus": config.Prometheus,515 "exporter": config.Exporter,516 "bitflyNodeMetrics": config.BitflyNodeMetrics,517 "native": config.Native,518 }519}520// Handle a network change on all of the parameters521func (config *RocketPoolConfig) ChangeNetwork(newNetwork Network) {522 // Get the current network523 oldNetwork, ok := config.Smartnode.Network.Value.(Network)524 if !ok {525 oldNetwork = Network_Unknown526 }527 if oldNetwork == newNetwork {528 return529 }530 config.Smartnode.Network.Value = newNetwork531 // Update the master parameters532 rootParams := config.GetParameters()533 for _, param := range rootParams {534 param.changeNetwork(oldNetwork, newNetwork)535 }536 // Update all of the child config objects537 subconfigs := config.GetSubconfigs()538 for _, subconfig := range subconfigs {539 for _, param := range subconfig.GetParameters() {540 param.changeNetwork(oldNetwork, newNetwork)541 }542 }543}544// Get the Consensus clients incompatible with the config's EC and fallback EC selection545func (config *RocketPoolConfig) GetIncompatibleConsensusClients() ([]ParameterOption, []ParameterOption) {546 // Get the compatible clients based on the EC choice547 var compatibleConsensusClients []ConsensusClient548 if config.ExecutionClientMode.Value == Mode_Local {549 executionClient := config.ExecutionClient.Value.(ExecutionClient)550 switch executionClient {551 case ExecutionClient_Geth:552 compatibleConsensusClients = config.Geth.CompatibleConsensusClients553 case ExecutionClient_Nethermind:554 compatibleConsensusClients = config.Nethermind.CompatibleConsensusClients555 case ExecutionClient_Besu:556 compatibleConsensusClients = config.Besu.CompatibleConsensusClients557 case ExecutionClient_Infura:558 compatibleConsensusClients = config.Infura.CompatibleConsensusClients559 case ExecutionClient_Pocket:560 compatibleConsensusClients = config.Pocket.CompatibleConsensusClients561 }562 }563 // Get the compatible clients based on the fallback EC choice564 var fallbackCompatibleConsensusClients []ConsensusClient565 if config.UseFallbackExecutionClient.Value == true && config.FallbackExecutionClientMode.Value == Mode_Local {566 fallbackExecutionClient := config.FallbackExecutionClient.Value.(ExecutionClient)567 switch fallbackExecutionClient {568 case ExecutionClient_Infura:569 fallbackCompatibleConsensusClients = config.FallbackInfura.CompatibleConsensusClients570 case ExecutionClient_Pocket:571 fallbackCompatibleConsensusClients = config.FallbackPocket.CompatibleConsensusClients572 }573 }574 // Sort every consensus client into good and bad lists575 var badClients []ParameterOption576 var badFallbackClients []ParameterOption577 var consensusClientOptions []ParameterOption578 if config.ConsensusClientMode.Value.(Mode) == Mode_Local {579 consensusClientOptions = config.ConsensusClient.Options580 } else {581 consensusClientOptions = config.ExternalConsensusClient.Options582 }583 for _, consensusClient := range consensusClientOptions {584 // Get the value for one of the consensus client options585 clientValue := consensusClient.Value.(ConsensusClient)586 // Check if it's in the list of clients compatible with the EC587 if len(compatibleConsensusClients) > 0 {588 isGood := false589 for _, compatibleWithEC := range compatibleConsensusClients {590 if compatibleWithEC == clientValue {591 isGood = true592 break593 }594 }595 // If it isn't, append it to the list of bad clients and move on596 if !isGood {597 badClients = append(badClients, consensusClient)598 continue599 }600 }601 // Check the fallback EC too602 if len(fallbackCompatibleConsensusClients) > 0 {603 isGood := false604 for _, compatibleWithFallbackEC := range fallbackCompatibleConsensusClients {605 if compatibleWithFallbackEC == clientValue {606 isGood = true607 break608 }609 }610 if !isGood {611 badFallbackClients = append(badFallbackClients, consensusClient)612 continue613 }614 }615 }616 return badClients, badFallbackClients617}618// Get the configuration for the selected client619func (config *RocketPoolConfig) GetSelectedConsensusClientConfig() (ConsensusConfig, error) {620 if config.IsNativeMode {621 return nil, fmt.Errorf("consensus config is not available in native mode")622 }623 mode := config.ConsensusClientMode.Value.(Mode)624 switch mode {625 case Mode_Local:626 client := config.ConsensusClient.Value.(ConsensusClient)627 switch client {628 case ConsensusClient_Lighthouse:629 return config.Lighthouse, nil630 case ConsensusClient_Nimbus:631 return config.Nimbus, nil632 case ConsensusClient_Prysm:633 return config.Prysm, nil634 case ConsensusClient_Teku:635 return config.Teku, nil636 default:637 return nil, fmt.Errorf("unknown consensus client [%v] selected", client)638 }639 case Mode_External:640 client := config.ExternalConsensusClient.Value.(ConsensusClient)641 switch client {642 case ConsensusClient_Lighthouse:643 return config.ExternalLighthouse, nil644 case ConsensusClient_Prysm:645 return config.ExternalPrysm, nil646 case ConsensusClient_Teku:647 return config.ExternalTeku, nil648 default:649 return nil, fmt.Errorf("unknown external consensus client [%v] selected", client)650 }651 default:652 return nil, fmt.Errorf("unknown consensus client mode [%v]", mode)653 }654}655// Check if doppelganger protection is enabled656func (config *RocketPoolConfig) IsDoppelgangerEnabled() (bool, error) {657 if config.IsNativeMode {658 return false, fmt.Errorf("consensus config is not available in native mode")659 }660 mode := config.ConsensusClientMode.Value.(Mode)661 switch mode {662 case Mode_Local:663 client := config.ConsensusClient.Value.(ConsensusClient)664 switch client {665 case ConsensusClient_Lighthouse:666 return config.ConsensusCommon.DoppelgangerDetection.Value.(bool), nil667 case ConsensusClient_Nimbus:668 return config.ConsensusCommon.DoppelgangerDetection.Value.(bool), nil669 case ConsensusClient_Prysm:670 return config.ConsensusCommon.DoppelgangerDetection.Value.(bool), nil671 case ConsensusClient_Teku:672 return false, nil673 default:674 return false, fmt.Errorf("unknown consensus client [%v] selected", client)675 }676 case Mode_External:677 client := config.ExternalConsensusClient.Value.(ConsensusClient)678 switch client {679 case ConsensusClient_Lighthouse:680 return config.ExternalLighthouse.DoppelgangerDetection.Value.(bool), nil681 case ConsensusClient_Prysm:682 return config.ExternalPrysm.DoppelgangerDetection.Value.(bool), nil683 case ConsensusClient_Teku:684 return false, nil685 default:686 return false, fmt.Errorf("unknown external consensus client [%v] selected", client)687 }688 default:689 return false, fmt.Errorf("unknown consensus client mode [%v]", mode)690 }691}692// Serializes the configuration into a map of maps, compatible with a settings file693func (config *RocketPoolConfig) Serialize() map[string]map[string]string {694 masterMap := map[string]map[string]string{}695 // Serialize root params696 rootParams := map[string]string{}697 for _, param := range config.GetParameters() {698 param.serialize(rootParams)699 }700 masterMap[rootConfigName] = rootParams701 masterMap[rootConfigName]["rpDir"] = config.RocketPoolDirectory702 masterMap[rootConfigName]["isNative"] = fmt.Sprint(config.IsNativeMode)703 masterMap[rootConfigName]["version"] = fmt.Sprintf("v%s", shared.RocketPoolVersion) // Update the version with the current Smartnode version704 // Serialize the subconfigs705 for name, subconfig := range config.GetSubconfigs() {706 subconfigParams := map[string]string{}707 for _, param := range subconfig.GetParameters() {708 param.serialize(subconfigParams)709 }710 masterMap[name] = subconfigParams711 }712 return masterMap713}714// Deserializes a settings file into this config715func (config *RocketPoolConfig) Deserialize(masterMap map[string]map[string]string) error {716 // Upgrade the config to the latest version717 err := migration.UpdateConfig(masterMap)718 if err != nil {719 return fmt.Errorf("error upgrading configuration to v%s: %w", shared.RocketPoolVersion, err)720 }721 // Get the network722 network := Network_Mainnet723 smartnodeConfig, exists := masterMap[config.Smartnode.Title]724 if exists {725 networkString, exists := smartnodeConfig[config.Smartnode.Network.ID]726 if exists {727 valueType := reflect.TypeOf(networkString)728 paramType := reflect.TypeOf(network)729 if !valueType.ConvertibleTo(paramType) {730 return fmt.Errorf("can't get default network: value type %s cannot be converted to parameter type %s", valueType.Name(), paramType.Name())731 } else {732 network = reflect.ValueOf(networkString).Convert(paramType).Interface().(Network)733 }734 }735 }736 // Deserialize root params737 rootParams := masterMap[rootConfigName]738 for _, param := range config.GetParameters() {739 // Note: if the root config doesn't exist, this will end up using the default values for all of its settings740 err := param.deserialize(rootParams, network)741 if err != nil {742 return fmt.Errorf("error deserializing root config: %w", err)743 }744 }745 config.RocketPoolDirectory = masterMap[rootConfigName]["rpDir"]746 config.IsNativeMode, err = strconv.ParseBool(masterMap[rootConfigName]["isNative"])747 if err != nil {748 return fmt.Errorf("error parsing isNative: %w", err)749 }750 config.Version = masterMap[rootConfigName]["version"]751 // Deserialize the subconfigs752 for name, subconfig := range config.GetSubconfigs() {753 subconfigParams := masterMap[name]754 for _, param := range subconfig.GetParameters() {755 // Note: if the subconfig doesn't exist, this will end up using the default values for all of its settings756 err := param.deserialize(subconfigParams, network)757 if err != nil {758 return fmt.Errorf("error deserializing [%s]: %w", name, err)759 }760 }761 }762 return nil763}764// Generates a collection of environment variables based on this config's settings765func (config *RocketPoolConfig) GenerateEnvironmentVariables() map[string]string {766 envVars := map[string]string{}767 // Basic variables and root parameters768 envVars["SMARTNODE_IMAGE"] = config.Smartnode.GetSmartnodeContainerTag()769 envVars["ROCKETPOOL_FOLDER"] = config.RocketPoolDirectory770 addParametersToEnvVars(config.Smartnode.GetParameters(), envVars)771 addParametersToEnvVars(config.GetParameters(), envVars)772 // EC parameters773 if config.ExecutionClientMode.Value.(Mode) == Mode_Local {774 envVars["EC_CLIENT"] = fmt.Sprint(config.ExecutionClient.Value)775 envVars["EC_HTTP_ENDPOINT"] = fmt.Sprintf("http://%s:%d", Eth1ContainerName, config.ExecutionCommon.HttpPort.Value)776 envVars["EC_WS_ENDPOINT"] = fmt.Sprintf("ws://%s:%d", Eth1ContainerName, config.ExecutionCommon.WsPort.Value)777 // Handle open API ports778 if config.ExecutionCommon.OpenRpcPorts.Value == true {779 switch config.ExecutionClient.Value.(ExecutionClient) {780 case ExecutionClient_Pocket:781 ecHttpPort := config.ExecutionCommon.HttpPort.Value.(uint16)782 envVars["EC_OPEN_API_PORTS"] = fmt.Sprintf(", \"%d:%d/tcp\"", ecHttpPort, ecHttpPort)783 default:784 ecHttpPort := config.ExecutionCommon.HttpPort.Value.(uint16)785 ecWsPort := config.ExecutionCommon.WsPort.Value.(uint16)786 envVars["EC_OPEN_API_PORTS"] = fmt.Sprintf(", \"%d:%d/tcp\", \"%d:%d/tcp\"", ecHttpPort, ecHttpPort, ecWsPort, ecWsPort)787 }788 }789 // Common params790 addParametersToEnvVars(config.ExecutionCommon.GetParameters(), envVars)791 // Client-specific params792 switch config.ExecutionClient.Value.(ExecutionClient) {793 case ExecutionClient_Geth:794 addParametersToEnvVars(config.Geth.GetParameters(), envVars)795 envVars["EC_STOP_SIGNAL"] = gethStopSignal796 case ExecutionClient_Nethermind:797 addParametersToEnvVars(config.Nethermind.GetParameters(), envVars)798 envVars["EC_STOP_SIGNAL"] = nethermindStopSignal799 case ExecutionClient_Besu:800 addParametersToEnvVars(config.Besu.GetParameters(), envVars)801 envVars["EC_STOP_SIGNAL"] = besuStopSignal802 case ExecutionClient_Infura:803 addParametersToEnvVars(config.Infura.GetParameters(), envVars)804 envVars["EC_STOP_SIGNAL"] = powProxyStopSignal805 case ExecutionClient_Pocket:806 addParametersToEnvVars(config.Pocket.GetParameters(), envVars)807 envVars["EC_STOP_SIGNAL"] = powProxyStopSignal808 }809 } else {810 envVars["EC_CLIENT"] = "X" // X is for external / unknown811 addParametersToEnvVars(config.ExternalExecution.GetParameters(), envVars)812 }813 // Get the hostname of the Execution client, necessary for Prometheus to work in hybrid mode814 ecUrl, err := url.Parse(envVars["EC_HTTP_ENDPOINT"])815 if err == nil && ecUrl != nil {816 envVars["EC_HOSTNAME"] = ecUrl.Hostname()817 }818 // Fallback EC parameters819 envVars["FALLBACK_EC_CLIENT"] = fmt.Sprint(config.FallbackExecutionClient.Value)820 if config.UseFallbackExecutionClient.Value == true {821 if config.FallbackExecutionClientMode.Value.(Mode) == Mode_Local {822 envVars["FALLBACK_EC_HTTP_ENDPOINT"] = fmt.Sprintf("http://%s:%d", Eth1FallbackContainerName, config.FallbackExecutionCommon.HttpPort.Value)823 envVars["FALLBACK_EC_WS_ENDPOINT"] = fmt.Sprintf("ws://%s:%d", Eth1FallbackContainerName, config.FallbackExecutionCommon.WsPort.Value)824 // Handle open API ports825 if config.FallbackExecutionCommon.OpenRpcPorts.Value == true {826 switch config.FallbackExecutionClient.Value.(ExecutionClient) {827 case ExecutionClient_Pocket:828 ecHttpPort := config.FallbackExecutionCommon.HttpPort.Value.(uint16)829 envVars["FALLBACK_EC_OPEN_API_PORTS"] = fmt.Sprintf("\"%d:%d/tcp\"", ecHttpPort, ecHttpPort)830 default:831 ecHttpPort := config.FallbackExecutionCommon.HttpPort.Value.(uint16)832 ecWsPort := config.FallbackExecutionCommon.WsPort.Value.(uint16)833 envVars["FALLBACK_EC_OPEN_API_PORTS"] = fmt.Sprintf("\"%d:%d/tcp\", \"%d:%d/tcp\"", ecHttpPort, ecHttpPort, ecWsPort, ecWsPort)834 }835 }836 // Common params837 addParametersToEnvVars(config.FallbackExecutionCommon.GetParameters(), envVars)838 // Client-specific params839 switch config.FallbackExecutionClient.Value.(ExecutionClient) {840 case ExecutionClient_Infura:841 addParametersToEnvVars(config.FallbackInfura.GetParameters(), envVars)842 case ExecutionClient_Pocket:843 addParametersToEnvVars(config.FallbackPocket.GetParameters(), envVars)844 }845 } else {846 addParametersToEnvVars(config.FallbackExternalExecution.GetParameters(), envVars)847 }848 }849 // CC parameters850 if config.ConsensusClientMode.Value.(Mode) == Mode_Local {851 envVars["CC_CLIENT"] = fmt.Sprint(config.ConsensusClient.Value)852 envVars["CC_API_ENDPOINT"] = fmt.Sprintf("http://%s:%d", Eth2ContainerName, config.ConsensusCommon.ApiPort.Value)853 // Handle open API ports854 bnOpenPorts := ""855 if config.ConsensusCommon.OpenApiPort.Value == true {856 ccApiPort := config.ConsensusCommon.ApiPort.Value.(uint16)857 bnOpenPorts += fmt.Sprintf(", \"%d:%d/tcp\"", ccApiPort, ccApiPort)858 }859 if config.ConsensusClient.Value.(ConsensusClient) == ConsensusClient_Prysm && config.Prysm.OpenRpcPort.Value == true {860 prysmRpcPort := config.Prysm.RpcPort.Value.(uint16)861 bnOpenPorts += fmt.Sprintf(", \"%d:%d/tcp\"", prysmRpcPort, prysmRpcPort)862 }863 envVars["BN_OPEN_PORTS"] = bnOpenPorts864 // Common params865 addParametersToEnvVars(config.ConsensusCommon.GetParameters(), envVars)866 // Client-specific params867 switch config.ConsensusClient.Value.(ConsensusClient) {868 case ConsensusClient_Lighthouse:869 addParametersToEnvVars(config.Lighthouse.GetParameters(), envVars)870 case ConsensusClient_Nimbus:871 addParametersToEnvVars(config.Nimbus.GetParameters(), envVars)872 case ConsensusClient_Prysm:873 addParametersToEnvVars(config.Prysm.GetParameters(), envVars)874 envVars["CC_RPC_ENDPOINT"] = fmt.Sprintf("http://%s:%d", Eth2ContainerName, config.Prysm.RpcPort.Value)875 case ConsensusClient_Teku:876 addParametersToEnvVars(config.Teku.GetParameters(), envVars)877 }878 } else {879 envVars["CC_CLIENT"] = fmt.Sprint(config.ExternalConsensusClient.Value)880 switch config.ExternalConsensusClient.Value.(ConsensusClient) {881 case ConsensusClient_Lighthouse:882 addParametersToEnvVars(config.ExternalLighthouse.GetParameters(), envVars)883 case ConsensusClient_Prysm:884 addParametersToEnvVars(config.ExternalPrysm.GetParameters(), envVars)885 case ConsensusClient_Teku:886 addParametersToEnvVars(config.ExternalTeku.GetParameters(), envVars)887 }888 }889 // Get the hostname of the Consensus client, necessary for Prometheus to work in hybrid mode890 ccUrl, err := url.Parse(envVars["CC_API_ENDPOINT"])891 if err == nil && ccUrl != nil {892 envVars["CC_HOSTNAME"] = ccUrl.Hostname()893 }894 // Metrics895 if config.EnableMetrics.Value == true {896 addParametersToEnvVars(config.Exporter.GetParameters(), envVars)897 addParametersToEnvVars(config.Prometheus.GetParameters(), envVars)898 addParametersToEnvVars(config.Grafana.GetParameters(), envVars)899 if config.Exporter.RootFs.Value == true {900 envVars["EXPORTER_ROOTFS_COMMAND"] = ", \"--path.rootfs=/rootfs\""901 envVars["EXPORTER_ROOTFS_VOLUME"] = ", \"/:/rootfs:ro\""902 }903 if config.Prometheus.OpenPort.Value == true {904 envVars["PROMETHEUS_OPEN_PORTS"] = fmt.Sprintf("%d:%d/tcp", config.Prometheus.Port.Value, config.Prometheus.Port.Value)905 }906 // Additional metrics flags907 if config.Exporter.AdditionalFlags.Value.(string) != "" {908 envVars["EXPORTER_ADDITIONAL_FLAGS"] = fmt.Sprintf(", \"%s\"", config.Exporter.AdditionalFlags.Value.(string))909 }910 if config.Prometheus.AdditionalFlags.Value.(string) != "" {911 envVars["PROMETHEUS_ADDITIONAL_FLAGS"] = fmt.Sprintf(", \"%s\"", config.Prometheus.AdditionalFlags.Value.(string))912 }913 }914 // Bitfly Node Metrics915 if config.EnableBitflyNodeMetrics.Value == true {916 addParametersToEnvVars(config.BitflyNodeMetrics.GetParameters(), envVars)917 }918 return envVars919}920// The the title for the config921func (config *RocketPoolConfig) GetConfigTitle() string {922 return config.Title923}924// Update the default settings for all overwrite-on-upgrade parameters925func (config *RocketPoolConfig) UpdateDefaults() error {926 // Update the root params927 currentNetwork := config.Smartnode.Network.Value.(Network)928 for _, param := range config.GetParameters() {929 defaultValue, err := param.GetDefault(currentNetwork)930 if err != nil {931 return fmt.Errorf("error getting defaults for root param [%s] on network [%v]: %w", param.ID, currentNetwork, err)932 }933 if param.OverwriteOnUpgrade {934 param.Value = defaultValue935 }936 }937 // Update the subconfigs938 for subconfigName, subconfig := range config.GetSubconfigs() {939 for _, param := range subconfig.GetParameters() {940 defaultValue, err := param.GetDefault(currentNetwork)941 if err != nil {942 return fmt.Errorf("error getting defaults for %s param [%s] on network [%v]: %w", subconfigName, param.ID, currentNetwork, err)943 }944 if param.OverwriteOnUpgrade {945 param.Value = defaultValue946 }947 }948 }949 return nil950}951// Get all of the settings that have changed between an old config and this config, and get all of the containers that are affected by those changes - also returns whether or not the selected network was changed952func (config *RocketPoolConfig) GetChanges(oldConfig *RocketPoolConfig) (map[string][]ChangedSetting, map[ContainerID]bool, bool) {953 // Get the map of changed settings by category954 changedSettings := getChangedSettingsMap(oldConfig, config)955 // Create a list of all of the container IDs that need to be restarted956 totalAffectedContainers := map[ContainerID]bool{}957 for _, settingList := range changedSettings {958 for _, setting := range settingList {959 for container := range setting.AffectedContainers {960 totalAffectedContainers[container] = true961 }962 }963 }964 // Check if the network has changed965 changeNetworks := false966 if oldConfig.Smartnode.Network.Value != config.Smartnode.Network.Value {967 changeNetworks = true968 }969 // Return everything970 return changedSettings, totalAffectedContainers, changeNetworks971}972// Checks to see if the current configuration is valid; if not, returns a list of errors973func (config *RocketPoolConfig) Validate() []string {974 errors := []string{}975 // Check for client incompatibility976 badClients, badFallbackClients := config.GetIncompatibleConsensusClients()977 if config.ConsensusClientMode.Value == Mode_Local {978 selectedCC := config.ConsensusClient.Value.(ConsensusClient)979 for _, badClient := range badClients {980 if badClient.Value == selectedCC {981 errors = append(errors, fmt.Sprintf("Selected Consensus client:\n\t%s\nis not compatible with selected Execution client:\n\t%v", badClient.Name, config.ExecutionClient.Value))982 break983 }984 }985 for _, badClient := range badFallbackClients {986 if badClient.Value == selectedCC {987 errors = append(errors, fmt.Sprintf("Selected Consensus client:\n\t%s\nis not compatible with selected fallback Execution client:\n\t%v", badClient.Name, config.FallbackExecutionClient.Value))988 break989 }990 }991 }992 // Check for illegal blank strings993 /* TODO - this needs to be smarter and ignore irrelevant settings994 for _, param := range config.GetParameters() {995 if param.Type == ParameterType_String && !param.CanBeBlank && param.Value == "" {996 errors = append(errors, fmt.Sprintf("[%s] cannot be blank.", param.Name))997 }998 }999 for name, subconfig := range config.GetSubconfigs() {1000 for _, param := range subconfig.GetParameters() {1001 if param.Type == ParameterType_String && !param.CanBeBlank && param.Value == "" {1002 errors = append(errors, fmt.Sprintf("[%s - %s] cannot be blank.", name, param.Name))1003 }1004 }1005 }1006 */1007 return errors1008}1009// Applies all of the defaults to all of the settings that have them defined1010func (config *RocketPoolConfig) applyAllDefaults() error {1011 for _, param := range config.GetParameters() {1012 err := param.setToDefault(config.Smartnode.Network.Value.(Network))1013 if err != nil {1014 return fmt.Errorf("error setting root parameter default: %w", err)1015 }1016 }1017 for name, subconfig := range config.GetSubconfigs() {1018 for _, param := range subconfig.GetParameters() {1019 err := param.setToDefault(config.Smartnode.Network.Value.(Network))1020 if err != nil {1021 return fmt.Errorf("error setting parameter default for %s: %w", name, err)1022 }1023 }1024 }1025 return nil1026}1027// Add the parameters to the collection of environment variabes1028func addParametersToEnvVars(params []*Parameter, envVars map[string]string) {1029 for _, param := range params {1030 for _, envVar := range param.EnvironmentVariables {1031 if envVar != "" {1032 envVars[envVar] = fmt.Sprint(param.Value)1033 }1034 }1035 }1036}1037// Get all of the changed settings between an old and new config1038func getChangedSettingsMap(oldConfig *RocketPoolConfig, newConfig *RocketPoolConfig) map[string][]ChangedSetting {1039 changedSettings := map[string][]ChangedSetting{}1040 // Root settings1041 oldRootParams := oldConfig.GetParameters()1042 newRootParams := newConfig.GetParameters()1043 changedSettings[oldConfig.Title] = getChangedSettings(oldRootParams, newRootParams, newConfig)1044 // Subconfig settings1045 oldSubconfigs := oldConfig.GetSubconfigs()1046 for name, subConfig := range newConfig.GetSubconfigs() {1047 oldParams := oldSubconfigs[name].GetParameters()1048 newParams := subConfig.GetParameters()1049 changedSettings[subConfig.GetConfigTitle()] = getChangedSettings(oldParams, newParams, newConfig)1050 }1051 return changedSettings1052}1053// Get all of the settings that have changed between the given parameter lists.1054// Assumes the parameter lists represent identical parameters (e.g. they have the same number of elements and1055// each element has the same ID).1056func getChangedSettings(oldParams []*Parameter, newParams []*Parameter, newConfig *RocketPoolConfig) []ChangedSetting {1057 changedSettings := []ChangedSetting{}1058 for i, param := range newParams {1059 oldValString := fmt.Sprint(oldParams[i].Value)1060 newValString := fmt.Sprint(param.Value)1061 if oldValString != newValString {1062 changedSettings = append(changedSettings, ChangedSetting{1063 Name: param.Name,1064 OldValue: oldValString,1065 NewValue: newValString,1066 AffectedContainers: getAffectedContainers(param, newConfig),1067 })1068 }1069 }1070 return changedSettings1071}1072// Handles custom container overrides1073func getAffectedContainers(param *Parameter, cfg *RocketPoolConfig) map[ContainerID]bool {1074 affectedContainers := map[ContainerID]bool{}1075 for _, container := range param.AffectsContainers {1076 affectedContainers[container] = true1077 }1078 // Nimbus doesn't operate in split mode, so all of the VC parameters need to get redirected to the BN instead1079 if cfg.ConsensusClientMode.Value.(Mode) == Mode_Local &&1080 cfg.ConsensusClient.Value.(ConsensusClient) == ConsensusClient_Nimbus {1081 for _, container := range param.AffectsContainers {1082 if container == ContainerID_Validator {1083 affectedContainers[ContainerID_Eth2] = true1084 }1085 }1086 }1087 return affectedContainers1088}...
settings-execution.go
Source:settings-execution.go
1package config2import (3 "github.com/gdamore/tcell/v2"4 "github.com/rocket-pool/smartnode/shared/services/config"5)6// The page wrapper for the EC config7type ExecutionConfigPage struct {8 home *settingsHome9 page *page10 layout *standardLayout11 masterConfig *config.RocketPoolConfig12 ecModeDropdown *parameterizedFormItem13 ecDropdown *parameterizedFormItem14 ecCommonItems []*parameterizedFormItem15 gethItems []*parameterizedFormItem16 nethermindItems []*parameterizedFormItem17 besuItems []*parameterizedFormItem18 infuraItems []*parameterizedFormItem19 pocketItems []*parameterizedFormItem20 externalEcItems []*parameterizedFormItem21}22// Creates a new page for the Execution client settings23func NewExecutionConfigPage(home *settingsHome) *ExecutionConfigPage {24 configPage := &ExecutionConfigPage{25 home: home,26 masterConfig: home.md.Config,27 }28 configPage.createContent()29 configPage.page = newPage(30 home.homePage,31 "settings-execution",32 "Execution Client (ETH1)",33 "Select this to choose your Execution client (formerly called \"ETH1 client\") and configure its settings.",34 configPage.layout.grid,35 )36 return configPage37}38// Get the underlying page39func (configPage *ExecutionConfigPage) getPage() *page {40 return configPage.page41}42// Creates the content for the Execution client settings page43func (configPage *ExecutionConfigPage) createContent() {44 // Create the layout45 configPage.layout = newStandardLayout()46 configPage.layout.createForm(&configPage.masterConfig.Smartnode.Network, "Execution Client (ETH1) Settings")47 // Return to the home page after pressing Escape48 configPage.layout.form.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {49 if event.Key() == tcell.KeyEsc {50 // Close all dropdowns and break if one was open51 for _, param := range configPage.layout.parameters {52 dropDown, ok := param.item.(*DropDown)53 if ok && dropDown.open {54 dropDown.CloseList(configPage.home.md.app)55 return nil56 }57 }58 // Return to the home page59 configPage.home.md.setPage(configPage.home.homePage)60 return nil61 }62 return event63 })64 // Set up the form items65 configPage.ecModeDropdown = createParameterizedDropDown(&configPage.masterConfig.ExecutionClientMode, configPage.layout.descriptionBox)66 configPage.ecDropdown = createParameterizedDropDown(&configPage.masterConfig.ExecutionClient, configPage.layout.descriptionBox)67 configPage.ecCommonItems = createParameterizedFormItems(configPage.masterConfig.ExecutionCommon.GetParameters(), configPage.layout.descriptionBox)68 configPage.gethItems = createParameterizedFormItems(configPage.masterConfig.Geth.GetParameters(), configPage.layout.descriptionBox)69 configPage.nethermindItems = createParameterizedFormItems(configPage.masterConfig.Nethermind.GetParameters(), configPage.layout.descriptionBox)70 configPage.besuItems = createParameterizedFormItems(configPage.masterConfig.Besu.GetParameters(), configPage.layout.descriptionBox)71 configPage.infuraItems = createParameterizedFormItems(configPage.masterConfig.Infura.GetParameters(), configPage.layout.descriptionBox)72 configPage.pocketItems = createParameterizedFormItems(configPage.masterConfig.Pocket.GetParameters(), configPage.layout.descriptionBox)73 configPage.externalEcItems = createParameterizedFormItems(configPage.masterConfig.ExternalExecution.GetParameters(), configPage.layout.descriptionBox)74 // Map the parameters to the form items in the layout75 configPage.layout.mapParameterizedFormItems(configPage.ecModeDropdown, configPage.ecDropdown)76 configPage.layout.mapParameterizedFormItems(configPage.ecCommonItems...)77 configPage.layout.mapParameterizedFormItems(configPage.gethItems...)78 configPage.layout.mapParameterizedFormItems(configPage.nethermindItems...)79 configPage.layout.mapParameterizedFormItems(configPage.besuItems...)80 configPage.layout.mapParameterizedFormItems(configPage.infuraItems...)81 configPage.layout.mapParameterizedFormItems(configPage.pocketItems...)82 configPage.layout.mapParameterizedFormItems(configPage.externalEcItems...)83 // Set up the setting callbacks84 configPage.ecModeDropdown.item.(*DropDown).SetSelectedFunc(func(text string, index int) {85 if configPage.masterConfig.ExecutionClientMode.Value == configPage.masterConfig.ExecutionClientMode.Options[index].Value {86 return87 }88 configPage.masterConfig.ExecutionClientMode.Value = configPage.masterConfig.ExecutionClientMode.Options[index].Value89 configPage.handleEcModeChanged()90 })91 configPage.ecDropdown.item.(*DropDown).SetSelectedFunc(func(text string, index int) {92 if configPage.masterConfig.ExecutionClient.Value == configPage.masterConfig.ExecutionClient.Options[index].Value {93 return94 }95 configPage.masterConfig.ExecutionClient.Value = configPage.masterConfig.ExecutionClient.Options[index].Value96 configPage.handleLocalEcChanged()97 })98 // Do the initial draw99 configPage.handleEcModeChanged()100}101// Handle all of the form changes when the EC mode has changed102func (configPage *ExecutionConfigPage) handleEcModeChanged() {103 configPage.layout.form.Clear(true)104 configPage.layout.form.AddFormItem(configPage.ecModeDropdown.item)105 selectedMode := configPage.masterConfig.ExecutionClientMode.Value.(config.Mode)106 switch selectedMode {107 case config.Mode_Local:108 // Local (Docker mode)109 configPage.handleLocalEcChanged()110 case config.Mode_External:111 // External (Hybrid mode)112 for _, param := range configPage.externalEcItems {113 configPage.layout.form.AddFormItem(param.item)114 }115 configPage.layout.refresh()116 }117}118// Handle all of the form changes when the EC has changed119func (configPage *ExecutionConfigPage) handleLocalEcChanged() {120 configPage.layout.form.Clear(true)121 configPage.layout.form.AddFormItem(configPage.ecModeDropdown.item)122 configPage.layout.form.AddFormItem(configPage.ecDropdown.item)123 selectedEc := configPage.masterConfig.ExecutionClient.Value.(config.ExecutionClient)124 switch selectedEc {125 case config.ExecutionClient_Geth:126 configPage.layout.addFormItemsWithCommonParams(configPage.ecCommonItems, configPage.gethItems, configPage.masterConfig.Geth.UnsupportedCommonParams)127 case config.ExecutionClient_Nethermind:128 configPage.layout.addFormItemsWithCommonParams(configPage.ecCommonItems, configPage.nethermindItems, configPage.masterConfig.Nethermind.UnsupportedCommonParams)129 case config.ExecutionClient_Besu:130 configPage.layout.addFormItemsWithCommonParams(configPage.ecCommonItems, configPage.besuItems, configPage.masterConfig.Besu.UnsupportedCommonParams)131 case config.ExecutionClient_Infura:132 configPage.layout.addFormItemsWithCommonParams(configPage.ecCommonItems, configPage.infuraItems, configPage.masterConfig.Infura.UnsupportedCommonParams)133 case config.ExecutionClient_Pocket:134 configPage.layout.addFormItemsWithCommonParams(configPage.ecCommonItems, configPage.pocketItems, configPage.masterConfig.Pocket.UnsupportedCommonParams)135 }136 configPage.layout.refresh()137}138// Handle a bulk redraw request139func (configPage *ExecutionConfigPage) handleLayoutChanged() {140 configPage.handleEcModeChanged()141}...
intcode.go
Source:intcode.go
...71 }72 }73 panic("invalid parameter mode")74}75func (r *Run) getParameters(ins instruction, num int64, numOutputs int64) []int64 {76 ip := r.Execution.InstructionPointer77 params := make([]int64, num)78 for i := int64(0); i < num; i++ {79 pm := ins.getParameterMode(i)80 if i >= num-numOutputs {81 if pm == relativeMode {82 _, rawpv := r.getParameterValue(ip+i+1, pm)83 params[i] = rawpv84 } else {85 // map to immediate mode86 params[i], _ = r.getParameterValue(ip+i+1, immediateMode)87 }88 } else {89 params[i], _ = r.getParameterValue(ip+i+1, pm)90 }91 }92 return params93}94func (r *Run) getValue(address int64) int64 {95 if v, ok := r.Execution.RAM[address]; ok {96 return v97 }98 if address < int64(len(r.P)) {99 return r.P[address]100 }101 return 0102}103func (r *Run) writeValue(address int64, value int64) {104 if address >= int64(len(r.P)) {105 r.Execution.RAM[address] = value106 } else {107 r.P[address] = value108 }109}110var debug = false111// Execute program112func (r *Run) Execute() {113 myID := -1114 if r.Identifier != nil {115 myID = *r.Identifier116 }117 r.Execution = Execution{118 InstructionPointer: 0,119 RAM: make(map[int64]int64),120 RelativeBase: 0,121 }122main:123 for r.Execution.InstructionPointer < int64(len(r.P)) {124 previousIP := r.Execution.InstructionPointer125 instruction := instruction(r.getValue(int64(r.Execution.InstructionPointer)))126 opcode := instruction.decodeOpcode()127 switch opcode {128 case add:129 {130 params := r.getParameters(instruction, 3, 1)131 r.writeValue(params[2], params[0]+params[1])132 r.Execution.InstructionPointer += 4133 }134 case multiply:135 {136 params := r.getParameters(instruction, 3, 1)137 r.writeValue(params[2], params[0]*params[1])138 r.Execution.InstructionPointer += 4139 }140 case save:141 {142 params := r.getParameters(instruction, 1, 1)143 input := <-r.Inputs144 r.writeValue(params[0], input)145 r.Execution.InstructionPointer += 2146 }147 case jumpIfTrue:148 {149 params := r.getParameters(instruction, 2, 0)150 if params[0] != 0 {151 r.Execution.InstructionPointer = params[1]152 } else {153 r.Execution.InstructionPointer += 3154 }155 }156 case jumpIfFalse:157 {158 params := r.getParameters(instruction, 2, 0)159 if params[0] == 0 {160 r.Execution.InstructionPointer = params[1]161 } else {162 r.Execution.InstructionPointer += 3163 }164 }165 case lessThan:166 {167 params := r.getParameters(instruction, 3, 1)168 if params[0] < params[1] {169 r.writeValue(params[2], 1)170 } else {171 r.writeValue(params[2], 0)172 }173 r.Execution.InstructionPointer += 4174 }175 case equals:176 {177 params := r.getParameters(instruction, 3, 1)178 if params[0] == params[1] {179 r.writeValue(params[2], 1)180 } else {181 r.writeValue(params[2], 0)182 }183 r.Execution.InstructionPointer += 4184 }185 case output:186 {187 params := r.getParameters(instruction, 1, 0)188 r.Outputs <- params[0]189 r.Execution.InstructionPointer += 2190 }191 case relativeBase:192 {193 params := r.getParameters(instruction, 1, 0)194 r.Execution.RelativeBase += params[0]195 r.Execution.InstructionPointer += 2196 }197 case halt:198 if debug {199 fmt.Println(myID, " halt.")200 }201 break main202 default:203 panic(fmt.Sprint("Unknown opcode", r.Execution.InstructionPointer, opcode))204 }205 if previousIP == r.Execution.InstructionPointer {206 panic("InstructionPointer is stuck")207 }...
getParameters
Using AI Code Generation
1import (2func main() {3 var execution = new(Execution)4 var parameters = execution.getParameters()5 fmt.Println(parameters)6}7import (8type Execution struct {9}10func (execution *Execution) getParameters() string {11}12import (13func main() {14 var execution = new(Execution)15 var parameters = execution.getParameters()16 fmt.Println(parameters)17}18import (19type Execution struct {20}21func (execution *Execution) getParameters() string {22}23import (24func main() {25 var execution = new(Execution)26 var parameters = execution.getParameters()27 fmt.Println(parameters)28}29import (30type Execution struct {31}32func (execution *Execution) getParameters() string {33}34import (35func main() {36 var execution = new(Execution)37 var parameters = execution.getParameters()38 fmt.Println(parameters)39}40import (41type Execution struct {42}43func (execution *Execution) getParameters() string {44}45import (46func main() {47 var execution = new(Execution)48 var parameters = execution.getParameters()49 fmt.Println(parameters)50}51import (52type Execution struct {53}54func (execution *Execution) getParameters() string {55}56import (57func main() {
getParameters
Using AI Code Generation
1func main() {2 execution.getParameters()3 fmt.Println(execution)4}5func main() {6 execution.getParameters()7 fmt.Println(execution)8}9func main() {10 execution.getParameters()11 fmt.Println(execution)12}13func main() {14 execution.getParameters()15 fmt.Println(execution)16}17func main() {18 execution.getParameters()19 fmt.Println(execution)20}21func main() {22 execution.getParameters()23 fmt.Println(execution)24}25func main() {26 execution.getParameters()27 fmt.Println(execution)28}29func main() {30 execution.getParameters()31 fmt.Println(execution)32}33func main() {34 execution.getParameters()35 fmt.Println(execution)36}37func main() {38 execution.getParameters()39 fmt.Println(execution)40}41func main() {42 execution.getParameters()43 fmt.Println(execution)44}45func main() {46 execution.getParameters()47 fmt.Println(execution)48}49func main() {50 execution.getParameters()51 fmt.Println(execution)52}
getParameters
Using AI Code Generation
1import (2func main() {3 var (4 data []byte = []byte("0x1234567890")5 exec := vm.NewExecution(nil, nil, nil, gas, gasPrice, value, data, false)6 gas, gasPrice, value, data = exec.GetParameters()7 fmt.Printf("gas: %v, gasPrice: %v, value: %v, data: %v", gas, gasPrice, value, data)8}
getParameters
Using AI Code Generation
1import (2func main() {3 getParameters("hello", 123, true)4}5func getParameters(args ...interface{}) {6 for _, arg := range args {7 t := reflect.TypeOf(arg)8 v := reflect.ValueOf(arg)9 fmt.Printf("Type: %v, Value: %v10 }11}12import (13func main() {14 getParameters("hello", 123, true)15}16func getParameters(args ...interface{}) {17 for _, arg := range args {18 t := reflect.TypeOf(arg)19 v := reflect.ValueOf(arg)20 fmt.Printf("Type: %v, Value: %v21 }22}23import (24func main() {25 getParameters("hello", 123, true)26}27func getParameters(args ...interface{}) {28 for _, arg := range args {29 t := reflect.TypeOf(arg)30 v := reflect.ValueOf(arg)31 fmt.Printf("Type: %v, Value: %v32 }33}34import (35func main() {36 getParameters("hello", 123, true)37}38func getParameters(args ...interface{}) {39 for _, arg := range args {40 t := reflect.TypeOf(arg)41 v := reflect.ValueOf(arg)42 fmt.Printf("Type: %v, Value: %v43 }44}
getParameters
Using AI Code Generation
1import (2func main() {3 cmd := exec.Command("cmd", "/C", "dir")4 params := cmd.GetParameters()5 fmt.Println(strings.Join(params, " "))6}
getParameters
Using AI Code Generation
1func main(){2 fmt.Println("Hello World!")3 execObj.GetParameters()4}5func main(){6 fmt.Println("Hello World!")7 execObj.GetParameters()8}9func main(){10 fmt.Println("Hello World!")11 execObj.GetParameters()12}13func main(){14 fmt.Println("Hello World!")15 execObj.GetParameters()16}17func main(){18 fmt.Println("Hello World!")19 execObj.GetParameters()20}21func main(){22 fmt.Println("Hello World!")23 execObj.GetParameters()24}25func main(){26 fmt.Println("Hello World!")27 execObj.GetParameters()28}29func main(){30 fmt.Println("Hello World!")31 execObj.GetParameters()32}33func main(){34 fmt.Println("Hello World!")35 execObj.GetParameters()36}37func main(){38 fmt.Println("Hello World!")39 execObj.GetParameters()40}41func main(){42 fmt.Println("Hello World!")43 execObj.GetParameters()44}45func main(){46 fmt.Println("Hello World!")47 execObj.GetParameters()48}
getParameters
Using AI Code Generation
1import (2func main() {3 execution := new(Execution)4 method := reflect.ValueOf(execution).MethodByName(methodName)5 methodParameters := method.Type().In(0)6 numOfParameters := methodParameters.NumField()7 parameters := make([]reflect.Value, numOfParameters)8 for i := 0; i < numOfParameters; i++ {9 parameter := methodParameters.Field(i)10 parameterValue := reflect.ValueOf(execution).MethodByName("get" + parameterName).Call([]reflect.Value{})11 if parameterType != parameterValue[0].Type() {12 panic("The parameter type is invalid")13 }14 }15 method.Call(parameters)16}17import (18func main() {19 execution := new(Execution)20 method := reflect.ValueOf(execution).MethodByName(methodName)21 methodParameters := method.Type().In(0)22 numOfParameters := methodParameters.NumField()23 parameters := make([]reflect.Value, numOfParameters)24 for i := 0; i < numOfParameters; i++ {25 parameter := methodParameters.Field(i)
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!