diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 000000000..33fdfcd9c --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,47 @@ +# Taken from https://github.com/golangci/golangci-lint-action +name: golangci-lint +on: + push: + tags: + - v* + branches: + - master + - main + 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.19.13 + - uses: actions/checkout@v3 + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + 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 + + # 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/.gitignore b/.gitignore index ebc361e2d..cdb6b427d 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ Dockerfile /rocketpool/rocketpool-daemon-linux-amd64 /rocketpool/rocketpool-daemon-darwin-arm64 /rocketpool/rocketpool-daemon-linux-arm64 +*.swp diff --git a/addons/rescue_node/addon.go b/addons/rescue_node/addon.go index 5855aae7d..fb7b2385c 100644 --- a/addons/rescue_node/addon.go +++ b/addons/rescue_node/addon.go @@ -33,7 +33,7 @@ type credentialDetails struct { func (c *credentialDetails) GetTimeLeft() time.Duration { - if c.solo == true { + if c.solo { return time.Until(c.issued.Add(soloAuthValidity)) } @@ -138,7 +138,7 @@ func (r *RescueNode) PrintStatusText(nodeAddr common.Address) { // Check the Username usernameNodeAddr, err := r.getCredentialNodeId() if err != nil { - fmt.Printf("%s%w%s", colorRed, err, colorReset) + fmt.Printf("%s%v%s\n", colorRed, err, colorReset) } else { fmt.Printf("Using a credential issued to %s%s%s.\n", colorBlue, usernameNodeAddr.String(), colorReset) if !bytes.Equal(usernameNodeAddr.Bytes(), nodeAddr.Bytes()) { @@ -148,7 +148,7 @@ func (r *RescueNode) PrintStatusText(nodeAddr common.Address) { credentialDetails, err := r.getCredentialDetails() if err != nil { - fmt.Printf("%s%w%s", colorRed, err, colorReset) + fmt.Printf("%s%v%s\n", colorRed, err, colorReset) } else { if credentialDetails.solo { fmt.Printf("%s - WARNING: This credential was issued to a solo staker!%s\n", colorYellow, colorReset) diff --git a/go.mod b/go.mod index b2f14299c..bd621ff85 100644 --- a/go.mod +++ b/go.mod @@ -45,6 +45,7 @@ require ( golang.org/x/crypto v0.6.0 golang.org/x/sync v0.1.0 golang.org/x/term v0.5.0 + google.golang.org/protobuf v1.28.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -174,7 +175,6 @@ require ( gonum.org/v1/gonum v0.12.0 // indirect google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect google.golang.org/grpc v1.53.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gotest.tools/v3 v3.4.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect diff --git a/rocketpool-cli/minipool/dissolve.go b/rocketpool-cli/minipool/dissolve.go deleted file mode 100644 index e582bdebb..000000000 --- a/rocketpool-cli/minipool/dissolve.go +++ /dev/null @@ -1,153 +0,0 @@ -package minipool - -import ( - "bytes" - "fmt" - - "github.com/ethereum/go-ethereum/common" - rocketpoolapi "github.com/rocket-pool/rocketpool-go/rocketpool" - "github.com/rocket-pool/rocketpool-go/types" - "github.com/rocket-pool/rocketpool-go/utils/eth" - "github.com/urfave/cli" - - "github.com/rocket-pool/smartnode/shared/services/gas" - "github.com/rocket-pool/smartnode/shared/services/rocketpool" - "github.com/rocket-pool/smartnode/shared/types/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" - "github.com/rocket-pool/smartnode/shared/utils/math" -) - -func dissolveMinipools(c *cli.Context) error { - - // Get RP client - rp, err := rocketpool.NewClientFromCtx(c).WithReady() - if err != nil { - return err - } - defer rp.Close() - - // Get minipool statuses - status, err := rp.MinipoolStatus() - if err != nil { - return err - } - - // Get initialized minipools - initializedMinipools := []api.MinipoolDetails{} - for _, minipool := range status.Minipools { - if minipool.Status.Status == types.Initialized { - initializedMinipools = append(initializedMinipools, minipool) - } - } - - // Check for initialized minipools - if len(initializedMinipools) == 0 { - fmt.Println("No minipools can be dissolved.") - return nil - } - - // Get selected minipools - var selectedMinipools []api.MinipoolDetails - if c.String("minipool") == "" { - - // Prompt for minipool selection - options := make([]string, len(initializedMinipools)+1) - options[0] = "All available minipools" - for mi, minipool := range initializedMinipools { - options[mi+1] = fmt.Sprintf("%s (%.6f ETH deposited)", minipool.Address.Hex(), math.RoundDown(eth.WeiToEth(minipool.Node.DepositBalance), 6)) - } - selected, _ := cliutils.Select("Please select a minipool to dissolve:", options) - - // Get minipools - if selected == 0 { - selectedMinipools = initializedMinipools - } else { - selectedMinipools = []api.MinipoolDetails{initializedMinipools[selected-1]} - } - - } else { - - // Get matching minipools - if c.String("minipool") == "all" { - selectedMinipools = initializedMinipools - } else { - selectedAddress := common.HexToAddress(c.String("minipool")) - for _, minipool := range initializedMinipools { - if bytes.Equal(minipool.Address.Bytes(), selectedAddress.Bytes()) { - selectedMinipools = []api.MinipoolDetails{minipool} - break - } - } - if selectedMinipools == nil { - return fmt.Errorf("The minipool %s is not available for dissolving.", selectedAddress.Hex()) - } - } - - } - - // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 - var gasInfo rocketpoolapi.GasInfo - for _, minipool := range selectedMinipools { - canResponse, err := rp.CanDissolveMinipool(minipool.Address) - if err != nil { - fmt.Printf("WARNING: Couldn't get gas price for dissolve transaction (%s)", err) - break - } else { - gasInfo = canResponse.GasInfo - totalGas += canResponse.GasInfo.EstGasLimit - totalSafeGas += canResponse.GasInfo.SafeGasLimit - } - } - gasInfo.EstGasLimit = totalGas - gasInfo.SafeGasLimit = totalSafeGas - - // Assign max fees - err = gas.AssignMaxFeeAndLimit(gasInfo, rp, c.Bool("yes")) - if err != nil { - return err - } - - // Prompt for confirmation - if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf("Are you sure you want to dissolve %d minipool(s)? This action cannot be undone!", len(selectedMinipools)))) { - fmt.Println("Cancelled.") - return nil - } - - // Dissolve and close minipools - for _, minipool := range selectedMinipools { - response, err := rp.DissolveMinipool(minipool.Address) - if err != nil { - fmt.Printf("Could not dissolve minipool %s: %s.\n", minipool.Address.Hex(), err) - continue - } - - fmt.Printf("Dissolving minipool %s...\n", minipool.Address.Hex()) - cliutils.PrintTransactionHash(rp, response.TxHash) - if _, err = rp.WaitForTransaction(response.TxHash); err != nil { - fmt.Printf("Could not dissolve minipool %s: %s.\n", minipool.Address.Hex(), err) - continue - } else { - fmt.Printf("Successfully dissolved minipool %s.\n", minipool.Address.Hex()) - } - - closeResponse, err := rp.CloseMinipool(minipool.Address) - if err != nil { - fmt.Printf("Could not close minipool %s: %s.\n", minipool.Address.Hex(), err) - continue - } - - fmt.Printf("Closing minipool %s...\n", minipool.Address.Hex()) - cliutils.PrintTransactionHash(rp, closeResponse.TxHash) - if _, err = rp.WaitForTransaction(closeResponse.TxHash); err != nil { - fmt.Printf("Could not close minipool %s: %s.\n", minipool.Address.Hex(), err) - } else { - fmt.Printf("Successfully closed minipool %s.\n", minipool.Address.Hex()) - } - } - - // Return - return nil - -} diff --git a/rocketpool-cli/minipool/reduce-bond.go b/rocketpool-cli/minipool/reduce-bond.go index 86f99a986..09b7f8e93 100644 --- a/rocketpool-cli/minipool/reduce-bond.go +++ b/rocketpool-cli/minipool/reduce-bond.go @@ -234,7 +234,8 @@ func reduceBondAmount(c *cli.Context) error { return err } - 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.MinipoolDetails{} @@ -360,10 +361,12 @@ func forceFeeDistribution(c *cli.Context, rp *rocketpool.Client) error { balance := eth.WeiToEth(canDistributeResponse.Balance) if balance == 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 rEthShare := balance - canDistributeResponse.NodeShare diff --git a/rocketpool-cli/minipool/rescue-dissolved.go b/rocketpool-cli/minipool/rescue-dissolved.go index 63afa82e4..32989a3e3 100644 --- a/rocketpool-cli/minipool/rescue-dissolved.go +++ b/rocketpool-cli/minipool/rescue-dissolved.go @@ -34,7 +34,9 @@ func rescueDissolved(c *cli.Context) error { return err } - 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() // Validate the amount var depositAmount *big.Int @@ -90,14 +92,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", colorReset) } if len(balanceCompletedMinipools) > 0 { - fmt.Printf("%NOTE: The following minipools already have 32 ETH or more deposited:\n", colorYellow) + fmt.Printf("%sNOTE: The following minipools already have 32 ETH or more deposited:\n", 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", colorReset) } if len(invalidBeaconStateMinipools) > 0 { - fmt.Printf("%NOTE: The following minipools have an invalid state on the Beacon Chain (expected 'initialized_pending'):\n", colorYellow) + fmt.Printf("%sNOTE: The following minipools have an invalid state on the Beacon Chain (expected 'initialized_pending'):\n", colorYellow) for _, mp := range invalidBeaconStateMinipools { fmt.Printf("\t%s (%s)\n", mp.Address, mp.BeaconState) } diff --git a/rocketpool-cli/minipool/stake.go b/rocketpool-cli/minipool/stake.go index e3ad90600..237508fc4 100644 --- a/rocketpool-cli/minipool/stake.go +++ b/rocketpool-cli/minipool/stake.go @@ -106,7 +106,9 @@ func stakeMinipools(c *cli.Context) error { return err } - fmt.Println("\nNOTE: Your validator container will be restarted after this process so it loads the new validator key.\n") + fmt.Println() + fmt.Println("NOTE: Your validator container will be restarted after this process so it loads the new validator key.") + fmt.Println() // Prompt for confirmation if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf("Are you sure you want to stake %d minipools?", len(selectedMinipools)))) { diff --git a/rocketpool-cli/minipool/vanity.go b/rocketpool-cli/minipool/vanity.go index ef9d52d39..ce156c6f2 100644 --- a/rocketpool-cli/minipool/vanity.go +++ b/rocketpool-cli/minipool/vanity.go @@ -185,7 +185,7 @@ func runWorker(report bool, stop *bool, targetPrefix *big.Int, nodeAddress []byt salt.FillBytes(saltBytes[:]) hasher.Write(nodeAddress) hasher.Write(saltBytes[:]) - hasher.Read(nodeSalt[:]) + _, _ = hasher.Read(nodeSalt[:]) hasher.Reset() // This block is the fast way to do `crypto.CreateAddress2(minipoolManagerAddress, nodeSalt, initHash)` @@ -198,7 +198,7 @@ func runWorker(report bool, stop *bool, targetPrefix *big.Int, nodeAddress []byt hasher.Write(minipoolManagerAddress.Bytes()) hasher.Write(nodeSalt[:]) hasher.Write(initHash) - hasher.Read(addressResult[:]) + _, _ = hasher.Read(addressResult[:]) hasher.Reset() hashInt.SetBytes(addressResult[12:]) diff --git a/rocketpool-cli/node/burn.go b/rocketpool-cli/node/burn.go deleted file mode 100644 index c8b1477a8..000000000 --- a/rocketpool-cli/node/burn.go +++ /dev/null @@ -1,71 +0,0 @@ -package node - -import ( - "fmt" - - "github.com/rocket-pool/rocketpool-go/utils/eth" - "github.com/urfave/cli" - - "github.com/rocket-pool/smartnode/shared/services/gas" - "github.com/rocket-pool/smartnode/shared/services/rocketpool" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" - "github.com/rocket-pool/smartnode/shared/utils/math" -) - -func nodeBurn(c *cli.Context, amount float64, token string) error { - - // Get RP client - rp, err := rocketpool.NewClientFromCtx(c).WithReady() - if err != nil { - return err - } - defer rp.Close() - - // Get amount in wei - amountWei := eth.EthToWei(amount) - - // Check tokens can be burned - canBurn, err := rp.CanNodeBurn(amountWei, token) - if err != nil { - return err - } - if !canBurn.CanBurn { - fmt.Println("Cannot burn tokens:") - if canBurn.InsufficientBalance { - fmt.Printf("The node's %s balance is insufficient.\n", token) - } - if canBurn.InsufficientCollateral { - fmt.Printf("There is insufficient ETH collateral to trade %s for.\n", token) - } - return nil - } - - // Assign max fees - err = gas.AssignMaxFeeAndLimit(canBurn.GasInfo, rp, c.Bool("yes")) - if err != nil { - return err - } - - // Prompt for confirmation - if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf("Are you sure you want to burn %.6f %s for ETH?", math.RoundDown(eth.WeiToEth(amountWei), 6), token))) { - fmt.Println("Cancelled.") - return nil - } - - // Burn tokens - response, err := rp.NodeBurn(amountWei, token) - if err != nil { - return err - } - - fmt.Printf("Burning tokens...\n") - cliutils.PrintTransactionHash(rp, response.TxHash) - if _, err = rp.WaitForTransaction(response.TxHash); err != nil { - return err - } - - // Log & return - fmt.Printf("Successfully burned %.6f %s for ETH.\n", math.RoundDown(eth.WeiToEth(amountWei), 6), token) - return nil - -} diff --git a/rocketpool-cli/node/claim-rewards.go b/rocketpool-cli/node/claim-rewards.go index bab70c0fd..d8da866b6 100644 --- a/rocketpool-cli/node/claim-rewards.go +++ b/rocketpool-cli/node/claim-rewards.go @@ -344,8 +344,7 @@ func getRestakeAmount(c *cli.Context, rewardsInfoResponse api.NodeGetRewardsInfo } else { // Prompt the user if rplToMaxCollateral <= 0 || availableRpl < rplToMaxCollateral { - var collateralString string - collateralString = fmt.Sprintf("All %.6f RPL, which will bring you to %.2f%% borrowed collateral (%.2f%% bonded collateral)", availableRpl, bestBorrowedCollateral*100, bestBondedCollateral*100) + collateralString := fmt.Sprintf("All %.6f RPL, which will bring you to %.2f%% borrowed collateral (%.2f%% bonded collateral)", availableRpl, bestBorrowedCollateral*100, bestBondedCollateral*100) amountOptions := []string{ "None (do not restake any RPL)", diff --git a/rocketpool-cli/node/create-vacant-minipool.go b/rocketpool-cli/node/create-vacant-minipool.go index ff5585748..7523559ff 100644 --- a/rocketpool-cli/node/create-vacant-minipool.go +++ b/rocketpool-cli/node/create-vacant-minipool.go @@ -41,7 +41,8 @@ func createVacantMinipool(c *cli.Context, pubkey types.ValidatorPubkey) error { return nil } - fmt.Println("Your eth2 client is on the correct network.\n") + fmt.Println("Your eth2 client is on the correct network.") + fmt.Println() // Check if the fee distributor has been initialized isInitializedResponse, err := rp.IsFeeDistributorInitialized() @@ -240,7 +241,8 @@ func createVacantMinipool(c *cli.Context, pubkey types.ValidatorPubkey) error { if c.IsSet("mnemonic") { mnemonic = c.String("mnemonic") } else if !c.Bool("yes") { - fmt.Println("You have the option of importing your validator's private key into the Smartnode's Validator Client instead of running your own Validator Client separately. In doing so, the Smartnode will also automatically migrate your validator's withdrawal credentials from your BLS private key to the minipool you just created.\n") + fmt.Println("You have the option of importing your validator's private key into the Smartnode's Validator Client instead of running your own Validator Client separately. In doing so, the Smartnode will also automatically migrate your validator's withdrawal credentials from your BLS private key to the minipool you just created.") + fmt.Println() if cliutils.Confirm("Would you like to import your key and automatically migrate your withdrawal credentials?") { mnemonic = wallet.PromptMnemonic() } @@ -250,7 +252,9 @@ func createVacantMinipool(c *cli.Context, pubkey types.ValidatorPubkey) error { handleImport(c, rp, response.MinipoolAddress, mnemonic) } else { // Ignore importing / it errored out - fmt.Println("Since you're not importing your validator key, you will still be responsible for running and maintaining your own Validator Client with the validator's private key loaded, just as you are today.\n\n") + fmt.Println("Since you're not importing your validator key, you will still be responsible for running and maintaining your own Validator Client with the validator's private key loaded, just as you are today.") + fmt.Println() + fmt.Println() fmt.Printf("You must now upgrade your validator's withdrawal credentials manually, using as tool such as `ethdo` (https://github.com/wealdtech/ethdo), to the following minipool address:\n\n\t%s\n\n", response.MinipoolAddress) } diff --git a/rocketpool-cli/node/deposit.go b/rocketpool-cli/node/deposit.go index 51abc724d..3e274da72 100644 --- a/rocketpool-cli/node/deposit.go +++ b/rocketpool-cli/node/deposit.go @@ -42,7 +42,8 @@ func nodeDeposit(c *cli.Context) error { return nil } - fmt.Println("Your eth2 client is on the correct network.\n") + fmt.Println("Your eth2 client is on the correct network.") + fmt.Println() // Check if the fee distributor has been initialized isInitializedResponse, err := rp.IsFeeDistributorInitialized() @@ -50,7 +51,8 @@ func nodeDeposit(c *cli.Context) error { return err } if !isInitializedResponse.IsInitialized { - fmt.Println("Your fee distributor has not been initialized yet so you cannot create a new minipool.\nPlease run `rocketpool node initialize-fee-distributor` to initialize it first.") + fmt.Println("Your fee distributor has not been initialized yet so you cannot create a new minipool.") + fmt.Println("Please run `rocketpool node initialize-fee-distributor` to initialize it first.") return nil } diff --git a/rocketpool-cli/node/smoothing-pool.go b/rocketpool-cli/node/smoothing-pool.go index 183eed195..f4b083dbb 100644 --- a/rocketpool-cli/node/smoothing-pool.go +++ b/rocketpool-cli/node/smoothing-pool.go @@ -36,7 +36,12 @@ func joinSmoothingPool(c *cli.Context) error { } // Print some info - 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.\n") + 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() // Get the gas estimate canResponse, err := rp.CanNodeSetSmoothingPoolStatus(true) @@ -102,7 +107,12 @@ func leaveSmoothingPool(c *cli.Context) error { } // Print some info - 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.\n") + 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() // Get the gas estimate canResponse, err := rp.CanNodeSetSmoothingPoolStatus(false) diff --git a/rocketpool-cli/node/status.go b/rocketpool-cli/node/status.go index c809d02a7..c2fa3a4c1 100644 --- a/rocketpool-cli/node/status.go +++ b/rocketpool-cli/node/status.go @@ -203,7 +203,8 @@ func getStatus(c *cli.Context) error { // RPL stake details fmt.Printf("%s=== RPL Stake ===%s\n", colorGreen, colorReset) - fmt.Println("NOTE: The following figures take *any pending bond reductions* into account.\n") + fmt.Println("NOTE: The following figures take *any pending bond reductions* into account.") + fmt.Println() fmt.Printf( "The node has a total stake of %.6f RPL and an effective stake of %.6f RPL.\n", math.RoundDown(eth.WeiToEth(status.RplStake), 6), diff --git a/rocketpool-cli/node/sync.go b/rocketpool-cli/node/sync.go index 8d92f2190..49fa2f876 100644 --- a/rocketpool-cli/node/sync.go +++ b/rocketpool-cli/node/sync.go @@ -3,7 +3,6 @@ package node import ( "fmt" "strings" - "time" "github.com/urfave/cli" @@ -12,9 +11,6 @@ import ( cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" ) -// Settings -var ethClientRecentBlockThreshold, _ = time.ParseDuration("5m") - func printClientStatus(status *api.ClientStatus, name string) { if status.Error != "" { @@ -84,7 +80,8 @@ func getSyncProgress(c *cli.Context) error { depositContractInfo.BeaconDepositContract) return nil } else { - fmt.Println("Your consensus client is on the correct network.\n") + fmt.Println("Your consensus client is on the correct network.") + fmt.Println() } // Get node status diff --git a/rocketpool-cli/node/utils.go b/rocketpool-cli/node/utils.go index 584c8aa09..555d634c2 100644 --- a/rocketpool-cli/node/utils.go +++ b/rocketpool-cli/node/utils.go @@ -13,15 +13,8 @@ import ( "unicode" "github.com/goccy/go-json" - "github.com/mitchellh/go-homedir" - "gopkg.in/yaml.v2" - "github.com/rocket-pool/rocketpool-go/types" - "github.com/rocket-pool/smartnode/shared/services/config" - "github.com/rocket-pool/smartnode/shared/services/rocketpool" - "github.com/rocket-pool/smartnode/shared/types/api" cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" - hexutils "github.com/rocket-pool/smartnode/shared/utils/hex" ) // IPInfo API @@ -158,7 +151,10 @@ 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\n") + 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 if len(countryNames) == 0 { @@ -184,8 +180,6 @@ func promptTimezone() string { // Prompt for country country := "" for { - time.Now().Zone() - timezone = "" country = cliutils.Prompt("Please enter a country / continent from the list above:", "^.+$", "Please enter a country / continent from the list above:") exists := false @@ -245,8 +239,6 @@ func promptTimezone() string { // Prompt for region region := "" for { - time.Now().Zone() - timezone = "" region = cliutils.Prompt("Please enter a region from the list above:", "^.+$", "Please enter a region from the list above:") exists := false @@ -314,75 +306,3 @@ func promptMinNodeFee(networkCurrentNodeFee, networkMinNodeFee float64) float64 } } - -// Prompt for the password to a solo validator key as part of migration -func promptForSoloKeyPassword(rp *rocketpool.Client, cfg *config.RocketPoolConfig, pubkey types.ValidatorPubkey) (string, error) { - - // Check for the custom key directory - datapath, err := homedir.Expand(cfg.Smartnode.DataPath.Value.(string)) - if err != nil { - return "", fmt.Errorf("error expanding data directory: %w", err) - } - customKeyDir := filepath.Join(datapath, "custom-keys") - 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 := cliutils.PromptPassword( - fmt.Sprintf("Please enter the password that the keystore for %s was encrypted with:", pubkey.Hex()), "^.*$", "", - ) - - formattedPubkey := strings.ToUpper(hexutils.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") - } - - // Store it in the file - fileBytes, err := yaml.Marshal(pubkeyPasswords) - if err != nil { - return "", fmt.Errorf("error serializing keystore passwords file: %w", err) - } - passwordFile := filepath.Join(datapath, "custom-key-passwords") - err = os.WriteFile(passwordFile, fileBytes, 0600) - if err != nil { - return "", fmt.Errorf("error writing keystore passwords file: %w", err) - } - - return passwordFile, nil - -} diff --git a/rocketpool-cli/odao/join.go b/rocketpool-cli/odao/join.go index 2dfad8a9c..241a7cbbe 100644 --- a/rocketpool-cli/odao/join.go +++ b/rocketpool-cli/odao/join.go @@ -71,7 +71,7 @@ func join(c *cli.Context) error { } // Prompt for confirmation - if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf("Do you want to let the new RPL contract interact with your legacy RPL?"))) { + if !(c.Bool("yes") || cliutils.Confirm("Do you want to let the new RPL contract interact with your legacy RPL?")) { fmt.Println("Cancelled.") return nil } @@ -168,7 +168,7 @@ func join(c *cli.Context) error { if err != nil { return err } - rp.PrintMultiTxWarning() + rocketpool.PrintMultiTxWarning() // Prompt for confirmation if !(c.Bool("yes") || cliutils.Confirm("Are you sure you want to join the oracle DAO? Your RPL bond will be locked until you leave.")) { diff --git a/rocketpool-cli/service/config/addons.go b/rocketpool-cli/service/config/addons.go index ae75edcd3..19214e88b 100644 --- a/rocketpool-cli/service/config/addons.go +++ b/rocketpool-cli/service/config/addons.go @@ -11,17 +11,14 @@ const addonPageID string = "addons" // The addons page type AddonsPage struct { - home *settingsHome - page *page - layout *standardLayout - masterConfig *config.RocketPoolConfig - gwwPage *AddonGwwPage - gwwButton *parameterizedFormItem - rescueNodePage *AddonRescueNodePage - rescueNodeButton *parameterizedFormItem - categoryList *tview.List - addonSubpages []settingsPage - content tview.Primitive + home *settingsHome + page *page + layout *standardLayout + masterConfig *config.RocketPoolConfig + gwwPage *AddonGwwPage + rescueNodePage *AddonRescueNodePage + categoryList *tview.List + addonSubpages []settingsPage } // Create a new addons page diff --git a/rocketpool-cli/service/config/config-form.go b/rocketpool-cli/service/config/config-form.go index 7be4b796a..f6ccc1a36 100644 --- a/rocketpool-cli/service/config/config-form.go +++ b/rocketpool-cli/service/config/config-form.go @@ -16,21 +16,6 @@ type parameterizedFormItem struct { item tview.FormItem } -func registerEnableCheckbox(param *cfgtypes.Parameter, checkbox *tview.Checkbox, form *Form, items []*parameterizedFormItem) { - checkbox.SetChangedFunc(func(checked bool) { - param.Value = checked - - if !checked { - form.Clear(true) - form.AddFormItem(checkbox) - } else { - for _, item := range items { - form.AddFormItem(item.item) - } - } - }) -} - // Create a list of form items based on a set of parameters func createParameterizedFormItems(params []*cfgtypes.Parameter, descriptionBox *tview.TextView) []*parameterizedFormItem { formItems := []*parameterizedFormItem{} diff --git a/rocketpool-cli/service/config/pseudomodal.go b/rocketpool-cli/service/config/pseudomodal.go index 327c9a1ed..624992582 100644 --- a/rocketpool-cli/service/config/pseudomodal.go +++ b/rocketpool-cli/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/service/config/review-native-page.go b/rocketpool-cli/service/config/review-native-page.go index 48eb02759..6b1206199 100644 --- a/rocketpool-cli/service/config/review-native-page.go +++ b/rocketpool-cli/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 map[string][]cfgtypes.ChangedSetting - page *page -} - // Create a page to review any changes func NewReviewNativePage(md *mainDisplay, oldConfig *config.RocketPoolConfig, newConfig *config.RocketPoolConfig) *ReviewPage { diff --git a/rocketpool-cli/service/config/review-page.go b/rocketpool-cli/service/config/review-page.go index 8dbdc2183..1dddf63ea 100644 --- a/rocketpool-cli/service/config/review-page.go +++ b/rocketpool-cli/service/config/review-page.go @@ -73,7 +73,7 @@ func NewReviewPage(md *mainDisplay, oldConfig *config.RocketPoolConfig, newConfi builder.WriteString("") } else { builder.WriteString("The following containers must be restarted for these changes to take effect:") - for container, _ := range totalAffectedContainers { + for container := range totalAffectedContainers { builder.WriteString(fmt.Sprintf("\n\t%v", container)) containersToRestart = append(containersToRestart, container) } diff --git a/rocketpool-cli/service/config/standard-layout.go b/rocketpool-cli/service/config/standard-layout.go index 77e07e80a..7c1cce8ec 100644 --- a/rocketpool-cli/service/config/standard-layout.go +++ b/rocketpool-cli/service/config/standard-layout.go @@ -16,7 +16,6 @@ type standardLayout struct { footer tview.Primitive form *Form parameters map[tview.FormItem]*parameterizedFormItem - cfg cfgtypes.Config } // Creates a new StandardLayout instance, which includes the grid and description box preconstructed. diff --git a/rocketpool-cli/service/config/step-finished.go b/rocketpool-cli/service/config/step-finished.go index f116ff6c1..65f2f8075 100644 --- a/rocketpool-cli/service/config/step-finished.go +++ b/rocketpool-cli/service/config/step-finished.go @@ -6,7 +6,6 @@ import ( "github.com/rivo/tview" "github.com/rocket-pool/smartnode/shared/types/config" - cfgtypes "github.com/rocket-pool/smartnode/shared/types/config" ) func createFinishedStep(wiz *wizard, currentStep int, totalSteps int) *choiceWizardStep { @@ -94,12 +93,12 @@ func processConfigAfterQuit(md *mainDisplay) { _, totalAffectedContainers, changeNetworks := md.Config.GetChanges(md.PreviousConfig) if md.isUpdate { - totalAffectedContainers[cfgtypes.ContainerID_Api] = true - totalAffectedContainers[cfgtypes.ContainerID_Node] = true - totalAffectedContainers[cfgtypes.ContainerID_Watchtower] = true + totalAffectedContainers[config.ContainerID_Api] = true + totalAffectedContainers[config.ContainerID_Node] = true + totalAffectedContainers[config.ContainerID_Watchtower] = true } - var containersToRestart []cfgtypes.ContainerID + var containersToRestart []config.ContainerID for container := range totalAffectedContainers { containersToRestart = append(containersToRestart, container) } diff --git a/rocketpool-cli/service/config/step-random-cc.go b/rocketpool-cli/service/config/step-random-cc.go index d7cb5ee6c..58dd447b7 100644 --- a/rocketpool-cli/service/config/step-random-cc.go +++ b/rocketpool-cli/service/config/step-random-cc.go @@ -9,6 +9,7 @@ import ( const randomCcPrysmID string = "step-random-cc-prysm" const randomCcID string = "step-random-cc" +//lint:ignore U1000 this function is unused but only because of the state of the chain- if it becomes a minority client it will be reinstated func createRandomPrysmStep(wiz *wizard, currentStep int, totalSteps int, goodOptions []cfgtypes.ParameterOption) *choiceWizardStep { helperText := "You have been randomly assigned to Prysm for your Consensus client.\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." diff --git a/rocketpool-cli/service/config/types.go b/rocketpool-cli/service/config/types.go index e122ac3fe..f3bf3eedf 100644 --- a/rocketpool-cli/service/config/types.go +++ b/rocketpool-cli/service/config/types.go @@ -4,7 +4,3 @@ type settingsPage interface { handleLayoutChanged() getPage() *page } - -type wizardStep interface { - show() -} diff --git a/rocketpool-cli/service/config/wizard.go b/rocketpool-cli/service/config/wizard.go index 129dbb51e..c16e52eb8 100644 --- a/rocketpool-cli/service/config/wizard.go +++ b/rocketpool-cli/service/config/wizard.go @@ -26,14 +26,15 @@ type wizard struct { externalMevModal *textBoxWizardStep finishedModal *choiceWizardStep consensusLocalRandomModal *choiceWizardStep - consensusLocalRandomPrysmModal *choiceWizardStep - consensusLocalPrysmWarning *choiceWizardStep - consensusLocalTekuWarning *choiceWizardStep - externalDoppelgangerModal *choiceWizardStep - executionLocalRandomModal *choiceWizardStep - useFallbackModal *choiceWizardStep - fallbackNormalModal *textBoxWizardStep - fallbackPrysmModal *textBoxWizardStep + //lint:ignore U1000 unused while prysm is a majority client + consensusLocalRandomPrysmModal *choiceWizardStep + consensusLocalPrysmWarning *choiceWizardStep + consensusLocalTekuWarning *choiceWizardStep + externalDoppelgangerModal *choiceWizardStep + executionLocalRandomModal *choiceWizardStep + useFallbackModal *choiceWizardStep + fallbackNormalModal *textBoxWizardStep + fallbackPrysmModal *textBoxWizardStep // Native mode nativeWelcomeModal *choiceWizardStep diff --git a/rocketpool-cli/service/service.go b/rocketpool-cli/service/service.go index e6ad1116c..5d219aa44 100644 --- a/rocketpool-cli/service/service.go +++ b/rocketpool-cli/service/service.go @@ -130,13 +130,16 @@ ______ _ _ ______ _ fmt.Printf("Changes you should be aware of before starting:\n\n") fmt.Printf("%s=== New Testnet: Holesky ===%s\n", colorGreen, colorReset) - fmt.Println("A new test network has been deployed named Holesky! This will replace Prater as the new long-term test network for Rocket Pool node operators. To use it, select the \"Holesky Testnet\" option from the Network dialog in the Smartnode section of `rocketpool service config`.\n") + fmt.Println("A new test network has been deployed named Holesky! This will replace Prater as the new long-term test network for Rocket Pool node operators. To use it, select the \"Holesky Testnet\" option from the Network dialog in the Smartnode section of `rocketpool service config`.") + fmt.Println() fmt.Printf("%s=== Prater Deprecation ===%s\n", colorGreen, colorReset) - fmt.Println("The Prater test network is now deprecated, as it is being replaced by Holesky. If you are running a Prater node, please exit your minipools to gracefully clean up the network before migration (https://docs.rocketpool.net/guides/node/withdraw.html).\n") + fmt.Println("The Prater test network is now deprecated, as it is being replaced by Holesky. If you are running a Prater node, please exit your minipools to gracefully clean up the network before migration (https://docs.rocketpool.net/guides/node/withdraw.html).") + fmt.Println() fmt.Printf("%s=== New Geth Mode: PBSS ===%s\n", colorGreen, colorReset) - fmt.Println("Geth has been updated to v1.13, which includes the much-anticipated Path-Based State Scheme (PBSS) storage mode. With PBSS, you never have to manually prune Geth again; it prunes automatically behind the scenes during runtime! To enable it, check the \"Enable PBSS\" box in the Execution Client section of the `rocketpool service config` UI. Note you **will have to resync** Geth after enabling this for it to take effect, and will lose attestations if you don't have a fallback client enabled!\n") + fmt.Println("Geth has been updated to v1.13, which includes the much-anticipated Path-Based State Scheme (PBSS) storage mode. With PBSS, you never have to manually prune Geth again; it prunes automatically behind the scenes during runtime! To enable it, check the \"Enable PBSS\" box in the Execution Client section of the `rocketpool service config` UI. Note you **will have to resync** Geth after enabling this for it to take effect, and will lose attestations if you don't have a fallback client enabled!") + fmt.Println() fmt.Printf("%s=== MEV-Boost Changes ===%s\n", colorGreen, colorReset) fmt.Println("The \"Blocknative\" relay has been shut down, so we have removed it from the MEV-Boost relay options. The other relays are still available.") @@ -323,8 +326,12 @@ func configureService(c *cli.Context) error { for _, container := range md.ContainersToRestart { fullName := fmt.Sprintf("%s_%s", prefix, container) fmt.Printf("Stopping %s... ", fullName) - rp.StopContainer(fullName) - fmt.Print("done!\n") + _, err := rp.StopContainer(fullName) + if err != nil { + fmt.Printf("Error while stopping container %s: %v\n", fullName, err) + } else { + fmt.Print("done!\n") + } } fmt.Println() @@ -525,7 +532,10 @@ func startService(c *cli.Context, ignoreConfigSuggestion bool) error { if err != nil { return fmt.Errorf("error upgrading configuration with the latest parameters: %w", err) } - rp.SaveConfig(cfg) + err = rp.SaveConfig(cfg) + if err != nil { + return fmt.Errorf("error saving configuration: %w", err) + } fmt.Printf("%sUpdated settings successfully.%s\n", colorGreen, colorReset) } else { fmt.Println("Cancelled.") @@ -560,8 +570,10 @@ func startService(c *cli.Context, ignoreConfigSuggestion bool) error { fmt.Printf("%sWARNING: couldn't verify that the validator container can be safely restarted:\n\t%s\n", colorYellow, err.Error()) fmt.Println("If you are changing to a different ETH2 client, it may resubmit an attestation you have already submitted.") fmt.Println("This will slash your validator!") - fmt.Println("To prevent slashing, you must wait 15 minutes from the time you stopped the clients before starting them again.\n") - fmt.Println("**If you did NOT change clients, you can safely ignore this warning.**\n") + fmt.Println("To prevent slashing, you must wait 15 minutes from the time you stopped the clients before starting them again.") + fmt.Println() + fmt.Println("**If you did NOT change clients, you can safely ignore this warning.**") + fmt.Println() if !cliutils.Confirm(fmt.Sprintf("Press y when you understand the above warning, have waited, and are ready to start Rocket Pool:%s", colorReset)) { fmt.Println("Cancelled.") return nil @@ -632,7 +644,6 @@ func startService(c *cli.Context, ignoreConfigSuggestion bool) error { // Versions prior to v1.9.0 had Nimbus in single mode instead of split mode, so handle the conversion to ensure the user doesn't get slashed func handleNimbusSplitConversion(rp *rocketpool.Client, cfg *config.RocketPoolConfig) (bool, error) { - previousVersion := "0.0.0" backupCfg, err := rp.LoadBackupConfig() if err != nil { fmt.Printf("%sWARNING: Couldn't determine previous Smartnode version from backup settings: %s%s\n", colorYellow, err.Error(), colorReset) @@ -643,9 +654,9 @@ func handleNimbusSplitConversion(rp *rocketpool.Client, cfg *config.RocketPoolCo return false, nil } return true, nil - } else if backupCfg != nil { - previousVersion = backupCfg.Version - } else { + } + + if backupCfg == nil { fmt.Printf("%sWARNING: Couldn't determine previous Smartnode version from backup settings because the backup configuration didn't exist.%s\n", colorYellow, colorReset) fmt.Printf("%sYou are configured to use Nimbus in local mode. Starting with v1.9.0, Nimbus is now configured to use a split-process configuration, which means the Beacon Node (the `eth2` container) no longer loads your validator keys - now the `validator` container does.\n\nDue to this, we must restart Nimbus as part of the upgrade.\n\nIf you were previously running Smartnode v1.7.5 or earlier, you **MUST** shut down the Docker containers with `rocketpool service stop` and wait **at least 15 minutes** to ensure that you've missed at least two attestations before proceeding to prevent being slashed. Please use an explorer such as https://beaconcha.in to confirm at least one of the missed attestations has been finalized before proceeding.%s\n\n", colorYellow, colorReset) fmt.Println() @@ -656,6 +667,8 @@ func handleNimbusSplitConversion(rp *rocketpool.Client, cfg *config.RocketPoolCo return true, nil } + previousVersion := backupCfg.Version + oldVersion, err := version.NewVersion(strings.TrimPrefix(previousVersion, "v")) if err != nil { fmt.Printf("%sWARNING: Backup configuration states the previous Smartnode installation used version %s, which is not a valid version%s\n", colorYellow, previousVersion, colorReset) @@ -925,25 +938,6 @@ func getContainerNameForValidatorDuties(CurrentValidatorClientName string, rp *r } -// Get the time that the container responsible for validator duties exited -func getValidatorFinishTime(CurrentValidatorClientName string, rp *rocketpool.Client) (time.Time, error) { - - prefix, err := getContainerPrefix(rp) - if err != nil { - return time.Time{}, err - } - - var validatorFinishTime time.Time - if CurrentValidatorClientName == "nimbus" { - validatorFinishTime, err = rp.GetDockerContainerShutdownTime(prefix + BeaconContainerSuffix) - } else { - validatorFinishTime, err = rp.GetDockerContainerShutdownTime(prefix + ValidatorContainerSuffix) - } - - return validatorFinishTime, err - -} - // Extract the image name from a Docker image string func getDockerImageName(imageString string) (string, error) { @@ -998,16 +992,19 @@ func pruneExecutionClient(c *cli.Context) error { // Sanity checks if cfg.ExecutionClientMode.Value.(cfgtypes.Mode) == cfgtypes.Mode_External { - fmt.Println("You are using an externally managed Execution client.\nThe Smartnode cannot prune it for you.") + fmt.Println("You are using an externally managed Execution client.") + fmt.Println("The Smartnode cannot prune it for you.") return nil } if cfg.IsNativeMode { - fmt.Println("You are using Native Mode.\nThe Smartnode cannot prune your Execution client for you, you'll have to do it manually.") + fmt.Println("You are using Native Mode.") + fmt.Println("The Smartnode cannot prune your Execution client for you, you'll have to do it manually.") } selectedEc := cfg.ExecutionClient.Value.(cfgtypes.ExecutionClient) switch selectedEc { case cfgtypes.ExecutionClient_Besu: - fmt.Println("You are using Besu as your Execution client.\nBesu does not need pruning.") + fmt.Println("You are using Besu as your Execution client.") + fmt.Println("Besu does not need pruning.") return nil case cfgtypes.ExecutionClient_Geth: if cfg.Geth.EnablePbss.Value == true { @@ -1017,7 +1014,8 @@ func pruneExecutionClient(c *cli.Context) error { } fmt.Println("This will shut down your main execution client and prune its database, freeing up disk space.") - fmt.Println("Once pruning is complete, your execution client will restart automatically.\n") + fmt.Println("Once pruning is complete, your execution client will restart automatically.") + fmt.Println() if selectedEc == cfgtypes.ExecutionClient_Geth { if cfg.UseFallbackClients.Value == false { @@ -1587,7 +1585,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 container prefix prefix, err := getContainerPrefix(rp) @@ -1710,7 +1709,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 := prefix + ExecutionContainerSuffix diff --git a/rocketpool-cli/wallet/bip39/mnemonic-validator.go b/rocketpool-cli/wallet/bip39/mnemonic-validator.go index 010ed2fa6..18701177f 100644 --- a/rocketpool-cli/wallet/bip39/mnemonic-validator.go +++ b/rocketpool-cli/wallet/bip39/mnemonic-validator.go @@ -47,14 +47,14 @@ 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.") } mnemonic := strings.Join(mv.mnemonic, " ") - if bip39.IsMnemonicValid(mnemonic) { - return mnemonic, nil + if !bip39.IsMnemonicValid(mnemonic) { + return "", errors.New("Invalid mnemonic") } - return "", errors.New("Invalid mnemonic") + return mnemonic, nil } diff --git a/rocketpool-cli/wallet/export.go b/rocketpool-cli/wallet/export.go index 5be237d6b..24f49c692 100644 --- a/rocketpool-cli/wallet/export.go +++ b/rocketpool-cli/wallet/export.go @@ -30,7 +30,7 @@ func exportWallet(c *cli.Context) error { // Check if stdout is interactive stat, err := os.Stdout.Stat() if err != nil { - fmt.Fprintf(os.Stderr, "An error occured while determining whether or not the output is a tty: %w\n"+ + fmt.Fprintf(os.Stderr, "An error occured while determining whether or not the output is a tty: %v\n"+ "Use \"rocketpool --secure-session wallet export\" to bypass.\n", err) os.Exit(1) } diff --git a/rocketpool-cli/wallet/utils.go b/rocketpool-cli/wallet/utils.go index d80628986..e1d00d587 100644 --- a/rocketpool-cli/wallet/utils.go +++ b/rocketpool-cli/wallet/utils.go @@ -62,7 +62,7 @@ func PromptMnemonic() string { } i := 0 - for mv.Filled() == false { + for !mv.Filled() { prompt := fmt.Sprintf("Enter %sWord Number %d%s of your mnemonic:", bold, i+1, unbold) word := cliutils.PromptPassword(prompt, "^[a-zA-Z]+$", "Please enter a single word only.") @@ -152,7 +152,8 @@ func promptForCustomKeyPasswords(rp *rocketpool.Client, cfg *config.RocketPoolCo } // 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.\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.") + fmt.Println() // Get the passwords for each one pubkeyPasswords := map[string]string{} @@ -181,14 +182,3 @@ func promptForCustomKeyPasswords(rp *rocketpool.Client, cfg *config.RocketPoolCo 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/api/debug/validators.go b/rocketpool/api/debug/validators.go index f011c26e7..90f3cbf6e 100644 --- a/rocketpool/api/debug/validators.go +++ b/rocketpool/api/debug/validators.go @@ -94,7 +94,7 @@ func ExportValidators(c *cli.Context) error { return err } - fmt.Printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", + fmt.Printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", "Minipool Address", "Validator Pub Key", "Activation Epoch", @@ -155,7 +155,6 @@ func getMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common var wg errgroup.Group var status types.MinipoolStatus var userDepositBalance *big.Int - var userDepositTime uint64 var nodeFee float64 // Load data @@ -169,13 +168,6 @@ func getMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common userDepositBalance, err = mp.GetUserDepositBalance(opts) return err }) - wg.Go(func() error { - userDepositAssignedTime, err := mp.GetUserDepositAssignedTime(opts) - if err == nil { - userDepositTime = uint64(userDepositAssignedTime.Unix()) - } - return err - }) wg.Go(func() error { nodeFee, err = mp.GetNodeFee(opts) return err @@ -186,14 +178,6 @@ func getMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common return err } - // Get start epoch for node balance calculation - startEpoch := eth2.EpochAt(eth2Config, userDepositTime) - if startEpoch < validator.ActivationEpoch { - startEpoch = validator.ActivationEpoch - } else if startEpoch > blockEpoch { - startEpoch = blockEpoch - } - // Get user balance at block blockBalance := eth.GweiToWei(float64(validator.Balance)) userBalance, err := mp.CalculateUserShare(blockBalance, opts) diff --git a/rocketpool/api/node/deposit.go b/rocketpool/api/node/deposit.go index afaa0955a..8d2fb7d99 100644 --- a/rocketpool/api/node/deposit.go +++ b/rocketpool/api/node/deposit.go @@ -382,7 +382,7 @@ func nodeDeposit(c *cli.Context, amountWei *big.Int, minNodeFee float64, salt *b if status.Exists { return nil, 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) diff --git a/rocketpool/api/node/smoothing-pool.go b/rocketpool/api/node/smoothing-pool.go index 0f2f7b6a4..d26a75612 100644 --- a/rocketpool/api/node/smoothing-pool.go +++ b/rocketpool/api/node/smoothing-pool.go @@ -191,7 +191,10 @@ func setSmoothingPoolStatus(c *cli.Context, status bool) (*api.SetSmoothingPoolR } // Restart the VC but don't pay attention to the errors, since a restart error got us here in the first place - validator.RestartValidator(cfg, bc, nil, d) + err2 = validator.RestartValidator(cfg, bc, nil, d) + if err2 != nil { + return nil, fmt.Errorf("***WARNING***\nError restarting validator: [%s]\nError setting fee recipient back to your node's distributor: [%w]\nYour node now has the Smoothing Pool as its fee recipient, even though you aren't opted in!\nPlease visit the Rocket Pool Discord server for help with these errors, so it can be set back to your node's distributor.", err.Error(), err2) + } return nil, fmt.Errorf("Error restarting validator after updating the fee recipient to the Smoothing Pool: [%w]\nYour fee recipient has been set back to your node's distributor contract.\nYou have not been opted into the Smoothing Pool.", err) } diff --git a/rocketpool/api/node/withdrawal-address.go b/rocketpool/api/node/withdrawal-address.go index 340c02001..67872afa8 100644 --- a/rocketpool/api/node/withdrawal-address.go +++ b/rocketpool/api/node/withdrawal-address.go @@ -217,75 +217,3 @@ func confirmWithdrawalAddress(c *cli.Context) (*api.ConfirmNodeWithdrawalAddress return &response, nil } - -func getNodeWithdrawalAddress(c *cli.Context) (*api.GetNodeWithdrawalAddressResponse, error) { - - // Get services - if err := services.RequireNodeRegistered(c); err != nil { - return nil, err - } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } - rp, err := services.GetRocketPool(c) - if err != nil { - return nil, err - } - - // Response - response := api.GetNodeWithdrawalAddressResponse{} - - // Get the node's account - nodeAccount, err := w.GetNodeAccount() - if err != nil { - return nil, err - } - - // Get the address - address, err := storage.GetNodeWithdrawalAddress(rp, nodeAccount.Address, nil) - if err != nil { - return nil, err - } - - // Return response - response.Address = address - return &response, nil - -} - -func getNodePendingWithdrawalAddress(c *cli.Context) (*api.GetNodePendingWithdrawalAddressResponse, error) { - - // Get services - if err := services.RequireNodeRegistered(c); err != nil { - return nil, err - } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } - rp, err := services.GetRocketPool(c) - if err != nil { - return nil, err - } - - // Response - response := api.GetNodePendingWithdrawalAddressResponse{} - - // Get the node's account - nodeAccount, err := w.GetNodeAccount() - if err != nil { - return nil, err - } - - // Get the address - address, err := storage.GetNodePendingWithdrawalAddress(rp, nodeAccount.Address, nil) - if err != nil { - return nil, err - } - - // Return response - response.Address = address - return &response, nil - -} diff --git a/rocketpool/node/collectors/demand-collector.go b/rocketpool/node/collectors/demand-collector.go index 8c67c2f5e..908e0cb0c 100644 --- a/rocketpool/node/collectors/demand-collector.go +++ b/rocketpool/node/collectors/demand-collector.go @@ -1,8 +1,6 @@ package collectors import ( - "fmt" - "github.com/prometheus/client_golang/prometheus" "github.com/rocket-pool/rocketpool-go/rocketpool" "github.com/rocket-pool/rocketpool-go/utils/eth" @@ -101,8 +99,3 @@ func (collector *DemandCollector) Collect(channel chan<- prometheus.Metric) { channel <- prometheus.MustNewConstMetric( collector.queueLength, prometheus.GaugeValue, queueLength) } - -// Log error messages -func (collector *DemandCollector) logError(err error) { - fmt.Printf("[%s] %s\n", collector.logPrefix, err.Error()) -} diff --git a/rocketpool/node/collectors/odao-collector.go b/rocketpool/node/collectors/odao-collector.go index 5161f2f91..bf620c93d 100644 --- a/rocketpool/node/collectors/odao-collector.go +++ b/rocketpool/node/collectors/odao-collector.go @@ -1,8 +1,6 @@ package collectors import ( - "fmt" - "github.com/prometheus/client_golang/prometheus" "github.com/rocket-pool/rocketpool-go/rocketpool" ) @@ -87,8 +85,3 @@ func (collector *OdaoCollector) Collect(channel chan<- prometheus.Metric) { channel <- prometheus.MustNewConstMetric( collector.latestReportableBlock, prometheus.GaugeValue, latestReportableBlockFloat) } - -// Log error messages -func (collector *OdaoCollector) logError(err error) { - fmt.Printf("[%s] %s\n", collector.logPrefix, err.Error()) -} diff --git a/rocketpool/node/collectors/performance-collector.go b/rocketpool/node/collectors/performance-collector.go index 2e7f34f7c..cba1de24d 100644 --- a/rocketpool/node/collectors/performance-collector.go +++ b/rocketpool/node/collectors/performance-collector.go @@ -1,8 +1,6 @@ package collectors import ( - "fmt" - "github.com/prometheus/client_golang/prometheus" "github.com/rocket-pool/rocketpool-go/rocketpool" "github.com/rocket-pool/rocketpool-go/utils/eth" @@ -110,8 +108,3 @@ func (collector *PerformanceCollector) Collect(channel chan<- prometheus.Metric) channel <- prometheus.MustNewConstMetric( collector.totalRethSupply, prometheus.GaugeValue, rethFloat) } - -// Log error messages -func (collector *PerformanceCollector) logError(err error) { - fmt.Printf("[%s] %s\n", collector.logPrefix, err.Error()) -} diff --git a/rocketpool/node/collectors/rpl-collector.go b/rocketpool/node/collectors/rpl-collector.go index 4df55e3ca..aca5226e8 100644 --- a/rocketpool/node/collectors/rpl-collector.go +++ b/rocketpool/node/collectors/rpl-collector.go @@ -1,8 +1,6 @@ package collectors import ( - "fmt" - "github.com/prometheus/client_golang/prometheus" "github.com/rocket-pool/rocketpool-go/rocketpool" "github.com/rocket-pool/rocketpool-go/utils/eth" @@ -98,8 +96,3 @@ func (collector *RplCollector) Collect(channel chan<- prometheus.Metric) { channel <- prometheus.MustNewConstMetric( collector.checkpointTime, prometheus.GaugeValue, nextRewardsTime) } - -// Log error messages -func (collector *RplCollector) logError(err error) { - fmt.Printf("[%s] %s\n", collector.logPrefix, err.Error()) -} diff --git a/rocketpool/node/collectors/smoothing-pool-collector.go b/rocketpool/node/collectors/smoothing-pool-collector.go index de6ade39e..d0ac94ace 100644 --- a/rocketpool/node/collectors/smoothing-pool-collector.go +++ b/rocketpool/node/collectors/smoothing-pool-collector.go @@ -1,8 +1,6 @@ package collectors import ( - "fmt" - "github.com/prometheus/client_golang/prometheus" "github.com/rocket-pool/rocketpool-go/rocketpool" "github.com/rocket-pool/rocketpool-go/utils/eth" @@ -60,8 +58,3 @@ func (collector *SmoothingPoolCollector) Collect(channel chan<- prometheus.Metri channel <- prometheus.MustNewConstMetric( collector.ethBalanceOnSmoothingPool, prometheus.GaugeValue, ethBalanceOnSmoothingPool) } - -// Log error messages -func (collector *SmoothingPoolCollector) logError(err error) { - fmt.Printf("[%s] %s\n", collector.logPrefix, err.Error()) -} diff --git a/rocketpool/node/metrics-exporter.go b/rocketpool/node/metrics-exporter.go index 492fb416e..8686ab744 100644 --- a/rocketpool/node/metrics-exporter.go +++ b/rocketpool/node/metrics-exporter.go @@ -98,7 +98,7 @@ func runMetricsServer(c *cli.Context, logger log.ColorLogger, stateLocker *colle metricsPath := "/metrics" http.Handle(metricsPath, handler) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(` + _, _ = w.Write([]byte(` Rocket Pool Metrics Exporter

Rocket Pool Metrics Exporter

diff --git a/rocketpool/node/node.go b/rocketpool/node/node.go index 58b8c7877..9ad36782d 100644 --- a/rocketpool/node/node.go +++ b/rocketpool/node/node.go @@ -223,7 +223,10 @@ func run(c *cli.Context) error { time.Sleep(tasksInterval) } - wg.Done() + // This is unreachable + // wg.Done() + // TODO: refactor daemons to use time.Ticker for scheduled tasks, and install a signal handler with signal.Notify + // to gracefully exit }() // Run metrics loop diff --git a/rocketpool/node/reduce-bonds.go b/rocketpool/node/reduce-bonds.go index 4686fe15c..3cb83b398 100644 --- a/rocketpool/node/reduce-bonds.go +++ b/rocketpool/node/reduce-bonds.go @@ -42,15 +42,6 @@ type reduceBonds struct { gasLimit uint64 } -// Details required to check for bond reduction eligibility -type minipoolBondReductionDetails struct { - Address common.Address - DepositBalance *big.Int - ReduceBondTime time.Time - ReduceBondCancelled bool - Status types.MinipoolStatus -} - // Create reduce bonds task func newReduceBonds(c *cli.Context, logger log.ColorLogger) (*reduceBonds, error) { diff --git a/rocketpool/watchtower/generate-rewards-tree.go b/rocketpool/watchtower/generate-rewards-tree.go index 49826a532..24eb73669 100644 --- a/rocketpool/watchtower/generate-rewards-tree.go +++ b/rocketpool/watchtower/generate-rewards-tree.go @@ -175,19 +175,19 @@ func (t *generateRewardsTree) generateRewardsTree(index uint64) { t.log.Printlnf("%s Primary EC cannot retrieve state for historical block %d, using archive EC [%s]", generationPrefix, elBlockHeader.Number.Uint64(), archiveEcUrl) ec, err := ethclient.Dial(archiveEcUrl) if err != nil { - t.handleError(fmt.Errorf("Error connecting to archive EC: %w", err)) + t.handleError(fmt.Errorf("%s Error connecting to archive EC: %w", generationPrefix, err)) return } client, err = rocketpool.NewRocketPool(ec, common.HexToAddress(t.cfg.Smartnode.GetStorageAddress())) if err != nil { - t.handleError(fmt.Errorf("%s Error creating Rocket Pool client connected to archive EC: %w", err)) + t.handleError(fmt.Errorf("%s Error creating Rocket Pool client connected to archive EC: %w", generationPrefix, err)) return } // Get the rETH address from the archive EC address, err = client.RocketStorage.GetAddress(opts, crypto.Keccak256Hash([]byte("contract.addressrocketTokenRETH"))) if err != nil { - t.handleError(fmt.Errorf("%s Error verifying rETH address with Archive EC: %w", err)) + t.handleError(fmt.Errorf("%s Error verifying rETH address with Archive EC: %w", generationPrefix, err)) return } } else { diff --git a/rocketpool/watchtower/metrics-exporter.go b/rocketpool/watchtower/metrics-exporter.go index b4830b79d..daea01733 100644 --- a/rocketpool/watchtower/metrics-exporter.go +++ b/rocketpool/watchtower/metrics-exporter.go @@ -45,7 +45,8 @@ func runMetricsServer(c *cli.Context, logger log.ColorLogger, scrubCollector *co metricsPath := "/metrics" http.Handle(metricsPath, handler) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(` + _, _ = w.Write([]byte(` + Rocket Pool Watchtower Metrics Exporter

Rocket Pool Watchtower Metrics Exporter

diff --git a/rocketpool/watchtower/process-penalties.go b/rocketpool/watchtower/process-penalties.go index 9fb8941f0..e1140cb6e 100644 --- a/rocketpool/watchtower/process-penalties.go +++ b/rocketpool/watchtower/process-penalties.go @@ -1,3 +1,5 @@ +//lint:file-ignore U1000 Ignore all unused code, penalty system TBD + package watchtower import ( diff --git a/rocketpool/watchtower/submit-rewards-tree-rolling.go b/rocketpool/watchtower/submit-rewards-tree-rolling.go index 1fe6db852..63001a5cb 100644 --- a/rocketpool/watchtower/submit-rewards-tree-rolling.go +++ b/rocketpool/watchtower/submit-rewards-tree-rolling.go @@ -580,7 +580,7 @@ func (t *submitRewardsTree_Rolling) generateTree(rp *rocketpool.RocketPool, stat minipoolPerformanceCid, err := t.uploadFileToWeb3Storage(minipoolPerformanceBytes, compressedMinipoolPerformancePath, "compressed minipool performance") if err != nil { // If it fails, get the CID and continue the submission process - t.printMessage(fmt.Sprintf("Error uploading minipool performance file to Web3.Storage: %w", err)) + t.printMessage(fmt.Sprintf("Error uploading minipool performance file to Web3.Storage: %v", err)) c, err := rprewards.GetCIDForSerializedFile(minipoolPerformanceBytes, filepath.Base(compressedMinipoolPerformancePath)) if err != nil { return fmt.Errorf("error getting CID for file %s: %w", compressedMinipoolPerformancePath, err) @@ -615,7 +615,7 @@ func (t *submitRewardsTree_Rolling) generateTree(rp *rocketpool.RocketPool, stat t.printMessage("Uploading to Web3.Storage and submitting results to the contracts...") cid, err := t.uploadFileToWeb3Storage(wrapperBytes, compressedRewardsTreePath, "compressed rewards tree") if err != nil { - t.printMessage(fmt.Sprintf("Error uploading Merkle tree to Web3.Storage: %w", err)) + t.printMessage(fmt.Sprintf("Error uploading Merkle tree to Web3.Storage: %v", err)) c, err := rprewards.GetCIDForSerializedFile(wrapperBytes, filepath.Base(compressedRewardsTreePath)) if err != nil { return fmt.Errorf("error getting CID for file %s: %w", compressedRewardsTreePath, err) @@ -766,7 +766,10 @@ func (t *submitRewardsTree_Rolling) uploadFileToWeb3Storage(wrapperBytes []byte, } // Rewind it to the start - compressedFile.Seek(0, 0) + _, err = compressedFile.Seek(0, 0) + if err != nil { + return "", fmt.Errorf("Error seeking to beginning of %s: %w", compressedPath, err) + } // Upload it cid, err := w3sClient.Put(context.Background(), compressedFile) diff --git a/rocketpool/watchtower/submit-rewards-tree-stateless.go b/rocketpool/watchtower/submit-rewards-tree-stateless.go index d58b8283d..da533622b 100644 --- a/rocketpool/watchtower/submit-rewards-tree-stateless.go +++ b/rocketpool/watchtower/submit-rewards-tree-stateless.go @@ -374,7 +374,7 @@ func (t *submitRewardsTree_Stateless) generateTreeImpl(rp *rocketpool.RocketPool t.printMessage("Uploading minipool performance file to Web3.Storage...") minipoolPerformanceCid, err := t.uploadFileToWeb3Storage(minipoolPerformanceBytes, compressedMinipoolPerformancePath, "compressed minipool performance") if err != nil { - t.printMessage(fmt.Sprintf("Error uploading minipool performance file to Web3.Storage: %w", err)) + t.printMessage(fmt.Sprintf("Error uploading minipool performance file to Web3.Storage: %v", err)) c, err := rprewards.GetCIDForSerializedFile(minipoolPerformanceBytes, filepath.Base(compressedMinipoolPerformancePath)) if err != nil { return fmt.Errorf("error getting CID for file %s: %w", compressedMinipoolPerformancePath, err) @@ -409,7 +409,7 @@ func (t *submitRewardsTree_Stateless) generateTreeImpl(rp *rocketpool.RocketPool t.printMessage("Uploading to Web3.Storage and submitting results to the contracts...") cid, err := t.uploadFileToWeb3Storage(wrapperBytes, compressedRewardsTreePath, "compressed rewards tree") if err != nil { - t.printMessage(fmt.Sprintf("Error uploading Merkle tree to Web3.Storage: %w", err)) + t.printMessage(fmt.Sprintf("Error uploading Merkle tree to Web3.Storage: %v", err)) c, err := rprewards.GetCIDForSerializedFile(wrapperBytes, filepath.Base(compressedRewardsTreePath)) if err != nil { return fmt.Errorf("error getting CID for file %s: %w", compressedRewardsTreePath, err) @@ -559,7 +559,10 @@ func (t *submitRewardsTree_Stateless) uploadFileToWeb3Storage(wrapperBytes []byt } // Rewind it to the start - compressedFile.Seek(0, 0) + _, err = compressedFile.Seek(0, 0) + if err != nil { + return "", fmt.Errorf("Error seeking to beginning of %s: %w", compressedPath, err) + } // Upload it cid, err := w3sClient.Put(context.Background(), compressedFile) diff --git a/rocketpool/watchtower/submit-rpl-price.go b/rocketpool/watchtower/submit-rpl-price.go index 2551b2e5f..91c2f0375 100644 --- a/rocketpool/watchtower/submit-rpl-price.go +++ b/rocketpool/watchtower/submit-rpl-price.go @@ -615,7 +615,7 @@ func (t *submitRplPrice) submitOptimismPrice() error { return fmt.Errorf("Failed to get member at %d: %q", i, err) } - if bytes.Compare(addr.Bytes(), opts.From.Bytes()) == 0 { + if bytes.Equal(addr.Bytes(), opts.From.Bytes()) { index = i break } @@ -755,7 +755,7 @@ func (t *submitRplPrice) submitPolygonPrice() error { return fmt.Errorf("Failed to get member at %d: %q", i, err) } - if bytes.Compare(addr.Bytes(), opts.From.Bytes()) == 0 { + if bytes.Equal(addr.Bytes(), opts.From.Bytes()) { index = i break } @@ -895,7 +895,7 @@ func (t *submitRplPrice) submitArbitrumPrice() error { return fmt.Errorf("Failed to get member at %d: %q", i, err) } - if bytes.Compare(addr.Bytes(), opts.From.Bytes()) == 0 { + if bytes.Equal(addr.Bytes(), opts.From.Bytes()) { index = i break } @@ -1060,7 +1060,7 @@ func (t *submitRplPrice) submitZkSyncEraPrice() error { return fmt.Errorf("Failed to get member at %d: %q", i, err) } - if bytes.Compare(addr.Bytes(), opts.From.Bytes()) == 0 { + if bytes.Equal(addr.Bytes(), opts.From.Bytes()) { index = i break } @@ -1218,7 +1218,7 @@ func (t *submitRplPrice) submitBasePrice() error { return fmt.Errorf("Failed to get member at %d: %q", i, err) } - if bytes.Compare(addr.Bytes(), opts.From.Bytes()) == 0 { + if bytes.Equal(addr.Bytes(), opts.From.Bytes()) { index = i break } diff --git a/rocketpool/watchtower/submit-scrub-minipools.go b/rocketpool/watchtower/submit-scrub-minipools.go index 9368af42e..7a4fe649d 100644 --- a/rocketpool/watchtower/submit-scrub-minipools.go +++ b/rocketpool/watchtower/submit-scrub-minipools.go @@ -184,7 +184,10 @@ func (t *submitScrubMinipools) run(state *state.NetworkState) error { t.initializeMinipoolDetails(prelaunchMinipools, opts) // Step 1: Verify the Beacon credentials if they exist - t.verifyBeaconWithdrawalCredentials(state) + err := t.verifyBeaconWithdrawalCredentials(state) + if err != nil { + t.log.Printlnf("%s Error verifying beacon withdrawal credentials: %v", checkPrefix, err) + } // If there aren't any minipools left to check, print the final tally and exit if len(t.it.minipools) == 0 { @@ -196,7 +199,7 @@ func (t *submitScrubMinipools) run(state *state.NetworkState) error { } // Get various elements needed to do eth1 prestake and deposit contract searches - err := t.getEth1SearchArtifacts(state) + err = t.getEth1SearchArtifacts(state) if err != nil { t.handleError(fmt.Errorf("%s %w", checkPrefix, err)) return diff --git a/rocketpool/watchtower/watchtower.go b/rocketpool/watchtower/watchtower.go index aab7ec107..d802c8eca 100644 --- a/rocketpool/watchtower/watchtower.go +++ b/rocketpool/watchtower/watchtower.go @@ -313,7 +313,10 @@ func run(c *cli.Context) error { time.Sleep(interval) } - wg.Done() + // This is unreachable + // wg.Done() + // TODO: refactor daemonst o use time.Ticker for scheduled tasks and install a signal handler with signal.Notify + // to gracefully exit }() // Run metrics loop diff --git a/shared/services/beacon/client/committee.go b/shared/services/beacon/client/committee.go index f3d197212..f2be8b65e 100644 --- a/shared/services/beacon/client/committee.go +++ b/shared/services/beacon/client/committee.go @@ -18,16 +18,16 @@ type Committee struct { // substantially. var validatorSlicePool sync.Pool = sync.Pool{ New: func() any { - return make([]string, 0, 1024) + out := make([]string, 0, 1024) + return &out }, } func (c *Committee) UnmarshalJSON(body []byte) error { var committee map[string]*json.RawMessage - pooledSlice := validatorSlicePool.Get().([]string) - - c.Validators = pooledSlice + pooledSlicePtr := validatorSlicePool.Get().(*[]string) + c.Validators = *pooledSlicePtr // Partially parse the json if err := json.Unmarshal(body, &committee); err != nil { @@ -70,6 +70,6 @@ func (c *CommitteesResponse) Release() { // Reset the slice length to 0 (capacity stays the same) committee.Validators = committee.Validators[:0] // Return the slice for reuse - validatorSlicePool.Put(committee.Validators) + validatorSlicePool.Put(&committee.Validators) } } diff --git a/shared/services/beacon/client/std-http-client.go b/shared/services/beacon/client/std-http-client.go index 7bbd79254..a702daa7b 100644 --- a/shared/services/beacon/client/std-http-client.go +++ b/shared/services/beacon/client/std-http-client.go @@ -735,10 +735,10 @@ func (c *StandardHttpClient) getValidatorsByOpts(pubkeysOrIndices []string, opts func (c *StandardHttpClient) postVoluntaryExit(request VoluntaryExitRequest) error { responseBody, status, err := c.postRequest(RequestVoluntaryExitPath, request) if err != nil { - return fmt.Errorf("Could not broadcast exit for validator at index %d: %w", request.Message.ValidatorIndex, err) + return fmt.Errorf("Could not broadcast exit for validator at index %s: %w", request.Message.ValidatorIndex, err) } if status != http.StatusOK { - return fmt.Errorf("Could not broadcast exit for validator at index %d: HTTP status %d; response body: '%s'", request.Message.ValidatorIndex, status, string(responseBody)) + return fmt.Errorf("Could not broadcast exit for validator at index %s: HTTP status %d; response body: '%s'", request.Message.ValidatorIndex, status, string(responseBody)) } return nil } @@ -856,10 +856,10 @@ func (c *StandardHttpClient) postWithdrawalCredentialsChange(request BLSToExecut requestArray := []BLSToExecutionChangeRequest{request} // This route must be wrapped in an array responseBody, status, err := c.postRequest(RequestWithdrawalCredentialsChangePath, requestArray) if err != nil { - return fmt.Errorf("Could not broadcast withdrawal credentials change for validator %d: %w", request.Message.ValidatorIndex, err) + return fmt.Errorf("Could not broadcast withdrawal credentials change for validator %s: %w", request.Message.ValidatorIndex, err) } if status != http.StatusOK { - return fmt.Errorf("Could not broadcast withdrawal credentials change for validator %d: HTTP status %d; response body: '%s'", request.Message.ValidatorIndex, status, string(responseBody)) + return fmt.Errorf("Could not broadcast withdrawal credentials change for validator %s: HTTP status %d; response body: '%s'", request.Message.ValidatorIndex, status, string(responseBody)) } return nil } diff --git a/shared/services/config/fallback-configs.go b/shared/services/config/fallback-configs.go index 62ba5470c..03bb0122e 100644 --- a/shared/services/config/fallback-configs.go +++ b/shared/services/config/fallback-configs.go @@ -121,11 +121,11 @@ func (cfg *FallbackPrysmConfig) GetParameters() []*config.Parameter { } // The the title for the config -func (config *FallbackNormalConfig) GetConfigTitle() string { - return config.Title +func (cfg *FallbackNormalConfig) GetConfigTitle() string { + return cfg.Title } // The the title for the config -func (config *FallbackPrysmConfig) GetConfigTitle() string { - return config.Title +func (cfg *FallbackPrysmConfig) GetConfigTitle() string { + return cfg.Title } diff --git a/shared/services/config/rocket-pool-config.go b/shared/services/config/rocket-pool-config.go index 8b6380f65..378a7dd39 100644 --- a/shared/services/config/rocket-pool-config.go +++ b/shared/services/config/rocket-pool-config.go @@ -474,7 +474,10 @@ func NewRocketPoolConfig(rpDir string, isNativeMode bool) *RocketPoolConfig { // Apply the default values for mainnet cfg.Smartnode.Network.Value = cfg.Smartnode.Network.Options[0].Value - cfg.applyAllDefaults() + err := cfg.applyAllDefaults() + if err != nil { + panic(err) + } return cfg } @@ -1024,7 +1027,9 @@ func (cfg *RocketPoolConfig) GenerateEnvironmentVariables() map[string]string { } // Addons - cfg.GraffitiWallWriter.UpdateEnvVars(envVars) + // Ignore errors. Addon will simply not function. + _ = cfg.GraffitiWallWriter.UpdateEnvVars(envVars) + // Don't do this- we only want the change to apply to the validator container //cfg.RescueNode.UpdateEnvVars(envVars, consensusClient) diff --git a/shared/services/config/smartnode-config.go b/shared/services/config/smartnode-config.go index 5555009db..18965c0d1 100644 --- a/shared/services/config/smartnode-config.go +++ b/shared/services/config/smartnode-config.go @@ -699,9 +699,9 @@ func (cfg *SmartnodeConfig) GetValidatorKeychainPathInCLI() string { return filepath.Join(cfg.DataPath.Value.(string), "validators") } -func (config *SmartnodeConfig) GetWatchtowerStatePath() string { - if config.parent.IsNativeMode { - return filepath.Join(config.DataPath.Value.(string), WatchtowerFolder, "state.yml") +func (cfg *SmartnodeConfig) GetWatchtowerStatePath() string { + if cfg.parent.IsNativeMode { + return filepath.Join(cfg.DataPath.Value.(string), WatchtowerFolder, "state.yml") } return filepath.Join(DaemonDataPath, WatchtowerFolder, "state.yml") @@ -743,7 +743,7 @@ func (cfg *SmartnodeConfig) GetSmartnodeContainerTag() string { return smartnodeTag } -func (config *SmartnodeConfig) GetPruneProvisionerContainerTag() string { +func (cfg *SmartnodeConfig) GetPruneProvisionerContainerTag() string { return pruneProvisionerTag } @@ -763,7 +763,7 @@ func (cfg *SmartnodeConfig) GetVotingSnapshotID() [32]byte { return buffer } -func (config *SmartnodeConfig) GetSnapshotID() string { +func (cfg *SmartnodeConfig) GetSnapshotID() string { return SnapshotID } diff --git a/shared/services/gas/gas.go b/shared/services/gas/gas.go index f6b1fb8a2..9991962ef 100644 --- a/shared/services/gas/gas.go +++ b/shared/services/gas/gas.go @@ -219,7 +219,7 @@ func handleEtherchainGasPrices(gasSuggestion etherchain.GasFeeSuggestion, gasInf 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 (%sv, try again.\n", err) continue } if desiredPriceFloat <= 0 { @@ -297,7 +297,7 @@ func handleEtherscanGasPrices(gasSuggestion etherscan.GasFeeSuggestion, gasInfo 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 (%v), try again.\n", err) continue } if desiredPriceFloat <= 0 { diff --git a/shared/services/requirements.go b/shared/services/requirements.go index 44c0db53d..d6b0dde68 100644 --- a/shared/services/requirements.go +++ b/shared/services/requirements.go @@ -553,7 +553,7 @@ func waitBeaconClientSynced(c *cli.Context, verbose bool, timeout int64) (bool, // Check sync status if syncStatus.Syncing { if verbose { - log.Println("Eth 2.0 node syncing: %.2f%%\n", syncStatus.Progress*100) + log.Printf("Eth 2.0 node syncing: %.2f%%\n", syncStatus.Progress*100) } } else { return true, nil diff --git a/shared/services/rewards/generator-impl-v1.go b/shared/services/rewards/generator-impl-v1.go index 2bad61033..cc5baf163 100644 --- a/shared/services/rewards/generator-impl-v1.go +++ b/shared/services/rewards/generator-impl-v1.go @@ -292,9 +292,9 @@ func (r *treeGeneratorImpl_v1) updateNetworksAndTotals() { // Create the map for each network, including unused ones for network := uint64(0); network <= highestNetworkIndex; network++ { - rewardsForNetwork, exists := r.rewardsFile.NetworkRewards[network] + _, exists := r.rewardsFile.NetworkRewards[network] if !exists { - rewardsForNetwork = &NetworkRewardsInfo{ + rewardsForNetwork := &NetworkRewardsInfo{ CollateralRpl: NewQuotedBigInt(0), OracleDaoRpl: NewQuotedBigInt(0), SmoothingPoolEth: NewQuotedBigInt(0), @@ -906,7 +906,7 @@ func (r *treeGeneratorImpl_v1) processEpoch(getDuties bool, epoch uint64) error } // Handle all of the attestations in the given slot -func (r *treeGeneratorImpl_v1) checkDutiesForSlot(attestations []beacon.AttestationInfo) error { +func (r *treeGeneratorImpl_v1) checkDutiesForSlot(attestations []beacon.AttestationInfo) { // Go through the attestations for the block for _, attestation := range attestations { @@ -936,8 +936,6 @@ func (r *treeGeneratorImpl_v1) checkDutiesForSlot(attestations []beacon.Attestat } } - return nil - } // Maps out the attestaion duties for the given epoch diff --git a/shared/services/rewards/generator-impl-v2.go b/shared/services/rewards/generator-impl-v2.go index 364139664..909af1483 100644 --- a/shared/services/rewards/generator-impl-v2.go +++ b/shared/services/rewards/generator-impl-v2.go @@ -296,9 +296,9 @@ func (r *treeGeneratorImpl_v2) updateNetworksAndTotals() { // Create the map for each network, including unused ones for network := uint64(0); network <= highestNetworkIndex; network++ { - rewardsForNetwork, exists := r.rewardsFile.NetworkRewards[network] + _, exists := r.rewardsFile.NetworkRewards[network] if !exists { - rewardsForNetwork = &NetworkRewardsInfo{ + rewardsForNetwork := &NetworkRewardsInfo{ CollateralRpl: NewQuotedBigInt(0), OracleDaoRpl: NewQuotedBigInt(0), SmoothingPoolEth: NewQuotedBigInt(0), @@ -925,7 +925,7 @@ func (r *treeGeneratorImpl_v2) processEpoch(getDuties bool, epoch uint64) error } // Handle all of the attestations in the given slot -func (r *treeGeneratorImpl_v2) checkDutiesForSlot(attestations []beacon.AttestationInfo) error { +func (r *treeGeneratorImpl_v2) checkDutiesForSlot(attestations []beacon.AttestationInfo) { // Go through the attestations for the block for _, attestation := range attestations { @@ -954,9 +954,6 @@ func (r *treeGeneratorImpl_v2) checkDutiesForSlot(attestations []beacon.Attestat } } } - - return nil - } // Maps out the attestaion duties for the given epoch diff --git a/shared/services/rewards/generator-impl-v3.go b/shared/services/rewards/generator-impl-v3.go index 270a34912..d4435e1fc 100644 --- a/shared/services/rewards/generator-impl-v3.go +++ b/shared/services/rewards/generator-impl-v3.go @@ -292,9 +292,9 @@ func (r *treeGeneratorImpl_v3) updateNetworksAndTotals() { // Create the map for each network, including unused ones for network := uint64(0); network <= highestNetworkIndex; network++ { - rewardsForNetwork, exists := r.rewardsFile.NetworkRewards[network] + _, exists := r.rewardsFile.NetworkRewards[network] if !exists { - rewardsForNetwork = &NetworkRewardsInfo{ + rewardsForNetwork := &NetworkRewardsInfo{ CollateralRpl: NewQuotedBigInt(0), OracleDaoRpl: NewQuotedBigInt(0), SmoothingPoolEth: NewQuotedBigInt(0), @@ -921,7 +921,7 @@ func (r *treeGeneratorImpl_v3) processEpoch(getDuties bool, epoch uint64) error } // Handle all of the attestations in the given slot -func (r *treeGeneratorImpl_v3) checkDutiesForSlot(attestations []beacon.AttestationInfo) error { +func (r *treeGeneratorImpl_v3) checkDutiesForSlot(attestations []beacon.AttestationInfo) { // Go through the attestations for the block for _, attestation := range attestations { @@ -950,9 +950,6 @@ func (r *treeGeneratorImpl_v3) checkDutiesForSlot(attestations []beacon.Attestat } } } - - return nil - } // Maps out the attestaion duties for the given epoch diff --git a/shared/services/rewards/generator-impl-v4.go b/shared/services/rewards/generator-impl-v4.go index e6b3a4dba..99abda124 100644 --- a/shared/services/rewards/generator-impl-v4.go +++ b/shared/services/rewards/generator-impl-v4.go @@ -331,9 +331,9 @@ func (r *treeGeneratorImpl_v4) updateNetworksAndTotals() { // Create the map for each network, including unused ones for network := uint64(0); network <= highestNetworkIndex; network++ { - rewardsForNetwork, exists := r.rewardsFile.NetworkRewards[network] + _, exists := r.rewardsFile.NetworkRewards[network] if !exists { - rewardsForNetwork = &NetworkRewardsInfo{ + rewardsForNetwork := &NetworkRewardsInfo{ CollateralRpl: NewQuotedBigInt(0), OracleDaoRpl: NewQuotedBigInt(0), SmoothingPoolEth: NewQuotedBigInt(0), @@ -978,7 +978,7 @@ func (r *treeGeneratorImpl_v4) processEpoch(getDuties bool, epoch uint64) error } // Handle all of the attestations in the given slot -func (r *treeGeneratorImpl_v4) checkDutiesForSlot(attestations []beacon.AttestationInfo) error { +func (r *treeGeneratorImpl_v4) checkDutiesForSlot(attestations []beacon.AttestationInfo) { // Go through the attestations for the block for _, attestation := range attestations { @@ -1007,9 +1007,6 @@ func (r *treeGeneratorImpl_v4) checkDutiesForSlot(attestations []beacon.Attestat } } } - - return nil - } // Maps out the attestaion duties for the given epoch diff --git a/shared/services/rewards/generator-impl-v5.go b/shared/services/rewards/generator-impl-v5.go index a02ae24ac..8e0fe1f53 100644 --- a/shared/services/rewards/generator-impl-v5.go +++ b/shared/services/rewards/generator-impl-v5.go @@ -293,9 +293,9 @@ func (r *treeGeneratorImpl_v5) updateNetworksAndTotals() { // Create the map for each network, including unused ones for network := uint64(0); network <= highestNetworkIndex; network++ { - rewardsForNetwork, exists := r.rewardsFile.NetworkRewards[network] + _, exists := r.rewardsFile.NetworkRewards[network] if !exists { - rewardsForNetwork = &NetworkRewardsInfo{ + rewardsForNetwork := &NetworkRewardsInfo{ CollateralRpl: NewQuotedBigInt(0), OracleDaoRpl: NewQuotedBigInt(0), SmoothingPoolEth: NewQuotedBigInt(0), @@ -832,7 +832,7 @@ func (r *treeGeneratorImpl_v5) processEpoch(getDuties bool, epoch uint64) error } // Handle all of the attestations in the given slot -func (r *treeGeneratorImpl_v5) checkDutiesForSlot(attestations []beacon.AttestationInfo, slot uint64) error { +func (r *treeGeneratorImpl_v5) checkDutiesForSlot(attestations []beacon.AttestationInfo, slot uint64) { one := eth.EthToWei(1) validatorReq := eth.EthToWei(32) @@ -885,9 +885,6 @@ func (r *treeGeneratorImpl_v5) checkDutiesForSlot(attestations []beacon.Attestat } } } - - return nil - } // Maps out the attestaion duties for the given epoch @@ -1164,7 +1161,7 @@ func (r *treeGeneratorImpl_v5) getMinipoolBondAndNodeFee(details *rpstate.Native previousBond := details.LastBondReductionPrevValue previousFee := details.LastBondReductionPrevNodeFee - var reductionTimeBig *big.Int = details.LastBondReductionTime + var reductionTimeBig = details.LastBondReductionTime if reductionTimeBig.Cmp(r.zero) == 0 { // Never reduced return currentBond, currentFee diff --git a/shared/services/rewards/generator-impl-v6-rolling.go b/shared/services/rewards/generator-impl-v6-rolling.go index f29eae883..af0b58ef5 100644 --- a/shared/services/rewards/generator-impl-v6-rolling.go +++ b/shared/services/rewards/generator-impl-v6-rolling.go @@ -284,9 +284,9 @@ func (r *treeGeneratorImpl_v6_rolling) updateNetworksAndTotals() { // Create the map for each network, including unused ones for network := uint64(0); network <= highestNetworkIndex; network++ { - rewardsForNetwork, exists := r.rewardsFile.NetworkRewards[network] + _, exists := r.rewardsFile.NetworkRewards[network] if !exists { - rewardsForNetwork = &NetworkRewardsInfo{ + rewardsForNetwork := &NetworkRewardsInfo{ CollateralRpl: NewQuotedBigInt(0), OracleDaoRpl: NewQuotedBigInt(0), SmoothingPoolEth: NewQuotedBigInt(0), diff --git a/shared/services/rewards/generator-impl-v6.go b/shared/services/rewards/generator-impl-v6.go index 64ab76e36..f576efcd4 100644 --- a/shared/services/rewards/generator-impl-v6.go +++ b/shared/services/rewards/generator-impl-v6.go @@ -294,9 +294,9 @@ func (r *treeGeneratorImpl_v6) updateNetworksAndTotals() { // Create the map for each network, including unused ones for network := uint64(0); network <= highestNetworkIndex; network++ { - rewardsForNetwork, exists := r.rewardsFile.NetworkRewards[network] + _, exists := r.rewardsFile.NetworkRewards[network] if !exists { - rewardsForNetwork = &NetworkRewardsInfo{ + rewardsForNetwork := &NetworkRewardsInfo{ CollateralRpl: NewQuotedBigInt(0), OracleDaoRpl: NewQuotedBigInt(0), SmoothingPoolEth: NewQuotedBigInt(0), @@ -813,7 +813,7 @@ func (r *treeGeneratorImpl_v6) processEpoch(getDuties bool, epoch uint64) error } // Handle all of the attestations in the given slot -func (r *treeGeneratorImpl_v6) checkDutiesForSlot(attestations []beacon.AttestationInfo, slot uint64) error { +func (r *treeGeneratorImpl_v6) checkDutiesForSlot(attestations []beacon.AttestationInfo, slot uint64) { one := eth.EthToWei(1) validatorReq := eth.EthToWei(32) @@ -871,9 +871,6 @@ func (r *treeGeneratorImpl_v6) checkDutiesForSlot(attestations []beacon.Attestat r.successfulAttestations++ } } - - return nil - } // Maps out the attestaion duties for the given epoch @@ -1158,7 +1155,7 @@ func (r *treeGeneratorImpl_v6) getMinipoolBondAndNodeFee(details *rpstate.Native previousBond := details.LastBondReductionPrevValue previousFee := details.LastBondReductionPrevNodeFee - var reductionTimeBig *big.Int = details.LastBondReductionTime + var reductionTimeBig = details.LastBondReductionTime if reductionTimeBig.Cmp(r.zero) == 0 { // Never reduced return currentBond, currentFee diff --git a/shared/services/rewards/generator-impl-v7.go b/shared/services/rewards/generator-impl-v7.go index 0dd237b27..38f40f087 100644 --- a/shared/services/rewards/generator-impl-v7.go +++ b/shared/services/rewards/generator-impl-v7.go @@ -837,7 +837,7 @@ func (r *treeGeneratorImpl_v7) processEpoch(getDuties bool, epoch uint64) error } // Handle all of the attestations in the given slot -func (r *treeGeneratorImpl_v7) checkDutiesForSlot(attestations []beacon.AttestationInfo, slot uint64) error { +func (r *treeGeneratorImpl_v7) checkDutiesForSlot(attestations []beacon.AttestationInfo, slot uint64) { one := eth.EthToWei(1) validatorReq := eth.EthToWei(32) @@ -895,9 +895,6 @@ func (r *treeGeneratorImpl_v7) checkDutiesForSlot(attestations []beacon.Attestat r.successfulAttestations++ } } - - return nil - } // Maps out the attestaion duties for the given epoch @@ -1182,7 +1179,7 @@ func (r *treeGeneratorImpl_v7) getMinipoolBondAndNodeFee(details *rpstate.Native previousBond := details.LastBondReductionPrevValue previousFee := details.LastBondReductionPrevNodeFee - var reductionTimeBig *big.Int = details.LastBondReductionTime + var reductionTimeBig = details.LastBondReductionTime if reductionTimeBig.Cmp(common.Big0) == 0 { // Never reduced return currentBond, currentFee diff --git a/shared/services/rewards/rewards-file-v1.go b/shared/services/rewards/rewards-file-v1.go index 133a11732..e9a618d1d 100644 --- a/shared/services/rewards/rewards-file-v1.go +++ b/shared/services/rewards/rewards-file-v1.go @@ -108,9 +108,9 @@ func (i *NodeRewardsInfo_v1) GetOracleDaoRpl() *QuotedBigInt { func (i *NodeRewardsInfo_v1) GetSmoothingPoolEth() *QuotedBigInt { return i.SmoothingPoolEth } -func (n *NodeRewardsInfo_v1) GetMerkleProof() ([]common.Hash, error) { +func (i *NodeRewardsInfo_v1) GetMerkleProof() ([]common.Hash, error) { proof := []common.Hash{} - for _, proofLevel := range n.MerkleProof { + for _, proofLevel := range i.MerkleProof { proof = append(proof, common.HexToHash(proofLevel)) } return proof, nil diff --git a/shared/services/rewards/rewards-file-v2.go b/shared/services/rewards/rewards-file-v2.go index 06b70f3c3..b35da5d9c 100644 --- a/shared/services/rewards/rewards-file-v2.go +++ b/shared/services/rewards/rewards-file-v2.go @@ -105,9 +105,9 @@ func (i *NodeRewardsInfo_v2) GetOracleDaoRpl() *QuotedBigInt { func (i *NodeRewardsInfo_v2) GetSmoothingPoolEth() *QuotedBigInt { return i.SmoothingPoolEth } -func (n *NodeRewardsInfo_v2) GetMerkleProof() ([]common.Hash, error) { +func (i *NodeRewardsInfo_v2) GetMerkleProof() ([]common.Hash, error) { proof := []common.Hash{} - for _, proofLevel := range n.MerkleProof { + for _, proofLevel := range i.MerkleProof { proof = append(proof, common.HexToHash(proofLevel)) } return proof, nil diff --git a/shared/services/rewards/utils.go b/shared/services/rewards/utils.go index 48a30729a..f363f1e3f 100644 --- a/shared/services/rewards/utils.go +++ b/shared/services/rewards/utils.go @@ -478,7 +478,7 @@ func getMinipoolBondAndNodeFee(details *rpstate.NativeMinipoolDetails, blockTime zero = big.NewInt(0) } - var reductionTimeBig *big.Int = details.LastBondReductionTime + var reductionTimeBig = details.LastBondReductionTime if reductionTimeBig.Cmp(zero) == 0 { // Never reduced return currentBond, currentFee diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index a05563236..75fe42698 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -75,14 +75,22 @@ func SyncRatioToPercent(in float64) float64 { func getExternalIP() (net.IP, error) { // Try IPv4 first ip4Consensus := externalip.DefaultConsensus(nil, nil) - ip4Consensus.UseIPProtocol(4) + err := ip4Consensus.UseIPProtocol(4) + if err != nil { + // This will only happen if we pass something other than 0/4/6 to UseIPProtocol + panic(err) + } if ip, err := ip4Consensus.ExternalIP(); err == nil { return ip, nil } // Try IPv6 as fallback ip6Consensus := externalip.DefaultConsensus(nil, nil) - ip6Consensus.UseIPProtocol(6) + err = ip6Consensus.UseIPProtocol(6) + if err != nil { + // This will only happen if we pass something other than 0/4/6 to UseIPProtocol + panic(err) + } return ip6Consensus.ExternalIP() } @@ -325,7 +333,7 @@ func (c *Client) UpdatePrometheusConfiguration(settings map[string]string) error } err = os.Chmod(prometheusConfigPath, 0664) if err != nil { - return fmt.Errorf("Could not set Prometheus config file permissions: %w", shellescape.Quote(prometheusConfigPath), err) + return fmt.Errorf("Could not set Prometheus config file %s permissions: %w", shellescape.Quote(prometheusConfigPath), err) } return nil @@ -425,7 +433,7 @@ func (c *Client) InstallUpdateTracker(verbose bool, version string) error { // Get installation script flags flags := []string{ - "-v", fmt.Sprintf("%s", shellescape.Quote(version)), + "-v", shellescape.Quote(version), } // Download the installer package @@ -590,7 +598,7 @@ func (c *Client) PrintServiceStatus(composeFiles []string) error { func (c *Client) PrintServiceLogs(composeFiles []string, tail string, serviceNames ...string) error { sanitizedStrings := make([]string, len(serviceNames)) for i, serviceName := range serviceNames { - sanitizedStrings[i] = fmt.Sprintf("%s", shellescape.Quote(serviceName)) + sanitizedStrings[i] = shellescape.Quote(serviceName) } cmd, err := c.compose(composeFiles, fmt.Sprintf("logs -f --tail %s %s", shellescape.Quote(tail), strings.Join(sanitizedStrings, " "))) if err != nil { @@ -1363,44 +1371,6 @@ func (c *Client) callAPI(args string, otherArgs ...string) ([]byte, error) { return c.runApiCall(cmd) } -// Call the Rocket Pool API with some custom environment variables -func (c *Client) callAPIWithEnvVars(envVars map[string]string, args string, otherArgs ...string) ([]byte, error) { - // Sanitize and parse the args - ignoreSyncCheckFlag, forceFallbackECFlag, args := c.getApiCallArgs(args, otherArgs...) - - // Create the command to run - var cmd string - if c.daemonPath == "" { - envArgs := "" - for key, value := range envVars { - os.Setenv(key, shellescape.Quote(value)) - envArgs += fmt.Sprintf("-e %s ", key) - } - containerName, err := c.getAPIContainerName() - if err != nil { - return []byte{}, err - } - cmd = fmt.Sprintf("docker exec %s %s %s %s %s %s %s api %s", envArgs, shellescape.Quote(containerName), shellescape.Quote(APIBinPath), ignoreSyncCheckFlag, forceFallbackECFlag, c.getGasOpts(), c.getCustomNonce(), args) - } else { - envArgs := "" - for key, value := range envVars { - envArgs += fmt.Sprintf("%s=%s ", key, shellescape.Quote(value)) - } - cmd = fmt.Sprintf("%s %s --settings %s %s %s %s %s api %s", - envArgs, - c.daemonPath, - shellescape.Quote(fmt.Sprintf("%s/%s", c.configPath, SettingsFile)), - ignoreSyncCheckFlag, - forceFallbackECFlag, - c.getGasOpts(), - c.getCustomNonce(), - args) - } - - // Run the command - return c.runApiCall(cmd) -} - func (c *Client) getApiCallArgs(args string, otherArgs ...string) (string, string, string) { // Sanitize arguments var sanitizedArgs []string diff --git a/shared/services/rocketpool/gas.go b/shared/services/rocketpool/gas.go index 1c45813a8..968239f84 100644 --- a/shared/services/rocketpool/gas.go +++ b/shared/services/rocketpool/gas.go @@ -11,7 +11,7 @@ const ( ) // Print a warning about the gas estimate for operations that have multiple transactions -func (rp *Client) PrintMultiTxWarning() { +func PrintMultiTxWarning() { fmt.Printf("%sNOTE: This operation requires multiple transactions.\n%s", colorYellow, diff --git a/shared/services/rocketpool/node.go b/shared/services/rocketpool/node.go index 6c76d5a34..42d39f27d 100644 --- a/shared/services/rocketpool/node.go +++ b/shared/services/rocketpool/node.go @@ -261,7 +261,7 @@ func (c *Client) NodeSwapRpl(amountWei *big.Int) (api.NodeSwapRplSwapResponse, e // Get a node's legacy RPL allowance for swapping on the new RPL contract func (c *Client) GetNodeSwapRplAllowance() (api.NodeSwapRplAllowanceResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node swap-rpl-allowance")) + responseBytes, err := c.callAPI("node swap-rpl-allowance") if err != nil { return api.NodeSwapRplAllowanceResponse{}, fmt.Errorf("Could not get node swap RPL allowance: %w", err) } @@ -357,7 +357,7 @@ func (c *Client) NodeStakeRpl(amountWei *big.Int) (api.NodeStakeRplStakeResponse // Get a node's RPL allowance for the staking contract func (c *Client) GetNodeStakeRplAllowance() (api.NodeStakeRplAllowanceResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node stake-rpl-allowance")) + responseBytes, err := c.callAPI("node stake-rpl-allowance") if err != nil { return api.NodeStakeRplAllowanceResponse{}, fmt.Errorf("Could not get node stake RPL allowance: %w", err) } diff --git a/shared/services/rocketpool/odao.go b/shared/services/rocketpool/odao.go index 562a69fc3..d828c0f56 100644 --- a/shared/services/rocketpool/odao.go +++ b/shared/services/rocketpool/odao.go @@ -66,7 +66,7 @@ func (c *Client) TNDAOProposals() (api.TNDAOProposalsResponse, error) { // Get a single oracle DAO proposal func (c *Client) TNDAOProposal(id uint64) (api.TNDAOProposalResponse, error) { - responseBytes, err := c.callAPI("odao proposal-details", string(id)) + responseBytes, err := c.callAPI("odao proposal-details", fmt.Sprint(id)) if err != nil { return api.TNDAOProposalResponse{}, fmt.Errorf("Could not get oracle DAO proposal: %w", err) } @@ -800,7 +800,7 @@ func (c *Client) ProposeTNDAOSettingBondReductionWindowLength(windowLength uint6 // Get the member settings func (c *Client) GetTNDAOMemberSettings() (api.GetTNDAOMemberSettingsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao get-member-settings")) + responseBytes, err := c.callAPI("odao get-member-settings") if err != nil { return api.GetTNDAOMemberSettingsResponse{}, fmt.Errorf("Could not get oracle DAO member settings: %w", err) } @@ -822,7 +822,7 @@ func (c *Client) GetTNDAOMemberSettings() (api.GetTNDAOMemberSettingsResponse, e // Get the proposal settings func (c *Client) GetTNDAOProposalSettings() (api.GetTNDAOProposalSettingsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao get-proposal-settings")) + responseBytes, err := c.callAPI("odao get-proposal-settings") if err != nil { return api.GetTNDAOProposalSettingsResponse{}, fmt.Errorf("Could not get oracle DAO proposal settings: %w", err) } @@ -838,7 +838,7 @@ func (c *Client) GetTNDAOProposalSettings() (api.GetTNDAOProposalSettingsRespons // Get the proposal settings func (c *Client) GetTNDAOMinipoolSettings() (api.GetTNDAOMinipoolSettingsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao get-minipool-settings")) + responseBytes, err := c.callAPI("odao get-minipool-settings") if err != nil { return api.GetTNDAOMinipoolSettingsResponse{}, fmt.Errorf("Could not get oracle DAO minipool settings: %w", err) } diff --git a/shared/services/services.go b/shared/services/services.go index dbce628ca..d8a8576a7 100644 --- a/shared/services/services.go +++ b/shared/services/services.go @@ -13,7 +13,6 @@ import ( "github.com/rocket-pool/rocketpool-go/utils/eth" "github.com/urfave/cli" - "github.com/rocket-pool/smartnode/shared/services/beacon" "github.com/rocket-pool/smartnode/shared/services/config" "github.com/rocket-pool/smartnode/shared/services/contracts" "github.com/rocket-pool/smartnode/shared/services/passwords" @@ -44,7 +43,6 @@ var ( rocketPool *rocketpool.RocketPool rplFaucet *contracts.RPLFaucet snapshotDelegation *contracts.SnapshotDelegation - beaconClient beacon.Client docker *client.Client initCfg sync.Once @@ -53,10 +51,8 @@ var ( initECManager sync.Once initBCManager sync.Once initRocketPool sync.Once - initOneInchOracle sync.Once initRplFaucet sync.Once initSnapshotDelegation sync.Once - initBeaconClient sync.Once initDocker sync.Once ) diff --git a/shared/services/state/network-state.go b/shared/services/state/network-state.go index 012d45b12..e2b574bc2 100644 --- a/shared/services/state/network-state.go +++ b/shared/services/state/network-state.go @@ -134,7 +134,10 @@ func CreateNetworkState(cfg *config.RocketPoolConfig, rp *rocketpool.RocketPool, // Calculate avg node fees and distributor shares for _, details := range state.NodeDetails { - rpstate.CalculateAverageFeeAndDistributorShares(rp, contracts, details, state.MinipoolDetailsByNode[details.NodeAddress]) + err = rpstate.CalculateAverageFeeAndDistributorShares(rp, contracts, details, state.MinipoolDetailsByNode[details.NodeAddress]) + if err != nil { + return nil, fmt.Errorf("error calculating average fee and distributor shares: %w", err) + } } // Oracle DAO member details @@ -268,7 +271,10 @@ func CreateNetworkStateForNode(cfg *config.RocketPoolConfig, rp *rocketpool.Rock // Calculate avg node fees and distributor shares for _, details := range state.NodeDetails { - rpstate.CalculateAverageFeeAndDistributorShares(rp, contracts, details, state.MinipoolDetailsByNode[details.NodeAddress]) + err = rpstate.CalculateAverageFeeAndDistributorShares(rp, contracts, details, state.MinipoolDetailsByNode[details.NodeAddress]) + if err != nil { + return nil, nil, fmt.Errorf("error calculating average fee and distributor shares: %w", err) + } } // Get the total network effective RPL stake diff --git a/shared/services/wallet/keystore/lodestar/keystore.go b/shared/services/wallet/keystore/lodestar/keystore.go index 932d10294..c3b1c87c4 100644 --- a/shared/services/wallet/keystore/lodestar/keystore.go +++ b/shared/services/wallet/keystore/lodestar/keystore.go @@ -2,7 +2,6 @@ package lodestar import ( "fmt" - "io/ioutil" "os" "path/filepath" @@ -99,7 +98,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write secret to disk - if err := ioutil.WriteFile(secretFilePath, []byte(password), FileMode); err != nil { + if err := os.WriteFile(secretFilePath, []byte(password), FileMode); err != nil { return fmt.Errorf("Could not write validator secret to disk: %w", err) } @@ -112,7 +111,7 @@ func (ks *Keystore) StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPa } // Write key store to disk - if err := ioutil.WriteFile(keyFilePath, keyStoreBytes, FileMode); err != nil { + if err := os.WriteFile(keyFilePath, keyStoreBytes, FileMode); err != nil { return fmt.Errorf("Could not write validator key to disk: %w", err) } diff --git a/shared/services/wallet/node.go b/shared/services/wallet/node.go index 6619a835a..d6247a3a6 100644 --- a/shared/services/wallet/node.go +++ b/shared/services/wallet/node.go @@ -139,6 +139,8 @@ func (w *Wallet) getNodeDerivedKey(index uint) (*hdkeychain.ExtendedKey, string, // Use the legacy implementation for Goerli // TODO: remove this if Prater ever goes away! if w.chainID.Cmp(big.NewInt(5)) == 0 { + //nolint:staticcheck + //lint:ignore SA1019 this function is deprecated but we must call it for prater key, err = key.DeriveNonStandard(n) } else { key, err = key.Derive(n) diff --git a/shared/services/wallet/validator.go b/shared/services/wallet/validator.go index b31be9dbc..ae68ffec9 100644 --- a/shared/services/wallet/validator.go +++ b/shared/services/wallet/validator.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/rocket-pool/rocketpool-go/types" - rptypes "github.com/rocket-pool/rocketpool-go/types" "github.com/rocket-pool/smartnode/shared/utils/validator" eth2types "github.com/wealdtech/go-eth2-types/v2" eth2util "github.com/wealdtech/go-eth2-util" @@ -55,7 +54,7 @@ func (w *Wallet) GetValidatorKeyAt(index uint) (*eth2types.BLSPrivateKey, error) } // Get a validator key by public key -func (w *Wallet) GetValidatorKeyByPubkey(pubkey rptypes.ValidatorPubkey) (*eth2types.BLSPrivateKey, error) { +func (w *Wallet) GetValidatorKeyByPubkey(pubkey types.ValidatorPubkey) (*eth2types.BLSPrivateKey, error) { // Check wallet is initialized if !w.IsInitialized() { @@ -222,7 +221,7 @@ func (w *Wallet) SaveValidatorKey(key ValidatorKey) error { } // Recover a validator key by public key -func (w *Wallet) RecoverValidatorKey(pubkey rptypes.ValidatorPubkey, startIndex uint) (uint, error) { +func (w *Wallet) RecoverValidatorKey(pubkey types.ValidatorPubkey, startIndex uint) (uint, error) { // Check wallet is initialized if !w.IsInitialized() { @@ -268,7 +267,7 @@ func (w *Wallet) RecoverValidatorKey(pubkey rptypes.ValidatorPubkey, startIndex } // Test recovery of a validator key by public key -func (w *Wallet) TestRecoverValidatorKey(pubkey rptypes.ValidatorPubkey, startIndex uint) (uint, error) { +func (w *Wallet) TestRecoverValidatorKey(pubkey types.ValidatorPubkey, startIndex uint) (uint, error) { // Check wallet is initialized if !w.IsInitialized() { diff --git a/shared/utils/cli/migration/import-key.go b/shared/utils/cli/migration/import-key.go index aa5e4211f..fc5d472cc 100644 --- a/shared/utils/cli/migration/import-key.go +++ b/shared/utils/cli/migration/import-key.go @@ -52,7 +52,8 @@ func ImportKey(c *cli.Context, rp *rocketpool.Client, minipoolAddress common.Add 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", colorYellow, err.Error(), colorReset) return false } - fmt.Println("done!\n") + fmt.Println("done!") + fmt.Println() } return true diff --git a/shared/utils/cli/validation.go b/shared/utils/cli/validation.go index 43db6cb41..d8c9eddc2 100644 --- a/shared/utils/cli/validation.go +++ b/shared/utils/cli/validation.go @@ -227,7 +227,7 @@ func ValidateWalletMnemonic(name, value string) (string, error) { // Validate a timezone location func ValidateTimezoneLocation(name, value string) (string, error) { - if !regexp.MustCompile("^([a-zA-Z_]{2,}\\/)+[a-zA-Z_]{2,}$").MatchString(value) { + if !regexp.MustCompile(`^([a-zA-Z_]{2,}\/)+[a-zA-Z_]{2,}$`).MatchString(value) { return "", fmt.Errorf("Invalid %s '%s' - must be in the format 'Country/City'", name, value) } return value, nil @@ -246,9 +246,7 @@ func ValidateDAOMemberID(name, value string) (string, error) { func ValidateTxHash(name, value string) (common.Hash, error) { // Remove a 0x prefix if present - if strings.HasPrefix(value, "0x") { - value = value[2:] - } + value = strings.TrimPrefix(value, "0x") // Hash should be 64 characters long if len(value) != hex.EncodedLen(common.HashLength) { @@ -278,9 +276,7 @@ func ValidatePubkey(name, value string) (types.ValidatorPubkey, error) { // Validate a hex-encoded byte array func ValidateByteArray(name, value string) ([]byte, error) { // Remove a 0x prefix if present - if strings.HasPrefix(value, "0x") { - value = value[2:] - } + value = strings.TrimPrefix(value, "0x") // Try to parse the string (removing the prefix) bytes, err := hex.DecodeString(value) diff --git a/shared/utils/eth1/eth1.go b/shared/utils/eth1/eth1.go index 0718ee8ad..4e7799e29 100644 --- a/shared/utils/eth1/eth1.go +++ b/shared/utils/eth1/eth1.go @@ -89,13 +89,13 @@ func GetBestApiClient(primary *rocketpool.RocketPool, cfg *config.RocketPoolConf } client, err = rocketpool.NewRocketPool(ec, common.HexToAddress(cfg.Smartnode.GetStorageAddress())) if err != nil { - return nil, fmt.Errorf("%s Error creating Rocket Pool client connected to archive EC: %w", err) + return nil, fmt.Errorf("Error creating Rocket Pool client connected to archive EC: %w", err) } // Get the rETH address from the archive EC address, err = client.RocketStorage.GetAddress(opts, crypto.Keccak256Hash([]byte("contract.addressrocketTokenRETH"))) if err != nil { - return nil, fmt.Errorf("%s Error verifying rETH address with Archive EC: %w", err) + return nil, fmt.Errorf("Error verifying rETH address with Archive EC: %w", err) } } else { // No archive node specified diff --git a/shared/utils/net/net.go b/shared/utils/net/net.go index 15c52a90a..26215adea 100644 --- a/shared/utils/net/net.go +++ b/shared/utils/net/net.go @@ -7,7 +7,7 @@ import ( // Add a default port to a host address func DefaultPort(host string, port string) string { - if !regexp.MustCompile(":\\d+$").MatchString(host) { + if !regexp.MustCompile(`:\d+$`).MatchString(host) { return fmt.Sprintf("%s:%s", host, port) } return host diff --git a/shared/utils/rp/config.go b/shared/utils/rp/config.go index dddb89805..af410d13a 100644 --- a/shared/utils/rp/config.go +++ b/shared/utils/rp/config.go @@ -101,11 +101,7 @@ func IsFirstRun(configDir string) bool { // Load the config normally if the upgrade flag file isn't there _, err := os.Stat(upgradeFilePath) - if os.IsNotExist(err) { - return false - } - - return true + return !os.IsNotExist(err) } // Remove the upgrade flag file diff --git a/shared/utils/validator/bls.go b/shared/utils/validator/bls.go index 9689a6c8e..6224a24b0 100644 --- a/shared/utils/validator/bls.go +++ b/shared/utils/validator/bls.go @@ -14,12 +14,6 @@ const ( ValidatorKeyPath string = "m/12381/3600/%d/0/0" ) -// BLS signing root with domain -type signingRoot struct { - ObjectRoot []byte `ssz-size:"32"` - Domain []byte `ssz-size:"32"` -} - // Initialize BLS support var initBLS sync.Once 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"]