diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..b714fed1d --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,21 @@ +name: Smart Node Build +on: + push: + tags: + - v* + branches: + - master + - main + pull_request: +permissions: + contents: read +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 + with: + go-version: 1.21.8 + - run: cd ${GITHUB_WORKSPACE}/rocketpool-cli && go build . + - run: cd ${GITHUB_WORKSPACE}/rocketpool-daemon && go build . diff --git a/.github/workflows/commits.yml b/.github/workflows/commits.yml new file mode 100644 index 000000000..1c9df192c --- /dev/null +++ b/.github/workflows/commits.yml @@ -0,0 +1,14 @@ +# Taken from https://github.com/marketplace/actions/block-fixup-commit-merge?version=v2.0.0 +# Updated to use newer ubuntu and checkout action +name: Git Checks + +on: [pull_request] + +jobs: + block-fixup: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Block Fixup Commit Merge + uses: 13rac1/block-fixup-merge-action@v2.0.0 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..45082bcb9 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,51 @@ +# Taken from https://github.com/golangci/golangci-lint-action +name: golangci-lint +on: + push: + tags: + - v* + branches: + - master + - main + - v2* + pull_request: +permissions: + contents: read + # Optional: allow read access to pull request. Use with `only-new-issues` option. + # pull-requests: read +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/setup-go@v4 + with: + go-version: 1.21.8 + - uses: actions/checkout@v3 + - name: golangci-lint + uses: golangci/golangci-lint-action@v4 + with: + # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version + version: latest + + # Optional: working directory, useful for monorepos + # working-directory: somedir + + # Optional: golangci-lint command line arguments. + # args: --issues-exit-code=0 + + # For now, Smart Node will enforce everything except errcheck + args: --disable errcheck + + # Optional: show only new issues if it's a pull request. The default value is `false`. + # only-new-issues: true + + # Optional: if set to true then the all caching functionality will be complete disabled, + # takes precedence over all other caching options. + # skip-cache: true + + # Optional: if set to true then the action don't cache or restore ~/go/pkg. + # skip-pkg-cache: true + + # Optional: if set to true then the action don't cache or restore ~/.cache/go-build. + # skip-build-cache: true diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 000000000..535dd3db3 --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,21 @@ +name: Smart Node Unit Tests +on: + push: + tags: + - v* + branches: + - master + - main + - v2* + pull_request: +permissions: + contents: read +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 + with: + go-version: 1.21.8 + - run: go test ./... diff --git a/go.mod b/go.mod index dfca43b00..5776c32f2 100644 --- a/go.mod +++ b/go.mod @@ -28,8 +28,8 @@ require ( github.com/prometheus/client_golang v1.19.0 github.com/prysmaticlabs/prysm/v5 v5.0.3 github.com/rivo/tview v0.0.0-20230208211350-7dfff1ce7854 // DO NOT UPGRADE - github.com/rocket-pool/node-manager-core v0.2.1-0.20240417132624-0e7d87e82ec8 - github.com/rocket-pool/rocketpool-go/v2 v2.0.0-20240417004432-ca6e3e2c4f32 + github.com/rocket-pool/node-manager-core v0.2.1-0.20240417173109-4b54852b003a + github.com/rocket-pool/rocketpool-go/v2 v2.0.0-20240418131940-9aa4643f67c7 github.com/shirou/gopsutil/v3 v3.24.3 github.com/tyler-smith/go-bip39 v1.1.0 github.com/wealdtech/go-ens/v3 v3.6.0 diff --git a/go.sum b/go.sum index b77a67fc4..bb122050f 100644 --- a/go.sum +++ b/go.sum @@ -467,10 +467,10 @@ github.com/rocket-pool/batch-query v1.0.0 h1:5HejmT1n1fIdLIqUhTNwbkG2PGOPl3IVjCp github.com/rocket-pool/batch-query v1.0.0/go.mod h1:d1CmxShzk0fioJ4yX0eFGhz2an1odnW/LZ2cp3eDGIQ= github.com/rocket-pool/go-merkletree v1.0.1-0.20220406020931-c262d9b976dd h1:p9KuetSKB9nte9I/MkkiM3pwKFVQgqxxPTQ0y56Ff6s= github.com/rocket-pool/go-merkletree v1.0.1-0.20220406020931-c262d9b976dd/go.mod h1:UE9fof8P7iESVtLn1K9CTSkNRYVFHZHlf96RKbU33kA= -github.com/rocket-pool/node-manager-core v0.2.1-0.20240417132624-0e7d87e82ec8 h1:DpNHfImur7EplInBi1mV8ZK8zCBueGFuQWpoDfjJWbw= -github.com/rocket-pool/node-manager-core v0.2.1-0.20240417132624-0e7d87e82ec8/go.mod h1:KeVUgf+tc7e+fDUzc/FH3COtgGPoAyIV2Tx3jLN4zng= -github.com/rocket-pool/rocketpool-go/v2 v2.0.0-20240417004432-ca6e3e2c4f32 h1:k+QY2qY5PyktCS9MAPKp6QWlM3sarJXIZ1U7CJtPZng= -github.com/rocket-pool/rocketpool-go/v2 v2.0.0-20240417004432-ca6e3e2c4f32/go.mod h1:2IMaRByN0wfkLgNa85LA0I9oJ1QKv1nCNoffFdhF714= +github.com/rocket-pool/node-manager-core v0.2.1-0.20240417173109-4b54852b003a h1:hBuBMT4XT1ne/6eUdnE3BIfnMsFmFPF7pIRud0aWod8= +github.com/rocket-pool/node-manager-core v0.2.1-0.20240417173109-4b54852b003a/go.mod h1:KeVUgf+tc7e+fDUzc/FH3COtgGPoAyIV2Tx3jLN4zng= +github.com/rocket-pool/rocketpool-go/v2 v2.0.0-20240418131940-9aa4643f67c7 h1:liWy3ZNMhHmNOlbKfJXZbUgbBaGj4ZyEZJv+0mWaZ+k= +github.com/rocket-pool/rocketpool-go/v2 v2.0.0-20240418131940-9aa4643f67c7/go.mod h1:2IMaRByN0wfkLgNa85LA0I9oJ1QKv1nCNoffFdhF714= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= diff --git a/rocketpool-cli/client/docker.go b/rocketpool-cli/client/docker.go index c3af98a35..014ec02e0 100644 --- a/rocketpool-cli/client/docker.go +++ b/rocketpool-cli/client/docker.go @@ -10,6 +10,7 @@ import ( dt "github.com/docker/docker/api/types" dtc "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" + dti "github.com/docker/docker/api/types/image" ) // Get the current Docker image used by the given container @@ -114,7 +115,7 @@ func (c *Client) DeleteImage(imageName string) error { return err } // TODO: handle the response here - _, err = d.ImageRemove(context.Background(), imageName, dt.ImageRemoveOptions{}) + _, err = d.ImageRemove(context.Background(), imageName, dti.RemoveOptions{}) return err } @@ -210,7 +211,7 @@ func (c *Client) GetAllDockerImages() ([]DockerImage, error) { return nil, err } - imageList, err := d.ImageList(context.Background(), dt.ImageListOptions{All: true}) + imageList, err := d.ImageList(context.Background(), dti.ListOptions{All: true}) if err != nil { return nil, fmt.Errorf("error getting image details: %w", err) } diff --git a/rocketpool-cli/client/service.go b/rocketpool-cli/client/service.go index 5bffa853c..d19621263 100644 --- a/rocketpool-cli/client/service.go +++ b/rocketpool-cli/client/service.go @@ -132,7 +132,7 @@ func (c *Client) InstallService(verbose bool, noDeps bool, version string, path func (c *Client) InstallUpdateTracker(verbose bool, version string, useLocalInstaller bool) error { // Get installation script flags flags := []string{ - "-v", fmt.Sprintf("%s", shellescape.Quote(version)), + "-v", shellescape.Quote(version), } var script []byte diff --git a/rocketpool-cli/client/utils.go b/rocketpool-cli/client/utils.go index 33b35d7c0..d97b88ffe 100644 --- a/rocketpool-cli/client/utils.go +++ b/rocketpool-cli/client/utils.go @@ -9,7 +9,6 @@ import ( "path/filepath" "github.com/alessio/shellescape" - "github.com/rocket-pool/node-manager-core/api/types" "github.com/rocket-pool/smartnode/v2/shared/config" "gopkg.in/yaml.v2" ) @@ -98,16 +97,3 @@ func SaveConfig(cfg *config.SmartNodeConfig, directory string, filename string) return nil } - -// Parse and augment the status of a client into a human-readable format -func getClientStatusString(clientStatus types.ClientStatus) string { - if clientStatus.IsSynced { - return "synced and ready" - } - - if clientStatus.IsWorking { - return fmt.Sprintf("syncing (%.2f%%)", SyncRatioToPercent(clientStatus.SyncProgress)) - } - - return fmt.Sprintf("unavailable (%s)", clientStatus.Error) -} diff --git a/rocketpool-cli/commands/minipool/reduce-bond.go b/rocketpool-cli/commands/minipool/reduce-bond.go index f42150378..26f83890c 100644 --- a/rocketpool-cli/commands/minipool/reduce-bond.go +++ b/rocketpool-cli/commands/minipool/reduce-bond.go @@ -24,11 +24,13 @@ func reduceBondAmount(c *cli.Context) error { // Check the fee distributor if !details.Data.IsFeeDistributorInitialized { - fmt.Println("Minipools cannot have their bonds reduced until your fee distributor has been initialized.\nPlease run `rocketpool node initialize-fee-distributor` first, then return here to reduce your bonds.") + fmt.Println("Minipools cannot have their bonds reduced until your fee distributor has been initialized.") + fmt.Println("Please run `rocketpool node initialize-fee-distributor` first, then return here to reduce your bonds.") return nil } - fmt.Println("NOTE: this function is used to complete the bond reduction process for a minipool. If you haven't started the process already, please run `rocketpool minipool begin-bond-reduction` first.\n") + fmt.Println("NOTE: this function is used to complete the bond reduction process for a minipool. If you haven't started the process already, please run `rocketpool minipool begin-bond-reduction` first.") + fmt.Println() // Get reduceable minipools reduceableMinipools := []api.MinipoolReduceBondDetails{} @@ -109,10 +111,12 @@ func forceFeeDistribution(c *cli.Context, rp *client.Client) error { balance := response.Data.Balance if balance.Cmp(common.Big0) == 0 { - fmt.Println("Your fee distributor does not have any ETH and does not need to be distributed.\n") + fmt.Println("Your fee distributor does not have any ETH and does not need to be distributed.") + fmt.Println() return nil } - fmt.Println("NOTE: prior to bond reduction, you must distribute the funds in your fee distributor.\n") + fmt.Println("NOTE: prior to bond reduction, you must distribute the funds in your fee distributor.") + fmt.Println() // Print info balanceFloat := eth.WeiToEth(response.Data.Balance) diff --git a/rocketpool-cli/commands/minipool/rescue-dissolved.go b/rocketpool-cli/commands/minipool/rescue-dissolved.go index 52a0cc936..749c573a1 100644 --- a/rocketpool-cli/commands/minipool/rescue-dissolved.go +++ b/rocketpool-cli/commands/minipool/rescue-dissolved.go @@ -29,7 +29,9 @@ func rescueDissolved(c *cli.Context) error { // Get RP client rp := client.NewClientFromCtx(c) - fmt.Println("This command will allow you to manually deposit the remaining ETH for any dissolved minipools, activating them so you can exit them and retrieve your minipool's funds.\nPlease read our guide at https://docs.rocketpool.net/guides/node/rescue-dissolved.html to fully read about the process before continuing.\n") + fmt.Println("This command will allow you to manually deposit the remaining ETH for any dissolved minipools, activating them so you can exit them and retrieve your minipool's funds.") + fmt.Println("Please read our guide at https://docs.rocketpool.net/guides/node/rescue-dissolved.html to fully read about the process before continuing.") + fmt.Println() // Get minipool statuses details, err := rp.Api.Minipool.GetRescueDissolvedDetails() @@ -91,14 +93,14 @@ func rescueDissolved(c *cli.Context) error { fmt.Printf("\nPlease upgrade the delegate for these minipools using `rocketpool minipool delegate-upgrade` before rescuing them.%s\n\n", terminal.ColorReset) } if len(balanceCompletedMinipools) > 0 { - fmt.Printf("%NOTE: The following minipools already have 32 ETH or more deposited:\n", terminal.ColorYellow) + fmt.Printf("%sNOTE: The following minipools already have 32 ETH or more deposited:\n", terminal.ColorYellow) for _, mp := range balanceCompletedMinipools { fmt.Printf("\t%s\n", mp.Address) } fmt.Printf("\nThese minipools don't need to be rescued.%s\n\n", terminal.ColorReset) } if len(invalidBeaconStateMinipools) > 0 { - fmt.Printf("%NOTE: The following minipools have an invalid state on the Beacon Chain (expected 'initialized_pending'):\n", terminal.ColorYellow) + fmt.Printf("%sNOTE: The following minipools have an invalid state on the Beacon Chain (expected 'initialized_pending'):\n", terminal.ColorYellow) for _, mp := range invalidBeaconStateMinipools { fmt.Printf("\t%s (%s)\n", mp.Address, mp.BeaconState) } diff --git a/rocketpool-cli/commands/node/create-vacant-minipool.go b/rocketpool-cli/commands/node/create-vacant-minipool.go index 59b332866..1130c6aa2 100644 --- a/rocketpool-cli/commands/node/create-vacant-minipool.go +++ b/rocketpool-cli/commands/node/create-vacant-minipool.go @@ -26,7 +26,7 @@ func createVacantMinipool(c *cli.Context, pubkey beacon.ValidatorPubkey) error { // Get RP client rp := client.NewClientFromCtx(c) - // Make sure ETH2 is on the correct chain + // Make sure Beacon is on the correct chain depositContractInfo, err := rp.Api.Network.GetDepositContractInfo() if err != nil { return err @@ -41,7 +41,7 @@ func createVacantMinipool(c *cli.Context, pubkey beacon.ValidatorPubkey) error { return nil } - fmt.Println("Your eth2 client is on the correct network.") + fmt.Println("Your Beacon Node is on the correct network.") fmt.Println() // Check if the fee distributor has been initialized diff --git a/rocketpool-cli/commands/node/deposit.go b/rocketpool-cli/commands/node/deposit.go index 4fc0d2dbd..af53ee149 100644 --- a/rocketpool-cli/commands/node/deposit.go +++ b/rocketpool-cli/commands/node/deposit.go @@ -25,7 +25,7 @@ func nodeDeposit(c *cli.Context) error { // Get RP client rp := client.NewClientFromCtx(c) - // Make sure ETH2 is on the correct chain + // Make sure Beacon is on the correct chain depositContractInfo, err := rp.Api.Network.GetDepositContractInfo() if err != nil { return err diff --git a/rocketpool-cli/commands/node/set-smoothing-pool-state.go b/rocketpool-cli/commands/node/set-smoothing-pool-state.go index e65053b55..9857efbcb 100644 --- a/rocketpool-cli/commands/node/set-smoothing-pool-state.go +++ b/rocketpool-cli/commands/node/set-smoothing-pool-state.go @@ -42,13 +42,21 @@ func setSmoothingPoolState(c *cli.Context, optIn bool) error { var identifierMsg string var submitMsg string if optIn { - fmt.Println("You are about to opt into the Smoothing Pool.\nYour fee recipient will be changed to the Smoothing Pool contract.\nAll priority fees and MEV you earn via proposals will be shared equally with other members of the Smoothing Pool.\n\nIf you desire, you can opt back out after one full rewards interval has passed.") + fmt.Println("You are about to opt into the Smoothing Pool.") + fmt.Println("Your fee recipient will be changed to the Smoothing Pool contract.") + fmt.Println("All priority fees and MEV you earn via proposals will be shared equally with other members of the Smoothing Pool.") + fmt.Println() + fmt.Println("If you desire, you can opt back out after one full rewards interval has passed.") fmt.Println() confirmMsg = "Are you sure you want to join the Smoothing Pool?" identifierMsg = "joining Smoothing Pool" submitMsg = "Joining the Smoothing Pool..." } else { - fmt.Println("You are about to opt out of the Smoothing Pool.\nYour fee recipient will be changed back to your node's distributor contract once the next Epoch has been finalized.\nAll priority fees and MEV you earn via proposals will go directly to your distributor and will not be shared by the Smoothing Pool members.\n\nIf you desire, you can opt back in after one full rewards interval has passed.") + fmt.Println("You are about to opt out of the Smoothing Pool.") + fmt.Println("Your fee recipient will be changed back to your node's distributor contract once the next Epoch has been finalized.") + fmt.Println("All priority fees and MEV you earn via proposals will go directly to your distributor and will not be shared by the Smoothing Pool members.") + fmt.Println() + fmt.Println("If you desire, you can opt back in after one full rewards interval has passed.") fmt.Println() confirmMsg = "Are you sure you want to leave the Smoothing Pool?" identifierMsg = "leaving Smoothing Pool" diff --git a/rocketpool-cli/commands/node/utils.go b/rocketpool-cli/commands/node/utils.go index 04bdc4581..79cd76ec3 100644 --- a/rocketpool-cli/commands/node/utils.go +++ b/rocketpool-cli/commands/node/utils.go @@ -15,19 +15,13 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/goccy/go-json" - "github.com/mitchellh/go-homedir" - "github.com/rocket-pool/node-manager-core/beacon" "github.com/urfave/cli/v2" - "gopkg.in/yaml.v2" "github.com/rocket-pool/node-manager-core/eth" - nmc_utils "github.com/rocket-pool/node-manager-core/utils" "github.com/rocket-pool/node-manager-core/utils/math" "github.com/rocket-pool/smartnode/v2/rocketpool-cli/client" "github.com/rocket-pool/smartnode/v2/rocketpool-cli/utils" "github.com/rocket-pool/smartnode/v2/rocketpool-cli/utils/tx" - "github.com/rocket-pool/smartnode/v2/shared/config" - "github.com/rocket-pool/smartnode/v2/shared/types/api" ) const ( @@ -170,7 +164,9 @@ func promptTimezone() string { } } - fmt.Println("You will now be prompted to enter a timezone.\nFor a complete list of valid entries, please use one of the \"TZ database name\" entries listed here:\nhttps://en.wikipedia.org/wiki/List_of_tz_database_time_zones") + fmt.Println("You will now be prompted to enter a timezone.") + fmt.Println("For a complete list of valid entries, please use one of the \"TZ database name\" entries listed here:") + fmt.Println("https://en.wikipedia.org/wiki/List_of_tz_database_time_zones") fmt.Println() // Handle situations where we couldn't parse any timezone info from the OS @@ -197,7 +193,6 @@ func promptTimezone() string { // Prompt for country country := "" for { - timezone = "" country = utils.Prompt("Please enter a country / continent from the list above:", "^.+$", "Please enter a country / continent from the list above:") exists := false @@ -257,7 +252,6 @@ func promptTimezone() string { // Prompt for region region := "" for { - timezone = "" region = utils.Prompt("Please enter a region from the list above:", "^.+$", "Please enter a region from the list above:") exists := false @@ -326,77 +320,6 @@ func promptMinNodeFee(networkCurrentNodeFee, networkMinNodeFee float64) float64 } -// Prompt for the password to a solo validator key as part of migration -func promptForSoloKeyPassword(cfg *config.SmartNodeConfig, pubkey beacon.ValidatorPubkey) (string, error) { - - // Check for the custom key directory - customKeyDir, err := homedir.Expand(cfg.GetCustomKeyPath()) - if err != nil { - return "", fmt.Errorf("error expanding custom keys directory: %w", err) - } - info, err := os.Stat(customKeyDir) - if os.IsNotExist(err) || !info.IsDir() { - return "", nil - } - - // Get the custom keystore files - files, err := os.ReadDir(customKeyDir) - if err != nil { - return "", fmt.Errorf("error enumerating custom keystores: %w", err) - } - if len(files) == 0 { - return "", nil - } - - // Get the pubkeys for the custom keystores - pubkeyPasswords := map[string]string{} - for _, file := range files { - // Read the file - bytes, err := os.ReadFile(filepath.Join(customKeyDir, file.Name())) - if err != nil { - return "", fmt.Errorf("error reading custom keystore %s: %w", file.Name(), err) - } - - // Deserialize it - keystore := api.ValidatorKeystore{} - err = json.Unmarshal(bytes, &keystore) - if err != nil { - return "", fmt.Errorf("error deserializing custom keystore %s: %w", file.Name(), err) - } - - if keystore.Pubkey == pubkey { - // Found it, prompt for the password - password := utils.PromptPassword( - fmt.Sprintf("Please enter the password that the keystore for %s was encrypted with:", pubkey.Hex()), "^.*$", "", - ) - - formattedPubkey := strings.ToUpper(nmc_utils.RemovePrefix(pubkey.Hex())) - pubkeyPasswords[formattedPubkey] = password - - fmt.Println() - break - } - } - - if len(pubkeyPasswords) == 0 { - return "", fmt.Errorf("couldn't find the keystore for validator %s in the custom-keys directory; if you want to import this key into the Smartnode stack, you will need to put its keystore file into custom-keys first", pubkey.HexWithPrefix()) - } - - // Store it in the file - fileBytes, err := yaml.Marshal(pubkeyPasswords) - if err != nil { - return "", fmt.Errorf("error serializing keystore passwords file: %w", err) - } - passwordFile := cfg.GetCustomKeyPasswordFilePath() - err = os.WriteFile(passwordFile, fileBytes, 0600) - if err != nil { - return "", fmt.Errorf("error writing keystore passwords file: %w", err) - } - - return passwordFile, nil - -} - func SwapRpl(c *cli.Context, rp *client.Client, amountWei *big.Int) error { // Get the TX response, err := rp.Api.Node.SwapRpl(amountWei) diff --git a/rocketpool-cli/commands/odao/proposals.go b/rocketpool-cli/commands/odao/proposals.go index 2feecd572..2703eee23 100644 --- a/rocketpool-cli/commands/odao/proposals.go +++ b/rocketpool-cli/commands/odao/proposals.go @@ -92,9 +92,8 @@ func getProposals(c *cli.Context, stateFilter string) error { if bytes.Equal(proposal.ProposerAddress.Bytes(), member.Address.Bytes()) { fmt.Printf("%d: %s - Proposed by: %s (%s)\n", proposal.ID, proposal.Message, member.ID, proposal.ProposerAddress) printed = true + break } - printed = true - break } if !printed { fmt.Printf("%d: %s - Proposed by: %s (no longer on the Oracle DAO)\n", proposal.ID, proposal.Message, proposal.ProposerAddress) diff --git a/rocketpool-cli/commands/service/config/cfg-form.go b/rocketpool-cli/commands/service/config/cfg-form.go index 1fbe2c95b..3898dbc84 100644 --- a/rocketpool-cli/commands/service/config/cfg-form.go +++ b/rocketpool-cli/commands/service/config/cfg-form.go @@ -16,6 +16,7 @@ type parameterizedFormItem struct { item tview.FormItem } +/* func registerEnableCheckbox(param *config.Parameter[bool], checkbox *tview.Checkbox, form *Form, items []*parameterizedFormItem) { checkbox.SetChangedFunc(func(checked bool) { param.Value = checked @@ -29,6 +30,7 @@ func registerEnableCheckbox(param *config.Parameter[bool], checkbox *tview.Check } }) } +*/ // Create a list of form items based on a set of parameters func createParameterizedFormItems(params []config.IParameter, descriptionBox *tview.TextView) []*parameterizedFormItem { diff --git a/rocketpool-cli/commands/service/config/pseudomodal.go b/rocketpool-cli/commands/service/config/pseudomodal.go index 327c9a1ed..624992582 100644 --- a/rocketpool-cli/commands/service/config/pseudomodal.go +++ b/rocketpool-cli/commands/service/config/pseudomodal.go @@ -36,12 +36,6 @@ type Pseudomodal struct { // The currently selected form (for vertical layouts) selected int - - // A fixed width for the description box (0 for auto) - descriptionWidth int - - // The collection of descriptions for each button, to be displayed in the description box - buttonDescriptions []string } // NewPseudomodal returns a new modal message window. diff --git a/rocketpool-cli/commands/service/config/review-native-page.go b/rocketpool-cli/commands/service/config/review-native-page.go index a7c047b82..7eb53077b 100644 --- a/rocketpool-cli/commands/service/config/review-native-page.go +++ b/rocketpool-cli/commands/service/config/review-native-page.go @@ -13,13 +13,6 @@ import ( // Constants const reviewNativePageID string = "review-native-settings" -// The changed settings review page -type ReviewNativePage struct { - md *mainDisplay - changedSettings []*config.ChangedSection - page *page -} - // Create a page to review any changes func NewReviewNativePage(md *mainDisplay, oldConfig *snCfg.SmartNodeConfig, newConfig *snCfg.SmartNodeConfig) *ReviewPage { var changedSettings []*config.ChangedSection diff --git a/rocketpool-cli/commands/service/config/step-random-bn.go b/rocketpool-cli/commands/service/config/step-random-bn.go index 84ea8ad8c..1850ccd82 100644 --- a/rocketpool-cli/commands/service/config/step-random-bn.go +++ b/rocketpool-cli/commands/service/config/step-random-bn.go @@ -9,43 +9,6 @@ import ( const randomBnPrysmID string = "step-random-bn-prysm" const randomBnID string = "step-random-bn" -func createRandomPrysmStep(wiz *wizard, currentStep int, totalSteps int, goodOptions []*config.ParameterOption[config.BeaconNode]) *choiceWizardStep { - helperText := "You have been randomly assigned to Prysm for your Beacon Node.\n\n[orange]NOTE: Prysm currently has a very high representation of the Beacon Chain. For the health of the network and the overall safety of your funds, please consider choosing a client with a lower representation. Please visit https://clientdiversity.org to learn more." - - show := func(modal *choiceModalLayout) { - wiz.md.setPage(modal.page) - modal.focus(0) - } - - done := func(buttonIndex int, buttonLabel string) { - if buttonIndex == 0 { - selectRandomBn(goodOptions, false, wiz, currentStep, totalSteps) - } else { - wiz.checkpointSyncProviderModal.show() - } - } - - back := func() { - wiz.localBnModal.show() - } - - return newChoiceStep( - wiz, - currentStep, - totalSteps, - helperText, - []string{"Choose Another Random Client", "Keep Prysm"}, - []string{}, - 76, - "Beacon Node > Selection", - DirectionalModalHorizontal, - show, - done, - back, - randomBnPrysmID, - ) -} - func createRandomBnStep(wiz *wizard, currentStep int, totalSteps int, goodOptions []*config.ParameterOption[config.BeaconNode]) *choiceWizardStep { var selectedClientName string selectedClient := wiz.md.Config.LocalBeaconClient.BeaconNode.Value diff --git a/rocketpool-cli/commands/service/config/types.go b/rocketpool-cli/commands/service/config/types.go index e122ac3fe..f3bf3eedf 100644 --- a/rocketpool-cli/commands/service/config/types.go +++ b/rocketpool-cli/commands/service/config/types.go @@ -4,7 +4,3 @@ type settingsPage interface { handleLayoutChanged() getPage() *page } - -type wizardStep interface { - show() -} diff --git a/rocketpool-cli/commands/service/config/wizard.go b/rocketpool-cli/commands/service/config/wizard.go index b818396fa..f42506436 100644 --- a/rocketpool-cli/commands/service/config/wizard.go +++ b/rocketpool-cli/commands/service/config/wizard.go @@ -25,7 +25,6 @@ type wizard struct { // Step 5 - BN settings localBnModal *choiceWizardStep localBnRandomModal *choiceWizardStep - localBnRandomPrysmModal *choiceWizardStep localBnPrysmWarning *choiceWizardStep localBnTekuWarning *choiceWizardStep checkpointSyncProviderModal *textBoxWizardStep diff --git a/rocketpool-cli/commands/service/export-ec-data.go b/rocketpool-cli/commands/service/export-ec-data.go index 88708d9e0..d3c6cbab8 100644 --- a/rocketpool-cli/commands/service/export-ec-data.go +++ b/rocketpool-cli/commands/service/export-ec-data.go @@ -57,7 +57,8 @@ func exportEcData(c *cli.Context, targetDir string) error { fmt.Println("This will export your execution client's chain data to an external directory, such as a portable hard drive.") fmt.Println("If your execution client is running, it will be shut down.") - fmt.Println("Once the export is complete, your execution client will restart automatically.\n") + fmt.Println("Once the export is complete, your execution client will restart automatically.") + fmt.Println() // Get the EC volume name executionContainerName := cfg.GetDockerArtifactName(config.ExecutionClientSuffix) diff --git a/rocketpool-cli/commands/service/import-ec-data.go b/rocketpool-cli/commands/service/import-ec-data.go index c5a597ada..55648e0fe 100644 --- a/rocketpool-cli/commands/service/import-ec-data.go +++ b/rocketpool-cli/commands/service/import-ec-data.go @@ -42,7 +42,8 @@ func importEcData(c *cli.Context, sourceDir string) error { fmt.Println("This will import execution layer chain data that you previously exported into your execution client.") fmt.Println("If your execution client is running, it will be shut down.") - fmt.Println("Once the import is complete, your execution client will restart automatically.\n") + fmt.Println("Once the import is complete, your execution client will restart automatically.") + fmt.Println() // Get the volume to import into executionContainerName := cfg.GetDockerArtifactName(config.ExecutionClientSuffix) diff --git a/rocketpool-cli/commands/service/sync.go b/rocketpool-cli/commands/service/sync.go index c356a00bc..7e27a444b 100644 --- a/rocketpool-cli/commands/service/sync.go +++ b/rocketpool-cli/commands/service/sync.go @@ -4,7 +4,6 @@ import ( "fmt" "math" "strings" - "time" "github.com/urfave/cli/v2" @@ -22,11 +21,6 @@ func SyncRatioToPercent(in float64) float64 { // TODO: INCORPORATE THIS } -// Settings -const ( - ethClientRecentBlockThreshold time.Duration = 5 * time.Minute -) - func printClientStatus(status *types.ClientStatus, name string) { if status.Error != "" { @@ -92,7 +86,8 @@ func getSyncProgress(c *cli.Context) error { depositContractInfo.Data.BeaconDepositContract) return nil } else { - fmt.Println("Your Beacon Node is on the correct network.\n") + fmt.Println("Your Beacon Node is on the correct network.") + fmt.Println() } // Get node status diff --git a/rocketpool-cli/commands/service/version.go b/rocketpool-cli/commands/service/version.go index 9ecdd8321..715cf315d 100644 --- a/rocketpool-cli/commands/service/version.go +++ b/rocketpool-cli/commands/service/version.go @@ -83,7 +83,7 @@ func serviceVersion(c *cli.Context) error { case config.ClientMode_External: // Execution client ec := cfg.ExternalExecutionClient.ExecutionClient.Value - ecFormat := "%s (Externally managed)\n\tImage: %s" + ecFormat := "%s (Externally managed)" switch ec { case config.ExecutionClient_Geth: executionClientString = fmt.Sprintf(ecFormat, "Geth") diff --git a/rocketpool-cli/commands/wallet/bip39/mnemonic-validator.go b/rocketpool-cli/commands/wallet/bip39/mnemonic-validator.go index 010ed2fa6..95f3b4adc 100644 --- a/rocketpool-cli/commands/wallet/bip39/mnemonic-validator.go +++ b/rocketpool-cli/commands/wallet/bip39/mnemonic-validator.go @@ -47,7 +47,7 @@ func (mv *MnemonicValidator) Filled() bool { func (mv *MnemonicValidator) Finalize() (string, error) { - if mv.Filled() == false { + if !mv.Filled() { return "", errors.New("Not enough words were entered.") } diff --git a/rocketpool-cli/commands/wallet/utils.go b/rocketpool-cli/commands/wallet/utils.go index 13eb8eec8..889a6c641 100644 --- a/rocketpool-cli/commands/wallet/utils.go +++ b/rocketpool-cli/commands/wallet/utils.go @@ -166,7 +166,7 @@ func promptForCustomKeyPasswords(cfg *config.SmartNodeConfig, testOnly bool) (st // Prompt the user with a warning message if !testOnly { - fmt.Printf("%sWARNING:\nThe Smartnode has detected that you have custom (externally-derived) validator keys for your minipools.\nIf these keys were actively used for validation by a service such as Allnodes, you MUST CONFIRM WITH THAT SERVICE that they have stopped validating and disabled those keys, and will NEVER validate with them again.\nOtherwise, you may both run the same keys at the same time which WILL RESULT IN YOUR VALIDATORS BEING SLASHED.%s\n\n", terminal.ColorRed, terminal.ColorReset) + fmt.Printf("%sWARNING:\nThe Smart Node has detected that you have custom (externally-derived) validator keys for your minipools.\nIf these keys were actively used for validation by a service such as Allnodes, you MUST CONFIRM WITH THAT SERVICE that they have stopped validating and disabled those keys, and will NEVER validate with them again.\nOtherwise, you may both run the same keys at the same time which WILL RESULT IN YOUR VALIDATORS BEING SLASHED.%s\n\n", terminal.ColorRed, terminal.ColorReset) if !utils.Confirm("Please confirm that you have coordinated with the service that was running your minipool validators previously to ensure they have STOPPED validation for your minipools, will NEVER start them again, and you have manually confirmed on a Blockchain explorer such as https://beaconcha.in that your minipools are no longer attesting.") { fmt.Println("Cancelled.") @@ -194,7 +194,9 @@ func promptForCustomKeyPasswords(cfg *config.SmartNodeConfig, testOnly bool) (st } // Notify the user - fmt.Println("It looks like you have some custom keystores for your minipool's validators.\nYou will be prompted for the passwords each one was encrypted with, so they can be loaded into the Validator Client that Rocket Pool manages for you.\n") + fmt.Println("It looks like you have some custom keystores for your minipool's validators.") + fmt.Println("You will be prompted for the passwords each one was encrypted with, so they can be loaded into the Validator Client that Rocket Pool manages for you.") + fmt.Println() // Get the passwords for each one pubkeyPasswords := map[string]string{} @@ -222,14 +224,3 @@ func promptForCustomKeyPasswords(cfg *config.SmartNodeConfig, testOnly bool) (st return passwordFile, nil } - -// Deletes the custom key password file -func deleteCustomKeyPasswordFile(passwordFile string) error { - _, err := os.Stat(passwordFile) - if os.IsNotExist(err) { - return nil - } - - err = os.Remove(passwordFile) - return err -} diff --git a/rocketpool-cli/rocketpool-cli.go b/rocketpool-cli/rocketpool-cli.go index 6bcf26f00..0822d8301 100644 --- a/rocketpool-cli/rocketpool-cli.go +++ b/rocketpool-cli/rocketpool-cli.go @@ -156,7 +156,7 @@ ______ _ _ ______ _ err := validateFlags(c) if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) + fmt.Fprint(os.Stderr, err.Error()) os.Exit(1) } return nil diff --git a/rocketpool-cli/utils/gas/gas.go b/rocketpool-cli/utils/gas/gas.go index 525fe6249..5467bd954 100644 --- a/rocketpool-cli/utils/gas/gas.go +++ b/rocketpool-cli/utils/gas/gas.go @@ -193,7 +193,7 @@ func handleEtherchainGasPrices(gasSuggestion gas.EtherchainGasFeeSuggestion, gas desiredPriceFloat, err := strconv.ParseFloat(desiredPrice, 64) if err != nil { - fmt.Println("Not a valid gas price (%s), try again.", err.Error()) + fmt.Printf("Not a valid gas price (%s), try again.\n", err.Error()) continue } if desiredPriceFloat <= 0 { @@ -271,7 +271,7 @@ func handleEtherscanGasPrices(gasSuggestion gas.EtherscanGasFeeSuggestion, gasIn desiredPriceFloat, err := strconv.ParseFloat(desiredPrice, 64) if err != nil { - fmt.Println("Not a valid gas price (%s), try again.", err.Error()) + fmt.Printf("Not a valid gas price (%s), try again.\n", err.Error()) continue } if desiredPriceFloat <= 0 { diff --git a/rocketpool-cli/utils/migration/import-key.go b/rocketpool-cli/utils/migration/import-key.go index ef5d90bc5..4a593be8e 100644 --- a/rocketpool-cli/utils/migration/import-key.go +++ b/rocketpool-cli/utils/migration/import-key.go @@ -47,7 +47,8 @@ func ImportKey(c *cli.Context, rp *client.Client, minipoolAddress common.Address fmt.Printf("failed!\n%sWARNING: error restarting validator client: %s\n\nPlease restart it manually so it picks up the new validator key for your minipool.%s", terminal.ColorYellow, err.Error(), terminal.ColorReset) return false } - fmt.Println("done!\n") + fmt.Println("done!") + fmt.Println() } return true diff --git a/rocketpool-daemon/api/minipool/can-change-withdrawal-creds.go b/rocketpool-daemon/api/minipool/can-change-withdrawal-creds.go index 2a6b88d01..374ad64e6 100644 --- a/rocketpool-daemon/api/minipool/can-change-withdrawal-creds.go +++ b/rocketpool-daemon/api/minipool/can-change-withdrawal-creds.go @@ -62,7 +62,6 @@ type minipoolCanChangeCredsContext struct { mnemonic string minipoolAddress common.Address - mpMgr *minipool.MinipoolManager mpv3 *minipool.MinipoolV3 } diff --git a/rocketpool-daemon/api/node/deposit.go b/rocketpool-daemon/api/node/deposit.go index 6321b61fc..dc12d9f03 100644 --- a/rocketpool-daemon/api/node/deposit.go +++ b/rocketpool-daemon/api/node/deposit.go @@ -267,10 +267,10 @@ func (c *nodeDepositContext) PrepareData(data *api.NodeDepositData, opts *bind.T if status.Exists { return types.ResponseStatus_InvalidChainState, fmt.Errorf("**** ALERT ****\n"+ "Your minipool %s has the following as a validator pubkey:\n\t%s\n"+ - "This key is already in use by validator %d on the Beacon chain!\n"+ + "This key is already in use by validator %s on the Beacon chain!\n"+ "Rocket Pool will not allow you to deposit this validator for your own safety so you do not get slashed.\n"+ "PLEASE REPORT THIS TO THE ROCKET POOL DEVELOPERS.\n"+ - "***************\n", minipoolAddress.Hex(), pubkey.Hex(), status.Index) + "***************\n", minipoolAddress.Hex(), pubkey.HexWithPrefix(), status.Index) } // Get tx info diff --git a/rocketpool-daemon/api/node/get-snapshot-proposals.go b/rocketpool-daemon/api/node/get-snapshot-proposals.go index 9a4768994..8615fddbf 100644 --- a/rocketpool-daemon/api/node/get-snapshot-proposals.go +++ b/rocketpool-daemon/api/node/get-snapshot-proposals.go @@ -9,8 +9,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/gorilla/mux" batch "github.com/rocket-pool/batch-query" - "github.com/rocket-pool/rocketpool-go/v2/node" - "github.com/rocket-pool/rocketpool-go/v2/rocketpool" "github.com/rocket-pool/node-manager-core/api/server" "github.com/rocket-pool/node-manager-core/api/types" @@ -49,10 +47,8 @@ func (f *nodeGetSnapshotProposalsContextFactory) RegisterRoute(router *mux.Route type nodeGetSnapshotProposalsContext struct { handler *NodeHandler - rp *rocketpool.RocketPool activeOnly bool - node *node.Node } func (c *nodeGetSnapshotProposalsContext) PrepareData(data *api.NodeGetSnapshotProposalsData, opts *bind.TransactOpts) (types.ResponseStatus, error) { diff --git a/rocketpool-daemon/api/node/get-snapshot-voting-power.go b/rocketpool-daemon/api/node/get-snapshot-voting-power.go index 8830ccb6c..5156479db 100644 --- a/rocketpool-daemon/api/node/get-snapshot-voting-power.go +++ b/rocketpool-daemon/api/node/get-snapshot-voting-power.go @@ -5,8 +5,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/gorilla/mux" - "github.com/rocket-pool/rocketpool-go/v2/node" - "github.com/rocket-pool/rocketpool-go/v2/rocketpool" "github.com/rocket-pool/node-manager-core/api/server" "github.com/rocket-pool/node-manager-core/api/types" @@ -41,9 +39,6 @@ func (f *nodeGetSnapshotVotingPowerContextFactory) RegisterRoute(router *mux.Rou type nodeGetSnapshotVotingPowerContext struct { handler *NodeHandler - rp *rocketpool.RocketPool - - node *node.Node } func (c *nodeGetSnapshotVotingPowerContext) PrepareData(data *api.NodeGetSnapshotVotingPowerData, opts *bind.TransactOpts) (types.ResponseStatus, error) { diff --git a/rocketpool-daemon/api/node/rewards.go b/rocketpool-daemon/api/node/rewards.go index 70c653550..903804d3a 100644 --- a/rocketpool-daemon/api/node/rewards.go +++ b/rocketpool-daemon/api/node/rewards.go @@ -91,6 +91,9 @@ func (c *nodeRewardsContext) PrepareData(data *api.NodeRewardsData, opts *bind.T pMgr.GetRewardsPercentages(mc, &percentages) return nil }, nil) + if err != nil { + return types.ResponseStatus_Error, fmt.Errorf("error getting RPL total supply and reward percentages: %w", err) + } // This thing is so complex it's easier to just get the state snapshot and go from there stateMgr, err := state.NewNetworkStateManager(ctx, rp, cfg, ec, bc, nil) diff --git a/rocketpool-daemon/api/pdao/get-claimable-bonds.go b/rocketpool-daemon/api/pdao/get-claimable-bonds.go index c665ad34e..1980203cf 100644 --- a/rocketpool-daemon/api/pdao/get-claimable-bonds.go +++ b/rocketpool-daemon/api/pdao/get-claimable-bonds.go @@ -1,12 +1,10 @@ package pdao import ( - "context" "fmt" "math/big" "net/url" "sort" - "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -234,16 +232,17 @@ func (c *protocolDaoGetClaimableBondsContext) PrepareData(data *api.ProtocolDaoG } // Make sure the prop and challenge are in the right states - if challengeInfo.State != rptypes.ChallengeState_Challenged { - if propInfo.State.Formatted() == rptypes.ProtocolDaoProposalState_Destroyed { - if challengeInfo.State != rptypes.ChallengeState_Responded { - // If the proposal is destroyed, a challenge must be in the challenged or responded states - continue - } - } else { - // Only refund non-responded challenges if the proposal was destroyed - continue - } + if challengeInfo.State == rptypes.ChallengeState_Paid { + // Ignore already paid challenges + continue + } + if challengeInfo.State == rptypes.ChallengeState_Responded && propInfo.State.Formatted() != rptypes.ProtocolDaoProposalState_Destroyed { + // Only refund responded challenges if the proposal was destroyed + continue + } + if challengeInfo.State == rptypes.ChallengeState_Challenged && propInfo.State.Formatted() < rptypes.ProtocolDaoProposalState_QuorumNotMet { + // Unresponded challenges may be claimed after the proposal is finished + continue } // Increment how many refundable challenges we made @@ -319,22 +318,3 @@ func isRewardedIndex(defeatIndex uint64, nodeIndex uint64) bool { } return false } - -func getElBlockForTimestamp(context context.Context, bc beacon.IBeaconClient, beaconCfg beacon.Eth2Config, creationTime time.Time) (*big.Int, error) { - // Get the slot number the first proposal was created on - genesisTime := time.Unix(int64(beaconCfg.GenesisTime), 0) - secondsPerSlot := time.Second * time.Duration(beaconCfg.SecondsPerSlot) - startSlot := uint64(creationTime.Sub(genesisTime) / secondsPerSlot) - - // Get the Beacon block for the slot - block, exists, err := bc.GetBeaconBlock(context, fmt.Sprint(startSlot)) - if err != nil { - return nil, fmt.Errorf("error getting Beacon block at slot %d: %w", startSlot, err) - } - if !exists { - return nil, fmt.Errorf("beacon block at slot %d was missing", startSlot) - } - - // Get the EL block for this slot - return big.NewInt(int64(block.ExecutionBlockNumber)), nil -} diff --git a/rocketpool-daemon/api/pdao/utils.go b/rocketpool-daemon/api/pdao/utils.go index 979579b8b..0d35bfd72 100644 --- a/rocketpool-daemon/api/pdao/utils.go +++ b/rocketpool-daemon/api/pdao/utils.go @@ -32,25 +32,3 @@ func createPollard(context context.Context, logger *slog.Logger, rp *rocketpool. } return blockNumber, pollard, nil } - -// Loads (or regenerates) the pollard for a proposal from a block number -func getPollard(context context.Context, logger *slog.Logger, rp *rocketpool.RocketPool, cfg *config.SmartNodeConfig, bc beacon.IBeaconClient, blockNumber uint32) ([]types.VotingTreeNode, error) { - // Create a proposal manager - propMgr, err := proposals.NewProposalManager(context, logger, cfg, rp, bc) - if err != nil { - return nil, err - } - - // Get the pollard - pollardPtrs, err := propMgr.GetPollardForProposal(blockNumber) - if err != nil { - return nil, err - } - - // Make a slice of nodes from their pointers - pollard := make([]types.VotingTreeNode, len(pollardPtrs)) - for i := range pollardPtrs { - pollard[i] = *pollardPtrs[i] - } - return pollard, nil -} diff --git a/rocketpool-daemon/api/wallet/delete-password.go b/rocketpool-daemon/api/wallet/delete-password.go index 2cb5b94b1..471e66a20 100644 --- a/rocketpool-daemon/api/wallet/delete-password.go +++ b/rocketpool-daemon/api/wallet/delete-password.go @@ -37,9 +37,7 @@ func (f *walletDeletePasswordContextFactory) RegisterRoute(router *mux.Router) { // =============== type walletDeletePasswordContext struct { - handler *WalletHandler - password []byte - save bool + handler *WalletHandler } func (c *walletDeletePasswordContext) PrepareData(data *types.SuccessData, opts *bind.TransactOpts) (types.ResponseStatus, error) { diff --git a/rocketpool-daemon/api/wallet/initialize.go b/rocketpool-daemon/api/wallet/initialize.go index a09b24a44..3b411e741 100644 --- a/rocketpool-daemon/api/wallet/initialize.go +++ b/rocketpool-daemon/api/wallet/initialize.go @@ -53,7 +53,6 @@ type walletInitializeContext struct { derivationPath string index uint64 password string - passwordExists bool savePassword bool saveWallet bool } diff --git a/rocketpool-daemon/api/wallet/search-and-recover.go b/rocketpool-daemon/api/wallet/search-and-recover.go index cb06bbea9..5dd1d1113 100644 --- a/rocketpool-daemon/api/wallet/search-and-recover.go +++ b/rocketpool-daemon/api/wallet/search-and-recover.go @@ -57,7 +57,6 @@ type walletSearchAndRecoverContext struct { mnemonic string address common.Address password string - passwordExists bool savePassword bool } diff --git a/rocketpool-daemon/common/alerting/alerting.go b/rocketpool-daemon/common/alerting/alerting.go index 25458bf71..ad59ce956 100644 --- a/rocketpool-daemon/common/alerting/alerting.go +++ b/rocketpool-daemon/common/alerting/alerting.go @@ -45,7 +45,7 @@ func AlertFeeRecipientChanged(cfg *config.SmartNodeConfig, newFeeRecipient commo return nil } - if cfg.Alertmanager.AlertEnabled_FeeRecipientChanged.Value != true { + if !cfg.Alertmanager.AlertEnabled_FeeRecipientChanged.Value { logMessage("alert for FeeRecipientChanged is disabled, not sending.") return nil } @@ -71,7 +71,7 @@ func AlertMinipoolBondReduced(cfg *config.SmartNodeConfig, minipoolAddress commo return nil } - if cfg.Alertmanager.AlertEnabled_MinipoolBondReduced.Value != true { + if !cfg.Alertmanager.AlertEnabled_MinipoolBondReduced.Value { logMessage("alert for MinipoolBondReduced is disabled, not sending.") return nil } @@ -100,7 +100,7 @@ func AlertMinipoolBalanceDistributed(cfg *config.SmartNodeConfig, minipoolAddres return nil } - if cfg.Alertmanager.AlertEnabled_MinipoolBalanceDistributed.Value != true { + if !cfg.Alertmanager.AlertEnabled_MinipoolBalanceDistributed.Value { logMessage("alert for MinipoolBalanceDistributed is disabled, not sending.") return nil } @@ -128,7 +128,7 @@ func AlertMinipoolPromoted(cfg *config.SmartNodeConfig, minipoolAddress common.A return nil } - if cfg.Alertmanager.AlertEnabled_MinipoolPromoted.Value != true { + if !cfg.Alertmanager.AlertEnabled_MinipoolPromoted.Value { logMessage("alert for MinipoolPromoted is disabled, not sending.") return nil } @@ -156,7 +156,7 @@ func AlertMinipoolStaked(cfg *config.SmartNodeConfig, minipoolAddress common.Add return nil } - if cfg.Alertmanager.AlertEnabled_MinipoolStaked.Value != true { + if !cfg.Alertmanager.AlertEnabled_MinipoolStaked.Value { logMessage("alert for MinipoolStaked is disabled, not sending.") return nil } @@ -193,7 +193,7 @@ func getAlertSettingsForEvent(succeeded bool) (strfmt.DateTime, Severity, string } func AlertExecutionClientSyncComplete(cfg *config.SmartNodeConfig) error { - if cfg.Alertmanager.AlertEnabled_ExecutionClientSyncComplete.Value != true { + if !cfg.Alertmanager.AlertEnabled_ExecutionClientSyncComplete.Value { logMessage("alert for ExecutionClientSyncComplete is disabled, not sending.") return nil } @@ -201,7 +201,7 @@ func AlertExecutionClientSyncComplete(cfg *config.SmartNodeConfig) error { } func AlertBeaconClientSyncComplete(cfg *config.SmartNodeConfig) error { - if cfg.Alertmanager.AlertEnabled_BeaconClientSyncComplete.Value != true { + if !cfg.Alertmanager.AlertEnabled_BeaconClientSyncComplete.Value { logMessage("alert for BeaconClientSyncComplete is disabled, not sending.") return nil } diff --git a/rocketpool-daemon/common/proposals/proposal-manager.go b/rocketpool-daemon/common/proposals/proposal-manager.go index 73bb3e927..09c07037c 100644 --- a/rocketpool-daemon/common/proposals/proposal-manager.go +++ b/rocketpool-daemon/common/proposals/proposal-manager.go @@ -158,6 +158,9 @@ func (m *ProposalManager) GetNodeTree(blockNumber uint32, nodeIndex uint64, snap if tree != nil { return tree, nil } + if err != nil { + return nil, err + } // Try to load the voting info snapshot from disk or create it m.logger.Info("Creating node tree...", slog.Uint64(keys.BlockKey, uint64(blockNumber)), slog.Uint64(keys.NodeIndexKey, nodeIndex)) diff --git a/rocketpool-daemon/common/rewards/files_test.go b/rocketpool-daemon/common/rewards/files_test.go index 5222b8605..8cad3fd4f 100644 --- a/rocketpool-daemon/common/rewards/files_test.go +++ b/rocketpool-daemon/common/rewards/files_test.go @@ -60,7 +60,7 @@ func TestFilesFromTree(t *testing.T) { ) } - localMinipoolPerformanceFile, err = ReadLocalMinipoolPerformanceFile(path.Join(dir, "performance.json")) + _, err = ReadLocalMinipoolPerformanceFile(path.Join(dir, "performance.json")) if err != nil { t.Fatal(err) } diff --git a/rocketpool-daemon/common/rewards/prater-events.go b/rocketpool-daemon/common/rewards/prater-events.go deleted file mode 100644 index b1f76dcda..000000000 --- a/rocketpool-daemon/common/rewards/prater-events.go +++ /dev/null @@ -1,132 +0,0 @@ -package rewards - -import ( - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/rocket-pool/rocketpool-go/v2/rewards" -) - -// This file contains hardcoded events for Prater for the intervals before the contracts emitted rewards snapshot events, -// so the Smartnode has something to "look up" during events collection. -var praterPrehistoryIntervalEvents []rewards.RewardsEvent = []rewards.RewardsEvent{ - // TX: 0xe90cb89e2f83fb6577a9cb27421ec802df090fea1b156fea8444d57e0c41040a - { - Index: big.NewInt(0), - ExecutionBlock: big.NewInt(7279809), - ConsensusBlock: big.NewInt(3509855), - MerkleRoot: common.HexToHash("0xae2f4ca79cb5176e7262201486739c614fd9197a9d95b1a28da23498a25000c4"), - MerkleTreeCID: "bafybeifcixenfbmzsbaar7zowpiyn3rh42px2sgci3zhc3oecr5ixfm754", - IntervalsPassed: big.NewInt(2), - TreasuryRPL: parseBigInt("3389231943988237492628"), - TrustedNodeRPL: []*big.Int{parseBigInt("3389231943988237492032")}, - NodeRPL: []*big.Int{parseBigInt("15816415738611774962240")}, - NodeETH: []*big.Int{big.NewInt(0)}, - UserETH: big.NewInt(0), - IntervalStartTime: time.Unix(1658107596, 0), - IntervalEndTime: time.Unix(1658625996, 0), - SubmissionTime: time.Unix(1658740664, 0), - }, - - // TX: 0x054bf4ca2c8649199b70f87ee6dec96eabb3184b77d8d396e85cb46c693acc19 - { - Index: big.NewInt(1), - ExecutionBlock: big.NewInt(7296892), - ConsensusBlock: big.NewInt(3531455), - MerkleRoot: common.HexToHash("0x76a5d0de3c7f92dab4d606c7a66246c07d4dc4003e330fc645541e828e8d11eb"), - MerkleTreeCID: "bafybeifhelxls7xsdeh4j7gokmqfherpzoyzo576s2j5gi42wl7zyhukeq", - IntervalsPassed: big.NewInt(1), - TreasuryRPL: parseBigInt("1134827945857665760894"), - TrustedNodeRPL: []*big.Int{parseBigInt("1134827945857665760312")}, - NodeRPL: []*big.Int{parseBigInt("5295863747335773547586")}, - NodeETH: []*big.Int{big.NewInt(565216198390830158)}, - UserETH: big.NewInt(0), - IntervalStartTime: time.Unix(1658625996, 0), - IntervalEndTime: time.Unix(1658885196, 0), - SubmissionTime: time.Unix(1658887477, 0), - }, - - // TX: 0xb70877c8cb8f63f59f67a2460f261b317d122349d869fea0796b7c692751eba7 - { - Index: big.NewInt(2), - ExecutionBlock: big.NewInt(7314096), - ConsensusBlock: big.NewInt(3553055), - MerkleRoot: common.HexToHash("0x2ef194dbd254c797c263089f9aa49132843a4b2881a2e8aa9c7456a06a59e6a4"), - MerkleTreeCID: "bafybeihsny3shsgsgiaft3u5oceur2wwj2quyspws7wceqpo6rlinriu3q", - IntervalsPassed: big.NewInt(1), - TreasuryRPL: parseBigInt("1135283120200590076960"), - TrustedNodeRPL: []*big.Int{parseBigInt("1135283120200590076448")}, - NodeRPL: []*big.Int{parseBigInt("5297987894269420356281")}, - NodeETH: []*big.Int{big.NewInt(245851786378530887)}, - UserETH: big.NewInt(0), - IntervalStartTime: time.Unix(1658885196, 0), - IntervalEndTime: time.Unix(1659144396, 0), - SubmissionTime: time.Unix(1659146709, 0), - }, - - // TX: 0x36baad3ecb07d9c1751b3f76f7378c23c0844296a333eafaa42d3fced5be0e93 - { - Index: big.NewInt(3), - ExecutionBlock: big.NewInt(7331289), - ConsensusBlock: big.NewInt(3574655), - MerkleRoot: common.HexToHash("0x64a1cba078633b82c12e32f5e6d94117c85bb41cfa1e237b60757d7e45d92ecb"), - MerkleTreeCID: "bafybeigbmzcdw2dbil5qkqiztqf3httceyd2fitwtk3aaf5x533x67dk2i", - IntervalsPassed: big.NewInt(1), - TreasuryRPL: parseBigInt("1135738477111879239196"), - TrustedNodeRPL: []*big.Int{parseBigInt("1135738477111879238408")}, - NodeRPL: []*big.Int{parseBigInt("5300112893188769778496")}, - NodeETH: []*big.Int{big.NewInt(106846466469715898)}, - UserETH: big.NewInt(0), - IntervalStartTime: time.Unix(1659144396, 0), - IntervalEndTime: time.Unix(1659403596, 0), - SubmissionTime: time.Unix(1659406463, 0), - }, - - // TX: 0xbd46261e656c6f446a127ca58484e1c9c6a68e735e2cb32d90a290062cb4efd9 - { - Index: big.NewInt(4), - ExecutionBlock: big.NewInt(7382763), - ConsensusBlock: big.NewInt(3639455), - MerkleRoot: common.HexToHash("0x7ff29433dead5b3f4f289b7ecbede03e0b8a2377748191584471283035e93fed"), - MerkleTreeCID: "bafybeiezkea32s4npgwv3nlkjfn6er4ohhiamnkl2if5ugf7cqmd5dnjne", - IntervalsPassed: big.NewInt(3), - TreasuryRPL: parseBigInt("3409949399585607533077"), - TrustedNodeRPL: []*big.Int{parseBigInt("3409949399585607532568")}, - NodeRPL: []*big.Int{parseBigInt("15913097198066168484824")}, - NodeETH: []*big.Int{parseBigInt("23844561349772065836")}, - UserETH: big.NewInt(0), - IntervalStartTime: time.Unix(1659403596, 0), - IntervalEndTime: time.Unix(1660181196, 0), - SubmissionTime: time.Unix(1660252236, 0), - }, - - // TX: 0xab81c7882d1646c31acab36145739ed87f76693e23eba50171a1dffd2d8aa4e0 - { - Index: big.NewInt(5), - ExecutionBlock: big.NewInt(7400317), - ConsensusBlock: big.NewInt(3661055), - MerkleRoot: common.HexToHash("0x9b6b9689f5638b3a86b356b3c5acdc44167c25415a3e3209c5c78a5f92567bb8"), - MerkleTreeCID: "bafybeiaukxxdzni6twjvebjamomtdkic4knccqdgdjwiunqfzfzohwtgq4", - IntervalsPassed: big.NewInt(1), - TreasuryRPL: parseBigInt("1137561731905671847934"), - TrustedNodeRPL: []*big.Int{parseBigInt("1137561731905671847312")}, - NodeRPL: []*big.Int{parseBigInt("5308621415559801953508")}, - NodeETH: []*big.Int{parseBigInt("10484778253257561700")}, - UserETH: big.NewInt(0), - IntervalStartTime: time.Unix(1660181196, 0), - IntervalEndTime: time.Unix(1660440396, 0), - SubmissionTime: time.Unix(1660609908, 0), - }, -} - -// Parses a string into a BigInt, panicking if it's not legal -func parseBigInt(number string) *big.Int { - result, success := big.NewInt(0).SetString(number, 10) - if !success { - panic(fmt.Sprintf("Error parsing Prater precompiled value %s", number)) - } - - return result -} diff --git a/rocketpool-daemon/common/state/network-state.go b/rocketpool-daemon/common/state/network-state.go index 3f111a2d3..d5f338862 100644 --- a/rocketpool-daemon/common/state/network-state.go +++ b/rocketpool-daemon/common/state/network-state.go @@ -337,7 +337,8 @@ func CreateNetworkStateForNode(cfg *config.SmartNodeConfig, rp *rocketpool.Rocke return nil, nil, fmt.Errorf("error getting Protocol DAO proposal details: %w", err) } logger.Info(fmt.Sprintf("%d/%d - Retrieved Protocol DAO proposals", currentStep, steps), slog.Duration(keys.TotalElapsedKey, time.Since(start))) - currentStep++ + // If adding more steps below, don't forget to increment currentStep: + // currentStep++ return state, totalEffectiveStake, nil } diff --git a/rocketpool-daemon/common/validator/next-account.go b/rocketpool-daemon/common/validator/next-account.go index c50354da9..466906a8e 100644 --- a/rocketpool-daemon/common/validator/next-account.go +++ b/rocketpool-daemon/common/validator/next-account.go @@ -6,6 +6,7 @@ import ( "io/fs" "os" "strconv" + "strings" "github.com/rocket-pool/node-manager-core/node/wallet" ) @@ -28,6 +29,7 @@ func loadNextAccount(nextAccountPath string) (uint64, error) { // Parse the account nextAccountString := string(bytes) + nextAccountString = strings.TrimSpace(nextAccountString) nextAccount, err := strconv.ParseUint(nextAccountString, 10, 64) if err != nil { return 0, fmt.Errorf("error parsing next account data at [%s]: %w", nextAccountPath, err) diff --git a/rocketpool-daemon/node/collectors/supply-collector.go b/rocketpool-daemon/node/collectors/supply-collector.go index 4aa0bc372..86f798312 100644 --- a/rocketpool-daemon/node/collectors/supply-collector.go +++ b/rocketpool-daemon/node/collectors/supply-collector.go @@ -86,7 +86,6 @@ func (c *SupplyCollector) Collect(channel chan<- prometheus.Metric) { } // Sync - nodeCount := float64(-1) nodeFee := state.NetworkDetails.NodeFee initializedCount := float64(-1) prelaunchCount := float64(-1) @@ -95,7 +94,7 @@ func (c *SupplyCollector) Collect(channel chan<- prometheus.Metric) { finalizedCount := float64(-1) // Get total number of Rocket Pool nodes - nodeCount = float64(len(state.NodeDetails)) + nodeCount := float64(len(state.NodeDetails)) // Get the total number of Rocket Pool minipools for _, mpd := range state.MinipoolDetails { diff --git a/rocketpool-daemon/node/collectors/trusted-node-collector.go b/rocketpool-daemon/node/collectors/trusted-node-collector.go index 83d08def0..0d6cdff89 100644 --- a/rocketpool-daemon/node/collectors/trusted-node-collector.go +++ b/rocketpool-daemon/node/collectors/trusted-node-collector.go @@ -3,7 +3,6 @@ package collectors import ( "log/slog" "strconv" - "time" "github.com/ethereum/go-ethereum/common" "github.com/prometheus/client_golang/prometheus" @@ -42,8 +41,6 @@ type TrustedNodeCollector struct { // The logger logger *slog.Logger - // Cached data - cacheTime time.Time cachedMetrics []prometheus.Metric // The thread-safe locker for the network state diff --git a/rocketpool-daemon/node/verify-pdao-props.go b/rocketpool-daemon/node/verify-pdao-props.go index dda9e90af..776b9cba1 100644 --- a/rocketpool-daemon/node/verify-pdao-props.go +++ b/rocketpool-daemon/node/verify-pdao-props.go @@ -299,15 +299,16 @@ func (t *VerifyPdaoProps) getChallengeOrDefeatForProposal(prop *protocol.Protoco } // Check if the index has been challenged yet - var state func() types.ChallengeState + var getState func() types.ChallengeState err = t.rp.Query(func(mc *batch.MultiCaller) error { - prop.GetChallengeState(mc, newChallengedIndex) + getState = prop.GetChallengeState(mc, newChallengedIndex) return nil }, opts) if err != nil { return nil, nil, fmt.Errorf("error checking challenge state for proposal %d, index %d: %w", prop.ID, challengedIndex, err) } - switch state() { + state := getState() + switch state { case types.ChallengeState_Unchallenged: // If it's unchallenged, this is the index to challenge return &challenge{ diff --git a/rocketpool-daemon/watchtower/generate-rewards-tree.go b/rocketpool-daemon/watchtower/generate-rewards-tree.go index 805ab7cc3..b5aa565dc 100644 --- a/rocketpool-daemon/watchtower/generate-rewards-tree.go +++ b/rocketpool-daemon/watchtower/generate-rewards-tree.go @@ -231,7 +231,7 @@ func (t *GenerateRewardsTree) generateRewardsTreeImpl(logger *slog.Logger, rp *r } rewardsFile, err := treegen.GenerateTree(t.ctx) if err != nil { - t.handleError(fmt.Errorf("%s Error generating Merkle tree: %w", err), logger) + t.handleError(fmt.Errorf("Error generating Merkle tree: %w", err), logger) return } header := rewardsFile.GetHeader() diff --git a/rocketpool-daemon/watchtower/submit-network-balances.go b/rocketpool-daemon/watchtower/submit-network-balances.go index a6d6c0894..23b0bfb30 100644 --- a/rocketpool-daemon/watchtower/submit-network-balances.go +++ b/rocketpool-daemon/watchtower/submit-network-balances.go @@ -41,16 +41,17 @@ const ( // Submit network balances task type SubmitNetworkBalances struct { - ctx context.Context - sp *services.ServiceProvider - logger *slog.Logger - cfg *config.SmartNodeConfig - w *wallet.Wallet - ec eth.IExecutionClient - rp *rocketpool.RocketPool - bc beacon.IBeaconClient - lock *sync.Mutex - isRunning bool + ctx context.Context + sp *services.ServiceProvider + logger *slog.Logger + cfg *config.SmartNodeConfig + w *wallet.Wallet + ec eth.IExecutionClient + rp *rocketpool.RocketPool + bc beacon.IBeaconClient + eventLogInterval *big.Int + lock *sync.Mutex + isRunning bool } // Network balance info @@ -75,16 +76,17 @@ type minipoolBalanceDetails struct { func NewSubmitNetworkBalances(ctx context.Context, sp *services.ServiceProvider, logger *log.Logger) *SubmitNetworkBalances { lock := &sync.Mutex{} return &SubmitNetworkBalances{ - ctx: ctx, - sp: sp, - logger: logger.With(slog.String(keys.TaskKey, "Balance Report")), - cfg: sp.GetConfig(), - w: sp.GetWallet(), - ec: sp.GetEthClient(), - rp: sp.GetRocketPool(), - bc: sp.GetBeaconClient(), - lock: lock, - isRunning: false, + ctx: ctx, + sp: sp, + logger: logger.With(slog.String(keys.TaskKey, "Balance Report")), + cfg: sp.GetConfig(), + w: sp.GetWallet(), + ec: sp.GetEthClient(), + rp: sp.GetRocketPool(), + bc: sp.GetBeaconClient(), + eventLogInterval: big.NewInt(int64(config.EventLogInterval)), + lock: lock, + isRunning: false, } } @@ -95,18 +97,18 @@ func (t *SubmitNetworkBalances) Run(state *state.NetworkState) error { return nil } - // Make a new RP binding just for this portion - rp := t.sp.GetRocketPool() + // Log + t.logger.Info("Starting network balance check.") // Check the last submission block lastSubmissionBlock := state.NetworkDetails.BalancesBlock.Uint64() - networkMgr, err := network.NewNetworkManager(rp) + networkMgr, err := network.NewNetworkManager(t.rp) if err != nil { return fmt.Errorf("error creating network manager binding: %w", err) } // Get the last balances updated event - found, event, err := networkMgr.GetBalancesUpdatedEvent(lastSubmissionBlock, nil) + found, event, err := networkMgr.GetBalancesUpdatedEvent(lastSubmissionBlock, t.eventLogInterval, nil, nil) if err != nil { return fmt.Errorf("error getting event for balances updated on block %d: %w", lastSubmissionBlock, err) } @@ -114,16 +116,20 @@ func (t *SubmitNetworkBalances) Run(state *state.NetworkState) error { // Get the duration in seconds for the interval between submissions submissionIntervalDuration := time.Duration(state.NetworkDetails.BalancesSubmissionFrequency * uint64(time.Second)) eth2Config := state.BeaconConfig + t.logger.Debug("Got last submission block and interval duration.", + slog.Uint64(keys.BlockKey, lastSubmissionBlock), + slog.Duration(keys.IntervalKey, submissionIntervalDuration), + ) var nextSubmissionTime time.Time if !found { // The first submission after Houston is deployed won't find an event emitted by this contract // The submission time will be adjusted to align with the reward time - rewardsPool, err := rewards.NewRewardsPool(rp) + rewardsPool, err := rewards.NewRewardsPool(t.rp) if err != nil { return fmt.Errorf("error creating rewards pool binding: %w", err) } - err = rp.Query(nil, nil, + err = t.rp.Query(nil, nil, rewardsPool.IntervalStart, rewardsPool.IntervalDuration, ) @@ -141,22 +147,34 @@ func (t *SubmitNetworkBalances) Run(state *state.NetworkState) error { submissionsUntilNextCheckpoint := int(timeDifference/submissionIntervalDuration) + 1 nextSubmissionTime = nextCheckpoint.Add(-time.Duration(submissionsUntilNextCheckpoint) * submissionIntervalDuration) + + t.logger.Debug("Balances updated event not found, using rewards pool", + slog.Time(keys.StartKey, lastCheckpoint), + slog.Duration(keys.IntervalKey, rewardsInterval), + slog.Time(keys.NextKey, nextCheckpoint), + ) } else { // Get the last submission reference time lastSubmissionTime := event.SlotTimestamp // Next submission adds the interval time to the last submission time nextSubmissionTime = lastSubmissionTime.Add(submissionIntervalDuration) + + t.logger.Debug("Found balances updated event", + slog.Uint64(keys.SubmittedKey, event.BlockNumber), + ) } + t.logger.Debug("Checking next submission time", + slog.Time(keys.TimeKey, time.Now().UTC()), + slog.Time(keys.NextKey, nextSubmissionTime), + ) + // Return if the time to submit has not arrived if time.Now().Before(nextSubmissionTime) { return nil } - // Log - t.logger.Info("Starting network balance check.") - // Get the Beacon block corresponding to this time genesisTime := time.Unix(int64(eth2Config.GenesisTime), 0) timeSinceGenesis := nextSubmissionTime.Sub(genesisTime) diff --git a/rocketpool-daemon/watchtower/submit-rpl-price.go b/rocketpool-daemon/watchtower/submit-rpl-price.go index d8de1f299..aae7c5f18 100644 --- a/rocketpool-daemon/watchtower/submit-rpl-price.go +++ b/rocketpool-daemon/watchtower/submit-rpl-price.go @@ -43,31 +43,34 @@ const ( // Submit RPL price task type SubmitRplPrice struct { - ctx context.Context - sp *services.ServiceProvider - logger *slog.Logger - cfg *config.SmartNodeConfig - ec eth.IExecutionClient - w *wallet.Wallet - rp *rocketpool.RocketPool - bc beacon.IBeaconClient - lock *sync.Mutex - isRunning bool + ctx context.Context + sp *services.ServiceProvider + logger *slog.Logger + cfg *config.SmartNodeConfig + ec eth.IExecutionClient + w *wallet.Wallet + rp *rocketpool.RocketPool + bc beacon.IBeaconClient + eventLogInterval *big.Int + lock *sync.Mutex + isRunning bool } // Create submit RPL price task func NewSubmitRplPrice(ctx context.Context, sp *services.ServiceProvider, logger *log.Logger) *SubmitRplPrice { lock := &sync.Mutex{} return &SubmitRplPrice{ - ctx: ctx, - sp: sp, - logger: logger.With(slog.String(keys.TaskKey, "Price Report")), - cfg: sp.GetConfig(), - ec: sp.GetEthClient(), - w: sp.GetWallet(), - rp: sp.GetRocketPool(), - bc: sp.GetBeaconClient(), - lock: lock, + ctx: ctx, + sp: sp, + logger: logger.With(slog.String(keys.TaskKey, "Price Report")), + cfg: sp.GetConfig(), + ec: sp.GetEthClient(), + w: sp.GetWallet(), + rp: sp.GetRocketPool(), + bc: sp.GetBeaconClient(), + eventLogInterval: big.NewInt(int64(config.EventLogInterval)), + lock: lock, + isRunning: false, } } @@ -82,7 +85,7 @@ func (t *SubmitRplPrice) Run(state *state.NetworkState) error { err := t.updateL2Prices(state) if err != nil { // Error is not fatal for this task so print and continue - t.logger.Error("Error updating L2 prices: %s", err.Error()) + t.logger.Error("Error updating L2 prices", log.Err(err)) } // Make a new RP binding just for this portion @@ -96,7 +99,7 @@ func (t *SubmitRplPrice) Run(state *state.NetworkState) error { } // Get the last prices updated event - found, event, err := networkMgr.GetPriceUpdatedEvent(lastSubmissionBlock, nil) + found, event, err := networkMgr.GetPriceUpdatedEvent(lastSubmissionBlock, t.eventLogInterval, nil, nil) if err != nil { return fmt.Errorf("error getting event for price updated on block %d: %w", lastSubmissionBlock, err) } diff --git a/shared/config/resources.go b/shared/config/resources.go index fc98dcd3f..38f4da5f0 100644 --- a/shared/config/resources.go +++ b/shared/config/resources.go @@ -51,10 +51,10 @@ type RocketPoolResources struct { V1_1_0_MinipoolFactoryAddress *common.Address // The contract address of rocketNetworkPrices from v1.2.0 - v1_2_0_NetworkPricesAddress *common.Address + V1_2_0_NetworkPricesAddress *common.Address // The contract address of rocketNetworkBalances from v1.2.0 - v1_2_0_NetworkBalancesAddress *common.Address + V1_2_0_NetworkBalancesAddress *common.Address // The contract address for Snapshot delegation SnapshotDelegationAddress *common.Address @@ -120,8 +120,8 @@ func newRocketPoolResources(network config.Network) *RocketPoolResources { V1_1_0_NodeDepositAddress: hexToAddressPtr("0x1Cc9cF5586522c6F483E84A19c3C2B0B6d027bF0"), V1_1_0_MinipoolQueueAddress: hexToAddressPtr("0x5870dA524635D1310Dc0e6F256Ce331012C9C19E"), V1_1_0_MinipoolFactoryAddress: hexToAddressPtr("0x54705f80D7C51Fcffd9C659ce3f3C9a7dCCf5788"), - v1_2_0_NetworkPricesAddress: hexToAddressPtr("0x751826b107672360b764327631cC5764515fFC37"), - v1_2_0_NetworkBalancesAddress: hexToAddressPtr("0x07FCaBCbe4ff0d80c2b1eb42855C0131b6cba2F4"), + V1_2_0_NetworkPricesAddress: hexToAddressPtr("0x751826b107672360b764327631cC5764515fFC37"), + V1_2_0_NetworkBalancesAddress: hexToAddressPtr("0x07FCaBCbe4ff0d80c2b1eb42855C0131b6cba2F4"), SnapshotDelegationAddress: hexToAddressPtr("0x469788fE6E9E9681C6ebF3bF78e7Fd26Fc015446"), SnapshotApiDomain: "hub.snapshot.org", PreviousRewardsPoolAddresses: []common.Address{ @@ -161,8 +161,8 @@ func newRocketPoolResources(network config.Network) *RocketPoolResources { V1_1_0_NodeDepositAddress: nil, V1_1_0_MinipoolQueueAddress: nil, V1_1_0_MinipoolFactoryAddress: nil, - v1_2_0_NetworkPricesAddress: hexToAddressPtr("0x029d946F28F93399a5b0D09c879FC8c94E596AEb"), - v1_2_0_NetworkBalancesAddress: hexToAddressPtr("0x9294Fc6F03c64Cc217f5BE8697EA3Ed2De77e2F8"), + V1_2_0_NetworkPricesAddress: hexToAddressPtr("0x029d946F28F93399a5b0D09c879FC8c94E596AEb"), + V1_2_0_NetworkBalancesAddress: hexToAddressPtr("0x9294Fc6F03c64Cc217f5BE8697EA3Ed2De77e2F8"), SnapshotDelegationAddress: nil, SnapshotApiDomain: "", PreviousRewardsPoolAddresses: []common.Address{}, @@ -200,8 +200,8 @@ func newRocketPoolResources(network config.Network) *RocketPoolResources { V1_1_0_NodeDepositAddress: nil, V1_1_0_MinipoolQueueAddress: nil, V1_1_0_MinipoolFactoryAddress: nil, - v1_2_0_NetworkPricesAddress: hexToAddressPtr("0xBba3FBCD4Bdbfc79118B1B31218602E5A71B426c"), - v1_2_0_NetworkBalancesAddress: hexToAddressPtr("0xBe8Dc8CA5f339c196Aef634DfcDFbA61E30DC743"), + V1_2_0_NetworkPricesAddress: hexToAddressPtr("0xBba3FBCD4Bdbfc79118B1B31218602E5A71B426c"), + V1_2_0_NetworkBalancesAddress: hexToAddressPtr("0xBe8Dc8CA5f339c196Aef634DfcDFbA61E30DC743"), SnapshotDelegationAddress: nil, SnapshotApiDomain: "", PreviousRewardsPoolAddresses: []common.Address{ diff --git a/shared/config/smartnode-config.go b/shared/config/smartnode-config.go index e652dc34e..ac3248c00 100644 --- a/shared/config/smartnode-config.go +++ b/shared/config/smartnode-config.go @@ -9,7 +9,6 @@ import ( "strings" "github.com/alessio/shellescape" - "github.com/pbnjay/memory" "github.com/rocket-pool/node-manager-core/config" "github.com/rocket-pool/smartnode/v2/shared" "github.com/rocket-pool/smartnode/v2/shared/config/ids" @@ -198,7 +197,7 @@ func NewSmartNodeConfig(rpDir string, isNativeMode bool) *SmartNodeConfig { ID: ids.WatchtowerStatePath, Name: "Watchtower Path", Description: "The absolute path of the watchtower state folder that contains persistent state that is used by the watchtower process on trusted nodes. **Only relevant for trusted nodes.**", - AffectsContainers: []config.ContainerID{}, + AffectsContainers: []config.ContainerID{config.ContainerID_Daemon}, CanBeBlank: false, OverwriteOnUpgrade: false, }, @@ -297,7 +296,7 @@ func NewSmartNodeConfig(rpDir string, isNativeMode bool) *SmartNodeConfig { ID: ids.RewardsTreeCustomUrlID, Name: "Rewards Tree Custom Download URLs", Description: "The Smartnode will automatically download missing rewards tree files from trusted sources like IPFS and Rocket Pool's repository on GitHub. Use this field if you would like to manually specify additional sources that host the rewards tree files, so the Smartnode can download from them as well.\nMultiple URLs can be provided using ';' as separator).\n\nUse '%s' to specify the location of the rewards file name in the URL - for example: `https://my-cool-domain.com/rewards-trees/mainnet/%s`.", - AffectsContainers: []config.ContainerID{}, + AffectsContainers: []config.ContainerID{config.ContainerID_Daemon}, CanBeBlank: true, OverwriteOnUpgrade: false, }, @@ -311,7 +310,7 @@ func NewSmartNodeConfig(rpDir string, isNativeMode bool) *SmartNodeConfig { ID: ids.ArchiveEcUrlID, Name: "Archive-Mode EC URL", Description: "[orange]**For manual Merkle rewards tree generation only.**[white]\n\nGenerating the Merkle rewards tree files for past rewards intervals typically requires an Execution client with Archive mode enabled, which is usually disabled on your primary and fallback Execution clients to save disk space.\nIf you want to generate your own rewards tree files for intervals from a long time ago, you may enter the URL of an Execution client with Archive access here.\n\nFor a free light client with Archive access, you may use https://www.alchemy.com/supernode.", - AffectsContainers: []config.ContainerID{}, + AffectsContainers: []config.ContainerID{config.ContainerID_Daemon}, CanBeBlank: true, OverwriteOnUpgrade: false, }, @@ -325,7 +324,7 @@ func NewSmartNodeConfig(rpDir string, isNativeMode bool) *SmartNodeConfig { ID: ids.WatchtowerMaxFeeOverrideID, Name: "Watchtower Max Fee Override", Description: fmt.Sprintf("[orange]**For Oracle DAO members only.**\n\n[white]Use this to override the max fee (in gwei) for watchtower transactions. Note that if you set it below %d, the setting will be ignored; it can only be used to set the max fee higher than %d during times of extreme network stress.", WatchtowerMaxFeeDefault, WatchtowerMaxFeeDefault), - AffectsContainers: []config.ContainerID{}, + AffectsContainers: []config.ContainerID{config.ContainerID_Daemon}, CanBeBlank: false, OverwriteOnUpgrade: true, }, @@ -339,7 +338,7 @@ func NewSmartNodeConfig(rpDir string, isNativeMode bool) *SmartNodeConfig { ID: ids.WatchtowerPriorityFeeOverrideID, Name: "Watchtower Priority Fee Override", Description: fmt.Sprintf("[orange]**For Oracle DAO members only.**\n\n[white]Use this to override the priority fee (in gwei) for watchtower transactions. Note that if you set it below %d, the setting will be ignored; it can only be used to set the priority fee higher than %d during times of extreme network stress.", WatchtowerPriorityFeeDefault, WatchtowerPriorityFeeDefault), - AffectsContainers: []config.ContainerID{}, + AffectsContainers: []config.ContainerID{config.ContainerID_Daemon}, CanBeBlank: false, OverwriteOnUpgrade: true, }, @@ -353,7 +352,7 @@ func NewSmartNodeConfig(rpDir string, isNativeMode bool) *SmartNodeConfig { ID: ids.UseRollingRecordsID, Name: "Use Rolling Records", Description: "Enable this to use the new rolling records feature, which stores attestation records for the entire Rocket Pool network in real time instead of collecting them all after a rewards period during tree generation.\n\nOnly useful for the Oracle DAO, or if you generate your own rewards trees.", - AffectsContainers: []config.ContainerID{}, + AffectsContainers: []config.ContainerID{config.ContainerID_Daemon}, CanBeBlank: false, OverwriteOnUpgrade: false, }, @@ -367,7 +366,7 @@ func NewSmartNodeConfig(rpDir string, isNativeMode bool) *SmartNodeConfig { ID: ids.RecordCheckpointIntervalID, Name: "Record Checkpoint Interval", Description: "The number of epochs that should pass before saving a new rolling record checkpoint. Used if Rolling Records is enabled.\n\nOnly useful for the Oracle DAO, or if you generate your own rewards trees.", - AffectsContainers: []config.ContainerID{}, + AffectsContainers: []config.ContainerID{config.ContainerID_Daemon}, CanBeBlank: false, OverwriteOnUpgrade: false, }, @@ -381,7 +380,7 @@ func NewSmartNodeConfig(rpDir string, isNativeMode bool) *SmartNodeConfig { ID: ids.CheckpointRetentionLimitID, Name: "Checkpoint Retention Limit", Description: "The number of checkpoint files to save on-disk before pruning old ones. Used if Rolling Records is enabled.\n\nOnly useful for the Oracle DAO, or if you generate your own rewards trees.", - AffectsContainers: []config.ContainerID{}, + AffectsContainers: []config.ContainerID{config.ContainerID_Daemon}, CanBeBlank: false, OverwriteOnUpgrade: false, }, @@ -395,7 +394,7 @@ func NewSmartNodeConfig(rpDir string, isNativeMode bool) *SmartNodeConfig { ID: ids.RecordsPathID, Name: "Records Path", Description: "The path of the folder to store rolling record checkpoints in during a rewards interval. Used if Rolling Records is enabled.\n\nOnly useful if you're an Oracle DAO member, or if you generate your own rewards trees.", - AffectsContainers: []config.ContainerID{}, + AffectsContainers: []config.ContainerID{config.ContainerID_Daemon}, CanBeBlank: false, OverwriteOnUpgrade: false, }, @@ -753,24 +752,6 @@ func getNetworkOptions() []*config.ParameterOption[config.Network] { return options } -// Get a more verbose client description, including warnings -func getAugmentedEcDescription(client config.ExecutionClient, originalDescription string) string { - switch client { - case config.ExecutionClient_Nethermind: - totalMemoryGB := memory.TotalMemory() / 1024 / 1024 / 1024 - if totalMemoryGB < 9 { - 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) - } - case config.ExecutionClient_Besu: - totalMemoryGB := memory.TotalMemory() / 1024 / 1024 / 1024 - if totalMemoryGB < 9 { - 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) - } - } - - return originalDescription -} - // Get the default data directory func getDefaultDataDir(rpDir string) string { return filepath.Join(rpDir, "data") diff --git a/shared/keys/keys.go b/shared/keys/keys.go index 021985f94..a6ce79998 100644 --- a/shared/keys/keys.go +++ b/shared/keys/keys.go @@ -74,4 +74,7 @@ const ( ExpectedKey string = "expected" PubkeyKey string = "pubkey" StateKey string = "state" + SubmittedKey string = "submitted" + NextKey string = "next" + TimeKey string = "time" ) diff --git a/shared/types/rewards.go b/shared/types/rewards.go index 218ecdaf9..88ba0b1b6 100644 --- a/shared/types/rewards.go +++ b/shared/types/rewards.go @@ -149,7 +149,7 @@ type IntervalInfo struct { SmoothingPoolEthAmount *QuotedBigInt `json:"smoothingPoolEthAmount"` MerkleProof []common.Hash `json:"merkleProof"` - TotalNodeWeight *QuotedBigInt `json:"-"` + TotalNodeWeight *QuotedBigInt `json:"-"` } type QuotedBigInt struct { diff --git a/sszgen.sh b/sszgen.sh deleted file mode 100755 index 660a35ffb..000000000 --- a/sszgen.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -# Generates the ssz encoding methods for eth2 types with fastssz -# Install sszgen with `go get github.com/ferranbt/fastssz/sszgen` -rm -f ./shared/types/eth2/types_encoding.go -sszgen --path ./shared/types/eth2 \ No newline at end of file diff --git a/staticcheck.conf b/staticcheck.conf new file mode 100644 index 000000000..49c689e46 --- /dev/null +++ b/staticcheck.conf @@ -0,0 +1,5 @@ +# Ignore ST1005 (error strings should not be capitalized) +# Ignore ST1020/ST1021/ST1022 (comment formatting for exported functions/types/vars) +# Ignore ST1000 (at least one package comment) +# Ignore ST1003 (allow underscores in names) +checks = ["all", "-ST1005", "-ST1020", "-ST1021", "-ST1022", "-ST1000", "-ST1003"]