diff --git a/.golangci.yml b/.golangci.yml index 654c62ca7..b2cc303b3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,9 +1,21 @@ version: "2" linters: - default: none enable: - - staticcheck + - revive settings: + revive: + enable-default-rules: true + rules: + - name: exported + disabled: true + - name: var-naming + disabled: true + - name: package-comments + disabled: true + - name: unused-parameter + disabled: true + - name: error-strings + disabled: true staticcheck: checks: - all @@ -18,6 +30,10 @@ linters: - -ST1020 - -ST1021 - -ST1022 + errcheck: + exclude-functions: + - (*os.File).Close + formatters: enable: diff --git a/bindings/dao/protocol/dao.go b/bindings/dao/protocol/dao.go deleted file mode 100644 index b908a20ed..000000000 --- a/bindings/dao/protocol/dao.go +++ /dev/null @@ -1,18 +0,0 @@ -package protocol - -import ( - "sync" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - - "github.com/rocket-pool/smartnode/bindings/rocketpool" -) - -// Get contracts -var rocketDAOProtocolLock sync.Mutex - -func getRocketDAOProtocol(rp *rocketpool.RocketPool, opts *bind.CallOpts) (*rocketpool.Contract, error) { - rocketDAOProtocolLock.Lock() - defer rocketDAOProtocolLock.Unlock() - return rp.GetContract("rocketDAOProtocol", opts) -} diff --git a/bindings/dao/protocol/verify.go b/bindings/dao/protocol/verify.go index a26328672..83836c724 100755 --- a/bindings/dao/protocol/verify.go +++ b/bindings/dao/protocol/verify.go @@ -233,9 +233,9 @@ func GetMultiChallengeStatesFast(rp *rocketpool.RocketPool, multicallAddress com rawStates := make([]uint8, count) for i := uint64(0); i < count; i += challengeStateBatchSize { i := i - max := i + challengeStateBatchSize - if max > count { - max = count + m := i + challengeStateBatchSize + if m > count { + m = count } // Load details @@ -245,10 +245,13 @@ func GetMultiChallengeStatesFast(rp *rocketpool.RocketPool, multicallAddress com if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { propID := big.NewInt(int64(proposalIds[j])) challengedIndex := big.NewInt(int64(challengedIndices[j])) - mc.AddCall(rocketDAOProtocolVerifier, &rawStates[j], "getChallengeState", propID, challengedIndex) + err = mc.AddCall(rocketDAOProtocolVerifier, &rawStates[j], "getChallengeState", propID, challengedIndex) + if err != nil { + return fmt.Errorf("error adding challenge state call for proposal %d / index %d: %w", proposalIds[j], challengedIndices[j], err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { diff --git a/bindings/deposit/deposit.go b/bindings/deposit/deposit.go index 34f4f9893..ffcd880b7 100644 --- a/bindings/deposit/deposit.go +++ b/bindings/deposit/deposit.go @@ -73,21 +73,21 @@ func Deposit(rp *rocketpool.RocketPool, opts *bind.TransactOpts) (common.Hash, e } // Estimate the gas of AssignDeposits -func EstimateAssignDepositsGas(rp *rocketpool.RocketPool, max *big.Int, opts *bind.TransactOpts) (rocketpool.GasInfo, error) { +func EstimateAssignDepositsGas(rp *rocketpool.RocketPool, m *big.Int, opts *bind.TransactOpts) (rocketpool.GasInfo, error) { rocketDepositPool, err := getRocketDepositPool(rp, nil) if err != nil { return rocketpool.GasInfo{}, err } - return rocketDepositPool.GetTransactionGasInfo(opts, "assignDeposits", max) + return rocketDepositPool.GetTransactionGasInfo(opts, "assignDeposits", m) } // Assign deposits -func AssignDeposits(rp *rocketpool.RocketPool, max *big.Int, opts *bind.TransactOpts) (common.Hash, error) { +func AssignDeposits(rp *rocketpool.RocketPool, m *big.Int, opts *bind.TransactOpts) (common.Hash, error) { rocketDepositPool, err := getRocketDepositPool(rp, nil) if err != nil { return common.Hash{}, err } - tx, err := rocketDepositPool.Transact(opts, "assignDeposits", max) + tx, err := rocketDepositPool.Transact(opts, "assignDeposits", m) if err != nil { return common.Hash{}, fmt.Errorf("error assigning deposits: %w", err) } diff --git a/bindings/legacy/v1.0.0/minipool/minipool.go b/bindings/legacy/v1.0.0/minipool/minipool.go index de9789216..d1da76163 100644 --- a/bindings/legacy/v1.0.0/minipool/minipool.go +++ b/bindings/legacy/v1.0.0/minipool/minipool.go @@ -544,7 +544,6 @@ func getRocketMinipoolManager(rp *rocketpool.RocketPool, address *common.Address defer rocketMinipoolManagerLock.Unlock() if address == nil { return rp.VersionManager.V1_0_0.GetContract("rocketMinipoolManager", opts) - } else { - return rp.VersionManager.V1_0_0.GetContractWithAddress("rocketMinipoolManager", *address) } + return rp.VersionManager.V1_0_0.GetContractWithAddress("rocketMinipoolManager", *address) } diff --git a/bindings/legacy/v1.0.0/rewards/node.go b/bindings/legacy/v1.0.0/rewards/node.go index 666a42e4a..38a4d7334 100644 --- a/bindings/legacy/v1.0.0/rewards/node.go +++ b/bindings/legacy/v1.0.0/rewards/node.go @@ -126,7 +126,6 @@ func getRocketClaimNode(rp *rocketpool.RocketPool, address *common.Address, opts defer rocketClaimNodeLock.Unlock() if address == nil { return rp.VersionManager.V1_0_0.GetContract("rocketClaimNode", opts) - } else { - return rp.VersionManager.V1_0_0.GetContractWithAddress("rocketClaimNode", *address) } + return rp.VersionManager.V1_0_0.GetContractWithAddress("rocketClaimNode", *address) } diff --git a/bindings/legacy/v1.0.0/rewards/rewards.go b/bindings/legacy/v1.0.0/rewards/rewards.go index 78df8fad5..f8286ed00 100644 --- a/bindings/legacy/v1.0.0/rewards/rewards.go +++ b/bindings/legacy/v1.0.0/rewards/rewards.go @@ -151,7 +151,6 @@ func getRocketRewardsPool(rp *rocketpool.RocketPool, address *common.Address, op defer rocketRewardsPoolLock.Unlock() if address == nil { return rp.VersionManager.V1_0_0.GetContract("rocketRewardsPool", opts) - } else { - return rp.VersionManager.V1_0_0.GetContractWithAddress("rocketRewardsPool", *address) } + return rp.VersionManager.V1_0_0.GetContractWithAddress("rocketRewardsPool", *address) } diff --git a/bindings/legacy/v1.0.0/rewards/trusted-node.go b/bindings/legacy/v1.0.0/rewards/trusted-node.go index 312da4cbd..c1adfd0d4 100644 --- a/bindings/legacy/v1.0.0/rewards/trusted-node.go +++ b/bindings/legacy/v1.0.0/rewards/trusted-node.go @@ -126,7 +126,6 @@ func getRocketClaimTrustedNode(rp *rocketpool.RocketPool, address *common.Addres defer rocketClaimTrustedNodeLock.Unlock() if address == nil { return rp.VersionManager.V1_0_0.GetContract("rocketClaimTrustedNode", opts) - } else { - return rp.VersionManager.V1_0_0.GetContractWithAddress("rocketClaimTrustedNode", *address) } + return rp.VersionManager.V1_0_0.GetContractWithAddress("rocketClaimTrustedNode", *address) } diff --git a/bindings/legacy/v1.0.0/utils/address_generation.go b/bindings/legacy/v1.0.0/utils/address_generation.go index 34a116319..f4da1d121 100644 --- a/bindings/legacy/v1.0.0/utils/address_generation.go +++ b/bindings/legacy/v1.0.0/utils/address_generation.go @@ -69,7 +69,6 @@ func getRocketMinipoolManager(rp *rocketpool.RocketPool, address *common.Address defer rocketMinipoolManagerLock.Unlock() if address == nil { return rp.VersionManager.V1_0_0.GetContract("rocketMinipoolManager", opts) - } else { - return rp.VersionManager.V1_0_0.GetContractWithAddress("rocketMinipoolManager", *address) } + return rp.VersionManager.V1_0_0.GetContractWithAddress("rocketMinipoolManager", *address) } diff --git a/bindings/legacy/v1.1.0-rc1/rewards/rewards.go b/bindings/legacy/v1.1.0-rc1/rewards/rewards.go index aa08af721..2a144f069 100644 --- a/bindings/legacy/v1.1.0-rc1/rewards/rewards.go +++ b/bindings/legacy/v1.1.0-rc1/rewards/rewards.go @@ -300,7 +300,6 @@ func getRocketRewardsPool(rp *rocketpool.RocketPool, address *common.Address, op defer rocketRewardsPoolLock.Unlock() if address == nil { return rp.VersionManager.V1_1_0_RC1.GetContract("rocketRewardsPool", opts) - } else { - return rp.VersionManager.V1_1_0_RC1.GetContractWithAddress("rocketRewardsPool", *address) } + return rp.VersionManager.V1_1_0_RC1.GetContractWithAddress("rocketRewardsPool", *address) } diff --git a/bindings/legacy/v1.1.0/minipool/factory.go b/bindings/legacy/v1.1.0/minipool/factory.go index 7bd47e3a9..1552396ea 100644 --- a/bindings/legacy/v1.1.0/minipool/factory.go +++ b/bindings/legacy/v1.1.0/minipool/factory.go @@ -31,7 +31,6 @@ func getRocketMinipoolFactory(rp *rocketpool.RocketPool, address *common.Address defer rocketMinipoolFactoryLock.Unlock() if address == nil { return rp.VersionManager.V1_1_0.GetContract("rocketMinipoolFactory", opts) - } else { - return rp.VersionManager.V1_1_0.GetContractWithAddress("rocketMinipoolFactory", *address) } + return rp.VersionManager.V1_1_0.GetContractWithAddress("rocketMinipoolFactory", *address) } diff --git a/bindings/legacy/v1.1.0/minipool/queue.go b/bindings/legacy/v1.1.0/minipool/queue.go index fe1ed496a..c0abe466d 100644 --- a/bindings/legacy/v1.1.0/minipool/queue.go +++ b/bindings/legacy/v1.1.0/minipool/queue.go @@ -296,7 +296,6 @@ func getRocketMinipoolQueue(rp *rocketpool.RocketPool, address *common.Address, defer rocketMinipoolQueueLock.Unlock() if address == nil { return rp.VersionManager.V1_1_0.GetContract("rocketMinipoolQueue", opts) - } else { - return rp.VersionManager.V1_1_0.GetContractWithAddress("rocketMinipoolQueue", *address) } + return rp.VersionManager.V1_1_0.GetContractWithAddress("rocketMinipoolQueue", *address) } diff --git a/bindings/legacy/v1.1.0/network/prices.go b/bindings/legacy/v1.1.0/network/prices.go index 6cb4b509d..de18d7027 100644 --- a/bindings/legacy/v1.1.0/network/prices.go +++ b/bindings/legacy/v1.1.0/network/prices.go @@ -93,7 +93,6 @@ func getRocketNetworkPrices(rp *rocketpool.RocketPool, address *common.Address, defer rocketNetworkPricesLock.Unlock() if address == nil { return rp.VersionManager.V1_1_0.GetContract("rocketNetworkPrices", opts) - } else { - return rp.VersionManager.V1_1_0.GetContractWithAddress("rocketNetworkPrices", *address) } + return rp.VersionManager.V1_1_0.GetContractWithAddress("rocketNetworkPrices", *address) } diff --git a/bindings/legacy/v1.1.0/node/deposit.go b/bindings/legacy/v1.1.0/node/deposit.go index d0ecad67a..557b1e561 100644 --- a/bindings/legacy/v1.1.0/node/deposit.go +++ b/bindings/legacy/v1.1.0/node/deposit.go @@ -58,7 +58,6 @@ func getRocketNodeDeposit(rp *rocketpool.RocketPool, address *common.Address, op defer rocketNodeDepositLock.Unlock() if address == nil { return rp.VersionManager.V1_1_0.GetContract("rocketNodeDeposit", opts) - } else { - return rp.VersionManager.V1_1_0.GetContractWithAddress("rocketNodeDeposit", *address) } + return rp.VersionManager.V1_1_0.GetContractWithAddress("rocketNodeDeposit", *address) } diff --git a/bindings/legacy/v1.1.0/node/staking.go b/bindings/legacy/v1.1.0/node/staking.go index 338bb7030..a855c9a43 100644 --- a/bindings/legacy/v1.1.0/node/staking.go +++ b/bindings/legacy/v1.1.0/node/staking.go @@ -205,7 +205,6 @@ func getRocketNodeStaking(rp *rocketpool.RocketPool, address *common.Address, op defer rocketNodeStakingLock.Unlock() if address == nil { return rp.VersionManager.V1_1_0.GetContract("rocketNodeStaking", opts) - } else { - return rp.VersionManager.V1_1_0.GetContractWithAddress("rocketNodeStaking", *address) } + return rp.VersionManager.V1_1_0.GetContractWithAddress("rocketNodeStaking", *address) } diff --git a/bindings/minipool/minipool-constructor.go b/bindings/minipool/minipool-constructor.go index 61c02b9e6..8ce75d03f 100644 --- a/bindings/minipool/minipool-constructor.go +++ b/bindings/minipool/minipool-constructor.go @@ -3,7 +3,6 @@ package minipool import ( "fmt" "strings" - "sync" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -77,12 +76,3 @@ func createMinipoolContractFromAbi(rp *rocketpool.RocketPool, address common.Add Client: rp.Client, }, nil } - -// Get a minipool contract -var rocketMinipoolLock sync.Mutex - -func getMinipoolContract(rp *rocketpool.RocketPool, minipoolAddress common.Address, opts *bind.CallOpts) (*rocketpool.Contract, error) { - rocketMinipoolLock.Lock() - defer rocketMinipoolLock.Unlock() - return rp.MakeContract("rocketMinipool", minipoolAddress, opts) -} diff --git a/bindings/minipool/minipool-contract-v2.go b/bindings/minipool/minipool-contract-v2.go index 984d488e7..2032d3b0a 100644 --- a/bindings/minipool/minipool-contract-v2.go +++ b/bindings/minipool/minipool-contract-v2.go @@ -575,7 +575,7 @@ func (mp *minipool_v2) GetPrestakeEvent(intervalSize *big.Int, opts *bind.CallOp // Decode the event prestakeEvent := new(MinipoolPrestakeEvent) - mp.Contract.Contract.UnpackLog(prestakeEvent, "MinipoolPrestaked", log) + err = mp.Contract.Contract.UnpackLog(prestakeEvent, "MinipoolPrestaked", log) if err != nil { return PrestakeData{}, fmt.Errorf("Error unpacking prestake data: %w", err) } diff --git a/bindings/minipool/minipool-contract-v3.go b/bindings/minipool/minipool-contract-v3.go index 65575c0b1..157746450 100644 --- a/bindings/minipool/minipool-contract-v3.go +++ b/bindings/minipool/minipool-contract-v3.go @@ -616,7 +616,7 @@ func (mp *minipool_v3) GetPrestakeEvent(intervalSize *big.Int, opts *bind.CallOp // Decode the event prestakeEvent := new(MinipoolPrestakeEvent) - mp.Contract.Contract.UnpackLog(prestakeEvent, "MinipoolPrestaked", log) + err = mp.Contract.Contract.UnpackLog(prestakeEvent, "MinipoolPrestaked", log) if err != nil { return PrestakeData{}, fmt.Errorf("Error unpacking prestake data: %w", err) } diff --git a/bindings/network/voting.go b/bindings/network/voting.go index 7ac4df9fc..110d14e2e 100644 --- a/bindings/network/voting.go +++ b/bindings/network/voting.go @@ -54,9 +54,9 @@ func GetNodeInfoSnapshotFast(rp *rocketpool.RocketPool, blockNumber uint32, mult votingInfos := make([]types.NodeVotingInfo, nodeCount) for i := uint64(0); i < nodeCount; i += nodeVotingDetailsBatchSize { i := i - max := i + nodeVotingDetailsBatchSize - if max > nodeCount { - max = nodeCount + m := i + nodeVotingDetailsBatchSize + if m > nodeCount { + m = nodeCount } // Load details @@ -66,11 +66,17 @@ func GetNodeInfoSnapshotFast(rp *rocketpool.RocketPool, blockNumber uint32, mult if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { nodeAddress := nodeAddresses[j] votingInfos[j].NodeAddress = nodeAddress - mc.AddCall(rocketNetworkVoting, &votingInfos[j].VotingPower, "getVotingPower", nodeAddress, blockNumber) - mc.AddCall(rocketNetworkVoting, &votingInfos[j].Delegate, "getDelegate", nodeAddress, blockNumber) + err = mc.AddCall(rocketNetworkVoting, &votingInfos[j].VotingPower, "getVotingPower", nodeAddress, blockNumber) + if err != nil { + return fmt.Errorf("error adding voting power call for node %s: %w", nodeAddress.Hex(), err) + } + err = mc.AddCall(rocketNetworkVoting, &votingInfos[j].Delegate, "getDelegate", nodeAddress, blockNumber) + if err != nil { + return fmt.Errorf("error adding delegate call for node %s: %w", nodeAddress.Hex(), err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { diff --git a/bindings/node/node.go b/bindings/node/node.go index 6fc44d533..5f327762c 100644 --- a/bindings/node/node.go +++ b/bindings/node/node.go @@ -173,9 +173,9 @@ func GetNodeAddressesFast(rp *rocketpool.RocketPool, multicallAddress common.Add count := int(nodeCount) for i := 0; i < count; i += nodeAddressFastBatchSize { i := i - max := i + nodeAddressFastBatchSize - if max > count { - max = count + m := i + nodeAddressFastBatchSize + if m > count { + m = count } wg.Go(func() error { @@ -184,8 +184,11 @@ func GetNodeAddressesFast(rp *rocketpool.RocketPool, multicallAddress common.Add if err != nil { return err } - for j := i; j < max; j++ { - mc.AddCall(rocketNodeManager, &addresses[j], "getNodeAt", big.NewInt(int64(j))) + for j := i; j < m; j++ { + err = mc.AddCall(rocketNodeManager, &addresses[j], "getNodeAt", big.NewInt(int64(j))) + if err != nil { + return fmt.Errorf("error adding node at call for index %d: %w", j, err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { diff --git a/bindings/rocketpool/contract.go b/bindings/rocketpool/contract.go index 4efd4c46f..aea10a78c 100644 --- a/bindings/rocketpool/contract.go +++ b/bindings/rocketpool/contract.go @@ -155,25 +155,6 @@ func (c *Contract) estimateGasLimit(opts *bind.TransactOpts, input []byte) (uint } -// Wait for a transaction to be mined and get a tx receipt -func (c *Contract) getTransactionReceipt(tx *types.Transaction) (*types.Receipt, error) { - - // Wait for transaction to be mined - txReceipt, err := bind.WaitMined(context.Background(), c.Client, tx) - if err != nil { - return nil, err - } - - // Check transaction status - if txReceipt.Status == 0 { - return txReceipt, errors.New("Transaction failed with status 0") - } - - // Return - return txReceipt, nil - -} - // Get contract events from a transaction // eventPrototype must be an event struct type // Returns a slice of untyped values; assert returned events to event struct type diff --git a/bindings/rocketpool/rocketpool.go b/bindings/rocketpool/rocketpool.go index 7bdc2ff68..408baf482 100644 --- a/bindings/rocketpool/rocketpool.go +++ b/bindings/rocketpool/rocketpool.go @@ -90,9 +90,8 @@ func (rp *RocketPool) GetAddress(contractName string, opts *bind.CallOpts) (*com if cached, ok := rp.getCachedAddress(contractName); ok { if time.Now().Unix()-cached.time <= CacheTTL { return cached.address, nil - } else { - rp.deleteCachedAddress(contractName) } + rp.deleteCachedAddress(contractName) } } @@ -150,9 +149,8 @@ func (rp *RocketPool) GetABI(contractName string, opts *bind.CallOpts) (*abi.ABI if cached, ok := rp.getCachedABI(contractName); ok { if time.Now().Unix()-cached.time <= CacheTTL { return cached.abi, nil - } else { - rp.deleteCachedABI(contractName) } + rp.deleteCachedABI(contractName) } } @@ -215,9 +213,8 @@ func (rp *RocketPool) GetContract(contractName string, opts *bind.CallOpts) (*Co if cached, ok := rp.getCachedContract(contractName); ok { if time.Now().Unix()-cached.time <= CacheTTL { return cached.contract, nil - } else { - rp.deleteCachedContract(contractName) } + rp.deleteCachedContract(contractName) } } diff --git a/bindings/rocketpool/version-manager.go b/bindings/rocketpool/version-manager.go index d4f52e097..85201733c 100644 --- a/bindings/rocketpool/version-manager.go +++ b/bindings/rocketpool/version-manager.go @@ -51,9 +51,8 @@ func getLegacyContract(rp *RocketPool, contractName string, m LegacyVersionWrapp if cached, ok := rp.getCachedContract(legacyName); ok { if time.Now().Unix()-cached.time <= CacheTTL { return cached.contract, nil - } else { - rp.deleteCachedContract(legacyName) } + rp.deleteCachedContract(legacyName) } // Try to get the legacy address from RocketStorage first diff --git a/bindings/utils/eth/logs.go b/bindings/utils/eth/logs.go index 9f0e1b179..0e135edd5 100644 --- a/bindings/utils/eth/logs.go +++ b/bindings/utils/eth/logs.go @@ -74,51 +74,50 @@ func GetLogs(rp *rocketpool.RocketPool, addressFilter []common.Address, topicFil return nil, err } return logs, nil - } else { - // Get the latest block - if toBlock == nil { - latestBlock, err := rp.Client.BlockNumber(context.Background()) - if err != nil { - return nil, err - } - toBlock = big.NewInt(0) - toBlock.SetUint64(latestBlock) + } + // Get the latest block + if toBlock == nil { + latestBlock, err := rp.Client.BlockNumber(context.Background()) + if err != nil { + return nil, err } + toBlock = big.NewInt(0) + toBlock.SetUint64(latestBlock) + } - // Set the start and end, clamping on the latest block - intervalSize := big.NewInt(0).Sub(intervalSize, big.NewInt(1)) - start := big.NewInt(0).Set(fromBlock) - end := big.NewInt(0).Add(start, intervalSize) - if end.Cmp(toBlock) == 1 { - end.Set(toBlock) + // Set the start and end, clamping on the latest block + intervalSize = big.NewInt(0).Sub(intervalSize, big.NewInt(1)) + start := big.NewInt(0).Set(fromBlock) + end := big.NewInt(0).Add(start, intervalSize) + if end.Cmp(toBlock) == 1 { + end.Set(toBlock) + } + for { + // Get the logs using the current interval + newLogs, err := rp.Client.FilterLogs(context.Background(), ethereum.FilterQuery{ + Addresses: addressFilter, + Topics: topicFilter, + FromBlock: start, + ToBlock: end, + BlockHash: blockHash, + }) + if err != nil { + return nil, err } - for { - // Get the logs using the current interval - newLogs, err := rp.Client.FilterLogs(context.Background(), ethereum.FilterQuery{ - Addresses: addressFilter, - Topics: topicFilter, - FromBlock: start, - ToBlock: end, - BlockHash: blockHash, - }) - if err != nil { - return nil, err - } - // Append the logs to the total list - logs = append(logs, newLogs...) + // Append the logs to the total list + logs = append(logs, newLogs...) - // Return once we've finished iterating - if end.Cmp(toBlock) == 0 { - return logs, nil - } + // Return once we've finished iterating + if end.Cmp(toBlock) == 0 { + return logs, nil + } - // Update to the next interval (end+1 : that + interval - 1) - start.Add(end, big.NewInt(1)) - end.Add(start, intervalSize) - if end.Cmp(toBlock) == 1 { - end.Set(toBlock) - } + // Update to the next interval (end+1 : that + interval - 1) + start.Add(end, big.NewInt(1)) + end.Add(start, intervalSize) + if end.Cmp(toBlock) == 1 { + end.Set(toBlock) } } } diff --git a/bindings/utils/multicall/abi.go b/bindings/utils/multicall/abi.go index 5bbaf033d..77d79cf27 100644 --- a/bindings/utils/multicall/abi.go +++ b/bindings/utils/multicall/abi.go @@ -16,6 +16,6 @@ type MultiCall struct { CallData []byte } -var MulticallABI string = "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"blockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryAggregate\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryBlockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" +const MulticallABI = "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"blockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryAggregate\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryBlockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" -var BalancesABI string = "[{\"constant\":true,\"inputs\":[{\"name\":\"user\",\"type\":\"address\"},{\"name\":\"token\",\"type\":\"address\"}],\"name\":\"tokenBalance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"users\",\"type\":\"address[]\"},{\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" +const BalancesABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"user\",\"type\":\"address\"},{\"name\":\"token\",\"type\":\"address\"}],\"name\":\"tokenBalance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"users\",\"type\":\"address[]\"},{\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" diff --git a/bindings/utils/multicall/balances.go b/bindings/utils/multicall/balances.go index 4ef78c1f6..942615d3b 100644 --- a/bindings/utils/multicall/balances.go +++ b/bindings/utils/multicall/balances.go @@ -49,10 +49,10 @@ func (b *BalanceBatcher) GetEthBalances(addresses []common.Address, opts *bind.C // Run the getters in batches for i := 0; i < count; i += balanceBatchSize { i := i - max := min(i+balanceBatchSize, count) + m := min(i+balanceBatchSize, count) wg.Go(func() error { - subAddresses := addresses[i:max] + subAddresses := addresses[i:m] tokens := []common.Address{ {}, // Empty token for ETH balance } diff --git a/bindings/utils/state/contracts.go b/bindings/utils/state/contracts.go index 1344db959..2cc1d3758 100644 --- a/bindings/utils/state/contracts.go +++ b/bindings/utils/state/contracts.go @@ -194,10 +194,16 @@ func NewNetworkContracts(rp *rocketpool.RocketPool, multicallerAddress common.Ad // Add the address and ABI getters to multicall for i, wrapper := range wrappers { // Add the address getter - contracts.Multicaller.AddCall(contracts.RocketStorage, &wrappers[i].address, "getAddress", [32]byte(crypto.Keccak256Hash([]byte("contract.address"), []byte(wrapper.name)))) + err := contracts.Multicaller.AddCall(contracts.RocketStorage, &wrappers[i].address, "getAddress", [32]byte(crypto.Keccak256Hash([]byte("contract.address"), []byte(wrapper.name)))) + if err != nil { + return nil, fmt.Errorf("error adding address getter for %s: %w", wrapper.name, err) + } // Add the ABI getter - contracts.Multicaller.AddCall(contracts.RocketStorage, &wrappers[i].abiEncoded, "getString", [32]byte(crypto.Keccak256Hash([]byte("contract.abi"), []byte(wrapper.name)))) + err = contracts.Multicaller.AddCall(contracts.RocketStorage, &wrappers[i].abiEncoded, "getString", [32]byte(crypto.Keccak256Hash([]byte("contract.abi"), []byte(wrapper.name)))) + if err != nil { + return nil, fmt.Errorf("error adding ABI getter for %s: %w", wrapper.name, err) + } } // Run the multi-getter diff --git a/bindings/utils/state/megapool.go b/bindings/utils/state/megapool.go index d3a0747c4..064eaf7d8 100644 --- a/bindings/utils/state/megapool.go +++ b/bindings/utils/state/megapool.go @@ -79,7 +79,7 @@ func GetAllMegapoolValidators(rp *rocketpool.RocketPool, contracts *NetworkContr wg.SetLimit(threadLimit) for i := 0; i < count; i += megapoolValidatorsBatchSize { i := i - max := min(i+megapoolValidatorsBatchSize, count) + m := min(i+megapoolValidatorsBatchSize, count) wg.Go(func() error { mc, err := multicall.NewMultiCaller(rp.Client, multicallerAddress) @@ -87,8 +87,11 @@ func GetAllMegapoolValidators(rp *rocketpool.RocketPool, contracts *NetworkContr return err } var dummy *big.Int - for j := i; j < max; j++ { - mc.AddCall(megapoolManagerContract, &dummy, "getValidatorInfo", big.NewInt(int64(j))) + for j := i; j < m; j++ { + err = mc.AddCall(megapoolManagerContract, &dummy, "getValidatorInfo", big.NewInt(int64(j))) + if err != nil { + return fmt.Errorf("error adding validator info call for global index %d: %w", j, err) + } } responses, err := mc.Execute(true, opts) if err != nil { @@ -211,14 +214,14 @@ func GetBulkMegapoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContrac wg.SetLimit(threadLimit) for i := 0; i < count; i += megapoolBatchSize { i := i - max := min(i+megapoolBatchSize, count) + m := min(i+megapoolBatchSize, count) wg.Go(func() error { mc, err := multicall.NewMultiCaller(rp.Client, multicallerAddress) if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { megapoolDetails[j].UserCapital = big.NewInt(0) megapoolDetails[j].NodeQueuedBond = big.NewInt(0) megapoolDetails[j].NodeBond = big.NewInt(0) @@ -228,7 +231,10 @@ func GetBulkMegapoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContrac megapoolDetails[j].NodeDebt = big.NewInt(0) megapoolDetails[j].BondRequirement = big.NewInt(0) megapoolDetails[j].EthBalance = big.NewInt(0) - addMegapoolDetailsCalls(mc, megaContracts[j], &megapoolDetails[j], &lastDistributionTimes[j]) + err = addMegapoolDetailsCalls(mc, megaContracts[j], &megapoolDetails[j], &lastDistributionTimes[j]) + if err != nil { + return fmt.Errorf("error adding megapool details calls: %w", err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { @@ -253,7 +259,7 @@ func GetBulkMegapoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContrac wg2.SetLimit(threadLimit) for i := 0; i < count; i += megapoolBatchSize { i := i - max := min(i+megapoolBatchSize, count) + m := min(i+megapoolBatchSize, count) wg2.Go(func() error { mc, err := multicall.NewMultiCaller(rp.Client, multicallerAddress) @@ -261,12 +267,18 @@ func GetBulkMegapoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContrac return err } callCount := 0 - for j := i; j < max; j++ { + for j := i; j < m; j++ { if megapoolDetails[j].DelegateExpired { continue } - mc.AddCall(megapoolFactory, &delegateExpiries[j], "getDelegateExpiry", megapoolDetails[j].DelegateAddress) - mc.AddCall(nodeDeposit, &megapoolDetails[j].BondRequirement, "getBondRequirement", big.NewInt(int64(megapoolDetails[j].ActiveValidatorCount))) + err = mc.AddCall(megapoolFactory, &delegateExpiries[j], "getDelegateExpiry", megapoolDetails[j].DelegateAddress) + if err != nil { + return fmt.Errorf("error adding delegate expiry call for megapool %s: %w", megapoolDetails[j].Address.Hex(), err) + } + err = mc.AddCall(nodeDeposit, &megapoolDetails[j].BondRequirement, "getBondRequirement", big.NewInt(int64(megapoolDetails[j].ActiveValidatorCount))) + if err != nil { + return fmt.Errorf("error adding bond requirement call for megapool %s: %w", megapoolDetails[j].Address.Hex(), err) + } callCount += 2 } if callCount == 0 { @@ -295,20 +307,31 @@ func GetBulkMegapoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContrac } // Add all independent multicall entries for a single megapool's details -func addMegapoolDetailsCalls(mc *multicall.MultiCaller, megaContract *rocketpool.Contract, details *NativeMegapoolDetails, lastDistributionTime **big.Int) { - mc.AddCall(megaContract, &details.EffectiveDelegateAddress, "getEffectiveDelegate") - mc.AddCall(megaContract, &details.DelegateAddress, "getDelegate") - mc.AddCall(megaContract, &details.DelegateExpired, "getDelegateExpired") - mc.AddCall(megaContract, lastDistributionTime, "getLastDistributionTime") - mc.AddCall(megaContract, &details.NodeDebt, "getDebt") - mc.AddCall(megaContract, &details.PendingRewards, "getPendingRewards") - mc.AddCall(megaContract, &details.RefundValue, "getRefundValue") - mc.AddCall(megaContract, &details.ValidatorCount, "getValidatorCount") - mc.AddCall(megaContract, &details.ActiveValidatorCount, "getActiveValidatorCount") - mc.AddCall(megaContract, &details.LockedValidatorCount, "getLockedValidatorCount") - mc.AddCall(megaContract, &details.UseLatestDelegate, "getUseLatestDelegate") - mc.AddCall(megaContract, &details.AssignedValue, "getAssignedValue") - mc.AddCall(megaContract, &details.NodeBond, "getNodeBond") - mc.AddCall(megaContract, &details.UserCapital, "getUserCapital") - mc.AddCall(megaContract, &details.NodeQueuedBond, "getNodeQueuedBond") +func addMegapoolDetailsCalls(mc *multicall.MultiCaller, megaContract *rocketpool.Contract, details *NativeMegapoolDetails, lastDistributionTime **big.Int) error { + allErrors := make([]error, 0) + addCall := func(contract *rocketpool.Contract, out any, method string, args ...any) { + allErrors = append(allErrors, mc.AddCall(contract, out, method, args...)) + } + + addCall(megaContract, &details.EffectiveDelegateAddress, "getEffectiveDelegate") + addCall(megaContract, &details.DelegateAddress, "getDelegate") + addCall(megaContract, &details.DelegateExpired, "getDelegateExpired") + addCall(megaContract, lastDistributionTime, "getLastDistributionTime") + addCall(megaContract, &details.NodeDebt, "getDebt") + addCall(megaContract, &details.PendingRewards, "getPendingRewards") + addCall(megaContract, &details.RefundValue, "getRefundValue") + addCall(megaContract, &details.ValidatorCount, "getValidatorCount") + addCall(megaContract, &details.ActiveValidatorCount, "getActiveValidatorCount") + addCall(megaContract, &details.LockedValidatorCount, "getLockedValidatorCount") + addCall(megaContract, &details.UseLatestDelegate, "getUseLatestDelegate") + addCall(megaContract, &details.AssignedValue, "getAssignedValue") + addCall(megaContract, &details.NodeBond, "getNodeBond") + addCall(megaContract, &details.UserCapital, "getUserCapital") + addCall(megaContract, &details.NodeQueuedBond, "getNodeQueuedBond") + for _, err := range allErrors { + if err != nil { + return fmt.Errorf("error adding megapool details calls: %w", err) + } + } + return nil } diff --git a/bindings/utils/state/minipool.go b/bindings/utils/state/minipool.go index 9f9f90dfe..0426a1f23 100644 --- a/bindings/utils/state/minipool.go +++ b/bindings/utils/state/minipool.go @@ -110,7 +110,10 @@ func GetNativeMinipoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContr return NativeMinipoolDetails{}, fmt.Errorf("error getting minipool version: %w", err) } details.Version = version - addMinipoolDetailsCalls(rp, contracts, contracts.Multicaller, &details, opts) + err = addMinipoolDetailsCalls(rp, contracts, contracts.Multicaller, &details, opts) + if err != nil { + return NativeMinipoolDetails{}, fmt.Errorf("error adding minipool details calls: %w", err) + } _, err = contracts.Multicaller.FlexibleCall(true, opts) if err != nil { @@ -177,7 +180,7 @@ func CalculateCompleteMinipoolShares(rp *rocketpool.RocketPool, contracts *Netwo count := len(minipoolDetails) for i := 0; i < count; i += minipoolCompleteShareBatchSize { i := i - max := min(i+minipoolCompleteShareBatchSize, count) + m := min(i+minipoolCompleteShareBatchSize, count) wg.Go(func() error { var err error @@ -185,7 +188,7 @@ func CalculateCompleteMinipoolShares(rp *rocketpool.RocketPool, contracts *Netwo if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { // Make the minipool contract details := minipoolDetails[j] @@ -198,8 +201,14 @@ func CalculateCompleteMinipoolShares(rp *rocketpool.RocketPool, contracts *Netwo // Calculate the Beacon shares beaconBalance := big.NewInt(0).Set(beaconBalances[j]) if beaconBalance.Sign() > 0 { - mc.AddCall(mpContract, &details.NodeShareOfBeaconBalance, "calculateNodeShare", beaconBalance) - mc.AddCall(mpContract, &details.UserShareOfBeaconBalance, "calculateUserShare", beaconBalance) + err = mc.AddCall(mpContract, &details.NodeShareOfBeaconBalance, "calculateNodeShare", beaconBalance) + if err != nil { + return fmt.Errorf("error adding node share of beacon balance call: %w", err) + } + err = mc.AddCall(mpContract, &details.UserShareOfBeaconBalance, "calculateUserShare", beaconBalance) + if err != nil { + return fmt.Errorf("error adding user share of beacon balance call: %w", err) + } } else { details.NodeShareOfBeaconBalance = big.NewInt(0) details.UserShareOfBeaconBalance = big.NewInt(0) @@ -212,8 +221,14 @@ func CalculateCompleteMinipoolShares(rp *rocketpool.RocketPool, contracts *Netwo // Calculate the node and user shares if totalBalance.Sign() > 0 { - mc.AddCall(mpContract, &details.NodeShareOfBalanceIncludingBeacon, "calculateNodeShare", totalBalance) - mc.AddCall(mpContract, &details.UserShareOfBalanceIncludingBeacon, "calculateUserShare", totalBalance) + err = mc.AddCall(mpContract, &details.NodeShareOfBalanceIncludingBeacon, "calculateNodeShare", totalBalance) + if err != nil { + return fmt.Errorf("error adding node share of balance including beacon call: %w", err) + } + err = mc.AddCall(mpContract, &details.UserShareOfBalanceIncludingBeacon, "calculateUserShare", totalBalance) + if err != nil { + return fmt.Errorf("error adding user share of balance including beacon call: %w", err) + } } else { details.NodeShareOfBalanceIncludingBeacon = big.NewInt(0) details.UserShareOfBalanceIncludingBeacon = big.NewInt(0) @@ -280,7 +295,7 @@ func getNodeMinipoolAddressesFast(rp *rocketpool.RocketPool, contracts *NetworkC count := int(minipoolCount) for i := 0; i < count; i += minipoolAddressBatchSize { i := i - max := min(i+minipoolAddressBatchSize, count) + m := min(i+minipoolAddressBatchSize, count) wg.Go(func() error { var err error @@ -288,8 +303,11 @@ func getNodeMinipoolAddressesFast(rp *rocketpool.RocketPool, contracts *NetworkC if err != nil { return err } - for j := i; j < max; j++ { - mc.AddCall(contracts.RocketMinipoolManager, &addresses[j], "getNodeMinipoolAt", nodeAddress, big.NewInt(int64(j))) + for j := i; j < m; j++ { + err = mc.AddCall(contracts.RocketMinipoolManager, &addresses[j], "getNodeMinipoolAt", nodeAddress, big.NewInt(int64(j))) + if err != nil { + return fmt.Errorf("error adding node minipool at call for index %d: %w", j, err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { @@ -323,7 +341,7 @@ func getAllMinipoolAddressesFast(rp *rocketpool.RocketPool, contracts *NetworkCo count := int(minipoolCount) for i := 0; i < count; i += minipoolAddressBatchSize { i := i - max := min(i+minipoolAddressBatchSize, count) + m := min(i+minipoolAddressBatchSize, count) wg.Go(func() error { var err error @@ -331,8 +349,11 @@ func getAllMinipoolAddressesFast(rp *rocketpool.RocketPool, contracts *NetworkCo if err != nil { return err } - for j := i; j < max; j++ { - mc.AddCall(contracts.RocketMinipoolManager, &addresses[j], "getMinipoolAt", big.NewInt(int64(j))) + for j := i; j < m; j++ { + err = mc.AddCall(contracts.RocketMinipoolManager, &addresses[j], "getMinipoolAt", big.NewInt(int64(j))) + if err != nil { + return fmt.Errorf("error adding minipool at call for index %d: %w", j, err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { @@ -360,7 +381,7 @@ func getMinipoolVersionsFast(rp *rocketpool.RocketPool, contracts *NetworkContra versions := make([]uint8, count) for i := 0; i < count; i += minipoolVersionBatchSize { i := i - max := min(i+minipoolVersionBatchSize, count) + m := min(i+minipoolVersionBatchSize, count) wg.Go(func() error { var err error @@ -368,12 +389,15 @@ func getMinipoolVersionsFast(rp *rocketpool.RocketPool, contracts *NetworkContra if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { contract, err := rocketpool.GetRocketVersionContractForAddress(rp, addresses[j]) if err != nil { return fmt.Errorf("error creating version contract for minipool %s: %w", addresses[j].Hex(), err) } - mc.AddCall(contract, &versions[j], "version") + err = mc.AddCall(contract, &versions[j], "version") + if err != nil { + return fmt.Errorf("error adding version call for minipool %s: %w", addresses[j].Hex(), err) + } } results, err := mc.FlexibleCall(false, opts) // Allow calls to fail - necessary for Prater for j, result := range results { @@ -414,7 +438,7 @@ func getBulkMinipoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContrac count := len(addresses) for i := 0; i < count; i += minipoolBatchSize { i := i - max := min(i+minipoolBatchSize, count) + m := min(i+minipoolBatchSize, count) wg.Go(func() error { var err error @@ -422,14 +446,17 @@ func getBulkMinipoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContrac if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { address := addresses[j] details := &minipoolDetails[j] details.MinipoolAddress = address details.Version = versions[j] - addMinipoolDetailsCalls(rp, contracts, mc, details, opts) + err = addMinipoolDetailsCalls(rp, contracts, mc, details, opts) + if err != nil { + return fmt.Errorf("error adding minipool details calls: %w", err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { @@ -449,7 +476,7 @@ func getBulkMinipoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContrac wg2.SetLimit(threadLimit) for i := 0; i < count; i += minipoolBatchSize { i := i - max := min(i+minipoolBatchSize, count) + m := min(i+minipoolBatchSize, count) wg2.Go(func() error { var err error @@ -457,10 +484,13 @@ func getBulkMinipoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContrac if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { details := &minipoolDetails[j] details.Version = versions[j] - addMinipoolShareCalls(rp, mc, details, opts) + err = addMinipoolShareCalls(rp, mc, details, opts) + if err != nil { + return fmt.Errorf("error adding minipool share calls: %w", err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { @@ -494,26 +524,32 @@ func addMinipoolDetailsCalls(rp *rocketpool.RocketPool, contracts *NetworkContra mpContract := mp.GetContract() details.Version = mp.GetVersion() - mc.AddCall(contracts.RocketMinipoolManager, &details.Exists, "getMinipoolExists", address) - mc.AddCall(contracts.RocketMinipoolManager, &details.Pubkey, "getMinipoolPubkey", address) - mc.AddCall(contracts.RocketMinipoolManager, &details.WithdrawalCredentials, "getMinipoolWithdrawalCredentials", address) - mc.AddCall(contracts.RocketMinipoolManager, &details.Slashed, "getMinipoolRPLSlashed", address) - mc.AddCall(mpContract, &details.StatusRaw, "getStatus") - mc.AddCall(mpContract, &details.StatusBlock, "getStatusBlock") - mc.AddCall(mpContract, &details.StatusTime, "getStatusTime") - mc.AddCall(mpContract, &details.Finalised, "getFinalised") - mc.AddCall(mpContract, &details.NodeFee, "getNodeFee") - mc.AddCall(mpContract, &details.NodeDepositBalance, "getNodeDepositBalance") - mc.AddCall(mpContract, &details.NodeDepositAssigned, "getNodeDepositAssigned") - mc.AddCall(mpContract, &details.UserDepositBalance, "getUserDepositBalance") - mc.AddCall(mpContract, &details.UserDepositAssigned, "getUserDepositAssigned") - mc.AddCall(mpContract, &details.UserDepositAssignedTime, "getUserDepositAssignedTime") - mc.AddCall(mpContract, &details.UseLatestDelegate, "getUseLatestDelegate") - mc.AddCall(mpContract, &details.Delegate, "getDelegate") - mc.AddCall(mpContract, &details.PreviousDelegate, "getPreviousDelegate") - mc.AddCall(mpContract, &details.EffectiveDelegate, "getEffectiveDelegate") - mc.AddCall(mpContract, &details.NodeAddress, "getNodeAddress") - mc.AddCall(mpContract, &details.NodeRefundBalance, "getNodeRefundBalance") + + allErrors := make([]error, 0) + addCall := func(contract *rocketpool.Contract, out any, method string, args ...any) { + allErrors = append(allErrors, mc.AddCall(contract, out, method, args...)) + } + + addCall(contracts.RocketMinipoolManager, &details.Exists, "getMinipoolExists", address) + addCall(contracts.RocketMinipoolManager, &details.Pubkey, "getMinipoolPubkey", address) + addCall(contracts.RocketMinipoolManager, &details.WithdrawalCredentials, "getMinipoolWithdrawalCredentials", address) + addCall(contracts.RocketMinipoolManager, &details.Slashed, "getMinipoolRPLSlashed", address) + addCall(mpContract, &details.StatusRaw, "getStatus") + addCall(mpContract, &details.StatusBlock, "getStatusBlock") + addCall(mpContract, &details.StatusTime, "getStatusTime") + addCall(mpContract, &details.Finalised, "getFinalised") + addCall(mpContract, &details.NodeFee, "getNodeFee") + addCall(mpContract, &details.NodeDepositBalance, "getNodeDepositBalance") + addCall(mpContract, &details.NodeDepositAssigned, "getNodeDepositAssigned") + addCall(mpContract, &details.UserDepositBalance, "getUserDepositBalance") + addCall(mpContract, &details.UserDepositAssigned, "getUserDepositAssigned") + addCall(mpContract, &details.UserDepositAssignedTime, "getUserDepositAssignedTime") + addCall(mpContract, &details.UseLatestDelegate, "getUseLatestDelegate") + addCall(mpContract, &details.Delegate, "getDelegate") + addCall(mpContract, &details.PreviousDelegate, "getPreviousDelegate") + addCall(mpContract, &details.EffectiveDelegate, "getEffectiveDelegate") + addCall(mpContract, &details.NodeAddress, "getNodeAddress") + addCall(mpContract, &details.NodeRefundBalance, "getNodeRefundBalance") if details.Version < 3 { // These fields are all v3+ only @@ -527,27 +563,33 @@ func addMinipoolDetailsCalls(rp *rocketpool.RocketPool, contracts *NetworkContra details.ReduceBondValue = big.NewInt(0) details.PreMigrationBalance = big.NewInt(0) } else { - mc.AddCall(mpContract, &details.UserDistributed, "getUserDistributed") - mc.AddCall(mpContract, &details.IsVacant, "getVacant") - mc.AddCall(mpContract, &details.PreMigrationBalance, "getPreMigrationBalance") + addCall(mpContract, &details.UserDistributed, "getUserDistributed") + addCall(mpContract, &details.IsVacant, "getVacant") + addCall(mpContract, &details.PreMigrationBalance, "getPreMigrationBalance") // If minipool v3 exists, RocketMinipoolBondReducer exists so this is safe - mc.AddCall(contracts.RocketMinipoolBondReducer, &details.ReduceBondTime, "getReduceBondTime", address) - mc.AddCall(contracts.RocketMinipoolBondReducer, &details.ReduceBondCancelled, "getReduceBondCancelled", address) - mc.AddCall(contracts.RocketMinipoolBondReducer, &details.LastBondReductionTime, "getLastBondReductionTime", address) - mc.AddCall(contracts.RocketMinipoolBondReducer, &details.LastBondReductionPrevValue, "getLastBondReductionPrevValue", address) - mc.AddCall(contracts.RocketMinipoolBondReducer, &details.LastBondReductionPrevNodeFee, "getLastBondReductionPrevNodeFee", address) - mc.AddCall(contracts.RocketMinipoolBondReducer, &details.ReduceBondValue, "getReduceBondValue", address) + addCall(contracts.RocketMinipoolBondReducer, &details.ReduceBondTime, "getReduceBondTime", address) + addCall(contracts.RocketMinipoolBondReducer, &details.ReduceBondCancelled, "getReduceBondCancelled", address) + addCall(contracts.RocketMinipoolBondReducer, &details.LastBondReductionTime, "getLastBondReductionTime", address) + addCall(contracts.RocketMinipoolBondReducer, &details.LastBondReductionPrevValue, "getLastBondReductionPrevValue", address) + addCall(contracts.RocketMinipoolBondReducer, &details.LastBondReductionPrevNodeFee, "getLastBondReductionPrevNodeFee", address) + addCall(contracts.RocketMinipoolBondReducer, &details.ReduceBondValue, "getReduceBondValue", address) } penaltyCountKey := crypto.Keccak256Hash([]byte("network.penalties.penalty"), address.Bytes()) - mc.AddCall(contracts.RocketStorage, &details.PenaltyCount, "getUint", penaltyCountKey) + addCall(contracts.RocketStorage, &details.PenaltyCount, "getUint", penaltyCountKey) penaltyRatekey := crypto.Keccak256Hash([]byte("minipool.penalty.rate"), address.Bytes()) - mc.AddCall(contracts.RocketStorage, &details.PenaltyRate, "getUint", penaltyRatekey) + addCall(contracts.RocketStorage, &details.PenaltyRate, "getUint", penaltyRatekey) // Query the minipool manager using the delegate-invariant function - mc.AddCall(contracts.RocketMinipoolManager, &details.DepositTypeRaw, "getMinipoolDepositType", address) + addCall(contracts.RocketMinipoolManager, &details.DepositTypeRaw, "getMinipoolDepositType", address) + + for _, err := range allErrors { + if err != nil { + return fmt.Errorf("error adding minipool details calls: %w", err) + } + } return nil } @@ -564,8 +606,14 @@ func addMinipoolShareCalls(rp *rocketpool.RocketPool, mc *multicall.MultiCaller, details.DistributableBalance = big.NewInt(0).Sub(details.Balance, details.NodeRefundBalance) if details.DistributableBalance.Sign() >= 0 { - mc.AddCall(mpContract, &details.NodeShareOfBalance, "calculateNodeShare", details.DistributableBalance) - mc.AddCall(mpContract, &details.UserShareOfBalance, "calculateUserShare", details.DistributableBalance) + err = mc.AddCall(mpContract, &details.NodeShareOfBalance, "calculateNodeShare", details.DistributableBalance) + if err != nil { + return fmt.Errorf("error adding minipool share of balance call: %w", err) + } + err = mc.AddCall(mpContract, &details.UserShareOfBalance, "calculateUserShare", details.DistributableBalance) + if err != nil { + return fmt.Errorf("error adding minipool share of balance call: %w", err) + } } else { details.NodeShareOfBalance = big.NewInt(0) details.UserShareOfBalance = big.NewInt(0) @@ -575,10 +623,8 @@ func addMinipoolShareCalls(rp *rocketpool.RocketPool, mc *multicall.MultiCaller, } // Fixes a minipool details struct with supplemental logic -func fixupMinipoolDetails(details *NativeMinipoolDetails) error { +func fixupMinipoolDetails(details *NativeMinipoolDetails) { details.Status = types.MinipoolStatus(details.StatusRaw) details.DepositType = types.MinipoolDeposit(details.DepositTypeRaw) - - return nil } diff --git a/bindings/utils/state/network.go b/bindings/utils/state/network.go index a74d82140..0c74fd6b3 100644 --- a/bindings/utils/state/network.go +++ b/bindings/utils/state/network.go @@ -116,60 +116,71 @@ func NewNetworkDetails(rp *rocketpool.RocketPool, contracts *NetworkContracts) ( var windowStartRaw *big.Int var windowLengthRaw *big.Int + allErrors := make([]error, 0) + addCall := func(contract *rocketpool.Contract, out any, method string, args ...any) { + allErrors = append(allErrors, contracts.Multicaller.AddCall(contract, out, method, args...)) + } + // Multicall getters - contracts.Multicaller.AddCall(contracts.RocketNetworkPrices, &details.RplPrice, "getRPLPrice") - contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &rewardIndex, "getRewardIndex") - contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &intervalStart, "getClaimIntervalTimeStart") - contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &intervalDuration, "getClaimIntervalTime") - contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &details.NodeOperatorRewardsPercent, "getClaimingContractPerc", "rocketClaimNode") - contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &details.TrustedNodeOperatorRewardsPercent, "getClaimingContractPerc", "rocketClaimTrustedNode") - contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &details.ProtocolDaoRewardsPercent, "getClaimingContractPerc", "rocketClaimDAO") - contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &details.PendingRPLRewards, "getPendingRPLRewards") - contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &details.PendingVoterShare, "getPendingVoterShare") - contracts.Multicaller.AddCall(contracts.RocketDAONodeTrustedSettingsMinipool, &scrubPeriodSeconds, "getScrubPeriod") - contracts.Multicaller.AddCall(contracts.RocketDepositPool, &details.DepositPoolBalance, "getBalance") - contracts.Multicaller.AddCall(contracts.RocketDepositPool, &details.DepositPoolExcess, "getExcessBalance") - contracts.Multicaller.AddCall(contracts.RocketMinipoolQueue, &totalQueueCapacity, "getTotalCapacity") - contracts.Multicaller.AddCall(contracts.RocketMinipoolQueue, &effectiveQueueCapacity, "getEffectiveCapacity") - contracts.Multicaller.AddCall(contracts.RocketMinipoolQueue, &totalQueueLength, "getTotalLength") - contracts.Multicaller.AddCall(contracts.RocketTokenRPL, &details.RPLInflationIntervalRate, "getInflationIntervalRate") - contracts.Multicaller.AddCall(contracts.RocketTokenRPL, &details.RPLTotalSupply, "totalSupply") - contracts.Multicaller.AddCall(contracts.RocketNetworkPrices, &pricesBlock, "getPricesBlock") - contracts.Multicaller.AddCall(contracts.RocketNetworkBalances, ðUtilizationRate, "getETHUtilizationRate") - contracts.Multicaller.AddCall(contracts.RocketNetworkBalances, &details.StakingETHBalance, "getStakingETHBalance") - contracts.Multicaller.AddCall(contracts.RocketTokenRETH, &rETHExchangeRate, "getExchangeRate") - contracts.Multicaller.AddCall(contracts.RocketNetworkBalances, &details.TotalETHBalance, "getTotalETHBalance") - contracts.Multicaller.AddCall(contracts.RocketTokenRETH, &details.TotalRETHSupply, "totalSupply") - contracts.Multicaller.AddCall(contracts.RocketNetworkFees, &nodeFee, "getNodeFee") - contracts.Multicaller.AddCall(contracts.RocketNetworkBalances, &balancesBlock, "getBalancesBlock") - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsNetwork, &details.SubmitBalancesEnabled, "getSubmitBalancesEnabled") - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsNetwork, &details.SubmitPricesEnabled, "getSubmitPricesEnabled") - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsMinipool, &minipoolLaunchTimeout, "getLaunchTimeout") + addCall(contracts.RocketNetworkPrices, &details.RplPrice, "getRPLPrice") + addCall(contracts.RocketRewardsPool, &rewardIndex, "getRewardIndex") + addCall(contracts.RocketRewardsPool, &intervalStart, "getClaimIntervalTimeStart") + addCall(contracts.RocketRewardsPool, &intervalDuration, "getClaimIntervalTime") + addCall(contracts.RocketRewardsPool, &details.NodeOperatorRewardsPercent, "getClaimingContractPerc", "rocketClaimNode") + addCall(contracts.RocketRewardsPool, &details.TrustedNodeOperatorRewardsPercent, "getClaimingContractPerc", "rocketClaimTrustedNode") + addCall(contracts.RocketRewardsPool, &details.ProtocolDaoRewardsPercent, "getClaimingContractPerc", "rocketClaimDAO") + addCall(contracts.RocketRewardsPool, &details.PendingRPLRewards, "getPendingRPLRewards") + addCall(contracts.RocketRewardsPool, &details.PendingVoterShare, "getPendingVoterShare") + addCall(contracts.RocketDAONodeTrustedSettingsMinipool, &scrubPeriodSeconds, "getScrubPeriod") + addCall(contracts.RocketDepositPool, &details.DepositPoolBalance, "getBalance") + addCall(contracts.RocketDepositPool, &details.DepositPoolExcess, "getExcessBalance") + addCall(contracts.RocketMinipoolQueue, &totalQueueCapacity, "getTotalCapacity") + addCall(contracts.RocketMinipoolQueue, &effectiveQueueCapacity, "getEffectiveCapacity") + addCall(contracts.RocketMinipoolQueue, &totalQueueLength, "getTotalLength") + addCall(contracts.RocketTokenRPL, &details.RPLInflationIntervalRate, "getInflationIntervalRate") + addCall(contracts.RocketTokenRPL, &details.RPLTotalSupply, "totalSupply") + addCall(contracts.RocketNetworkPrices, &pricesBlock, "getPricesBlock") + addCall(contracts.RocketNetworkBalances, ðUtilizationRate, "getETHUtilizationRate") + addCall(contracts.RocketNetworkBalances, &details.StakingETHBalance, "getStakingETHBalance") + addCall(contracts.RocketTokenRETH, &rETHExchangeRate, "getExchangeRate") + addCall(contracts.RocketNetworkBalances, &details.TotalETHBalance, "getTotalETHBalance") + addCall(contracts.RocketTokenRETH, &details.TotalRETHSupply, "totalSupply") + addCall(contracts.RocketNetworkFees, &nodeFee, "getNodeFee") + addCall(contracts.RocketNetworkBalances, &balancesBlock, "getBalancesBlock") + addCall(contracts.RocketDAOProtocolSettingsNetwork, &details.SubmitBalancesEnabled, "getSubmitBalancesEnabled") + addCall(contracts.RocketDAOProtocolSettingsNetwork, &details.SubmitPricesEnabled, "getSubmitPricesEnabled") + addCall(contracts.RocketDAOProtocolSettingsMinipool, &minipoolLaunchTimeout, "getLaunchTimeout") // Atlas things - contracts.Multicaller.AddCall(contracts.RocketDAONodeTrustedSettingsMinipool, &promotionScrubPeriodSeconds, "getPromotionScrubPeriod") - contracts.Multicaller.AddCall(contracts.RocketDAONodeTrustedSettingsMinipool, &windowStartRaw, "getBondReductionWindowStart") - contracts.Multicaller.AddCall(contracts.RocketDAONodeTrustedSettingsMinipool, &windowLengthRaw, "getBondReductionWindowLength") - contracts.Multicaller.AddCall(contracts.RocketDepositPool, &details.DepositPoolUserBalance, "getUserBalance") + addCall(contracts.RocketDAONodeTrustedSettingsMinipool, &promotionScrubPeriodSeconds, "getPromotionScrubPeriod") + addCall(contracts.RocketDAONodeTrustedSettingsMinipool, &windowStartRaw, "getBondReductionWindowStart") + addCall(contracts.RocketDAONodeTrustedSettingsMinipool, &windowLengthRaw, "getBondReductionWindowLength") + addCall(contracts.RocketDepositPool, &details.DepositPoolUserBalance, "getUserBalance") // Houston - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsNetwork, &pricesSubmissionFrequency, "getSubmitPricesFrequency") - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsNetwork, &balancesSubmissionFrequency, "getSubmitBalancesFrequency") + addCall(contracts.RocketDAOProtocolSettingsNetwork, &pricesSubmissionFrequency, "getSubmitPricesFrequency") + addCall(contracts.RocketDAOProtocolSettingsNetwork, &balancesSubmissionFrequency, "getSubmitBalancesFrequency") // Saturn - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsNetwork, &details.MegapoolRevenueSplitSettings.NodeOperatorCommissionShare, "getNodeShare") - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsNetwork, &details.MegapoolRevenueSplitSettings.NodeOperatorCommissionAdder, "getNodeShareSecurityCouncilAdder") - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsNetwork, &details.MegapoolRevenueSplitSettings.VoterCommissionShare, "getVoterShare") - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsNetwork, &details.MegapoolRevenueSplitSettings.PdaoCommissionShare, "getProtocolDAOShare") - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsNode, &details.ReducedBond, "getReducedBond") - contracts.Multicaller.AddCall(contracts.RocketDAOProtocolSettingsNode, &details.MinimumLegacyRplStakeFraction, "getMinimumLegacyRPLStake") - contracts.Multicaller.AddCall(contracts.RocketNetworkRevenues, &details.MegapoolRevenueSplitTimeWeightedAverages.NodeShare, "getCurrentNodeShare") - contracts.Multicaller.AddCall(contracts.RocketNetworkRevenues, &details.MegapoolRevenueSplitTimeWeightedAverages.VoterShare, "getCurrentVoterShare") - contracts.Multicaller.AddCall(contracts.RocketNetworkRevenues, &details.MegapoolRevenueSplitTimeWeightedAverages.PdaoShare, "getCurrentProtocolDAOShare") - contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &details.PendingVoterShareEth, "getPendingVoterShare") - contracts.Multicaller.AddCall(contracts.RocketNodeStaking, &details.TotalNetworkMegapoolStakedRpl, "getTotalMegapoolStakedRPL") - contracts.Multicaller.AddCall(contracts.RocketNodeStaking, &details.TotalRPLStake, "getTotalStakedRPL") - contracts.Multicaller.AddCall(contracts.RocketNodeStaking, &details.TotalLegacyStakedRpl, "getTotalLegacyStakedRPL") + addCall(contracts.RocketDAOProtocolSettingsNetwork, &details.MegapoolRevenueSplitSettings.NodeOperatorCommissionShare, "getNodeShare") + addCall(contracts.RocketDAOProtocolSettingsNetwork, &details.MegapoolRevenueSplitSettings.NodeOperatorCommissionAdder, "getNodeShareSecurityCouncilAdder") + addCall(contracts.RocketDAOProtocolSettingsNetwork, &details.MegapoolRevenueSplitSettings.VoterCommissionShare, "getVoterShare") + addCall(contracts.RocketDAOProtocolSettingsNetwork, &details.MegapoolRevenueSplitSettings.PdaoCommissionShare, "getProtocolDAOShare") + addCall(contracts.RocketDAOProtocolSettingsNode, &details.ReducedBond, "getReducedBond") + addCall(contracts.RocketDAOProtocolSettingsNode, &details.MinimumLegacyRplStakeFraction, "getMinimumLegacyRPLStake") + addCall(contracts.RocketNetworkRevenues, &details.MegapoolRevenueSplitTimeWeightedAverages.NodeShare, "getCurrentNodeShare") + addCall(contracts.RocketNetworkRevenues, &details.MegapoolRevenueSplitTimeWeightedAverages.VoterShare, "getCurrentVoterShare") + addCall(contracts.RocketNetworkRevenues, &details.MegapoolRevenueSplitTimeWeightedAverages.PdaoShare, "getCurrentProtocolDAOShare") + addCall(contracts.RocketRewardsPool, &details.PendingVoterShareEth, "getPendingVoterShare") + addCall(contracts.RocketNodeStaking, &details.TotalNetworkMegapoolStakedRpl, "getTotalMegapoolStakedRPL") + addCall(contracts.RocketNodeStaking, &details.TotalRPLStake, "getTotalStakedRPL") + addCall(contracts.RocketNodeStaking, &details.TotalLegacyStakedRpl, "getTotalLegacyStakedRPL") + + for _, err := range allErrors { + if err != nil { + return nil, fmt.Errorf("error getting network details: %w", err) + } + } _, err := contracts.Multicaller.FlexibleCall(true, opts) if err != nil { @@ -243,7 +254,7 @@ func GetTotalEffectiveRplStake(rp *rocketpool.RocketPool, contracts *NetworkCont // Run the getters in batches for i := 0; i < count; i += networkEffectiveStakeBatchSize { i := i - max := min(i+networkEffectiveStakeBatchSize, count) + m := min(i+networkEffectiveStakeBatchSize, count) wg.Go(func() error { var err error @@ -251,10 +262,16 @@ func GetTotalEffectiveRplStake(rp *rocketpool.RocketPool, contracts *NetworkCont if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { address := addresses[j] - mc.AddCall(contracts.RocketNodeStaking, &minimumStakes[j], "getNodeMinimumRPLStake", address) - mc.AddCall(contracts.RocketNodeStaking, &effectiveStakes[j], "getNodeEffectiveRPLStake", address) + err = mc.AddCall(contracts.RocketNodeStaking, &minimumStakes[j], "getNodeMinimumRPLStake", address) + if err != nil { + return fmt.Errorf("error adding node minimum RPL stake call for address %s: %w", address.Hex(), err) + } + err = mc.AddCall(contracts.RocketNodeStaking, &effectiveStakes[j], "getNodeEffectiveRPLStake", address) + if err != nil { + return fmt.Errorf("error adding node effective RPL stake call for address %s: %w", address.Hex(), err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { diff --git a/bindings/utils/state/node.go b/bindings/utils/state/node.go index 0d63e7133..08cd838d1 100644 --- a/bindings/utils/state/node.go +++ b/bindings/utils/state/node.go @@ -108,9 +108,12 @@ func GetNativeNodeDetails(rp *rocketpool.RocketPool, contracts *NetworkContracts DistributorBalanceNodeETH: big.NewInt(0), } - addNodeDetailsCalls(contracts, contracts.Multicaller, &details, nodeAddress) + err := addNodeDetailsCalls(contracts, contracts.Multicaller, &details, nodeAddress) + if err != nil { + return NativeNodeDetails{}, fmt.Errorf("error adding node details calls: %w", err) + } - _, err := contracts.Multicaller.FlexibleCall(true, opts) + _, err = contracts.Multicaller.FlexibleCall(true, opts) if err != nil { return NativeNodeDetails{}, fmt.Errorf("error executing multicall: %w", err) } @@ -173,7 +176,7 @@ func GetAllNativeNodeDetails(rp *rocketpool.RocketPool, contracts *NetworkContra // Run the getters in batches for i := 0; i < count; i += legacyNodeBatchSize { i := i - max := min(i+legacyNodeBatchSize, count) + m := min(i+legacyNodeBatchSize, count) wg.Go(func() error { var err error @@ -181,7 +184,7 @@ func GetAllNativeNodeDetails(rp *rocketpool.RocketPool, contracts *NetworkContra if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { address := addresses[j] details := &nodeDetails[j] details.NodeAddress = address @@ -190,7 +193,10 @@ func GetAllNativeNodeDetails(rp *rocketpool.RocketPool, contracts *NetworkContra details.DistributorBalanceNodeETH = big.NewInt(0) details.CollateralisationRatio = big.NewInt(0) - addNodeDetailsCalls(contracts, mc, details, address) + err = addNodeDetailsCalls(contracts, mc, details, address) + if err != nil { + return fmt.Errorf("error adding node details calls: %w", err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { @@ -252,7 +258,7 @@ func (node *NativeNodeDetails) WasOptedInAt(t time.Time) bool { } // Calculate the average node fee and user/node shares of the distributor's balance -func (node *NativeNodeDetails) CalculateAverageFeeAndDistributorShares(minipoolDetails []*NativeMinipoolDetails) error { +func (node *NativeNodeDetails) CalculateAverageFeeAndDistributorShares(minipoolDetails []*NativeMinipoolDetails) { // Calculate the total of all fees for staking minipools that aren't finalized totalFee := big.NewInt(0) @@ -299,7 +305,6 @@ func (node *NativeNodeDetails) CalculateAverageFeeAndDistributorShares(minipoolD node.DistributorBalanceUserETH = big.NewInt(0) } - return nil } // Get all node addresses using the multicaller @@ -319,7 +324,7 @@ func getNodeAddressesFast(rp *rocketpool.RocketPool, contracts *NetworkContracts count := int(nodeCount) for i := 0; i < count; i += nodeAddressBatchSize { i := i - max := min(i+nodeAddressBatchSize, count) + m := min(i+nodeAddressBatchSize, count) wg.Go(func() error { var err error @@ -327,8 +332,11 @@ func getNodeAddressesFast(rp *rocketpool.RocketPool, contracts *NetworkContracts if err != nil { return err } - for j := i; j < max; j++ { - mc.AddCall(contracts.RocketNodeManager, &addresses[j], "getNodeAt", big.NewInt(int64(j))) + for j := i; j < m; j++ { + err = mc.AddCall(contracts.RocketNodeManager, &addresses[j], "getNodeAt", big.NewInt(int64(j))) + if err != nil { + return fmt.Errorf("error adding node address call for index %d: %w", j, err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { @@ -346,48 +354,59 @@ func getNodeAddressesFast(rp *rocketpool.RocketPool, contracts *NetworkContracts } // Add all of the calls for the node details to the multicaller -func addNodeDetailsCalls(contracts *NetworkContracts, mc *multicall.MultiCaller, details *NativeNodeDetails, address common.Address) { - mc.AddCall(contracts.RocketNodeManager, &details.Exists, "getNodeExists", address) - mc.AddCall(contracts.RocketNodeManager, &details.RegistrationTime, "getNodeRegistrationTime", address) - mc.AddCall(contracts.RocketNodeManager, &details.TimezoneLocation, "getNodeTimezoneLocation", address) - mc.AddCall(contracts.RocketNodeManager, &details.FeeDistributorInitialised, "getFeeDistributorInitialised", address) - mc.AddCall(contracts.RocketNodeDistributorFactory, &details.FeeDistributorAddress, "getProxyAddress", address) - mc.AddCall(contracts.RocketNodeManager, &details.RewardNetwork, "getRewardNetwork", address) - - mc.AddCall(contracts.RocketMinipoolManager, &details.MinipoolCount, "getNodeMinipoolCount", address) - mc.AddCall(contracts.RocketTokenRETH, &details.BalanceRETH, "balanceOf", address) - mc.AddCall(contracts.RocketTokenRPL, &details.BalanceRPL, "balanceOf", address) - mc.AddCall(contracts.RocketTokenRPLFixedSupply, &details.BalanceOldRPL, "balanceOf", address) - mc.AddCall(contracts.RocketStorage, &details.WithdrawalAddress, "getNodeWithdrawalAddress", address) - mc.AddCall(contracts.RocketStorage, &details.PendingWithdrawalAddress, "getNodePendingWithdrawalAddress", address) - mc.AddCall(contracts.RocketNodeManager, &details.SmoothingPoolRegistrationState, "getSmoothingPoolRegistrationState", address) - mc.AddCall(contracts.RocketNodeManager, &details.SmoothingPoolRegistrationChanged, "getSmoothingPoolRegistrationChanged", address) +func addNodeDetailsCalls(contracts *NetworkContracts, mc *multicall.MultiCaller, details *NativeNodeDetails, address common.Address) error { + allErrors := make([]error, 0) + addCall := func(contract *rocketpool.Contract, out any, method string, args ...any) { + allErrors = append(allErrors, mc.AddCall(contract, out, method, args...)) + } + addCall(contracts.RocketNodeManager, &details.Exists, "getNodeExists", address) + addCall(contracts.RocketNodeManager, &details.RegistrationTime, "getNodeRegistrationTime", address) + addCall(contracts.RocketNodeManager, &details.TimezoneLocation, "getNodeTimezoneLocation", address) + addCall(contracts.RocketNodeManager, &details.FeeDistributorInitialised, "getFeeDistributorInitialised", address) + addCall(contracts.RocketNodeDistributorFactory, &details.FeeDistributorAddress, "getProxyAddress", address) + addCall(contracts.RocketNodeManager, &details.RewardNetwork, "getRewardNetwork", address) + + addCall(contracts.RocketMinipoolManager, &details.MinipoolCount, "getNodeMinipoolCount", address) + addCall(contracts.RocketTokenRETH, &details.BalanceRETH, "balanceOf", address) + addCall(contracts.RocketTokenRPL, &details.BalanceRPL, "balanceOf", address) + addCall(contracts.RocketTokenRPLFixedSupply, &details.BalanceOldRPL, "balanceOf", address) + addCall(contracts.RocketStorage, &details.WithdrawalAddress, "getNodeWithdrawalAddress", address) + addCall(contracts.RocketStorage, &details.PendingWithdrawalAddress, "getNodePendingWithdrawalAddress", address) + addCall(contracts.RocketNodeManager, &details.SmoothingPoolRegistrationState, "getSmoothingPoolRegistrationState", address) + addCall(contracts.RocketNodeManager, &details.SmoothingPoolRegistrationChanged, "getSmoothingPoolRegistrationChanged", address) // Atlas - mc.AddCall(contracts.RocketNodeDeposit, &details.DepositCreditBalance, "getNodeDepositCredit", address) - mc.AddCall(contracts.RocketNodeStaking, &details.CollateralisationRatio, "getNodeETHCollateralisationRatio", address) + addCall(contracts.RocketNodeDeposit, &details.DepositCreditBalance, "getNodeDepositCredit", address) + addCall(contracts.RocketNodeStaking, &details.CollateralisationRatio, "getNodeETHCollateralisationRatio", address) // Saturn // a node's total borrowed ETH amount (minipool + megapool) - mc.AddCall(contracts.RocketNodeStaking, &details.EthBorrowed, "getNodeETHBorrowed", address) + addCall(contracts.RocketNodeStaking, &details.EthBorrowed, "getNodeETHBorrowed", address) // a node's borrowed megapool ETH amount - mc.AddCall(contracts.RocketNodeStaking, &details.MegapoolETHBorrowed, "getNodeMegapoolETHBorrowed", address) + addCall(contracts.RocketNodeStaking, &details.MegapoolETHBorrowed, "getNodeMegapoolETHBorrowed", address) // a node's borrowed minipool ETH amount - mc.AddCall(contracts.RocketNodeStaking, &details.MinipoolETHBorrowed, "getNodeMinipoolETHBorrowed", address) + addCall(contracts.RocketNodeStaking, &details.MinipoolETHBorrowed, "getNodeMinipoolETHBorrowed", address) // a node's total amount of a node operator's bonded ETH (minipool + megapool) - mc.AddCall(contracts.RocketNodeStaking, &details.EthBonded, "getNodeETHBonded", address) + addCall(contracts.RocketNodeStaking, &details.EthBonded, "getNodeETHBonded", address) // the amount of a node operator's megapool bonded ETH - mc.AddCall(contracts.RocketNodeStaking, &details.MegapoolEthBonded, "getNodeMegapoolETHBonded", address) + addCall(contracts.RocketNodeStaking, &details.MegapoolEthBonded, "getNodeMegapoolETHBonded", address) // the amount of a node operator's minipool bonded ETH - mc.AddCall(contracts.RocketNodeStaking, &details.MinipoolETHBonded, "getNodeMinipoolETHBonded", address) + addCall(contracts.RocketNodeStaking, &details.MinipoolETHBonded, "getNodeMinipoolETHBonded", address) // the amount of megapool staked RPL for a node operator - mc.AddCall(contracts.RocketNodeStaking, &details.MegapoolStakedRPL, "getNodeMegapoolStakedRPL", address) + addCall(contracts.RocketNodeStaking, &details.MegapoolStakedRPL, "getNodeMegapoolStakedRPL", address) // the amount of legacy staked RPL for a node operator - mc.AddCall(contracts.RocketNodeStaking, &details.LegacyStakedRPL, "getNodeLegacyStakedRPL", address) + addCall(contracts.RocketNodeStaking, &details.LegacyStakedRPL, "getNodeLegacyStakedRPL", address) // the timestamp at which a node last unstaked megapool staked RPL - mc.AddCall(contracts.RocketNodeStaking, &details.UnstakingRPL, "getNodeUnstakingRPL", address) + addCall(contracts.RocketNodeStaking, &details.UnstakingRPL, "getNodeUnstakingRPL", address) // the amount of RPL that is locked for a given node - mc.AddCall(contracts.RocketNodeStaking, &details.LockedRPL, "getNodeLockedRPL", address) - mc.AddCall(contracts.RocketMegapoolFactory, &details.MegapoolAddress, "getExpectedAddress", address) - mc.AddCall(contracts.RocketMegapoolFactory, &details.MegapoolDeployed, "getMegapoolDeployed", address) + addCall(contracts.RocketNodeStaking, &details.LockedRPL, "getNodeLockedRPL", address) + addCall(contracts.RocketMegapoolFactory, &details.MegapoolAddress, "getExpectedAddress", address) + addCall(contracts.RocketMegapoolFactory, &details.MegapoolDeployed, "getMegapoolDeployed", address) + + for _, err := range allErrors { + if err != nil { + return fmt.Errorf("error adding node details call: %w", err) + } + } + return nil } diff --git a/bindings/utils/state/odao.go b/bindings/utils/state/odao.go index d022abeb6..ea8cdf3ff 100644 --- a/bindings/utils/state/odao.go +++ b/bindings/utils/state/odao.go @@ -41,9 +41,12 @@ func GetOracleDaoMemberDetails(rp *rocketpool.RocketPool, contracts *NetworkCont details := OracleDaoMemberDetails{} details.Address = memberAddress - addOracleDaoMemberDetailsCalls(contracts, contracts.Multicaller, &details) + err := addOracleDaoMemberDetailsCalls(contracts, contracts.Multicaller, &details) + if err != nil { + return OracleDaoMemberDetails{}, fmt.Errorf("error adding Oracle DAO member details calls: %w", err) + } - _, err := contracts.Multicaller.FlexibleCall(true, opts) + _, err = contracts.Multicaller.FlexibleCall(true, opts) if err != nil { return OracleDaoMemberDetails{}, fmt.Errorf("error executing multicall: %w", err) } @@ -86,7 +89,7 @@ func getOdaoAddresses(rp *rocketpool.RocketPool, contracts *NetworkContracts, op count := int(memberCount) for i := 0; i < count; i += minipoolAddressBatchSize { i := i - max := min(i+oDaoAddressBatchSize, count) + m := min(i+oDaoAddressBatchSize, count) wg.Go(func() error { var err error @@ -94,8 +97,11 @@ func getOdaoAddresses(rp *rocketpool.RocketPool, contracts *NetworkContracts, op if err != nil { return err } - for j := i; j < max; j++ { - mc.AddCall(contracts.RocketDAONodeTrusted, &addresses[j], "getMemberAt", big.NewInt(int64(j))) + for j := i; j < m; j++ { + err = mc.AddCall(contracts.RocketDAONodeTrusted, &addresses[j], "getMemberAt", big.NewInt(int64(j))) + if err != nil { + return fmt.Errorf("error adding Oracle DAO member address call for index %d: %w", j, err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { @@ -122,7 +128,7 @@ func getOracleDaoDetails(rp *rocketpool.RocketPool, contracts *NetworkContracts, count := len(addresses) for i := 0; i < count; i += minipoolBatchSize { i := i - max := min(i+minipoolBatchSize, count) + m := min(i+minipoolBatchSize, count) wg.Go(func() error { var err error @@ -130,13 +136,16 @@ func getOracleDaoDetails(rp *rocketpool.RocketPool, contracts *NetworkContracts, if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { address := addresses[j] details := &memberDetails[j] details.Address = address - addOracleDaoMemberDetailsCalls(contracts, mc, details) + err = addOracleDaoMemberDetailsCalls(contracts, mc, details) + if err != nil { + return fmt.Errorf("error adding Oracle DAO member details calls: %w", err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { @@ -163,20 +172,28 @@ func getOracleDaoDetails(rp *rocketpool.RocketPool, contracts *NetworkContracts, // Add the Oracle DAO details getters to the multicaller func addOracleDaoMemberDetailsCalls(contracts *NetworkContracts, mc *multicall.MultiCaller, details *OracleDaoMemberDetails) error { address := details.Address - mc.AddCall(contracts.RocketDAONodeTrusted, &details.Exists, "getMemberIsValid", address) - mc.AddCall(contracts.RocketDAONodeTrusted, &details.ID, "getMemberID", address) - mc.AddCall(contracts.RocketDAONodeTrusted, &details.Url, "getMemberUrl", address) - mc.AddCall(contracts.RocketDAONodeTrusted, &details.joinedTimeRaw, "getMemberJoinedTime", address) - mc.AddCall(contracts.RocketDAONodeTrusted, &details.lastProposalTimeRaw, "getMemberLastProposalTime", address) - mc.AddCall(contracts.RocketDAONodeTrusted, &details.RPLBondAmount, "getMemberRPLBondAmount", address) - mc.AddCall(contracts.RocketDAONodeTrusted, &details.ReplacementAddress, "getMemberReplacedAddress", address) - mc.AddCall(contracts.RocketDAONodeTrusted, &details.IsChallenged, "getMemberIsChallenged", address) + allErrors := make([]error, 0) + addCall := func(contract *rocketpool.Contract, out any, method string, args ...any) { + allErrors = append(allErrors, mc.AddCall(contract, out, method, args...)) + } + addCall(contracts.RocketDAONodeTrusted, &details.Exists, "getMemberIsValid", address) + addCall(contracts.RocketDAONodeTrusted, &details.ID, "getMemberID", address) + addCall(contracts.RocketDAONodeTrusted, &details.Url, "getMemberUrl", address) + addCall(contracts.RocketDAONodeTrusted, &details.joinedTimeRaw, "getMemberJoinedTime", address) + addCall(contracts.RocketDAONodeTrusted, &details.lastProposalTimeRaw, "getMemberLastProposalTime", address) + addCall(contracts.RocketDAONodeTrusted, &details.RPLBondAmount, "getMemberRPLBondAmount", address) + addCall(contracts.RocketDAONodeTrusted, &details.ReplacementAddress, "getMemberReplacedAddress", address) + addCall(contracts.RocketDAONodeTrusted, &details.IsChallenged, "getMemberIsChallenged", address) + for _, err := range allErrors { + if err != nil { + return fmt.Errorf("error adding Oracle DAO member details calls: %w", err) + } + } return nil } // Fixes a member details struct with supplemental logic -func fixupOracleDaoMemberDetails(details *OracleDaoMemberDetails) error { +func fixupOracleDaoMemberDetails(details *OracleDaoMemberDetails) { details.JoinedTime = convertToTime(details.joinedTimeRaw) details.LastProposalTime = convertToTime(details.lastProposalTimeRaw) - return nil } diff --git a/bindings/utils/state/pdao.go b/bindings/utils/state/pdao.go index 04aa541cc..0ec899c12 100644 --- a/bindings/utils/state/pdao.go +++ b/bindings/utils/state/pdao.go @@ -59,9 +59,12 @@ func GetProtocolDaoProposalDetails(rp *rocketpool.RocketPool, contracts *Network rawDetails := protocolDaoProposalDetailsRaw{} details.ID = proposalID - addProposalCalls(contracts, contracts.Multicaller, &rawDetails) + err := addProposalCalls(contracts, contracts.Multicaller, &rawDetails) + if err != nil { + return details, fmt.Errorf("error adding proposal calls: %w", err) + } - _, err := contracts.Multicaller.FlexibleCall(true, opts) + _, err = contracts.Multicaller.FlexibleCall(true, opts) if err != nil { return details, fmt.Errorf("error executing multicall: %w", err) } @@ -101,7 +104,7 @@ func getProposalDetails(rp *rocketpool.RocketPool, contracts *NetworkContracts, count := len(propDetailsRaw) for i := 0; i < count; i += pDaoPropDetailsBatchSize { i := i - max := min(i+pDaoPropDetailsBatchSize, count) + m := min(i+pDaoPropDetailsBatchSize, count) wg.Go(func() error { var err error @@ -109,12 +112,15 @@ func getProposalDetails(rp *rocketpool.RocketPool, contracts *NetworkContracts, if err != nil { return err } - for j := i; j < max; j++ { + for j := i; j < m; j++ { id := ids[j] details := &propDetailsRaw[j] details.ID = id - addProposalCalls(contracts, mc, details) + err = addProposalCalls(contracts, mc, details) + if err != nil { + return fmt.Errorf("error adding proposal calls: %w", err) + } } _, err = mc.FlexibleCall(true, opts) if err != nil { @@ -143,36 +149,45 @@ func getProposalDetails(rp *rocketpool.RocketPool, contracts *NetworkContracts, // Get the details of a proposal func addProposalCalls(contracts *NetworkContracts, mc *multicall.MultiCaller, details *protocolDaoProposalDetailsRaw) error { id := big.NewInt(0).SetUint64(details.ID) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.ProposerAddress, "getProposer", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.DAO, "getDAO", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.TargetBlock, "getProposalBlock", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.Message, "getMessage", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.VotingStartTime, "getStart", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.Phase1EndTime, "getPhase1End", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.Phase2EndTime, "getPhase2End", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.ExpiryTime, "getExpires", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.CreatedTime, "getCreated", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.VotingPowerRequired, "getVotingPowerRequired", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.VotingPowerFor, "getVotingPowerFor", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.VotingPowerAgainst, "getVotingPowerAgainst", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.VotingPowerAbstained, "getVotingPowerAbstained", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.VotingPowerToVeto, "getVotingPowerVeto", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.IsDestroyed, "getDestroyed", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.IsFinalized, "getFinalised", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.IsExecuted, "getExecuted", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.IsVetoed, "getVetoed", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.VetoQuorum, "getProposalVetoQuorum", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.Payload, "getPayload", id) - mc.AddCall(contracts.RocketDAOProtocolProposal, &details.State, "getState", id) - mc.AddCall(contracts.RocketDAOProtocolVerifier, &details.DefeatIndex, "getDefeatIndex", id) - mc.AddCall(contracts.RocketDAOProtocolVerifier, &details.ProposalBond, "getProposalBond", id) - mc.AddCall(contracts.RocketDAOProtocolVerifier, &details.ChallengeBond, "getChallengeBond", id) - mc.AddCall(contracts.RocketDAOProtocolVerifier, &details.ChallengeWindow, "getChallengePeriod", id) + allErrors := make([]error, 0) + addCall := func(contract *rocketpool.Contract, out any, method string, args ...any) { + allErrors = append(allErrors, mc.AddCall(contract, out, method, args...)) + } + addCall(contracts.RocketDAOProtocolProposal, &details.ProposerAddress, "getProposer", id) + addCall(contracts.RocketDAOProtocolProposal, &details.DAO, "getDAO", id) + addCall(contracts.RocketDAOProtocolProposal, &details.TargetBlock, "getProposalBlock", id) + addCall(contracts.RocketDAOProtocolProposal, &details.Message, "getMessage", id) + addCall(contracts.RocketDAOProtocolProposal, &details.VotingStartTime, "getStart", id) + addCall(contracts.RocketDAOProtocolProposal, &details.Phase1EndTime, "getPhase1End", id) + addCall(contracts.RocketDAOProtocolProposal, &details.Phase2EndTime, "getPhase2End", id) + addCall(contracts.RocketDAOProtocolProposal, &details.ExpiryTime, "getExpires", id) + addCall(contracts.RocketDAOProtocolProposal, &details.CreatedTime, "getCreated", id) + addCall(contracts.RocketDAOProtocolProposal, &details.VotingPowerRequired, "getVotingPowerRequired", id) + addCall(contracts.RocketDAOProtocolProposal, &details.VotingPowerFor, "getVotingPowerFor", id) + addCall(contracts.RocketDAOProtocolProposal, &details.VotingPowerAgainst, "getVotingPowerAgainst", id) + addCall(contracts.RocketDAOProtocolProposal, &details.VotingPowerAbstained, "getVotingPowerAbstained", id) + addCall(contracts.RocketDAOProtocolProposal, &details.VotingPowerToVeto, "getVotingPowerVeto", id) + addCall(contracts.RocketDAOProtocolProposal, &details.IsDestroyed, "getDestroyed", id) + addCall(contracts.RocketDAOProtocolProposal, &details.IsFinalized, "getFinalised", id) + addCall(contracts.RocketDAOProtocolProposal, &details.IsExecuted, "getExecuted", id) + addCall(contracts.RocketDAOProtocolProposal, &details.IsVetoed, "getVetoed", id) + addCall(contracts.RocketDAOProtocolProposal, &details.VetoQuorum, "getProposalVetoQuorum", id) + addCall(contracts.RocketDAOProtocolProposal, &details.Payload, "getPayload", id) + addCall(contracts.RocketDAOProtocolProposal, &details.State, "getState", id) + addCall(contracts.RocketDAOProtocolVerifier, &details.DefeatIndex, "getDefeatIndex", id) + addCall(contracts.RocketDAOProtocolVerifier, &details.ProposalBond, "getProposalBond", id) + addCall(contracts.RocketDAOProtocolVerifier, &details.ChallengeBond, "getChallengeBond", id) + addCall(contracts.RocketDAOProtocolVerifier, &details.ChallengeWindow, "getChallengePeriod", id) + for _, err := range allErrors { + if err != nil { + return fmt.Errorf("error adding proposal calls: %w", err) + } + } return nil } // Converts a raw proposal to a well-formatted one -func fixupPdaoProposalDetails(rp *rocketpool.RocketPool, rawDetails *protocolDaoProposalDetailsRaw, details *protocol.ProtocolDaoProposalDetails, opts *bind.CallOpts) error { +func fixupPdaoProposalDetails(rp *rocketpool.RocketPool, rawDetails *protocolDaoProposalDetailsRaw, details *protocol.ProtocolDaoProposalDetails, opts *bind.CallOpts) { details.ID = rawDetails.ID details.DAO = rawDetails.DAO details.ProposerAddress = rawDetails.ProposerAddress @@ -205,5 +220,4 @@ func fixupPdaoProposalDetails(rp *rocketpool.RocketPool, rawDetails *protocolDao if err != nil { details.PayloadStr = fmt.Sprintf("", err.Error()) } - return nil } diff --git a/rocketpool-cli/auction/claim-lot.go b/rocketpool-cli/auction/claim-lot.go index c18c5c14a..a5c8e88de 100644 --- a/rocketpool-cli/auction/claim-lot.go +++ b/rocketpool-cli/auction/claim-lot.go @@ -92,8 +92,8 @@ func claimFromLot(lot string, yes bool) error { } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas uint64 + var totalSafeGas uint64 var gasInfo rocketpoolapi.GasInfo for _, lot := range selectedLots { canResponse, err := rp.CanClaimFromLot(lot.Details.Index) diff --git a/rocketpool-cli/auction/recover-lot.go b/rocketpool-cli/auction/recover-lot.go index 669ecf654..9749688c4 100644 --- a/rocketpool-cli/auction/recover-lot.go +++ b/rocketpool-cli/auction/recover-lot.go @@ -92,8 +92,8 @@ func recoverRplFromLot(lot string, yes bool) error { } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas uint64 + var totalSafeGas uint64 var gasInfo rocketpoolapi.GasInfo for _, lot := range selectedLots { canResponse, err := rp.CanRecoverUnclaimedRPLFromLot(lot.Details.Index) diff --git a/rocketpool-cli/megapool/exit-validator.go b/rocketpool-cli/megapool/exit-validator.go index 703f66aae..06d3eb47c 100644 --- a/rocketpool-cli/megapool/exit-validator.go +++ b/rocketpool-cli/megapool/exit-validator.go @@ -53,10 +53,9 @@ func getExitableValidator() (uint64, bool, error) { // Get validators return uint64(activeValidators[selected].ValidatorId), true, nil - } else { - fmt.Println("No validators can be exited at the moment") - return 0, false, nil } + fmt.Println("No validators can be exited at the moment") + return 0, false, nil } func exitValidator(validatorId uint64, yes bool) error { diff --git a/rocketpool-cli/megapool/notify-final-balance.go b/rocketpool-cli/megapool/notify-final-balance.go index 41464465a..c1607df75 100644 --- a/rocketpool-cli/megapool/notify-final-balance.go +++ b/rocketpool-cli/megapool/notify-final-balance.go @@ -48,10 +48,9 @@ func getNotifiableValidator() (uint64, uint64, bool, error) { // Get validators return uint64(exitingValidators[selected].ValidatorId), uint64(exitingValidators[selected].ValidatorIndex), true, nil - } else { - fmt.Println("No validators at the state where the full withdrawal can be proved") - return 0, 0, false, nil } + fmt.Println("No validators at the state where the full withdrawal can be proved") + return 0, 0, false, nil } func notifyFinalBalance(validatorId, validatorIndex, slot uint64, yes bool) error { diff --git a/rocketpool-cli/megapool/notify-validator-exit.go b/rocketpool-cli/megapool/notify-validator-exit.go index e4a31d258..d15cb4cd4 100644 --- a/rocketpool-cli/megapool/notify-validator-exit.go +++ b/rocketpool-cli/megapool/notify-validator-exit.go @@ -44,11 +44,9 @@ func getExitedValidator() (uint64, bool, error) { // Get validators return uint64(activeValidators[selected].ValidatorId), true, nil - - } else { - fmt.Println("Can't notify the exit of any validators") - return 0, false, nil } + fmt.Println("Can't notify the exit of any validators") + return 0, false, nil } func notifyValidatorExit(validatorId uint64, yes bool) error { diff --git a/rocketpool-cli/minipool/delegate.go b/rocketpool-cli/minipool/delegate.go index 96634e25d..f3eecce2c 100644 --- a/rocketpool-cli/minipool/delegate.go +++ b/rocketpool-cli/minipool/delegate.go @@ -81,20 +81,19 @@ func delegateUpgradeMinipools(minipool string, includeFinalized, yes bool) error } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas uint64 + var totalSafeGas uint64 var gasInfo rocketpoolapi.GasInfo for _, minipool := range selectedMinipools { canResponse, err := rp.CanDelegateUpgradeMinipool(minipool) if err != nil { fmt.Printf("WARNING: Couldn't get gas price for upgrade transaction (%s)\n", err) break - } else { - fmt.Printf("Minipool %s will upgrade to delegate contract %s.\n", minipool.Hex(), canResponse.LatestDelegateAddress.Hex()) - gasInfo = canResponse.GasInfo - totalGas += canResponse.GasInfo.EstGasLimit - totalSafeGas += canResponse.GasInfo.SafeGasLimit } + fmt.Printf("Minipool %s will upgrade to delegate contract %s.\n", minipool.Hex(), canResponse.LatestDelegateAddress.Hex()) + gasInfo = canResponse.GasInfo + totalGas += canResponse.GasInfo.EstGasLimit + totalSafeGas += canResponse.GasInfo.SafeGasLimit } gasInfo.EstGasLimit = totalGas gasInfo.SafeGasLimit = totalSafeGas diff --git a/rocketpool-cli/minipool/distribute.go b/rocketpool-cli/minipool/distribute.go index 6beab9b5a..deebe4076 100644 --- a/rocketpool-cli/minipool/distribute.go +++ b/rocketpool-cli/minipool/distribute.go @@ -204,8 +204,8 @@ func distributeBalance(minipool string, threshold float64, yes bool) error { } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas uint64 + var totalSafeGas uint64 var gasInfo rocketpoolapi.GasInfo for _, minipool := range selectedMinipools { gasInfo = minipool.GasInfo diff --git a/rocketpool-cli/minipool/refund.go b/rocketpool-cli/minipool/refund.go index e12c7aa93..4d561ada5 100644 --- a/rocketpool-cli/minipool/refund.go +++ b/rocketpool-cli/minipool/refund.go @@ -85,19 +85,18 @@ func refundMinipools(minipool string, yes bool) error { } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas uint64 + var totalSafeGas uint64 var gasInfo rocketpoolapi.GasInfo for _, minipool := range selectedMinipools { canResponse, err := rp.CanRefundMinipool(minipool.Address) if err != nil { fmt.Printf("WARNING: Couldn't get gas price for refund transaction (%s)", err.Error()) break - } else { - gasInfo = canResponse.GasInfo - totalGas += canResponse.GasInfo.EstGasLimit - totalSafeGas += canResponse.GasInfo.SafeGasLimit } + gasInfo = canResponse.GasInfo + totalGas += canResponse.GasInfo.EstGasLimit + totalSafeGas += canResponse.GasInfo.SafeGasLimit } gasInfo.EstGasLimit = totalGas gasInfo.SafeGasLimit = totalSafeGas diff --git a/rocketpool-cli/minipool/rescue-dissolved.go b/rocketpool-cli/minipool/rescue-dissolved.go index 4cc3f4ed9..f9d203071 100644 --- a/rocketpool-cli/minipool/rescue-dissolved.go +++ b/rocketpool-cli/minipool/rescue-dissolved.go @@ -230,12 +230,10 @@ func rescueDissolved(minipool string, amount string, noSend bool, yes bool) erro cliutils.PrintTransactionHash(rp, response.TxHash) if _, err = rp.WaitForTransaction(response.TxHash); err != nil { return fmt.Errorf("Could not rescue minipool %s: %s.\n", selectedMinipool.Address.Hex(), err.Error()) - } else { - fmt.Printf("Successfully deposited to minipool %s.\n", selectedMinipool.Address.Hex()) - fmt.Println("Please watch its status on a chain explorer such as https://beaconcha.in; it may take up to 24 hours for this deposit to be seen by the chain.") } + fmt.Printf("Successfully deposited to minipool %s.\n", selectedMinipool.Address.Hex()) + fmt.Println("Please watch its status on a chain explorer such as https://beaconcha.in; it may take up to 24 hours for this deposit to be seen by the chain.") - // Return return nil } diff --git a/rocketpool-cli/minipool/stake.go b/rocketpool-cli/minipool/stake.go index ac2dda574..d9de9925e 100644 --- a/rocketpool-cli/minipool/stake.go +++ b/rocketpool-cli/minipool/stake.go @@ -83,19 +83,18 @@ func stakeMinipools(minipool string, yes bool) error { } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas = uint64(0) + var totalSafeGas = uint64(0) var gasInfo rocketpoolapi.GasInfo for _, minipool := range selectedMinipools { canResponse, err := rp.CanStakeMinipool(minipool.Address) if err != nil { fmt.Printf("WARNING: Couldn't get gas price for stake transaction (%s)", err) break - } else { - gasInfo = canResponse.GasInfo - totalGas += canResponse.GasInfo.EstGasLimit - totalSafeGas += canResponse.GasInfo.SafeGasLimit } + gasInfo = canResponse.GasInfo + totalGas += canResponse.GasInfo.EstGasLimit + totalSafeGas += canResponse.GasInfo.SafeGasLimit } gasInfo.EstGasLimit = totalGas gasInfo.SafeGasLimit = totalSafeGas diff --git a/rocketpool-cli/node/claim-rewards.go b/rocketpool-cli/node/claim-rewards.go index 07ad916c9..15ca8ffe0 100644 --- a/rocketpool-cli/node/claim-rewards.go +++ b/rocketpool-cli/node/claim-rewards.go @@ -149,35 +149,34 @@ func nodeClaimRewards(restakeAmountFlag string, yes bool) error { indices = append(indices, intervalInfo.Index) } break - } else { - elements := strings.Split(indexSelection, ",") - allValid := true - seenIndices := map[uint64]bool{} - - for _, element := range elements { - found := slices.Contains(validIndices, element) - if !found { - fmt.Printf("'%s' is an invalid index.\nValid indices are: %s\n", element, strings.Join(validIndices, ",")) - allValid = false - break - } - index, err := strconv.ParseUint(element, 0, 64) - if err != nil { - fmt.Printf("'%s' is an invalid index.\nValid indices are: %s\n", element, strings.Join(validIndices, ",")) - allValid = false - break - } - - // Ignore duplicates - _, exists := seenIndices[index] - if !exists { - indices = append(indices, index) - seenIndices[index] = true - } + } + elements := strings.Split(indexSelection, ",") + allValid := true + seenIndices := map[uint64]bool{} + + for _, element := range elements { + found := slices.Contains(validIndices, element) + if !found { + fmt.Printf("'%s' is an invalid index.\nValid indices are: %s\n", element, strings.Join(validIndices, ",")) + allValid = false + break } - if allValid { + index, err := strconv.ParseUint(element, 0, 64) + if err != nil { + fmt.Printf("'%s' is an invalid index.\nValid indices are: %s\n", element, strings.Join(validIndices, ",")) + allValid = false break } + + // Ignore duplicates + _, exists := seenIndices[index] + if !exists { + indices = append(indices, index) + seenIndices[index] = true + } + } + if allValid { + break } } diff --git a/rocketpool-cli/node/stake-rpl.go b/rocketpool-cli/node/stake-rpl.go index e8615f7dd..2454f1aea 100644 --- a/rocketpool-cli/node/stake-rpl.go +++ b/rocketpool-cli/node/stake-rpl.go @@ -178,7 +178,10 @@ func nodeStakeRpl(amount string, swap bool, yes bool) error { // Amount flag custom percentage input if strings.HasSuffix(amount, "%") { - fmt.Sscanf(amount, "%f%%", &stakePercent) + _, err := fmt.Sscanf(amount, "%f%%", &stakePercent) + if err != nil { + return fmt.Errorf("Invalid stake amount '%s': %w", amount, err) + } amountWei = rplStakePerValidator(ethBorrowed, eth.EthToWei(stakePercent/100), rplPrice.RplPrice) } else if amount == "all" { @@ -226,7 +229,10 @@ func nodeStakeRpl(amount string, swap bool, yes bool) error { if amountWei == nil { inputAmountOrPercent := prompt.Prompt("Please enter an amount of RPL or percentage of borrowed ETH to stake. (e.g '50' for 50 RPL or '5%' for 5% borrowed ETH as RPL):", "^(0|[1-9]\\d*)(\\.\\d+)?%?$", "Invalid amount") if strings.HasSuffix(inputAmountOrPercent, "%") { - fmt.Sscanf(inputAmountOrPercent, "%f%%", &stakePercent) + _, err := fmt.Sscanf(inputAmountOrPercent, "%f%%", &stakePercent) + if err != nil { + return fmt.Errorf("Invalid stake amount '%s': %w", inputAmountOrPercent, err) + } amountWei = rplStakePerValidator(ethBorrowed, eth.EthToWei(stakePercent/100), rplPrice.RplPrice) } else { stakeAmount, err := strconv.ParseFloat(inputAmountOrPercent, 64) diff --git a/rocketpool-cli/node/sync.go b/rocketpool-cli/node/sync.go index f6fca0b13..ba61c691c 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/rocket-pool/smartnode/shared/services/rocketpool" "github.com/rocket-pool/smartnode/shared/types/api" @@ -11,9 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/utils/cli/color" ) -// Settings -var ethClientRecentBlockThreshold, _ = time.ParseDuration("5m") - func printClientStatus(status *api.ClientStatus, name string) { if status.Error != "" { diff --git a/rocketpool-cli/node/utils.go b/rocketpool-cli/node/utils.go index 40516e40e..4315b8b1e 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/smartnode/bindings/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" "github.com/rocket-pool/smartnode/shared/utils/cli/prompt" - hexutils "github.com/rocket-pool/smartnode/shared/utils/hex" ) // IPInfo API @@ -184,7 +177,6 @@ func promptTimezone() string { // Prompt for country country := "" for { - timezone = "" country = prompt.Prompt("Please enter a country / continent from the list above:", "^.+$", "Please enter a country / continent from the list above:") exists := slices.Contains(countryNames, country) @@ -238,7 +230,6 @@ func promptTimezone() string { // Prompt for region region := "" for { - timezone = "" region = prompt.Prompt("Please enter a region from the list above:", "^.+$", "Please enter a region from the list above:") exists := slices.Contains(regionNames, region) @@ -255,75 +246,3 @@ func promptTimezone() string { fmt.Printf("Using timezone %s.\n", timezone) return timezone } - -// 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 := prompt.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 Smart Node stack, you will need to put its keystore file into custom-keys first", pubkey.String()) - } - - // 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/execute-proposal.go b/rocketpool-cli/odao/execute-proposal.go index d5f0650d0..c29cbbc3d 100644 --- a/rocketpool-cli/odao/execute-proposal.go +++ b/rocketpool-cli/odao/execute-proposal.go @@ -91,19 +91,18 @@ func executeProposal(proposal string, yes bool) error { } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas uint64 + var totalSafeGas uint64 var gasInfo rocketpoolapi.GasInfo for _, proposal := range selectedProposals { canResponse, err := rp.CanExecuteTNDAOProposal(proposal.ID) if err != nil { fmt.Printf("WARNING: Couldn't get gas price for execute transaction (%s)", err) break - } else { - gasInfo = canResponse.GasInfo - totalGas += canResponse.GasInfo.EstGasLimit - totalSafeGas += canResponse.GasInfo.SafeGasLimit } + gasInfo = canResponse.GasInfo + totalGas += canResponse.GasInfo.EstGasLimit + totalSafeGas += canResponse.GasInfo.SafeGasLimit } gasInfo.EstGasLimit = totalGas gasInfo.SafeGasLimit = totalSafeGas diff --git a/rocketpool-cli/odao/execute-upgrade.go b/rocketpool-cli/odao/execute-upgrade.go index 5e0eb1a08..323402b57 100644 --- a/rocketpool-cli/odao/execute-upgrade.go +++ b/rocketpool-cli/odao/execute-upgrade.go @@ -147,19 +147,18 @@ func executeUpgrade(proposal string, yes bool) error { } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas = uint64(0) + var totalSafeGas = uint64(0) var gasInfo rocketpoolapi.GasInfo for _, proposal := range selectedProposals { canResponse, err := rp.CanExecuteUpgradeProposal(proposal.ID) if err != nil { fmt.Printf("WARNING: Couldn't get gas price for execute transaction (%s)", err) break - } else { - gasInfo = canResponse.GasInfo - totalGas += canResponse.GasInfo.EstGasLimit - totalSafeGas += canResponse.GasInfo.SafeGasLimit } + gasInfo = canResponse.GasInfo + totalGas += canResponse.GasInfo.EstGasLimit + totalSafeGas += canResponse.GasInfo.SafeGasLimit } gasInfo.EstGasLimit = totalGas gasInfo.SafeGasLimit = totalSafeGas diff --git a/rocketpool-cli/pdao/claim-bonds.go b/rocketpool-cli/pdao/claim-bonds.go index f40f29230..34a49364d 100644 --- a/rocketpool-cli/pdao/claim-bonds.go +++ b/rocketpool-cli/pdao/claim-bonds.go @@ -85,19 +85,18 @@ func claimBonds(proposal string, yes bool) error { } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas = uint64(0) + var totalSafeGas = uint64(0) var gasInfo rocketpoolapi.GasInfo for _, bond := range selectedClaims { indices := getClaimIndicesForBond(bond) canResponse, err := rp.PDAOCanClaimBonds(bond.ProposalID, indices) if err != nil { return fmt.Errorf("error simulating claim-bond on proposal %d: %s", bond.ProposalID, err.Error()) - } else { - gasInfo = canResponse.GasInfo - totalGas += canResponse.GasInfo.EstGasLimit - totalSafeGas += canResponse.GasInfo.SafeGasLimit } + gasInfo = canResponse.GasInfo + totalGas += canResponse.GasInfo.EstGasLimit + totalSafeGas += canResponse.GasInfo.SafeGasLimit } gasInfo.EstGasLimit = totalGas gasInfo.SafeGasLimit = totalSafeGas diff --git a/rocketpool-cli/pdao/execute-proposal.go b/rocketpool-cli/pdao/execute-proposal.go index 3c79cb0db..e35bbfa2b 100644 --- a/rocketpool-cli/pdao/execute-proposal.go +++ b/rocketpool-cli/pdao/execute-proposal.go @@ -96,19 +96,18 @@ func executeProposal(proposal string, yes bool) error { } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas = uint64(0) + var totalSafeGas = uint64(0) var gasInfo rocketpoolapi.GasInfo for _, proposal := range selectedProposals { canResponse, err := rp.PDAOCanExecuteProposal(proposal.ID) if err != nil { fmt.Printf("WARNING: Couldn't get gas price for execute transaction (%s)", err.Error()) break - } else { - gasInfo = canResponse.GasInfo - totalGas += canResponse.GasInfo.EstGasLimit - totalSafeGas += canResponse.GasInfo.SafeGasLimit } + gasInfo = canResponse.GasInfo + totalGas += canResponse.GasInfo.EstGasLimit + totalSafeGas += canResponse.GasInfo.SafeGasLimit } gasInfo.EstGasLimit = totalGas gasInfo.SafeGasLimit = totalSafeGas diff --git a/rocketpool-cli/pdao/propose-settings.go b/rocketpool-cli/pdao/propose-settings.go index 60e92e768..46b0876dc 100644 --- a/rocketpool-cli/pdao/propose-settings.go +++ b/rocketpool-cli/pdao/propose-settings.go @@ -3,10 +3,8 @@ package pdao import ( "fmt" "math/big" - "strings" "time" - "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/settings/protocol" "github.com/rocket-pool/smartnode/bindings/utils/eth" @@ -318,15 +316,6 @@ func proposeSettingSecurityProposalActionTime(value time.Duration, yes bool) err return proposeSetting(protocol.SecuritySettingsContractName, protocol.SecurityProposalActionTimeSettingPath, trueValue, yes) } -func proposeSettingNetworkAllowListedControllers(value []common.Address, yes bool) error { - strs := make([]string, len(value)) - for i, addr := range value { - strs[i] = addr.Hex() - } - trueValue := strings.Join(strs, "") - return proposeSetting(protocol.NetworkSettingsContractName, protocol.NetworkAllowListedControllersPath, trueValue, yes) -} - func proposeSettingMegapoolTimeBeforeDissolve(value time.Duration, yes bool) error { trueValue := fmt.Sprint(uint64(value.Seconds())) return proposeSetting(protocol.MegapoolSettingsContractName, protocol.MegapoolTimeBeforeDissolveSettingsPath, trueValue, yes) diff --git a/rocketpool-cli/security/execute-proposal.go b/rocketpool-cli/security/execute-proposal.go index f1a198460..5436cb176 100644 --- a/rocketpool-cli/security/execute-proposal.go +++ b/rocketpool-cli/security/execute-proposal.go @@ -91,19 +91,18 @@ func executeProposal(proposal string, yes bool) error { } // Get the total gas limit estimate - var totalGas uint64 = 0 - var totalSafeGas uint64 = 0 + var totalGas uint64 + var totalSafeGas uint64 var gasInfo rocketpoolapi.GasInfo for _, proposal := range selectedProposals { canResponse, err := rp.SecurityCanExecuteProposal(proposal.ID) if err != nil { fmt.Printf("WARNING: Couldn't get gas price for execute transaction (%s)", err) break - } else { - gasInfo = canResponse.GasInfo - totalGas += canResponse.GasInfo.EstGasLimit - totalSafeGas += canResponse.GasInfo.SafeGasLimit } + gasInfo = canResponse.GasInfo + totalGas += canResponse.GasInfo.EstGasLimit + totalSafeGas += canResponse.GasInfo.SafeGasLimit } gasInfo.EstGasLimit = totalGas gasInfo.SafeGasLimit = totalSafeGas 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/checkbox-modal-layout.go b/rocketpool-cli/service/config/checkbox-modal-layout.go index 9de9afd0a..29800db9c 100644 --- a/rocketpool-cli/service/config/checkbox-modal-layout.go +++ b/rocketpool-cli/service/config/checkbox-modal-layout.go @@ -106,14 +106,20 @@ func newCheckBoxModalLayout(app *tview.Application, title string, width int, tex SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView1, navString1) + _, err := fmt.Fprint(navTextView1, navString1) + if err != nil { + panic(fmt.Errorf("error writing nav string 1: %w", err)) + } navString2 := "Esc: Go Back Ctrl+C: Quit without Saving" navTextView2 := tview.NewTextView(). SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView2, navString2) + _, err = fmt.Fprint(navTextView2, navString2) + if err != nil { + panic(fmt.Errorf("error writing nav string 2: %w", err)) + } // Create the nav footer navBar := tview.NewFlex(). @@ -285,12 +291,11 @@ func (layout *checkBoxModalLayout) generateCheckboxes(labels []string, descripti layout.selected = nextSelection layout.app.SetFocus(layout.buttonForm) return nil - } else { - nextSelection = i + 1 - layout.selected = nextSelection - layout.descriptionBox.SetText(descriptions[nextSelection]) - return tcell.NewEventKey(tcell.KeyTab, 0, 0) } + nextSelection = i + 1 + layout.selected = nextSelection + layout.descriptionBox.SetText(descriptions[nextSelection]) + return tcell.NewEventKey(tcell.KeyTab, 0, 0) case tcell.KeyUp, tcell.KeyBacktab: var nextSelection int if layout.selected == 0 { @@ -298,12 +303,11 @@ func (layout *checkBoxModalLayout) generateCheckboxes(labels []string, descripti layout.selected = nextSelection layout.app.SetFocus(layout.buttonForm) return nil - } else { - nextSelection = i - 1 - layout.selected = nextSelection - layout.descriptionBox.SetText(descriptions[nextSelection]) - return tcell.NewEventKey(tcell.KeyBacktab, 0, 0) } + nextSelection = i - 1 + layout.selected = nextSelection + layout.descriptionBox.SetText(descriptions[nextSelection]) + return tcell.NewEventKey(tcell.KeyBacktab, 0, 0) default: return event } diff --git a/rocketpool-cli/service/config/choice-modal-layout.go b/rocketpool-cli/service/config/choice-modal-layout.go index d0fe43909..869e9297b 100644 --- a/rocketpool-cli/service/config/choice-modal-layout.go +++ b/rocketpool-cli/service/config/choice-modal-layout.go @@ -108,14 +108,20 @@ func newChoiceModalLayout(app *tview.Application, title string, width int, text SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView1, navString1) + _, err := fmt.Fprint(navTextView1, navString1) + if err != nil { + panic(fmt.Errorf("error writing nav string 1: %w", err)) + } navString2 := "Esc: Go Back Ctrl+C: Quit without Saving" navTextView2 := tview.NewTextView(). SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView2, navString2) + _, err = fmt.Fprint(navTextView2, navString2) + if err != nil { + panic(fmt.Errorf("error writing nav string 2: %w", err)) + } // Create the nav footer navBar := tview.NewFlex(). 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/main-display.go b/rocketpool-cli/service/config/main-display.go index 690bc0147..dfb21b924 100644 --- a/rocketpool-cli/service/config/main-display.go +++ b/rocketpool-cli/service/config/main-display.go @@ -11,7 +11,7 @@ import ( ) // This represents the primary TUI for the configuration command -type mainDisplay struct { +type MainDisplay struct { navHeader *tview.TextView pages *tview.Pages app *tview.Application @@ -38,7 +38,7 @@ const ( ) // Creates a new MainDisplay instance. -func NewMainDisplay(app *tview.Application, previousConfig *config.RocketPoolConfig, config *config.RocketPoolConfig, isNew bool, isUpdate bool, isNative bool) *mainDisplay { +func NewMainDisplay(app *tview.Application, previousConfig *config.RocketPoolConfig, config *config.RocketPoolConfig, isNew bool, isUpdate bool, isNative bool) *MainDisplay { // Create a copy of the original config for comparison purposes if previousConfig == nil { @@ -98,7 +98,7 @@ func NewMainDisplay(app *tview.Application, previousConfig *config.RocketPoolCon resizeWarning.SetBorderPadding(0, 0, 1, 1) // Create the main display object - md := &mainDisplay{ + md := &MainDisplay{ navHeader: navHeader, pages: pages, app: app, @@ -154,7 +154,7 @@ func NewMainDisplay(app *tview.Application, previousConfig *config.RocketPoolCon } // Sets the current page that is on display. -func (md *mainDisplay) setPage(page *page) { +func (md *MainDisplay) setPage(page *page) { md.navHeader.SetText(page.getHeader()) md.pages.SwitchToPage(page.id) } diff --git a/rocketpool-cli/service/config/pseudomodal.go b/rocketpool-cli/service/config/pseudomodal.go index 9d8f1e3ce..5f95ed201 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 d9f10f688..124dc28bf 100644 --- a/rocketpool-cli/service/config/review-native-page.go +++ b/rocketpool-cli/service/config/review-native-page.go @@ -13,15 +13,8 @@ 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 { +func NewReviewNativePage(md *MainDisplay, oldConfig *config.RocketPoolConfig, newConfig *config.RocketPoolConfig) *ReviewPage { var changedSettings map[string][]cfgtypes.ChangedSetting @@ -154,14 +147,20 @@ func NewReviewNativePage(md *mainDisplay, oldConfig *config.RocketPoolConfig, ne SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView1, navString1) + _, err := fmt.Fprint(navTextView1, navString1) + if err != nil { + panic(fmt.Errorf("error writing nav string 1: %w", err)) + } navString2 := "Esc: Go Back Ctrl+C: Quit without Saving" navTextView2 := tview.NewTextView(). SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView2, navString2) + _, err = fmt.Fprint(navTextView2, navString2) + if err != nil { + panic(fmt.Errorf("error writing nav string 2: %w", err)) + } // Create the nav footer navBar := tview.NewFlex(). diff --git a/rocketpool-cli/service/config/review-page.go b/rocketpool-cli/service/config/review-page.go index ee2b0b5c0..9350a4783 100644 --- a/rocketpool-cli/service/config/review-page.go +++ b/rocketpool-cli/service/config/review-page.go @@ -16,13 +16,13 @@ const reviewPageID string = "review-settings" // The changed settings review page type ReviewPage struct { - md *mainDisplay + md *MainDisplay changedSettings map[string][]cfgtypes.ChangedSetting page *page } // Create a page to review any changes -func NewReviewPage(md *mainDisplay, oldConfig *config.RocketPoolConfig, newConfig *config.RocketPoolConfig) *ReviewPage { +func NewReviewPage(md *MainDisplay, oldConfig *config.RocketPoolConfig, newConfig *config.RocketPoolConfig) *ReviewPage { var changedSettings map[string][]cfgtypes.ChangedSetting var totalAffectedContainers map[cfgtypes.ContainerID]bool @@ -190,14 +190,20 @@ func NewReviewPage(md *mainDisplay, oldConfig *config.RocketPoolConfig, newConfi SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView1, navString1) + _, err := fmt.Fprint(navTextView1, navString1) + if err != nil { + panic(fmt.Errorf("error writing nav string 1: %w", err)) + } navString2 := "Esc: Go Back Ctrl+C: Quit without Saving" navTextView2 := tview.NewTextView(). SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView2, navString2) + _, err = fmt.Fprint(navTextView2, navString2) + if err != nil { + panic(fmt.Errorf("error writing nav string 2: %w", err)) + } // Create the nav footer navBar := tview.NewFlex(). diff --git a/rocketpool-cli/service/config/settings-alerting.go b/rocketpool-cli/service/config/settings-alerting.go index 7b7f89587..36dabdef7 100644 --- a/rocketpool-cli/service/config/settings-alerting.go +++ b/rocketpool-cli/service/config/settings-alerting.go @@ -7,7 +7,7 @@ import ( "github.com/rocket-pool/smartnode/shared/services/config" ) -var alertingParametersNativeMode map[string]interface{} = map[string]interface{}{ +var alertingParametersNativeMode = map[string]interface{}{ "enableAlerting": nil, "showAlertsOnCLI": nil, "nativeModeHost": nil, @@ -27,7 +27,7 @@ var alertingParametersNativeMode map[string]interface{} = map[string]interface{} "lowETHBalanceThreshold": nil, } -var alertingParametersDockerMode map[string]interface{} = map[string]interface{}{ +var alertingParametersDockerMode = map[string]interface{}{ "enableAlerting": nil, "showAlertsOnCLI": nil, "port": nil, @@ -60,7 +60,7 @@ var alertingParametersDockerMode map[string]interface{} = map[string]interface{} // The page wrapper for the alerting config type AlertingConfigPage struct { - mainDisplay *mainDisplay + mainDisplay *MainDisplay homePage *page page *page layout *standardLayout @@ -125,7 +125,7 @@ func (configPage *AlertingConfigPage) createContent() { // Map the config parameters to the UI form items: configPage.layout.mapParameterizedFormItems(allItems...) - var enableAlertingBox *tview.Checkbox = nil + var enableAlertingBox *tview.Checkbox for _, item := range allItems { if item.parameter.ID == "enableAlerting" { configPage.alertingEnabledItem = *item diff --git a/rocketpool-cli/service/config/settings-home.go b/rocketpool-cli/service/config/settings-home.go index 177543bf0..c77d3d092 100644 --- a/rocketpool-cli/service/config/settings-home.go +++ b/rocketpool-cli/service/config/settings-home.go @@ -26,11 +26,11 @@ type settingsHome struct { categoryList *tview.List settingsSubpages []settingsPage content tview.Primitive - md *mainDisplay + md *MainDisplay } // Creates a new SettingsHome instance and adds (and its subpages) it to the main display. -func newSettingsHome(md *mainDisplay) *settingsHome { +func newSettingsHome(md *MainDisplay) *settingsHome { homePage := newPage(nil, settingsHomeID, "Categories", "", nil) @@ -132,7 +132,10 @@ func (home *settingsHome) createFooter() (tview.Primitive, int) { AddItem(nil, 0, 1, false). AddItem(navTextView1, len(navString1), 1, false). AddItem(nil, 0, 1, false) - fmt.Fprint(navTextView1, navString1) + _, err := fmt.Fprint(navTextView1, navString1) + if err != nil { + panic(fmt.Errorf("error writing nav string 1: %w", err)) + } navString2 := "Tab: Go to the Buttons Ctrl+C: Quit without Saving" navTextView2 := tview.NewTextView(). @@ -143,7 +146,10 @@ func (home *settingsHome) createFooter() (tview.Primitive, int) { AddItem(nil, 0, 1, false). AddItem(navTextView2, len(navString2), 1, false). AddItem(nil, 0, 1, false) - fmt.Fprint(navTextView2, navString2) + _, err = fmt.Fprint(navTextView2, navString2) + if err != nil { + panic(fmt.Errorf("error writing nav string 2: %w", err)) + } // Save and Quit buttons saveButton := tview.NewButton("Review Changes and Save") diff --git a/rocketpool-cli/service/config/settings-native-home.go b/rocketpool-cli/service/config/settings-native-home.go index 390674942..bee778a0c 100644 --- a/rocketpool-cli/service/config/settings-native-home.go +++ b/rocketpool-cli/service/config/settings-native-home.go @@ -22,11 +22,11 @@ type settingsNativeHome struct { categoryList *tview.List settingsSubpages []*page content tview.Primitive - md *mainDisplay + md *MainDisplay } // Creates a new SettingsNativeHome instance and adds (and its subpages) it to the main display. -func newSettingsNativeHome(md *mainDisplay) *settingsNativeHome { +func newSettingsNativeHome(md *MainDisplay) *settingsNativeHome { homePage := newPage(nil, settingsNativeHomeID, "Categories", "", nil) @@ -119,7 +119,10 @@ func (home *settingsNativeHome) createFooter() (tview.Primitive, int) { AddItem(nil, 0, 1, false). AddItem(navTextView1, len(navString1), 1, false). AddItem(nil, 0, 1, false) - fmt.Fprint(navTextView1, navString1) + _, err := fmt.Fprint(navTextView1, navString1) + if err != nil { + panic(fmt.Errorf("error writing nav string 1: %w", err)) + } navString2 := "Tab: Go to the Buttons Ctrl+C: Quit without Saving" navTextView2 := tview.NewTextView(). @@ -130,7 +133,10 @@ func (home *settingsNativeHome) createFooter() (tview.Primitive, int) { AddItem(nil, 0, 1, false). AddItem(navTextView2, len(navString2), 1, false). AddItem(nil, 0, 1, false) - fmt.Fprint(navTextView2, navString2) + _, err = fmt.Fprint(navTextView2, navString2) + if err != nil { + panic(fmt.Errorf("error writing nav string 2: %w", err)) + } // Save and Quit buttons saveButton := tview.NewButton("Review Changes and Save") diff --git a/rocketpool-cli/service/config/standard-layout.go b/rocketpool-cli/service/config/standard-layout.go index 7547290fc..cf28d4748 100644 --- a/rocketpool-cli/service/config/standard-layout.go +++ b/rocketpool-cli/service/config/standard-layout.go @@ -17,7 +17,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. @@ -142,14 +141,20 @@ func (layout *standardLayout) createSettingFooter() { SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView1, navString1) + _, err := fmt.Fprint(navTextView1, navString1) + if err != nil { + panic(fmt.Errorf("error writing nav string 1: %w", err)) + } navString2 := "Esc: Go Back to Categories" navTextView2 := tview.NewTextView(). SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView2, navString2) + _, err = fmt.Fprint(navTextView2, navString2) + if err != nil { + panic(fmt.Errorf("error writing nav string 2: %w", err)) + } navBar := tview.NewFlex(). SetDirection(tview.FlexRow). @@ -205,7 +210,7 @@ func (layout *standardLayout) mapParameterizedFormItems(params ...*parameterized } // Sets up a handler to return to the specified homePage when the user presses escape on the layout. -func (layout *standardLayout) setupEscapeReturnHomeHandler(md *mainDisplay, homePage *page) { +func (layout *standardLayout) setupEscapeReturnHomeHandler(md *MainDisplay, homePage *page) { layout.grid.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { // Return to the home page if event.Key() == tcell.KeyEsc { diff --git a/rocketpool-cli/service/config/step-finished.go b/rocketpool-cli/service/config/step-finished.go index fe93fcf38..c126c8379 100644 --- a/rocketpool-cli/service/config/step-finished.go +++ b/rocketpool-cli/service/config/step-finished.go @@ -62,7 +62,7 @@ func createFinishedStep(wiz *wizard, currentStep int, totalSteps int) *choiceWiz } // Processes a configuration after saving and exiting without looking at the review screen -func processConfigAfterQuit(md *mainDisplay) { +func processConfigAfterQuit(md *MainDisplay) { errors := md.Config.Validate() if len(errors) > 0 { builder := strings.Builder{} diff --git a/rocketpool-cli/service/config/step-native-finished.go b/rocketpool-cli/service/config/step-native-finished.go index 3a9c1f212..b93d79f73 100644 --- a/rocketpool-cli/service/config/step-native-finished.go +++ b/rocketpool-cli/service/config/step-native-finished.go @@ -62,7 +62,7 @@ func createNativeFinishedStep(wiz *wizard, currentStep int, totalSteps int) *cho } // Processes a configuration after saving and exiting without looking at the review screen -func processConfigAfterQuitNative(md *mainDisplay) { +func processConfigAfterQuitNative(md *MainDisplay) { errors := md.Config.Validate() if len(errors) > 0 { builder := strings.Builder{} diff --git a/rocketpool-cli/service/config/step-random-cc.go b/rocketpool-cli/service/config/step-random-cc.go index d7cb5ee6c..cf3b4240e 100644 --- a/rocketpool-cli/service/config/step-random-cc.go +++ b/rocketpool-cli/service/config/step-random-cc.go @@ -9,45 +9,6 @@ import ( const randomCcPrysmID string = "step-random-cc-prysm" const randomCcID string = "step-random-cc" -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." - - show := func(modal *choiceModalLayout) { - wiz.md.setPage(modal.page) - modal.focus(0) - } - - done := func(buttonIndex int, buttonLabel string) { - if buttonIndex == 0 { - selectRandomCC(goodOptions, false, wiz, currentStep, totalSteps) - } else { - wiz.graffitiModal.show() - } - } - - back := func() { - wiz.consensusLocalModal.show() - } - - return newChoiceStep( - wiz, - currentStep, - totalSteps, - helperText, - []string{"Choose Another Random Client", "Keep Prysm"}, - []string{}, - 76, - "Consensus Client > Selection", - DirectionalModalHorizontal, - show, - done, - back, - randomCcPrysmID, - ) - -} - func createRandomCCStep(wiz *wizard, currentStep int, totalSteps int, goodOptions []cfgtypes.ParameterOption) *choiceWizardStep { var selectedClientName string diff --git a/rocketpool-cli/service/config/textbox-modal-layout.go b/rocketpool-cli/service/config/textbox-modal-layout.go index 79d7bc22d..de88defd7 100644 --- a/rocketpool-cli/service/config/textbox-modal-layout.go +++ b/rocketpool-cli/service/config/textbox-modal-layout.go @@ -99,14 +99,20 @@ func newTextBoxModalLayout(app *tview.Application, title string, width int, text SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView1, navString1) + _, err := fmt.Fprint(navTextView1, navString1) + if err != nil { + panic(fmt.Errorf("error writing nav string 1: %w", err)) + } navString2 := "Esc: Go Back Ctrl+C: Quit without Saving" navTextView2 := tview.NewTextView(). SetDynamicColors(false). SetRegions(false). SetWrap(false) - fmt.Fprint(navTextView2, navString2) + _, err = fmt.Fprint(navTextView2, navString2) + if err != nil { + panic(fmt.Errorf("error writing nav string 2: %w", err)) + } // Create the nav footer navBar := tview.NewFlex(). 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..7023b6e87 100644 --- a/rocketpool-cli/service/config/wizard.go +++ b/rocketpool-cli/service/config/wizard.go @@ -1,7 +1,7 @@ package config type wizard struct { - md *mainDisplay + md *MainDisplay // Docker mode welcomeModal *choiceWizardStep @@ -26,7 +26,6 @@ type wizard struct { externalMevModal *textBoxWizardStep finishedModal *choiceWizardStep consensusLocalRandomModal *choiceWizardStep - consensusLocalRandomPrysmModal *choiceWizardStep consensusLocalPrysmWarning *choiceWizardStep consensusLocalTekuWarning *choiceWizardStep externalDoppelgangerModal *choiceWizardStep @@ -49,7 +48,7 @@ type wizard struct { nativeFinishedModal *choiceWizardStep } -func newWizard(md *mainDisplay) *wizard { +func newWizard(md *MainDisplay) *wizard { wiz := &wizard{ md: md, diff --git a/rocketpool-cli/service/service.go b/rocketpool-cli/service/service.go index 71959c0e5..73695ea0d 100644 --- a/rocketpool-cli/service/service.go +++ b/rocketpool-cli/service/service.go @@ -349,7 +349,10 @@ func configureService(configPath string, isNative, yes bool, composeFiles []stri for _, container := range md.ContainersToRestart { fullName := fmt.Sprintf("%s_%s", prefix, container) fmt.Printf("Stopping %s... ", fullName) - rp.StopContainer(fullName) + _, err = rp.StopContainer(fullName) + if err != nil { + return fmt.Errorf("error stopping container: %w", err) + } fmt.Print("done!\n") } @@ -527,7 +530,10 @@ func startService(params startServiceParams) 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) + } color.GreenPrintln("Updated settings successfully.") } else { fmt.Println("Cancelled.") @@ -726,25 +732,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 := rp.GetContainerPrefix() - 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) { @@ -1485,37 +1472,3 @@ func getConfigYaml() error { fmt.Println(string(bytes)) return nil } - -// Get the amount of space used by a Docker volume -func getVolumeSpaceUsed(rp *rocketpool.Client, volume string) (uint64, error) { - size, err := rp.GetVolumeSize(volume) - if err != nil { - return 0, fmt.Errorf("error getting execution client volume name: %w", err) - } - volumeBytes, err := humanize.ParseBytes(size) - if err != nil { - return 0, fmt.Errorf("couldn't parse size of EC volume (%s): %w", size, err) - } - return volumeBytes, nil -} - -// Get the amount of free space available in the target dir -func getPartitionFreeSpace(rp *rocketpool.Client, targetDir string) (uint64, error) { - partitions, err := disk.Partitions(true) - if err != nil { - return 0, fmt.Errorf("error getting partition list: %w", err) - } - longestPath := 0 - bestPartition := disk.PartitionStat{} - for _, partition := range partitions { - if strings.HasPrefix(targetDir, partition.Mountpoint) && len(partition.Mountpoint) > longestPath { - bestPartition = partition - longestPath = len(partition.Mountpoint) - } - } - diskUsage, err := disk.Usage(bestPartition.Mountpoint) - if err != nil { - return 0, fmt.Errorf("error getting free disk space available: %w", err) - } - return diskUsage.Free, nil -} diff --git a/rocketpool-cli/update/update.go b/rocketpool-cli/update/update.go index 4bc9a7143..fd6f0ffbc 100644 --- a/rocketpool-cli/update/update.go +++ b/rocketpool-cli/update/update.go @@ -112,14 +112,21 @@ func Update(yes bool, skipSignatureVerification bool, force bool) error { if err != nil { return fmt.Errorf("error creating temporary directory: %w", err) } - defer os.RemoveAll(tempDir) + defer func() { + // Ignore errors, tmpreaper will handle it + _ = os.RemoveAll(tempDir) + }() // Create a file that is executable and has the correct permissions tempFile, err := os.CreateTemp(tempDir, "rocketpool-cli-update-*.bin") if err != nil { return fmt.Errorf("error creating temporary file: %w", err) } - tempFile.Chmod(0755) + err = tempFile.Chmod(0755) + if err != nil { + return fmt.Errorf("error setting temporary file permissions: %w", err) + } + defer tempFile.Close() // Download the new binary downloadUrl := fmt.Sprintf(downloadUrlFormatString, runtime.GOOS, runtime.GOARCH) @@ -132,7 +139,9 @@ func Update(yes bool, skipSignatureVerification bool, force bool) error { if response.StatusCode != 200 { return fmt.Errorf("error downloading new binary: %s", response.Status) } - defer response.Body.Close() + defer func() { + _ = response.Body.Close() + }() if !skipSignatureVerification { // Download the signature file fmt.Println("Verifying the binary signature") @@ -142,7 +151,9 @@ func Update(yes bool, skipSignatureVerification bool, force bool) error { if err != nil { return fmt.Errorf("error downloading signature: %w", err) } - defer signatureResponse.Body.Close() + defer func() { + _ = signatureResponse.Body.Close() + }() if signatureResponse.StatusCode != 200 { return fmt.Errorf("error downloading signature: %s", signatureResponse.Status) } diff --git a/rocketpool-cli/wallet/utils.go b/rocketpool-cli/wallet/utils.go index 8c16f81ec..9246461cf 100644 --- a/rocketpool-cli/wallet/utils.go +++ b/rocketpool-cli/wallet/utils.go @@ -185,14 +185,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/beacon_state.go b/rocketpool/api/debug/beacon_state.go deleted file mode 100644 index b20ebe21e..000000000 --- a/rocketpool/api/debug/beacon_state.go +++ /dev/null @@ -1,226 +0,0 @@ -package debug - -import ( - "encoding/json" - "fmt" - "math/big" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/services" - "github.com/rocket-pool/smartnode/shared/types/api" - cfgtypes "github.com/rocket-pool/smartnode/shared/types/config" - "github.com/rocket-pool/smartnode/shared/types/eth2" - "github.com/rocket-pool/smartnode/shared/types/eth2/generic" - hexutil "github.com/rocket-pool/smartnode/shared/utils/hex" -) - -const MAX_WITHDRAWAL_SLOT_DISTANCE = 432000 // 60 days. -const capellaSlotMainnet uint64 = 6209536 -const capellaSlotHoodi uint64 = 0 - -func getBeaconStateForSlot(c *cli.Command, slot uint64, validatorIndex uint64) error { - // Create a new response - response := api.BeaconStateResponse{} - - // Get services - if err := services.RequireNodeRegistered(c); err != nil { - return err - } - bc, err := services.GetBeaconClient(c) - if err != nil { - return err - } - - // Get beacon state - beaconStateResponse, err := bc.GetBeaconStateSSZ(slot) - if err != nil { - return err - } - - beaconState, err := eth2.NewBeaconState(beaconStateResponse.Data, beaconStateResponse.Fork) - if err != nil { - return err - } - - proof, err := beaconState.ValidatorProof(validatorIndex) - if err != nil { - return err - } - - // Convert the proof to a list of 0x-prefixed hex strings - response.Proof = make([]string, 0, len(proof)) - for _, hash := range proof { - response.Proof = append(response.Proof, hexutil.EncodeToString(hash)) - } - - // Render response json - json, err := json.Marshal(response) - if err != nil { - return err - } - fmt.Println(string(json)) - - return nil -} - -func getWithdrawalProofForSlot(c *cli.Command, slot uint64, validatorIndex uint64) error { - // Create a new response - response := api.WithdrawalProofResponse{} - response.ValidatorIndex = validatorIndex - response.Slot = slot - // Get services - if err := services.RequireNodeRegistered(c); err != nil { - return err - } - bc, err := services.GetBeaconClient(c) - if err != nil { - return err - } - - // Get the network - cfg, err := services.GetConfig(c) - if err != nil { - return err - } - - // Get the network - network := cfg.Smartnode.Network.Value.(cfgtypes.Network) - - // Find the most recent withdrawal to slot. - // Keep track of 404s- if we get 24 missing slots in a row, assume we don't have full history. - notFounds := 0 - var block eth2.SignedBeaconBlock - for candidateSlot := slot; candidateSlot >= slot-MAX_WITHDRAWAL_SLOT_DISTANCE; candidateSlot-- { - // Get the block at the candidate slot. - blockResponse, found, err := bc.GetBeaconBlockSSZ(candidateSlot) - if err != nil { - return err - } - if !found { - notFounds++ - if notFounds >= 64 { - return fmt.Errorf("2 epochs of missing slots detected. It is likely that the Beacon Client was checkpoint synced after the most recent withdrawal to slot %d, and does not have the history required to generate a withdrawal proof", slot) - } - continue - } else { - notFounds = 0 - } - - beaconBlock, err := eth2.NewSignedBeaconBlock(blockResponse.Data, blockResponse.Fork) - if err != nil { - return err - } - - if !beaconBlock.HasExecutionPayload() { - continue - } - - foundWithdrawal := false - - // Check the block for a withdrawal for the given validator index. - for i, withdrawal := range beaconBlock.Withdrawals() { - if withdrawal.ValidatorIndex != validatorIndex { - continue - } - response.WithdrawalSlot = candidateSlot - response.Amount = big.NewInt(0).SetUint64(withdrawal.Amount) - foundWithdrawal = true - response.IndexInWithdrawalsArray = uint(i) - response.WithdrawalIndex = withdrawal.Index - response.WithdrawalAddress = withdrawal.Address - break - } - - if foundWithdrawal { - block = beaconBlock - break - } - } - - if response.Slot == 0 { - return fmt.Errorf("no withdrawal found for validator index %d within %d slots of slot %d", validatorIndex, MAX_WITHDRAWAL_SLOT_DISTANCE, slot) - } - - // Start by proving from the withdrawal to the block_root - proof, err := block.ProveWithdrawal(uint64(response.IndexInWithdrawalsArray)) - if err != nil { - return err - } - - // Get beacon state - stateResponse, err := bc.GetBeaconStateSSZ(slot) - if err != nil { - return err - } - - state, err := eth2.NewBeaconState(stateResponse.Data, stateResponse.Fork) - if err != nil { - return err - } - - var summaryProof [][]byte - - var stateProof [][]byte - if response.WithdrawalSlot+generic.SlotsPerHistoricalRoot > state.GetSlot() { - stateProof, err = state.BlockRootProof(response.WithdrawalSlot) - if err != nil { - return err - } - } else { - var capellaOffset uint64 - if network == cfgtypes.Network_Mainnet { - capellaOffset = capellaSlotMainnet / uint64(generic.SlotsPerHistoricalRoot) - } else { - capellaOffset = capellaSlotHoodi / uint64(generic.SlotsPerHistoricalRoot) - } - stateProof, err = state.HistoricalSummaryProof(response.WithdrawalSlot, capellaOffset) - if err != nil { - return err - } - - // Additionally, we need to prove from the block_root in the historical summary - // up to the beginning of the above proof, which is the entry in the historical summaries vector. - blockRootsStateSlot := generic.SlotsPerHistoricalRoot + ((response.WithdrawalSlot / generic.SlotsPerHistoricalRoot) * generic.SlotsPerHistoricalRoot) - // get the state that has the block roots tree - blockRootsStateResponse, err := bc.GetBeaconStateSSZ(blockRootsStateSlot) - if err != nil { - return err - } - blockRootsState, err := eth2.NewBeaconState(blockRootsStateResponse.Data, blockRootsStateResponse.Fork) - if err != nil { - return err - } - summaryProof, err = blockRootsState.HistoricalSummaryBlockRootProof(int(response.WithdrawalSlot)) - if err != nil { - return err - } - - } - - // Convert the proof to a list of 0x-prefixed hex strings - response.Proof = make([]string, 0, len(proof)+len(stateProof)+len(summaryProof)) - // First we prove from the withdrawal to the block_root - for _, hash := range proof { - response.Proof = append(response.Proof, hexutil.EncodeToString(hash)) - } - - // Then, if summaryProof has rows, we add them to prove from the block_root to the historical_summary row - for _, hash := range summaryProof { - response.Proof = append(response.Proof, hexutil.EncodeToString(hash)) - } - - // Finally, we prove either from the historical_summary or the block_root to the state_root - for _, hash := range stateProof { - response.Proof = append(response.Proof, hexutil.EncodeToString(hash)) - } - - // Render response json - json, err := json.Marshal(response) - if err != nil { - return err - } - fmt.Println(string(json)) - - return nil -} diff --git a/rocketpool/api/megapool/exit-queue.go b/rocketpool/api/megapool/exit-queue.go index e69ce609b..213993749 100644 --- a/rocketpool/api/megapool/exit-queue.go +++ b/rocketpool/api/megapool/exit-queue.go @@ -65,10 +65,9 @@ func canExitQueue(c *cli.Command, validatorIndex uint32) (*api.CanExitQueueRespo gasInfo, err := mp.EstimateDequeueGas(validatorIndex, opts) if err != nil { return nil, err - } else { - response.GasInfo = gasInfo - response.CanExit = true } + response.GasInfo = gasInfo + response.CanExit = true return &response, nil diff --git a/rocketpool/api/megapool/routes.go b/rocketpool/api/megapool/routes.go index 3e6e5523b..43612511b 100644 --- a/rocketpool/api/megapool/routes.go +++ b/rocketpool/api/megapool/routes.go @@ -381,20 +381,6 @@ func parseUint32(r *http.Request, name string) (uint32, error) { return uint32(v), err } -func parseAddress(r *http.Request, name string) (common.Address, error) { - raw := r.URL.Query().Get(name) - if raw == "" { - raw = r.FormValue(name) - } - if raw == "" { - return common.Address{}, &apiutils.BadRequestError{Err: fmt.Errorf("missing required parameter '%s'", name)} - } - if !common.IsHexAddress(raw) { - return common.Address{}, &apiutils.BadRequestError{Err: fmt.Errorf("invalid %s: %s", name, raw)} - } - return common.HexToAddress(raw), nil -} - func parseBool(r *http.Request, name string) (bool, error) { raw := r.URL.Query().Get(name) if raw == "" { diff --git a/rocketpool/api/node/set-timezone.go b/rocketpool/api/node/set-timezone.go index 9a2a95105..520b40ff1 100644 --- a/rocketpool/api/node/set-timezone.go +++ b/rocketpool/api/node/set-timezone.go @@ -1,7 +1,7 @@ package node import ( - _ "time/tzdata" + _ "time/tzdata" // Load the embedded tz data "github.com/ethereum/go-ethereum/accounts/abi/bind" diff --git a/rocketpool/api/node/sign-message.go b/rocketpool/api/node/sign-message.go index 9fc08eb37..0e2dc2bf5 100644 --- a/rocketpool/api/node/sign-message.go +++ b/rocketpool/api/node/sign-message.go @@ -3,7 +3,6 @@ package node import ( "encoding/hex" "fmt" - _ "time/tzdata" "github.com/urfave/cli/v3" diff --git a/rocketpool/api/node/sign.go b/rocketpool/api/node/sign.go index b1065d22a..043db404c 100644 --- a/rocketpool/api/node/sign.go +++ b/rocketpool/api/node/sign.go @@ -3,7 +3,7 @@ package node import ( "encoding/hex" "fmt" - _ "time/tzdata" + _ "time/tzdata" // Must be imported somewhere for the embedded tz data to load "github.com/urfave/cli/v3" diff --git a/rocketpool/api/node/smoothing-pool.go b/rocketpool/api/node/smoothing-pool.go index a1bc9d6b7..16c6d4e95 100644 --- a/rocketpool/api/node/smoothing-pool.go +++ b/rocketpool/api/node/smoothing-pool.go @@ -178,7 +178,7 @@ func setSmoothingPoolStatus(c *cli.Command, status bool, opts *bind.TransactOpts } // 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) + _ = validator.RestartValidator(cfg, bc, nil, d) 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/swap-rpl.go b/rocketpool/api/node/swap-rpl.go index 74e2d2dbb..668dc439d 100644 --- a/rocketpool/api/node/swap-rpl.go +++ b/rocketpool/api/node/swap-rpl.go @@ -168,10 +168,8 @@ func approveFsRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) ( } // Approve fixed-supply RPL allowance - if hash, err := tokens.ApproveFixedSupplyRPL(rp, *rocketTokenRPLAddress, amountWei, opts); err != nil { + if response.ApproveTxHash, err = tokens.ApproveFixedSupplyRPL(rp, *rocketTokenRPLAddress, amountWei, opts); err != nil { return nil, err - } else { - response.ApproveTxHash = hash } // Return response @@ -218,10 +216,8 @@ func swapRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api. response := api.NodeSwapRplSwapResponse{} // Swap fixed-supply RPL for RPL - if hash, err := tokens.SwapFixedSupplyRPLForRPL(rp, amountWei, opts); err != nil { + if response.SwapTxHash, err = tokens.SwapFixedSupplyRPLForRPL(rp, amountWei, opts); err != nil { return nil, err - } else { - response.SwapTxHash = hash } // Return response diff --git a/rocketpool/api/odao/routes.go b/rocketpool/api/odao/routes.go index 55de36b6b..91dbd26e4 100644 --- a/rocketpool/api/odao/routes.go +++ b/rocketpool/api/odao/routes.go @@ -325,17 +325,17 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/odao/can-propose-members-minipool-unbonded-max", func(w http.ResponseWriter, r *http.Request) { - max, err := parseUint64(r, "max") + m, err := parseUint64(r, "max") if err != nil { apiutils.WriteErrorResponse(w, err) return } - resp, err := canProposeSettingMinipoolUnbondedMax(c, max) + resp, err := canProposeSettingMinipoolUnbondedMax(c, m) apiutils.WriteResponse(w, resp, err) }) mux.HandleFunc("/api/odao/propose-members-minipool-unbonded-max", func(w http.ResponseWriter, r *http.Request) { - max, err := parseUint64(r, "max") + m, err := parseUint64(r, "max") if err != nil { apiutils.WriteErrorResponse(w, err) return @@ -345,7 +345,7 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingMinipoolUnbondedMax(c, max, opts) + resp, err := proposeSettingMinipoolUnbondedMax(c, m, opts) apiutils.WriteResponse(w, resp, err) }) diff --git a/rocketpool/api/pdao/claimable-bonds.go b/rocketpool/api/pdao/claimable-bonds.go index abaec7d25..4e56fadca 100644 --- a/rocketpool/api/pdao/claimable-bonds.go +++ b/rocketpool/api/pdao/claimable-bonds.go @@ -4,7 +4,6 @@ import ( "fmt" "math/big" "sort" - "time" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" @@ -12,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/utils/state" "github.com/rocket-pool/smartnode/shared/services" - "github.com/rocket-pool/smartnode/shared/services/beacon" "github.com/rocket-pool/smartnode/shared/types/api" "github.com/urfave/cli/v3" ) @@ -279,22 +277,3 @@ func isRewardedIndex(defeatIndex uint64, nodeIndex uint64) bool { } return false } - -func getElBlockForTimestamp(bc beacon.Client, beaconCfg beacon.Eth2Config, creationTime time.Time) (*big.Int, error) { - // Get the slot number the first proposal was created on - genesisTime := time.Unix(int64(beaconCfg.GenesisTime), 0) - secondsPerSlot := time.Second * time.Duration(beaconCfg.SecondsPerSlot) - startSlot := uint64(creationTime.Sub(genesisTime) / secondsPerSlot) - - // Get the Beacon block for the slot - block, exists, err := bc.GetBeaconBlock(fmt.Sprint(startSlot)) - if err != nil { - return nil, fmt.Errorf("error getting Beacon block at slot %d: %w", startSlot, err) - } - if !exists { - return nil, fmt.Errorf("Beacon block at slot %d was missing", startSlot) - } - - // Get the EL block for this slot - return big.NewInt(int64(block.ExecutionBlockNumber)), nil -} diff --git a/rocketpool/api/pdao/status.go b/rocketpool/api/pdao/status.go index 2b9967442..d0df70399 100644 --- a/rocketpool/api/pdao/status.go +++ b/rocketpool/api/pdao/status.go @@ -226,7 +226,9 @@ func GetSnapshotVotedProposals(apiDomain string, space string, nodeAddress commo if err != nil { return nil, err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() // Check the response code if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("request failed with code %d", resp.StatusCode) @@ -275,7 +277,9 @@ func GetSnapshotProposals(apiDomain string, space string, state string) (*api.Sn if err != nil { return nil, err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() // Check the response code if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("request failed with code %d", resp.StatusCode) @@ -317,7 +321,9 @@ func GetSnapshotVotingPower(apiDomain string, space string, nodeAddress common.A if err != nil { return nil, err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() // Check the response code if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("request failed with code %d", resp.StatusCode) diff --git a/rocketpool/api/queue/assign-deposits.go b/rocketpool/api/queue/assign-deposits.go index 014e527a9..69c9496d1 100644 --- a/rocketpool/api/queue/assign-deposits.go +++ b/rocketpool/api/queue/assign-deposits.go @@ -13,7 +13,7 @@ import ( "github.com/rocket-pool/smartnode/shared/types/api" ) -func canAssignDeposits(c *cli.Command, max int64) (*api.CanAssignDepositsResponse, error) { +func canAssignDeposits(c *cli.Command, m int64) (*api.CanAssignDepositsResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -52,7 +52,7 @@ func canAssignDeposits(c *cli.Command, max int64) (*api.CanAssignDepositsRespons if err != nil { return err } - gasInfo, err := deposit.EstimateAssignDepositsGas(rp, big.NewInt(max), opts) + gasInfo, err := deposit.EstimateAssignDepositsGas(rp, big.NewInt(m), opts) if err == nil { response.GasInfo = gasInfo } @@ -69,7 +69,7 @@ func canAssignDeposits(c *cli.Command, max int64) (*api.CanAssignDepositsRespons } -func assignDeposits(c *cli.Command, max int64, opts *bind.TransactOpts) (*api.AssignDepositsResponse, error) { +func assignDeposits(c *cli.Command, m int64, opts *bind.TransactOpts) (*api.AssignDepositsResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -87,7 +87,7 @@ func assignDeposits(c *cli.Command, max int64, opts *bind.TransactOpts) (*api.As response := api.AssignDepositsResponse{} // Assign deposits - hash, err := deposit.AssignDeposits(rp, big.NewInt(max), opts) + hash, err := deposit.AssignDeposits(rp, big.NewInt(m), opts) if err != nil { return nil, err } diff --git a/rocketpool/api/queue/process.go b/rocketpool/api/queue/process.go index 2845a3ddf..89a270041 100644 --- a/rocketpool/api/queue/process.go +++ b/rocketpool/api/queue/process.go @@ -13,7 +13,7 @@ import ( "github.com/rocket-pool/smartnode/shared/types/api" ) -func canProcessQueue(c *cli.Command, max int64) (*api.CanProcessQueueResponse, error) { +func canProcessQueue(c *cli.Command, m int64) (*api.CanProcessQueueResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -52,7 +52,7 @@ func canProcessQueue(c *cli.Command, max int64) (*api.CanProcessQueueResponse, e if err != nil { return err } - gasInfo, err := deposit.EstimateAssignDepositsGas(rp, big.NewInt(max), opts) + gasInfo, err := deposit.EstimateAssignDepositsGas(rp, big.NewInt(m), opts) if err == nil { response.GasInfo = gasInfo } @@ -70,7 +70,7 @@ func canProcessQueue(c *cli.Command, max int64) (*api.CanProcessQueueResponse, e } -func processQueue(c *cli.Command, max int64, opts *bind.TransactOpts) (*api.ProcessQueueResponse, error) { +func processQueue(c *cli.Command, m int64, opts *bind.TransactOpts) (*api.ProcessQueueResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -88,7 +88,7 @@ func processQueue(c *cli.Command, max int64, opts *bind.TransactOpts) (*api.Proc response := api.ProcessQueueResponse{} // Process queue - hash, err := deposit.AssignDeposits(rp, big.NewInt(max), opts) + hash, err := deposit.AssignDeposits(rp, big.NewInt(m), opts) if err != nil { return nil, err diff --git a/rocketpool/api/queue/routes.go b/rocketpool/api/queue/routes.go index 2a0e662d9..198572b5d 100644 --- a/rocketpool/api/queue/routes.go +++ b/rocketpool/api/queue/routes.go @@ -18,17 +18,17 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/queue/can-process", func(w http.ResponseWriter, r *http.Request) { - max, err := parseUint32Param(r, "max") + m, err := parseUint32Param(r, "max") if err != nil { apiutils.WriteErrorResponse(w, err) return } - resp, err := canProcessQueue(c, int64(max)) + resp, err := canProcessQueue(c, int64(m)) apiutils.WriteResponse(w, resp, err) }) mux.HandleFunc("/api/queue/process", func(w http.ResponseWriter, r *http.Request) { - max, err := parseUint32Param(r, "max") + m, err := parseUint32Param(r, "max") if err != nil { apiutils.WriteErrorResponse(w, err) return @@ -38,7 +38,7 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := processQueue(c, int64(max), opts) + resp, err := processQueue(c, int64(m), opts) apiutils.WriteResponse(w, resp, err) }) @@ -48,17 +48,17 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/queue/can-assign-deposits", func(w http.ResponseWriter, r *http.Request) { - max, err := parseUint32Param(r, "max") + m, err := parseUint32Param(r, "max") if err != nil { apiutils.WriteErrorResponse(w, err) return } - resp, err := canAssignDeposits(c, int64(max)) + resp, err := canAssignDeposits(c, int64(m)) apiutils.WriteResponse(w, resp, err) }) mux.HandleFunc("/api/queue/assign-deposits", func(w http.ResponseWriter, r *http.Request) { - max, err := parseUint32Param(r, "max") + m, err := parseUint32Param(r, "max") if err != nil { apiutils.WriteErrorResponse(w, err) return @@ -68,7 +68,7 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := assignDeposits(c, int64(max), opts) + resp, err := assignDeposits(c, int64(m), opts) apiutils.WriteResponse(w, resp, err) }) } diff --git a/rocketpool/api/upgrade/status.go b/rocketpool/api/upgrade/status.go deleted file mode 100644 index 61c1d29e0..000000000 --- a/rocketpool/api/upgrade/status.go +++ /dev/null @@ -1,56 +0,0 @@ -package upgrade - -import ( - "github.com/rocket-pool/smartnode/bindings/dao/upgrades" - "github.com/urfave/cli/v3" - "golang.org/x/sync/errgroup" - - "github.com/rocket-pool/smartnode/shared/services" - "github.com/rocket-pool/smartnode/shared/types/api" -) - -func getStatus(c *cli.Command) (*api.TNDAOUpgradeStatusResponse, error) { - - // Get services - if err := services.RequireNodeWallet(c); err != nil { - return nil, err - } - if err := services.RequireRocketStorage(c); err != nil { - return nil, err - } - rp, err := services.GetRocketPool(c) - if err != nil { - return nil, err - } - - // Response - response := api.TNDAOUpgradeStatusResponse{} - - // Sync - var wg errgroup.Group - - // Get upgrade proposal count - upgradeProposalCount, err := upgrades.GetTotalUpgradeProposals(rp, nil) - if err != nil { - return nil, err - } - response.UpgradeProposalCount = upgradeProposalCount - - // // Get upgrade proposal state - // wg.Go(func() error { - // upgradeProposalStates, err := getUpgradeProposalStates(rp) - // if err == nil { - // response.UpgradeProposalState = upgradeProposalState.String() - // } - // return err - // }) - - // Wait for data - if err := wg.Wait(); err != nil { - return nil, err - } - - // Return response - return &response, nil - -} diff --git a/rocketpool/api/upgrade/utils.go b/rocketpool/api/upgrade/utils.go deleted file mode 100644 index 7a8ab7d2e..000000000 --- a/rocketpool/api/upgrade/utils.go +++ /dev/null @@ -1,55 +0,0 @@ -package upgrade - -import ( - "github.com/rocket-pool/smartnode/bindings/dao" - "github.com/rocket-pool/smartnode/bindings/dao/upgrades" - "github.com/rocket-pool/smartnode/bindings/rocketpool" - rptypes "github.com/rocket-pool/smartnode/bindings/types" - "golang.org/x/sync/errgroup" -) - -// Settings -const UpgradeProposalStatesBatchSize = 50 - -// Get all proposal states -func getUpgradeProposalStates(rp *rocketpool.RocketPool) ([]rptypes.UpgradeProposalState, error) { - - // Get proposal IDs - proposalIds, err := dao.GetDAOProposalIDs(rp, "rocketDAONodeTrustedProposals", nil) - if err != nil { - return []rptypes.UpgradeProposalState{}, err - } - - // Load proposal states in batches - states := make([]rptypes.UpgradeProposalState, len(proposalIds)) - for bsi := 0; bsi < len(proposalIds); bsi += UpgradeProposalStatesBatchSize { - - // Get batch start & end index - psi := bsi - pei := bsi + UpgradeProposalStatesBatchSize - if pei > len(proposalIds) { - pei = len(proposalIds) - } - - // Load states - var wg errgroup.Group - for pi := psi; pi < pei; pi++ { - pi := pi - wg.Go(func() error { - proposalState, err := upgrades.GetUpgradeProposalState(rp, proposalIds[pi], nil) - if err == nil { - states[pi] = proposalState - } - return err - }) - } - if err := wg.Wait(); err != nil { - return []rptypes.UpgradeProposalState{}, err - } - - } - - // Return - return states, nil - -} diff --git a/rocketpool/api/wallet/init.go b/rocketpool/api/wallet/init.go index 19bd1167c..e3454ca38 100644 --- a/rocketpool/api/wallet/init.go +++ b/rocketpool/api/wallet/init.go @@ -10,10 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/types/api" ) -func initWallet(c *cli.Command) (*api.InitWalletResponse, error) { - return initWalletWithPath(c, c.String("derivation-path")) -} - func initWalletWithPath(c *cli.Command, derivationPath string) (*api.InitWalletResponse, error) { // Get services diff --git a/rocketpool/api/wallet/recover.go b/rocketpool/api/wallet/recover.go index 5bfee2262..7c1e938b0 100644 --- a/rocketpool/api/wallet/recover.go +++ b/rocketpool/api/wallet/recover.go @@ -18,10 +18,6 @@ const ( findIterations uint = 100000 ) -func recoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletResponse, error) { - return recoverWalletWithParams(c, mnemonic, c.Bool("skip-validator-key-recovery"), c.String("derivation-path"), c.Uint("wallet-index")) -} - func recoverWalletWithParams(c *cli.Command, mnemonic string, skipValidatorKeyRecovery bool, derivationPath string, walletIndex uint) (*api.RecoverWalletResponse, error) { // Get services @@ -92,10 +88,6 @@ func recoverWalletWithParams(c *cli.Command, mnemonic string, skipValidatorKeyRe } -func searchAndRecoverWallet(c *cli.Command, mnemonic string, address common.Address) (*api.SearchAndRecoverWalletResponse, error) { - return searchAndRecoverWalletWithParams(c, mnemonic, address, c.Bool("skip-validator-key-recovery")) -} - func searchAndRecoverWalletWithParams(c *cli.Command, mnemonic string, address common.Address, skipValidatorKeyRecovery bool) (*api.SearchAndRecoverWalletResponse, error) { // Get services diff --git a/rocketpool/api/wallet/test.go b/rocketpool/api/wallet/test.go index 639e819aa..f8bb981b5 100644 --- a/rocketpool/api/wallet/test.go +++ b/rocketpool/api/wallet/test.go @@ -13,10 +13,6 @@ import ( walletutils "github.com/rocket-pool/smartnode/shared/utils/wallet" ) -func testRecoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletResponse, error) { - return testRecoverWalletWithParams(c, mnemonic, c.Bool("skip-validator-key-recovery"), c.String("derivation-path"), c.Uint("wallet-index")) -} - func testRecoverWalletWithParams(c *cli.Command, mnemonic string, skipValidatorKeyRecovery bool, derivationPath string, walletIndex uint) (*api.RecoverWalletResponse, error) { // Get services @@ -85,10 +81,6 @@ func testRecoverWalletWithParams(c *cli.Command, mnemonic string, skipValidatorK } -func testSearchAndRecoverWallet(c *cli.Command, mnemonic string, address common.Address) (*api.SearchAndRecoverWalletResponse, error) { - return testSearchAndRecoverWalletWithParams(c, mnemonic, address, c.Bool("skip-validator-key-recovery")) -} - func testSearchAndRecoverWalletWithParams(c *cli.Command, mnemonic string, address common.Address, skipValidatorKeyRecovery bool) (*api.SearchAndRecoverWalletResponse, error) { // Get services diff --git a/rocketpool/node/collectors/demand-collector.go b/rocketpool/node/collectors/demand-collector.go index 6abe3d33e..7e9d1c956 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/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/bindings/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/governance-collector.go b/rocketpool/node/collectors/governance-collector.go index c6f42c64a..f6fff4077 100644 --- a/rocketpool/node/collectors/governance-collector.go +++ b/rocketpool/node/collectors/governance-collector.go @@ -85,13 +85,13 @@ func (collector *GovernanceCollector) Collect(channel chan<- prometheus.Metric) for _, proposal := range onchainProposals { switch proposal.State { case types.ProtocolDaoProposalState_Pending: - onchainPending += 1 + onchainPending++ case types.ProtocolDaoProposalState_ActivePhase1: - onchainPhase1 += 1 + onchainPhase1++ case types.ProtocolDaoProposalState_ActivePhase2: - onchainPhase2 += 1 + onchainPhase2++ default: - onchainClosed += 1 + onchainClosed++ } } return err diff --git a/rocketpool/node/collectors/node-collector.go b/rocketpool/node/collectors/node-collector.go index 36a3c21fc..f76f3015e 100644 --- a/rocketpool/node/collectors/node-collector.go +++ b/rocketpool/node/collectors/node-collector.go @@ -561,11 +561,10 @@ func (collector *NodeCollector) Collect(channel chan<- prometheus.Metric) { // NOTE: returning here causes the metric to not be emitted. the endpoint stays responsive, but also slightly more accurate (progress=nothing instead of 0) fmt.Printf("error getting beacon chain sync status: %s", err.Error()) return nil - } else { - progress = syncStatus.Progress - if !syncStatus.Syncing { - progress = 1.0 - } + } + progress = syncStatus.Progress + if !syncStatus.Syncing { + progress = 1.0 } // note this metric is emitted asynchronously, while others in this file tend to be emitted at the end of the outer function (mostly due to dependencies between metrics). See https://github.com/rocket-pool/smartnode/issues/186 channel <- prometheus.MustNewConstMetric( diff --git a/rocketpool/node/collectors/odao-collector.go b/rocketpool/node/collectors/odao-collector.go index 28c8d45b3..c7c1863cd 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/smartnode/bindings/rocketpool" ) @@ -83,8 +81,3 @@ func (collector *OdaoCollector) Collect(channel chan<- prometheus.Metric) { channel <- prometheus.MustNewConstMetric( collector.effectiveRplStakeBlock, prometheus.GaugeValue, effectiveRplStakeBlockFloat) } - -// 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 c64681e32..9a4954ec3 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/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/bindings/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 268b1d38d..a9bee3939 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/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/bindings/utils/eth" @@ -119,8 +117,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 4493c89dd..7e3f8e737 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/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/bindings/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/collectors/snapshot-collector.go b/rocketpool/node/collectors/snapshot-collector.go index 99ef3491e..1dc651c8c 100644 --- a/rocketpool/node/collectors/snapshot-collector.go +++ b/rocketpool/node/collectors/snapshot-collector.go @@ -151,9 +151,9 @@ func (collector *SnapshotCollector) Collect(channel chan<- prometheus.Metric) { for _, proposal := range proposals.Data.Proposals { if proposal.State == "active" { - activeProposals += 1 + activeProposals++ } else { - closedProposals += 1 + closedProposals++ } } collector.cachedActiveProposals = activeProposals @@ -287,9 +287,9 @@ func (collector *SnapshotCollector) collectVotes(votedProposals *api.SnapshotVot _, exists := handledProposals[votedProposal.Proposal.Id] if !exists { if votedProposal.Proposal.State == "active" { - votesActiveProposals += 1 + votesActiveProposals++ } else { - votesClosedProposals += 1 + votesClosedProposals++ } handledProposals[votedProposal.Proposal.Id] = true } diff --git a/rocketpool/node/defend-challenge-exit.go b/rocketpool/node/defend-challenge-exit.go index 776687464..f7578b704 100644 --- a/rocketpool/node/defend-challenge-exit.go +++ b/rocketpool/node/defend-challenge-exit.go @@ -157,7 +157,10 @@ func (t *defendChallengeExit) run(state *state.NetworkState) error { t.log.Printlnf("The validator %d was incorrectly challenged and needs a not-exiting proof", validatorInfo[i].ValidatorId) } - t.defendChallenge(t.rp, mp, validatorInfo[i].ValidatorId, state, types.ValidatorPubkey(validatorInfo[i].PubKey), exiting, opts) + err := t.defendChallenge(t.rp, mp, validatorInfo[i].ValidatorId, state, types.ValidatorPubkey(validatorInfo[i].PubKey), exiting, opts) + if err != nil { + t.log.Printlnf("error defending the challenge: %v", err) + } } } diff --git a/rocketpool/node/distribute-minipools.go b/rocketpool/node/distribute-minipools.go index 2a4078191..2dc9577a7 100644 --- a/rocketpool/node/distribute-minipools.go +++ b/rocketpool/node/distribute-minipools.go @@ -163,7 +163,10 @@ func (t *distributeMinipools) run(state *state.NetworkState) error { successCount := 0 for _, mpd := range minipools { success, err := t.distributeMinipool(mpd, opts) - alerting.AlertMinipoolBalanceDistributed(t.cfg, mpd.MinipoolAddress, err == nil) + err = alerting.AlertMinipoolBalanceDistributed(t.cfg, mpd.MinipoolAddress, err == nil) + if err != nil { + t.log.Printlnf("error alerting minipool balance distributed: %v", err) + } if err != nil { t.log.Println(fmt.Errorf("Could not distribute balance of minipool %s: %w", mpd.MinipoolAddress.Hex(), err)) return err diff --git a/rocketpool/node/http.go b/rocketpool/node/http.go index f6a62831f..3fa950ab9 100644 --- a/rocketpool/node/http.go +++ b/rocketpool/node/http.go @@ -13,11 +13,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services/config" ) -type httpServer struct { - server *http.Server - mux *http.ServeMux -} - // statusRecorder wraps http.ResponseWriter to capture the written status code. type statusRecorder struct { http.ResponseWriter diff --git a/rocketpool/node/manage-fee-recipient.go b/rocketpool/node/manage-fee-recipient.go index 6d1096ba8..6d52e79f4 100644 --- a/rocketpool/node/manage-fee-recipient.go +++ b/rocketpool/node/manage-fee-recipient.go @@ -115,7 +115,10 @@ func (m *manageFeeRecipient) run(state *state.NetworkState) error { m.log.Printlnf("WARNING: Fee recipient files did not contain the correct fee recipient of %s, regenerating...", correctFeeRecipient.Hex()) // Regenerate the fee recipient files err = rpsvc.UpdateGlobalFeeRecipientFile(correctFeeRecipient, m.cfg) - alerting.AlertFeeRecipientChanged(m.cfg, correctFeeRecipient, err == nil) + err = alerting.AlertFeeRecipientChanged(m.cfg, correctFeeRecipient, err == nil) + if err != nil { + m.log.Printlnf("error alerting fee recipient changed: %v", err) + } if err != nil { m.log.Println("***ERROR***") m.log.Printlnf("Error updating fee recipient files: %s", err.Error()) diff --git a/rocketpool/node/metrics-exporter.go b/rocketpool/node/metrics-exporter.go index f9fb13f30..8cab237ec 100644 --- a/rocketpool/node/metrics-exporter.go +++ b/rocketpool/node/metrics-exporter.go @@ -109,7 +109,7 @@ func runMetricsServer(ctx context.Context, c *cli.Command, logger log.ColorLogge mux := http.NewServeMux() mux.Handle(metricsPath, handler) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(` + _, err := w.Write([]byte(` Rocket Pool Metrics Exporter

Rocket Pool Metrics Exporter

@@ -117,6 +117,9 @@ func runMetricsServer(ctx context.Context, c *cli.Command, logger log.ColorLogge `, )) + if err != nil { + logger.Printlnf("Error writing metrics exporter HTML: %v", err) + } }) srv := &http.Server{ Addr: fmt.Sprintf("%s:%d", metricsAddress, metricsPort), diff --git a/rocketpool/node/node.go b/rocketpool/node/node.go index 3670d6163..8322bcca9 100644 --- a/rocketpool/node/node.go +++ b/rocketpool/node/node.go @@ -2,7 +2,6 @@ package node import ( "context" - _ "embed" "fmt" "math/big" "net/http" @@ -243,7 +242,10 @@ func run(c *cli.Command) error { if !wasExecutionClientSynced { updateLog.Println("Execution client is now synced.") wasExecutionClientSynced = true - alerting.AlertExecutionClientSyncComplete(cfg) + err := alerting.AlertExecutionClientSyncComplete(cfg) + if err != nil { + errorLog.Printlnf("error alerting execution client sync complete: %v", err) + } } // Check the BC status @@ -261,7 +263,10 @@ func run(c *cli.Command) error { if !wasBeaconClientSynced { updateLog.Println("Beacon client is now synced.") wasBeaconClientSynced = true - alerting.AlertBeaconClientSyncComplete(cfg) + err := alerting.AlertBeaconClientSyncComplete(cfg) + if err != nil { + errorLog.Printlnf("error alerting beacon client sync complete: %v", err) + } } // Check if the protocol version has changed @@ -519,7 +524,6 @@ func GetPriorityFee(priorityFee *big.Int, maxFee *big.Int) *big.Int { // Gets the min(priorityFee, 25% of the oracle based maxFee) if priorityFee.Cmp(quarterMaxFee) < 0 { return priorityFee - } else { - return quarterMaxFee } + return quarterMaxFee } diff --git a/rocketpool/node/prestake-megapool-validator.go b/rocketpool/node/prestake-megapool-validator.go index bf10512d7..8f5c26c3e 100644 --- a/rocketpool/node/prestake-megapool-validator.go +++ b/rocketpool/node/prestake-megapool-validator.go @@ -154,7 +154,11 @@ func (t *prestakeMegapoolValidator) run(state *state.NetworkState) error { // Check if the assignment is possible if nextAssignment.AssignmentPossible { // Call assign - t.assignDeposit(nil) + err := t.assignDeposit(nil) + if err != nil { + t.log.Printlnf("error assigning the deposit: %v", err) + return err + } } } else { t.log.Printlnf("Time left until the automatic stake %s", remainingTime) diff --git a/rocketpool/node/set-latest-delegate.go b/rocketpool/node/set-latest-delegate.go index acc974edc..2341a1f99 100644 --- a/rocketpool/node/set-latest-delegate.go +++ b/rocketpool/node/set-latest-delegate.go @@ -138,7 +138,10 @@ func (t *setUseLatestDelegate) run(state *state.NetworkState) error { // If the node has been running for less than 24 hours, alert the user. After that, set the flag for the minipools. if time.Since(t.startTime) < 24*time.Hour { t.log.Println("Alerting user they have minipools that can have the 'use latest delegate' flag set...") - alerting.AlertMinipoolUseLatestDelegateSet(t.cfg) + err := alerting.AlertMinipoolUseLatestDelegateSet(t.cfg) + if err != nil { + t.log.Printlnf("error alerting user they have minipools that can have the 'use latest delegate' flag set: %v", err) + } return nil } diff --git a/rocketpool/watchtower/check-solo-migrations.go b/rocketpool/watchtower/check-solo-migrations.go index 1275d809b..8ed2e041e 100644 --- a/rocketpool/watchtower/check-solo-migrations.go +++ b/rocketpool/watchtower/check-solo-migrations.go @@ -169,20 +169,20 @@ func (t *checkSoloMigrations) checkSoloMigrations(state *state.NetworkState) err continue } - totalCount += 1 + totalCount++ // Scrub minipools that aren't seen on Beacon yet validator := state.MinipoolValidatorDetails[mpd.Pubkey] if !validator.Exists { t.scrubVacantMinipool(mpd.MinipoolAddress, fmt.Sprintf("minipool %s (pubkey %s) did not exist on Beacon yet, but is required to be active_ongoing for migration", mpd.MinipoolAddress.Hex(), mpd.Pubkey.Hex())) - doesntExistCount += 1 + doesntExistCount++ continue } // Scrub minipools that are in the wrong state if validator.Status != beacon.ValidatorState_ActiveOngoing { t.scrubVacantMinipool(mpd.MinipoolAddress, fmt.Sprintf("minipool %s (pubkey %s) was in state %v, but is required to be active_ongoing for migration", mpd.MinipoolAddress.Hex(), mpd.Pubkey.Hex(), validator.Status)) - invalidStateCount += 1 + invalidStateCount++ continue } @@ -194,19 +194,19 @@ func (t *checkSoloMigrations) checkSoloMigrations(state *state.NetworkState) err remainingTime := creationTime.Add(scrubThreshold).Sub(blockTime) if remainingTime < 0 { t.scrubVacantMinipool(mpd.MinipoolAddress, fmt.Sprintf("minipool timed out (created %s, current time %s, scrubbed after %s)", creationTime, blockTime, scrubThreshold)) - timedOutCount += 1 + timedOutCount++ continue } continue case elPrefix: if withdrawalCreds != mpd.WithdrawalCredentials { t.scrubVacantMinipool(mpd.MinipoolAddress, fmt.Sprintf("withdrawal credentials do not match (expected %s, actual %s)", mpd.WithdrawalCredentials.Hex(), withdrawalCreds.Hex())) - invalidCredentialsCount += 1 + invalidCredentialsCount++ continue } default: t.scrubVacantMinipool(mpd.MinipoolAddress, fmt.Sprintf("unexpected prefix in withdrawal credentials: %s", withdrawalCreds.Hex())) - invalidCredentialsCount += 1 + invalidCredentialsCount++ continue } @@ -220,12 +220,12 @@ func (t *checkSoloMigrations) checkSoloMigrations(state *state.NetworkState) err if currentBalance < threshold { t.scrubVacantMinipool(mpd.MinipoolAddress, fmt.Sprintf("current balance of %d is lower than the threshold of %d", currentBalance, threshold)) - balanceTooLowCount += 1 + balanceTooLowCount++ continue } if currentBalance < (creationBalanceGwei - buffer) { t.scrubVacantMinipool(mpd.MinipoolAddress, fmt.Sprintf("current balance of %d is lower than the creation balance of %d, and below the acceptable buffer threshold of %d", currentBalance, creationBalanceGwei, buffer)) - balanceTooLowCount += 1 + balanceTooLowCount++ continue } diff --git a/rocketpool/watchtower/constants.go b/rocketpool/watchtower/constants.go index f419f87e4..e118640ce 100644 --- a/rocketpool/watchtower/constants.go +++ b/rocketpool/watchtower/constants.go @@ -1,9 +1,5 @@ package watchtower -import "time" - const ( enableSubmissionAfterConsensus_Balances bool = true - - contextTimeout = 10 * time.Second ) diff --git a/rocketpool/watchtower/dissolve-invalid-credentials.go b/rocketpool/watchtower/dissolve-invalid-credentials.go index 12573af52..b36c55d24 100644 --- a/rocketpool/watchtower/dissolve-invalid-credentials.go +++ b/rocketpool/watchtower/dissolve-invalid-credentials.go @@ -2,7 +2,6 @@ package watchtower import ( "bytes" - "fmt" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/bindings/rocketpool" @@ -144,36 +143,40 @@ func (t *dissolveInvalidCredentials) dissolveInvalidCredentialValidators(state * return nil } -func (t *dissolveInvalidCredentials) dissolveMegapoolValidator(validator megapool.ValidatorInfoFromGlobalIndex) error { +func (t *dissolveInvalidCredentials) dissolveMegapoolValidator(validator megapool.ValidatorInfoFromGlobalIndex) { // Log t.log.Printlnf("Dissolving megapool validator ID: %d from megapool %s...", validator.ValidatorId, validator.MegapoolAddress) // Get transactor opts, err := t.w.GetNodeAccountTransactor() if err != nil { - return err + t.log.Printlnf("error getting the node account transactor: %v", err) + return } eth2Config, err := t.bc.GetEth2Config() if err != nil { - return err + t.log.Printlnf("error getting the eth2 config: %v", err) + return } validatorProof, slotTimestamp, slotProof, err := services.GetValidatorProof(t.c, 0, t.w, eth2Config, validator.MegapoolAddress, types.ValidatorPubkey(validator.Pubkey), nil) if err != nil { - return fmt.Errorf("error getting validator proof: %w", err) + t.log.Printlnf("error getting validator proof: %v", err) + return } // Get the gas limit gasInfo, err := megapool.EstimateDissolveWithProof(t.rp, validator.MegapoolAddress, validator.ValidatorId, slotTimestamp, validatorProof, slotProof, opts) if err != nil { - return fmt.Errorf("could not estimate the gas required to dissolve the validator: %w", err) + t.log.Printlnf("error estimating the gas required to dissolve the validator: %v", err) + return } // Print the gas info maxFee := eth.GweiToWei(utils.GetWatchtowerMaxFee(t.cfg)) if !api.PrintAndCheckGasInfo(gasInfo, false, 0, &t.log, maxFee, 0) { - return nil + return } // Set the gas settings @@ -184,18 +187,17 @@ func (t *dissolveInvalidCredentials) dissolveMegapoolValidator(validator megapoo // Dissolve tx, err := megapool.DissolveWithProof(t.rp, validator.MegapoolAddress, validator.ValidatorId, slotTimestamp, validatorProof, slotProof, opts) if err != nil { - return err + t.log.Printlnf("error dissolving the validator: %v", err) + return } // Print TX info and wait for it to be included in a block err = api.PrintAndWaitForTransaction(t.cfg, tx.Hash(), t.rp.Client, &t.log) if err != nil { - return err + t.log.Printlnf("error waiting for the transaction to be included in a block: %v", err) + return } // Log t.log.Printlnf("Successfully dissolved megapool validator ID: %s from megapool %s. (Invalid credentials)", validator.ValidatorId, validator.MegapoolAddress) - - // Return - return nil } diff --git a/rocketpool/watchtower/dissolve-timed-out-megapool-validators.go b/rocketpool/watchtower/dissolve-timed-out-megapool-validators.go index 2f645beae..b6e12d28e 100644 --- a/rocketpool/watchtower/dissolve-timed-out-megapool-validators.go +++ b/rocketpool/watchtower/dissolve-timed-out-megapool-validators.go @@ -91,7 +91,11 @@ func (t *dissolveTimedOutMegapoolValidators) dissolveMegapoolValidators(state *s assignTime := time.Unix(int64(validator.ValidatorInfo.LastAssignmentTime), 0) if time.Since(assignTime) >= time.Duration(timeBeforeDissolve)*time.Second { // dissolve - t.dissolveMegapoolValidator(validator) + err := t.dissolveMegapoolValidator(validator) + if err != nil { + t.log.Printlnf("error dissolving the validator: %v", err) + continue + } } } diff --git a/rocketpool/watchtower/metrics-exporter.go b/rocketpool/watchtower/metrics-exporter.go index c5658ce72..bc7692f3d 100644 --- a/rocketpool/watchtower/metrics-exporter.go +++ b/rocketpool/watchtower/metrics-exporter.go @@ -48,7 +48,7 @@ func runMetricsServer(c *cli.Command, logger log.ColorLogger, scrubCollector *co metricsPath := "/metrics" http.Handle(metricsPath, handler) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(` + _, err := w.Write([]byte(` Rocket Pool Watchtower Metrics Exporter

Rocket Pool Watchtower Metrics Exporter

@@ -56,6 +56,9 @@ func runMetricsServer(c *cli.Command, logger log.ColorLogger, scrubCollector *co `, )) + if err != nil { + logger.Printlnf("Error writing metrics exporter HTML: %v", err) + } }) err = http.ListenAndServe(fmt.Sprintf("%s:%d", metricsAddress, metricsPort), nil) if err != nil { diff --git a/rocketpool/watchtower/process-penalties.go b/rocketpool/watchtower/process-penalties.go deleted file mode 100644 index 4d5518107..000000000 --- a/rocketpool/watchtower/process-penalties.go +++ /dev/null @@ -1,539 +0,0 @@ -package watchtower - -import ( - "bytes" - "fmt" - "math/big" - "os" - "path/filepath" - "strconv" - "sync" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/rocket-pool/smartnode/bindings/dao/trustednode" - "github.com/rocket-pool/smartnode/bindings/minipool" - "github.com/rocket-pool/smartnode/bindings/network" - "github.com/rocket-pool/smartnode/bindings/node" - "github.com/rocket-pool/smartnode/bindings/rocketpool" - "github.com/rocket-pool/smartnode/bindings/utils/eth" - "github.com/rocket-pool/smartnode/shared/services/beacon" - "github.com/rocket-pool/smartnode/shared/services/config" - rpgas "github.com/rocket-pool/smartnode/shared/services/gas" - "github.com/rocket-pool/smartnode/shared/services/state" - "github.com/urfave/cli/v3" - "gopkg.in/yaml.v2" - - fee "github.com/rocket-pool/smartnode/rocketpool/node" - "github.com/rocket-pool/smartnode/shared/services" - "github.com/rocket-pool/smartnode/shared/services/wallet" - "github.com/rocket-pool/smartnode/shared/utils/api" - "github.com/rocket-pool/smartnode/shared/utils/log" -) - -// Number of slots to go back in time and scan for penalties if state is empty (400k is approx. 8 weeks) -const NewPenaltyScanBuffer = 400000 - -// Process withdrawals task -type processPenalties struct { - c *cli.Command - log log.ColorLogger - errLog log.ColorLogger - cfg *config.RocketPoolConfig - w wallet.Wallet - rp *rocketpool.RocketPool - ec rocketpool.ExecutionClient - bc beacon.Client - lock *sync.Mutex - isRunning bool - maxFee *big.Int - maxPriorityFee *big.Int - gasLimit uint64 - beaconConfig beacon.Eth2Config - m *state.NetworkStateManager - s *state.NetworkState -} - -type penaltyState struct { - LatestPenaltySlot uint64 `yaml:"latestPenaltySlot"` -} - -// Create process penalties task -func newProcessPenalties(c *cli.Command, logger log.ColorLogger, errorLogger log.ColorLogger, m *state.NetworkStateManager) (*processPenalties, error) { - // Get services - cfg, err := services.GetConfig(c) - if err != nil { - return nil, err - } - w, err := services.GetHdWallet(c) - if err != nil { - return nil, err - } - ec, err := services.GetEthClient(c) - if err != nil { - return nil, err - } - rp, err := services.GetRocketPool(c) - if err != nil { - return nil, err - } - bc, err := services.GetBeaconClient(c) - if err != nil { - return nil, err - } - - // Get the user-requested max fee - maxFeeGwei := cfg.Smartnode.ManualMaxFee.Value.(float64) - var maxFee *big.Int - if maxFeeGwei == 0 { - maxFee = nil - } else { - maxFee = eth.GweiToWei(maxFeeGwei) - } - - // Get the user-requested max fee - priorityFeeGwei := cfg.Smartnode.PriorityFee.Value.(float64) - var priorityFee *big.Int - if priorityFeeGwei == 0 { - logger.Printlnf("WARNING: priority fee was missing or 0, setting a default of %.2f.", rpgas.DefaultPriorityFeeGwei) - priorityFee = eth.GweiToWei(rpgas.DefaultPriorityFeeGwei) - } else { - priorityFee = eth.GweiToWei(priorityFeeGwei) - } - - // Get the Beacon config - beaconConfig, err := bc.GetEth2Config() - if err != nil { - return nil, err - } - - // Return task - lock := &sync.Mutex{} - return &processPenalties{ - c: c, - log: logger, - errLog: errorLogger, - cfg: cfg, - w: w, - ec: ec, - bc: bc, - rp: rp, - lock: lock, - isRunning: false, - maxFee: maxFee, - maxPriorityFee: priorityFee, - gasLimit: 0, - beaconConfig: beaconConfig, - m: m, - }, nil -} - -func stateFileExists(path string) bool { - // Check if file exists - _, err := os.Stat(path) - if os.IsNotExist(err) { - return false - } - if err != nil { - return false - } - - return true -} - -func (s *penaltyState) loadState(path string) (*penaltyState, error) { - - // Load file into memory - yamlFile, err := os.ReadFile(path) - if err != nil { - return s, err - } - - // Unmarshal into state object - err = yaml.Unmarshal(yamlFile, s) - if err != nil { - return s, err - } - - return s, nil -} - -func (s *penaltyState) saveState(path string) error { - // Marshal state object - data, err := yaml.Marshal(s) - - if err != nil { - return err - } - - // Write to disk - watchtowerDir := filepath.Dir(path) - err = os.MkdirAll(watchtowerDir, 0755) - if err != nil { - return fmt.Errorf("error creating watchtower directory: %w", err) - } - return os.WriteFile(path, data, 0644) -} - -// Process penalties -func (t *processPenalties) run() error { - - // Wait for eth clients to sync - if err := services.WaitEthClientSynced(t.c, true); err != nil { - return err - } - if err := services.WaitBeaconClientSynced(t.c, true); err != nil { - return err - } - - // Get node account - nodeAccount, err := t.w.GetNodeAccount() - if err != nil { - return err - } - - // Get trusted node status - nodeTrusted, err := trustednode.GetMemberExists(t.rp, nodeAccount.Address, nil) - if err != nil { - return err - } - if !(nodeTrusted) { - return nil - } - - // Log - t.log.Println("Checking for illegal fee recipients...") - - // Check if the check is already running - t.lock.Lock() - if t.isRunning { - t.log.Println("Fee recipient check is already running in the background.") - t.lock.Unlock() - return nil - } - t.lock.Unlock() - - // Run the check - go func() { - t.lock.Lock() - t.isRunning = true - t.lock.Unlock() - checkPrefix := "[Fee Recipients]" - - // Get the Smoothing Pool address - smoothingPoolContract, err := t.rp.GetContract("rocketSmoothingPool", nil) - if err != nil { - t.handleError(fmt.Errorf("%s Error getting smoothing pool contract: %w", checkPrefix, err)) - return - } - smoothingPoolAddress := *smoothingPoolContract.Address - - // Get latest block - head, headExists, err := t.bc.GetBeaconBlock("finalized") - if err != nil { - t.handleError(fmt.Errorf("%s Error getting beacon block: %w", checkPrefix, err)) - return - } - - currentSlot := head.Slot - - // Read state from file or create if this is the first run - watchtowerStatePath := t.cfg.Smartnode.GetWatchtowerStatePath() - var s penaltyState - - if stateFileExists(watchtowerStatePath) { - _, err := s.loadState(watchtowerStatePath) - if err != nil { - t.handleError(fmt.Errorf("%s Error loading watchtower state: %w", checkPrefix, err)) - return - } - } else { - // No state file so start from NewPenaltyScanBuffer slots ago - if currentSlot > NewPenaltyScanBuffer { - s.LatestPenaltySlot = currentSlot - NewPenaltyScanBuffer - } - } - - if currentSlot <= s.LatestPenaltySlot { - // Nothing to do - t.log.Printlnf("%s Finished checking for illegal fee recipients.", checkPrefix) - t.lock.Lock() - t.isRunning = false - t.lock.Unlock() - return - } - - t.log.Printlnf("Starting check in a separate thread at block %d", s.LatestPenaltySlot) - - // Loop over unprocessed slots - slotsSinceUpdate := 0 - for i := s.LatestPenaltySlot; i < currentSlot; i++ { - block, exists, err := t.bc.GetBeaconBlock(strconv.FormatUint(i, 10)) - if err != nil { - t.handleError(fmt.Errorf("%s Error getting beacon block: %w", checkPrefix, err)) - return - } - if exists { - illegalFeeRecipientFound, err := t.processBlock(&block, smoothingPoolAddress) - if illegalFeeRecipientFound { - s.LatestPenaltySlot = block.Slot - saveErr := s.saveState(watchtowerStatePath) - if saveErr != nil { - t.handleError(fmt.Errorf("%s Error saving watchtower state file: %w", checkPrefix, saveErr)) - return - } - } - if err != nil { - t.handleError(fmt.Errorf("%s %w", checkPrefix, err)) - return - } - } - - slotsSinceUpdate++ - if slotsSinceUpdate >= 10000 { - t.log.Printlnf("\t%s At block %d of %d...", checkPrefix, i, currentSlot) - slotsSinceUpdate = 0 - s.LatestPenaltySlot = block.Slot - err = s.saveState(watchtowerStatePath) - if err != nil { - t.handleError(fmt.Errorf("%s Error saving watchtower state file: %w", checkPrefix, err)) - return - } - } - } - - if headExists { - _, err = t.processBlock(&head, smoothingPoolAddress) - if err != nil { - t.handleError(fmt.Errorf("%s %w", checkPrefix, err)) - return - } - } - - // Update latest slot in state - s.LatestPenaltySlot = currentSlot - err = s.saveState(watchtowerStatePath) - if err != nil { - t.handleError(fmt.Errorf("%s Error saving watchtower state file: %w", checkPrefix, err)) - return - } - - t.log.Printlnf("%s Finished checking for illegal fee recipients.", checkPrefix) - t.lock.Lock() - t.isRunning = false - t.lock.Unlock() - }() - - // Return - return nil - -} - -func (t *processPenalties) handleError(err error) { - t.errLog.Println(err) - t.errLog.Println("*** Illegal fee recipient check failed. ***") - t.lock.Lock() - t.isRunning = false - t.lock.Unlock() -} - -func (t *processPenalties) processBlock(block *beacon.BeaconBlock, smoothingPoolAddress common.Address) (bool, error) { - - isIllegalFeeRecipient := false - - if !block.HasExecutionPayload { - // Merge hasn't occurred yet so skip - return isIllegalFeeRecipient, nil - } - - status, err := t.bc.GetValidatorStatusByIndex(block.ProposerIndex, nil) - if err != nil { - return isIllegalFeeRecipient, err - } - - // Get the minipool address from the proposer's pubkey - minipoolAddress, err := minipool.GetMinipoolByPubkey(t.rp, status.Pubkey, nil) - if err != nil { - return isIllegalFeeRecipient, err - } - - // A zero result indicates this proposer is not a RocketPool node operator - var emptyAddress [20]byte - if bytes.Equal(emptyAddress[:], minipoolAddress[:]) { - return isIllegalFeeRecipient, nil - } - - // Retrieve the node's distributor address - mp, err := minipool.NewMinipool(t.rp, minipoolAddress, nil) - if err != nil { - return isIllegalFeeRecipient, err - } - - nodeAddress, err := mp.GetNodeAddress(nil) - if err != nil { - return isIllegalFeeRecipient, err - } - - distributorAddress, err := node.GetDistributorAddress(t.rp, nodeAddress, nil) - if err != nil { - return isIllegalFeeRecipient, err - } - - // Retrieve the rETH address - rethAddress := t.cfg.Smartnode.GetRethAddress() - - // Ignore blocks that were sent to the smoothing pool - if smoothingPoolAddress != emptyAddress && block.FeeRecipient == smoothingPoolAddress { - return isIllegalFeeRecipient, nil - } - - // Ignore blocks that were sent to the rETH address - if block.FeeRecipient == rethAddress { - return isIllegalFeeRecipient, nil - } - - // Check if the user was opted into the smoothing pool for this block - opts := bind.CallOpts{ - BlockNumber: big.NewInt(int64(block.ExecutionBlockNumber)), - } - isOptedIn, err := node.GetSmoothingPoolRegistrationState(t.rp, nodeAddress, &opts) - if err != nil { - t.log.Printlnf("*** WARNING: Couldn't check if node %s was opted into the smoothing pool for slot %d (execution block %d), skipping check... error: %w\n***", nodeAddress.Hex(), block.Slot, block.ExecutionBlockNumber, err) - isOptedIn = false - } - - // Check for smoothing pool theft - if isOptedIn && block.FeeRecipient != smoothingPoolAddress { - t.log.Println("=== SMOOTHING POOL THEFT DETECTED ===") - t.log.Printlnf("Beacon Block: %d", block.Slot) - t.log.Printlnf("Minipool: %s", minipoolAddress.Hex()) - t.log.Printlnf("Node: %s", nodeAddress.Hex()) - t.log.Printlnf("FEE RECIPIENT: %s", block.FeeRecipient.Hex()) - t.log.Println("=====================================") - - isIllegalFeeRecipient = true - err = t.submitPenalty(minipoolAddress, block) - return isIllegalFeeRecipient, err - } - - // Make sure they didn't opt out in order to steal a block - if !isOptedIn { - // Get the opt out time - optOutTime, err := node.GetSmoothingPoolRegistrationChanged(t.rp, nodeAddress, &opts) - if err != nil { - t.log.Printlnf("*** WARNING: Couldn't check when node %s opted out of the smoothing pool for slot %d (execution block %d), skipping check... error: %w\n***", nodeAddress.Hex(), block.Slot, block.ExecutionBlockNumber, err) - } else if optOutTime != time.Unix(0, 0) { - // Get the time of the epoch before this one - blockEpoch := block.Slot / t.beaconConfig.SlotsPerEpoch - previousEpoch := blockEpoch - 1 - genesisTime := time.Unix(int64(t.beaconConfig.GenesisTime), 0) - epochStartTime := genesisTime.Add(time.Second * time.Duration(t.beaconConfig.SecondsPerEpoch*previousEpoch)) - - // If they opted out after the start of the previous epoch, they cheated - if optOutTime.Sub(epochStartTime) > 0 { - t.log.Println("=== SMOOTHING POOL THEFT DETECTED ===") - t.log.Printlnf("Beacon Block: %d", block.Slot) - t.log.Printlnf("Safe Opt Out Time: %s", epochStartTime) - t.log.Printlnf("ACTUAL OPT OUT TIME: %s", optOutTime) - t.log.Printlnf("Minipool: %s", minipoolAddress.Hex()) - t.log.Printlnf("Node: %s", nodeAddress.Hex()) - t.log.Printlnf("FEE RECIPIENT: %s", block.FeeRecipient.Hex()) - t.log.Println("=====================================") - - isIllegalFeeRecipient = true - err = t.submitPenalty(minipoolAddress, block) - return isIllegalFeeRecipient, err - } - } - } - - // Check for distributor address theft - if !isOptedIn && block.FeeRecipient != distributorAddress { - t.log.Println("=== ILLEGAL FEE RECIPIENT DETECTED ===") - t.log.Printlnf("Beacon Block: %d", block.Slot) - t.log.Printlnf("Minipool: %s", minipoolAddress.Hex()) - t.log.Printlnf("Node: %s", nodeAddress.Hex()) - t.log.Printlnf("Distributor: %s", distributorAddress.Hex()) - t.log.Printlnf("FEE RECIPIENT: %s", block.FeeRecipient.Hex()) - t.log.Println("======================================") - - isIllegalFeeRecipient = true - err = t.submitPenalty(minipoolAddress, block) - return isIllegalFeeRecipient, err - } - - // No cheating detected - return isIllegalFeeRecipient, nil - -} - -func (t *processPenalties) submitPenalty(minipoolAddress common.Address, block *beacon.BeaconBlock) error { - - // Check if this penalty has already been applied - blockNumberBuf := make([]byte, 32) - slotBig := big.NewInt(int64(block.Slot)) - slotBig.FillBytes(blockNumberBuf) - penaltyExecuted, err := t.rp.RocketStorage.GetBool(nil, crypto.Keccak256Hash([]byte("network.penalties.executed"), minipoolAddress.Bytes(), blockNumberBuf)) - if err != nil { - return fmt.Errorf("Could not check if penalty has already been applied for block %d, minipool %s: %w", block.Slot, minipoolAddress.Hex(), err) - } - if penaltyExecuted { - t.log.Printlnf("NOTE: Minipool %s was already penalized on block %d, skipping...", minipoolAddress.Hex(), block.Slot) - return nil - } - - // Get transactor - opts, err := t.w.GetNodeAccountTransactor() - if err != nil { - return err - } - - // Get the gas limit - gasInfo, err := network.EstimateSubmitPenaltyGas(t.rp, minipoolAddress, slotBig, opts) - if err != nil { - return fmt.Errorf("Could not estimate the gas required to submit penalty: %w", err) - } - var gas *big.Int - if t.gasLimit != 0 { - gas = new(big.Int).SetUint64(t.gasLimit) - } else { - gas = new(big.Int).SetUint64(gasInfo.SafeGasLimit) - } - - // Get the max fee - maxFee := t.maxFee - if maxFee == nil || maxFee.Uint64() == 0 { - maxFee, err = rpgas.GetHeadlessMaxFeeWeiWithLatestBlock(t.cfg, t.rp) - if err != nil { - return err - } - } - - // Print the gas info - if !api.PrintAndCheckGasInfo(gasInfo, false, 0, &t.log, maxFee, t.gasLimit) { - return nil - } - - opts.GasFeeCap = maxFee - opts.GasTipCap = fee.GetPriorityFee(t.maxPriorityFee, maxFee) - opts.GasLimit = gas.Uint64() - - hash, err := network.SubmitPenalty(t.rp, minipoolAddress, slotBig, opts) - if err != nil { - return fmt.Errorf("Error submitting penalty against %s for block %d: %w", minipoolAddress.Hex(), block.Slot, err) - } - - // Print TX info and wait for it to be included in a block - err = api.PrintAndWaitForTransaction(t.cfg, hash, t.rp.Client, &t.log) - if err != nil { - return err - } - - // Log result - t.log.Printlnf("Submitted penalty against %s with fee recipient %s on block %d with tx %s", minipoolAddress.Hex(), block.FeeRecipient.Hex(), block.Slot, hash.Hex()) - - return nil - -} diff --git a/rocketpool/watchtower/submit-network-balances.go b/rocketpool/watchtower/submit-network-balances.go index d661e31f0..7f5d872f0 100644 --- a/rocketpool/watchtower/submit-network-balances.go +++ b/rocketpool/watchtower/submit-network-balances.go @@ -417,7 +417,7 @@ func (t *submitNetworkBalances) getNetworkBalances(elBlockHeader *types.Header, if err != nil { return fmt.Errorf("error getting megapool balance details: %w", err) } - i += 1 + i++ } return nil }) @@ -685,11 +685,10 @@ func (t *submitNetworkBalances) getMinipoolBalanceDetails(mpd *rpstate.NativeMin IsStaking: (validator.ExitEpoch > blockEpoch), UserBalance: big.NewInt(0).Sub(userBalance, eth.EthToWei(16)), // Remove 16 ETH from the user balance for full minipools in the refund queue } - } else { - return validatorBalanceDetails{ - IsStaking: (validator.ExitEpoch > blockEpoch), - UserBalance: userBalance, - } + } + return validatorBalanceDetails{ + IsStaking: (validator.ExitEpoch > blockEpoch), + UserBalance: userBalance, } } diff --git a/rocketpool/watchtower/submit-network-balances_test.go b/rocketpool/watchtower/submit-network-balances_test.go index ec6e86e18..1916b2e57 100644 --- a/rocketpool/watchtower/submit-network-balances_test.go +++ b/rocketpool/watchtower/submit-network-balances_test.go @@ -18,7 +18,6 @@ import ( rpstate "github.com/rocket-pool/smartnode/bindings/utils/state" "github.com/rocket-pool/smartnode/rocketpool/watchtower/utils" "github.com/rocket-pool/smartnode/shared/services/beacon" - "github.com/rocket-pool/smartnode/shared/services/config" "github.com/rocket-pool/smartnode/shared/services/state" ) @@ -58,11 +57,6 @@ func makeEth2Config(secondsPerSlot, slotsPerEpoch uint64) beacon.Eth2Config { } } -// slotToTime converts a slot number to a wall-clock time given the config. -func slotToTime(slot uint64, cfg beacon.Eth2Config) time.Time { - return testGenesisTime.Add(time.Duration(slot*cfg.SecondsPerSlot) * time.Second) -} - // makeParentBeaconRoot returns a deterministic hash used as ParentBeaconRoot // in EL headers so the stub's blocksByID map can be keyed on its hex string. func makeParentBeaconRoot(slot uint64) common.Hash { @@ -269,10 +263,6 @@ func newMpd(status rptypes.MinipoolStatus, depositType rptypes.MinipoolDeposit) } } -func (t *submitNetworkBalances) testGetMinipoolBalanceDetails(mpd *rpstate.NativeMinipoolDetails, s *state.NetworkState) validatorBalanceDetails { - return t.getMinipoolBalanceDetails(mpd, s, &config.RocketPoolConfig{}) -} - func TestGetMinipoolBalanceDetails_VacantMinipool(t *testing.T) { task := &submitNetworkBalances{} mpd := newMpd(rptypes.Staking, rptypes.Full) diff --git a/rocketpool/watchtower/submit-rewards-tree-stateless.go b/rocketpool/watchtower/submit-rewards-tree-stateless.go index 1e16b11c3..a1b2f5475 100644 --- a/rocketpool/watchtower/submit-rewards-tree-stateless.go +++ b/rocketpool/watchtower/submit-rewards-tree-stateless.go @@ -115,12 +115,11 @@ func (t *submitRewardsTree_Stateless) Run(nodeTrusted bool, state *state.Network if !nodeTrusted { if t.cfg.Smartnode.RewardsTreeMode.Value.(cfgtypes.RewardsMode) != cfgtypes.RewardsMode_Generate { return nil - } else { - // Create the state, since it's not done except for manual generators - state, err = t.m.GetStateForSlot(beaconSlot) - if err != nil { - return fmt.Errorf("error getting state for beacon slot %d: %w", beaconSlot, err) - } + } + // Create the state, since it's not done except for manual generators + state, err = t.m.GetStateForSlot(beaconSlot) + if err != nil { + return fmt.Errorf("error getting state for beacon slot %d: %w", beaconSlot, err) } } diff --git a/rocketpool/watchtower/submit-rpl-price.go b/rocketpool/watchtower/submit-rpl-price.go index e3f3c2a36..5e176ef48 100644 --- a/rocketpool/watchtower/submit-rpl-price.go +++ b/rocketpool/watchtower/submit-rpl-price.go @@ -381,7 +381,7 @@ func (t *submitRplPrice) run(state *state.NetworkState) error { var lastSubmissionSlotTimestamp uint64 // Check if the node has submitted prices for the latest block if lastSubmissionBlock != 0 { - lastSubmissionEvent := network.PriceUpdatedEvent{} + var lastSubmissionEvent network.PriceUpdatedEvent eventFound, lastSubmissionEvent, err = network.GetPriceUpdatedEvent(t.rp, lastSubmissionBlock, nil) if err != nil { t.log.Printlnf("Error getting price submission event for block %d", lastSubmissionBlock) diff --git a/rocketpool/watchtower/submit-scrub-minipools.go b/rocketpool/watchtower/submit-scrub-minipools.go index b7d644fa4..644913c8a 100644 --- a/rocketpool/watchtower/submit-scrub-minipools.go +++ b/rocketpool/watchtower/submit-scrub-minipools.go @@ -283,7 +283,7 @@ func (t *submitScrubMinipools) initializeMinipoolDetails(minipools []rpstate.Nat } // Step 1: Verify the Beacon Chain credentials for a minipool if they're present -func (t *submitScrubMinipools) verifyBeaconWithdrawalCredentials(state *state.NetworkState) error { +func (t *submitScrubMinipools) verifyBeaconWithdrawalCredentials(state *state.NetworkState) { minipoolsToScrub := []minipool.Minipool{} // Get the withdrawal credentials on Beacon for each validator if they exist @@ -322,7 +322,6 @@ func (t *submitScrubMinipools) verifyBeaconWithdrawalCredentials(state *state.Ne } } - return nil } // Get various elements needed to do eth1 prestake and deposit contract searches diff --git a/rocketpool/watchtower/utils/utils.go b/rocketpool/watchtower/utils/utils.go index 192bbfe21..c3e80c5f9 100644 --- a/rocketpool/watchtower/utils/utils.go +++ b/rocketpool/watchtower/utils/utils.go @@ -35,7 +35,7 @@ func GetWatchtowerPrioFee(cfg *config.RocketPoolConfig) float64 { func FindLastBlockWithExecutionPayload(bc beacon.Client, slotNumber uint64) (beacon.BeaconBlock, error) { beaconBlock := beacon.BeaconBlock{} var err error - for blockExists, searchSlot := false, slotNumber; !blockExists; searchSlot -= 1 { + for blockExists, searchSlot := false, slotNumber; !blockExists; searchSlot-- { beaconBlock, blockExists, err = bc.GetBeaconBlock(strconv.FormatUint(searchSlot, 10)) if err != nil { return beacon.BeaconBlock{}, err diff --git a/rocketpool/watchtower/watchtower.go b/rocketpool/watchtower/watchtower.go index 4e23f2cfb..bdba151b0 100644 --- a/rocketpool/watchtower/watchtower.go +++ b/rocketpool/watchtower/watchtower.go @@ -7,7 +7,6 @@ import ( "math/rand" "net/http" "os" - "sync" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -184,11 +183,7 @@ func run(c *cli.Command) error { intervalDelta := maxTasksInterval - minTasksInterval secondsDelta := intervalDelta.Seconds() - // Wait group to handle the various threads - wg := new(sync.WaitGroup) - wg.Add(2) - - // Run task loop + // Run task loop forever go func() { for { // Randomize the next interval @@ -336,7 +331,6 @@ func run(c *cli.Command) error { time.Sleep(interval) } - wg.Done() }() // Run metrics loop @@ -345,11 +339,8 @@ func run(c *cli.Command) error { if err != nil { errorLog.Println(err) } - wg.Done() }() - // Wait for both threads to stop - wg.Wait() return nil } diff --git a/shared/services/alerting/alerting_test.go b/shared/services/alerting/alerting_test.go index e78e7578f..186d7fad0 100644 --- a/shared/services/alerting/alerting_test.go +++ b/shared/services/alerting/alerting_test.go @@ -53,7 +53,10 @@ func TestFetchAlerts_LowETHBalance(t *testing.T) { return } w.Header().Set("Content-Type", "application/json") - fmt.Fprint(w, lowETHAlertJSON()) + _, err := fmt.Fprint(w, lowETHAlertJSON()) + if err != nil { + t.Fatalf("Error writing lowETHAlertJSON: %v", err) + } })) defer srv.Close() @@ -86,7 +89,10 @@ func TestFetchAlerts_AlertingDisabled(t *testing.T) { called := false srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { called = true - fmt.Fprint(w, lowETHAlertJSON()) + _, err := fmt.Fprint(w, lowETHAlertJSON()) + if err != nil { + t.Fatalf("Error writing lowETHAlertJSON: %v", err) + } })) defer srv.Close() diff --git a/shared/services/beacon/client/committee.go b/shared/services/beacon/client/committee.go index 3d552a689..d231ae7ad 100644 --- a/shared/services/beacon/client/committee.go +++ b/shared/services/beacon/client/committee.go @@ -16,7 +16,7 @@ type Committee struct { // Custom deserialization logic for Committee allows us to pool the validator // slices for reuse. They're quite large, so this cuts down on allocations // substantially. -var validatorSlicePool sync.Pool = sync.Pool{ +var validatorSlicePool = sync.Pool{ New: func() any { s := make([]string, 0, 1024) return &s diff --git a/shared/services/beacon/client/std-http-client.go b/shared/services/beacon/client/std-http-client.go index aa708e0ab..476a5fd57 100644 --- a/shared/services/beacon/client/std-http-client.go +++ b/shared/services/beacon/client/std-http-client.go @@ -280,13 +280,13 @@ func (c *StandardHttpClient) GetValidatorBalances(indices []string, opts *beacon data := make(map[string]*big.Int, count) for i := 0; i < count; i += MaxRequestValidatorsCount { i := i - max := i + MaxRequestValidatorsCount - if max > count { - max = count + m := i + MaxRequestValidatorsCount + if m > count { + m = count } // Get & add validators - batch := indices[i:max] + batch := indices[i:m] balances, err := c.getValidatorBalances(stateId, batch) if err != nil { return nil, fmt.Errorf("error getting validator balances: %w", err) @@ -821,22 +821,6 @@ func (c *StandardHttpClient) getFinalityCheckpoints(stateId string) (FinalityChe return finalityCheckpoints, nil } -// Get fork -func (c *StandardHttpClient) getFork(stateId string) (ForkResponse, error) { - responseBody, status, err := c.getRequest(fmt.Sprintf(RequestForkPath, stateId)) - if err != nil { - return ForkResponse{}, fmt.Errorf("Could not get fork data: %w", err) - } - if status != http.StatusOK { - return ForkResponse{}, fmt.Errorf("Could not get fork data: HTTP status %d; response body: '%s'", status, string(responseBody)) - } - var fork ForkResponse - if err := json.Unmarshal(responseBody, &fork); err != nil { - return ForkResponse{}, fmt.Errorf("Could not decode fork data: %w", err) - } - return fork, nil -} - // Get validator balances func (c *StandardHttpClient) getValidatorBalances(stateId string, indices []string) (ValidatorBalancesResponse, error) { var query string @@ -942,14 +926,14 @@ func (c *StandardHttpClient) getValidatorsByOpts(pubkeysOrIndices []string, opts wg.SetLimit(threadLimit) for i := 0; i < count; i += MaxRequestValidatorsCount { i := i - max := i + MaxRequestValidatorsCount - if max > count { - max = count + m := i + MaxRequestValidatorsCount + if m > count { + m = count } wg.Go(func() error { // Get & add validators - batch := pubkeysOrIndices[i:max] + batch := pubkeysOrIndices[i:m] validators, err := c.getValidators(stateId, batch) if err != nil { return fmt.Errorf("error getting validator statuses: %w", err) @@ -1121,7 +1105,7 @@ func (c *committeesDecoder) Read(p []byte) (int, error) { return n, err } -var committeesDecoderPool sync.Pool = sync.Pool{ +var committeesDecoderPool = sync.Pool{ New: func() any { var out committeesDecoder diff --git a/shared/services/config/nethermind-params.go b/shared/services/config/nethermind-params.go index e90a3c9ca..ea414f0f9 100644 --- a/shared/services/config/nethermind-params.go +++ b/shared/services/config/nethermind-params.go @@ -198,19 +198,23 @@ func calculateNethermindCache() uint64 { if totalMemoryGB == 0 { return 0 - } else if totalMemoryGB < 9 { + } + if totalMemoryGB < 9 { return 512 - } else if totalMemoryGB < 13 { + } + if totalMemoryGB < 13 { return 512 - } else if totalMemoryGB < 17 { + } + if totalMemoryGB < 17 { return 1024 - } else if totalMemoryGB < 25 { + } + if totalMemoryGB < 25 { return 1024 - } else if totalMemoryGB < 33 { + } + if totalMemoryGB < 33 { return 1024 - } else { - return 2048 } + return 2048 } // Calculate the default number of Nethermind peers diff --git a/shared/services/config/reth-params.go b/shared/services/config/reth-params.go index 7617732f7..593461bdb 100644 --- a/shared/services/config/reth-params.go +++ b/shared/services/config/reth-params.go @@ -128,19 +128,23 @@ func calculateRethCache() uint64 { if totalMemoryGB == 0 { return 0 - } else if totalMemoryGB < 9 { + } + if totalMemoryGB < 9 { return 256 - } else if totalMemoryGB < 13 { + } + if totalMemoryGB < 13 { return 2048 - } else if totalMemoryGB < 17 { + } + if totalMemoryGB < 17 { return 4096 - } else if totalMemoryGB < 25 { + } + if totalMemoryGB < 25 { return 8192 - } else if totalMemoryGB < 33 { + } + if totalMemoryGB < 33 { return 12288 - } else { - return 16384 } + return 16384 } // Calculate the default number of Reth peers diff --git a/shared/services/config/rocket-pool-config.go b/shared/services/config/rocket-pool-config.go index e70ecceff..97cbc070d 100644 --- a/shared/services/config/rocket-pool-config.go +++ b/shared/services/config/rocket-pool-config.go @@ -144,14 +144,22 @@ func getExternalIP() (net.IP, error) { // Try IPv4 first consensusConfig := externalip.ConsensusConfig{Timeout: 3 * time.Second} ip4Consensus := externalip.DefaultConsensus(&consensusConfig, nil) - ip4Consensus.UseIPProtocol(4) + err := ip4Consensus.UseIPProtocol(4) + if err != nil { + // Only panics if the IP protocol isn't one of 0, 4, or 6 + 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 { + // Only panics if the IP protocol isn't one of 0, 4, or 6 + panic(err) + } return ip6Consensus.ExternalIP() } @@ -502,7 +510,13 @@ 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 { + // This function is called in a lot of pure contexts, and + // we shouldn't ever see a failure on applying the defaults anyway - at runtime. + // This panic should get caught during CI + panic(err) + } return cfg } @@ -1699,9 +1713,8 @@ func addAndCheckForDuplicate(portMap map[interface{}]bool, param config.Paramete } if portMap[port] { return portMap, append(errors, fmt.Sprintf("Port %s for %s is already in use", port, param.Name)) - } else { - portMap[port] = true } + portMap[port] = true return portMap, errors } diff --git a/shared/services/connectivity/check-port-connectivity.go b/shared/services/connectivity/check-port-connectivity.go index b77ad3038..9c8800d37 100644 --- a/shared/services/connectivity/check-port-connectivity.go +++ b/shared/services/connectivity/check-port-connectivity.go @@ -178,12 +178,12 @@ func getPublicIP() (string, error) { // isPortReachableNATReflection attempts a TCP connection to host:port and returns true if // the connection succeeds within portCheckTimeout. func isPortReachableNATReflection(host string, port uint16) bool { - address := fmt.Sprintf("%s:%d", host, port) + address := net.JoinHostPort(host, strconv.FormatUint(uint64(port), 10)) conn, err := net.DialTimeout("tcp", address, portCheckTimeout) if err != nil { return false } - conn.Close() + _ = conn.Close() return true } @@ -212,7 +212,9 @@ func isPortReachableExternalService(port uint16) (bool, string, error) { if err != nil { return false, "", err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() // Read response body, err := io.ReadAll(resp.Body) diff --git a/shared/services/ec-manager.go b/shared/services/ec-manager.go index 931ca7576..1f46cb947 100644 --- a/shared/services/ec-manager.go +++ b/shared/services/ec-manager.go @@ -24,8 +24,8 @@ import ( type ExecutionClientManager struct { primaryEcUrl string fallbackEcUrl string - primaryEc *ethClient - fallbackEc *ethClient + primaryEc *EthClient + fallbackEc *EthClient logger log.ColorLogger primaryReady bool fallbackReady bool @@ -33,7 +33,7 @@ type ExecutionClientManager struct { } // This is a signature for a wrapped ethclient.Client function -type ecFunction func(*ethClient) (interface{}, error) +type ecFunction func(*EthClient) (interface{}, error) // Creates a new ExecutionClientManager instance based on the Rocket Pool config func NewExecutionClientManager(cfg *config.RocketPoolConfig) (*ExecutionClientManager, error) { @@ -81,13 +81,13 @@ func NewExecutionClientManager(cfg *config.RocketPoolConfig) (*ExecutionClientMa out := &ExecutionClientManager{ primaryEcUrl: primaryEcUrl, fallbackEcUrl: fallbackEcUrl, - primaryEc: ðClient{primaryEc}, + primaryEc: &EthClient{primaryEc}, logger: log.NewColorLogger(color.FgYellow), primaryReady: true, fallbackReady: fallbackEc != nil, } if fallbackEc != nil { - out.fallbackEc = ðClient{fallbackEc} + out.fallbackEc = &EthClient{fallbackEc} } return out, nil @@ -100,7 +100,7 @@ func NewExecutionClientManager(cfg *config.RocketPoolConfig) (*ExecutionClientMa // CodeAt returns the code of the given account. This is needed to differentiate // between contract internal errors and the local chain being out of sync. func (p *ExecutionClientManager) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.CodeAt(ctx, contract, blockNumber) }) if err != nil { @@ -112,7 +112,7 @@ func (p *ExecutionClientManager) CodeAt(ctx context.Context, contract common.Add // CallContract executes an Ethereum contract call with the specified data as the // input. func (p *ExecutionClientManager) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.CallContract(ctx, call, blockNumber) }) if err != nil { @@ -127,7 +127,7 @@ func (p *ExecutionClientManager) CallContract(ctx context.Context, call ethereum // HeaderByHash returns the block header with the given hash. func (p *ExecutionClientManager) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.HeaderByHash(ctx, hash) }) if err != nil { @@ -139,7 +139,7 @@ func (p *ExecutionClientManager) HeaderByHash(ctx context.Context, hash common.H // HeaderByNumber returns a block header from the current canonical chain. If number is // nil, the latest known header is returned. func (p *ExecutionClientManager) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.HeaderByNumber(ctx, number) }) if err != nil { @@ -150,7 +150,7 @@ func (p *ExecutionClientManager) HeaderByNumber(ctx context.Context, number *big // PendingCodeAt returns the code of the given account in the pending state. func (p *ExecutionClientManager) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.PendingCodeAt(ctx, account) }) if err != nil { @@ -161,7 +161,7 @@ func (p *ExecutionClientManager) PendingCodeAt(ctx context.Context, account comm // PendingNonceAt retrieves the current pending nonce associated with an account. func (p *ExecutionClientManager) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.PendingNonceAt(ctx, account) }) if err != nil { @@ -173,7 +173,7 @@ func (p *ExecutionClientManager) PendingNonceAt(ctx context.Context, account com // SuggestGasPrice retrieves the currently suggested gas price to allow a timely // execution of a transaction. func (p *ExecutionClientManager) SuggestGasPrice(ctx context.Context) (*big.Int, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.SuggestGasPrice(ctx) }) if err != nil { @@ -185,7 +185,7 @@ func (p *ExecutionClientManager) SuggestGasPrice(ctx context.Context) (*big.Int, // SuggestGasTipCap retrieves the currently suggested 1559 priority fee to allow // a timely execution of a transaction. func (p *ExecutionClientManager) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.SuggestGasTipCap(ctx) }) if err != nil { @@ -200,7 +200,7 @@ func (p *ExecutionClientManager) SuggestGasTipCap(ctx context.Context) (*big.Int // transactions may be added or removed by miners, but it should provide a basis // for setting a reasonable default. func (p *ExecutionClientManager) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.EstimateGas(ctx, call) }) if err != nil { @@ -211,7 +211,7 @@ func (p *ExecutionClientManager) EstimateGas(ctx context.Context, call ethereum. // SendTransaction injects the transaction into the pending pool for execution. func (p *ExecutionClientManager) SendTransaction(ctx context.Context, tx *types.Transaction) error { - _, err := p.runFunction(func(client *ethClient) (interface{}, error) { + _, err := p.runFunction(func(client *EthClient) (interface{}, error) { return nil, client.SendTransaction(ctx, tx) }) return err @@ -226,7 +226,7 @@ func (p *ExecutionClientManager) SendTransaction(ctx context.Context, tx *types. // // TODO(karalabe): Deprecate when the subscription one can return past data too. func (p *ExecutionClientManager) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.FilterLogs(ctx, query) }) if err != nil { @@ -238,7 +238,7 @@ func (p *ExecutionClientManager) FilterLogs(ctx context.Context, query ethereum. // SubscribeFilterLogs creates a background log filtering operation, returning // a subscription immediately, which can be used to stream the found events. func (p *ExecutionClientManager) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.SubscribeFilterLogs(ctx, query, ch) }) if err != nil { @@ -254,7 +254,7 @@ func (p *ExecutionClientManager) SubscribeFilterLogs(ctx context.Context, query // TransactionReceipt returns the receipt of a transaction by transaction hash. // Note that the receipt is not available for pending transactions. func (p *ExecutionClientManager) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.TransactionReceipt(ctx, txHash) }) if err != nil { @@ -269,7 +269,7 @@ func (p *ExecutionClientManager) TransactionReceipt(ctx context.Context, txHash // BlockNumber returns the most recent block number func (p *ExecutionClientManager) BlockNumber(ctx context.Context) (uint64, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.BlockNumber(ctx) }) if err != nil { @@ -281,7 +281,7 @@ func (p *ExecutionClientManager) BlockNumber(ctx context.Context) (uint64, error // BalanceAt returns the wei balance of the given account. // The block number can be nil, in which case the balance is taken from the latest known block. func (p *ExecutionClientManager) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.BalanceAt(ctx, account, blockNumber) }) if err != nil { @@ -292,7 +292,7 @@ func (p *ExecutionClientManager) BalanceAt(ctx context.Context, account common.A // TransactionByHash returns the transaction with the given hash. func (p *ExecutionClientManager) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { tx, isPending, err := client.TransactionByHash(ctx, hash) result := []interface{}{tx, isPending} return result, err @@ -311,7 +311,7 @@ func (p *ExecutionClientManager) TransactionByHash(ctx context.Context, hash com // NonceAt returns the account nonce of the given account. // The block number can be nil, in which case the nonce is taken from the latest known block. func (p *ExecutionClientManager) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.NonceAt(ctx, account, blockNumber) }) if err != nil { @@ -323,7 +323,7 @@ func (p *ExecutionClientManager) NonceAt(ctx context.Context, account common.Add // SyncProgress retrieves the current progress of the sync algorithm. If there's // no sync currently running, it returns nil. func (p *ExecutionClientManager) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.SyncProgress(ctx) }) if err != nil { @@ -333,7 +333,7 @@ func (p *ExecutionClientManager) SyncProgress(ctx context.Context) (*ethereum.Sy } func (p *ExecutionClientManager) LatestBlockTime(ctx context.Context) (time.Time, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.LatestBlockTime(ctx) }) if err != nil { @@ -344,7 +344,7 @@ func (p *ExecutionClientManager) LatestBlockTime(ctx context.Context) (time.Time // BlockNumber returns the most recent block number func (p *ExecutionClientManager) ChainID(ctx context.Context) (*big.Int, error) { - result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + result, err := p.runFunction(func(client *EthClient) (interface{}, error) { return client.ChainID(ctx) }) if err != nil { @@ -416,7 +416,7 @@ func getNetworkNameFromId(networkId uint) string { const ecStatusTimeout = 10 * time.Second // Check the client status -func checkEcStatus(client *ethClient) api.ClientStatus { +func checkEcStatus(client *EthClient) api.ClientStatus { status := api.ClientStatus{} diff --git a/shared/services/ethclient.go b/shared/services/ethclient.go index 5ecb2e2aa..d1c7176a8 100644 --- a/shared/services/ethclient.go +++ b/shared/services/ethclient.go @@ -7,19 +7,19 @@ import ( "github.com/ethereum/go-ethereum/ethclient" ) -type ethClient struct { +type EthClient struct { *ethclient.Client } -func NewEthClient(url string) (*ethClient, error) { +func NewEthClient(url string) (*EthClient, error) { ec, err := ethclient.Dial(url) if err != nil { return nil, err } - return ðClient{ec}, nil + return &EthClient{ec}, nil } -func (c *ethClient) LatestBlockTime(ctx context.Context) (time.Time, error) { +func (c *EthClient) LatestBlockTime(ctx context.Context) (time.Time, error) { header, err := c.HeaderByNumber(ctx, nil) if err != nil { return time.Time{}, err diff --git a/shared/services/megapools.go b/shared/services/megapools.go index 5e76b31bc..b415232eb 100644 --- a/shared/services/megapools.go +++ b/shared/services/megapools.go @@ -15,9 +15,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ssz "github.com/ferranbt/fastssz" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" - prdeposit "github.com/prysmaticlabs/prysm/v5/contracts/deposit" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/bindings/network" "github.com/rocket-pool/smartnode/bindings/node" @@ -34,7 +31,6 @@ import ( "github.com/rocket-pool/smartnode/shared/types/eth2/fork/fulu" "github.com/rocket-pool/smartnode/shared/types/eth2/generic" "github.com/urfave/cli/v3" - eth2types "github.com/wealdtech/go-eth2-types/v2" "golang.org/x/sync/errgroup" ) @@ -214,27 +210,6 @@ func ConvertToFixedSize(proofBytes [][]byte) [][32]byte { return proofWithFixedSize } -func validateDepositInfo(eth2Config beacon.Eth2Config, depositAmount uint64, pubkey types.ValidatorPubkey, withdrawalCredentials common.Hash, signature types.ValidatorSignature) error { - - // Get the deposit domain based on the eth2 config - depositDomain, err := signing.ComputeDomain(eth2types.DomainDeposit, eth2Config.GenesisForkVersion, eth2types.ZeroGenesisValidatorsRoot) - if err != nil { - return err - } - - // Create the deposit struct - depositData := new(ethpb.Deposit_Data) - depositData.Amount = depositAmount - depositData.PublicKey = pubkey.Bytes() - depositData.WithdrawalCredentials = withdrawalCredentials.Bytes() - depositData.Signature = signature.Bytes() - - // Validate the signature - err = prdeposit.VerifyDepositSignature(depositData, depositDomain) - return err - -} - func CalculateMegapoolWithdrawalCredentials(megapoolAddress common.Address) common.Hash { // Convert the address to a uint160 (20 bytes) and then to a uint256 (32 bytes) addressBigInt := new(big.Int) @@ -614,9 +589,8 @@ func findInQueue(rp *rocketpool.RocketPool, megapoolAddress common.Address, vali } if slice.NextIndex.Cmp(big.NewInt(0)) == 0 { return nil, nil - } else { - return findInQueue(rp, megapoolAddress, validatorId, queueKey, slice.NextIndex, positionOffset) } + return findInQueue(rp, megapoolAddress, validatorId, queueKey, slice.NextIndex, positionOffset) } @@ -682,14 +656,19 @@ func GetWithdrawalProofForSlotFromAPI(c *cli.Command, finalizedSlot uint64, with if err != nil { return megapool.FinalBalanceProof{}, 0, err } - defer response.Body.Close() + defer func() { + _ = response.Body.Close() + }() body, err := io.ReadAll(response.Body) if err != nil { return megapool.FinalBalanceProof{}, 0, err } // unmarshal the response into the WithdrawalProofResponse type var withdrawalProofResponse WithdrawalProofResponse - json.Unmarshal([]byte(body), &withdrawalProofResponse) + err = json.Unmarshal([]byte(body), &withdrawalProofResponse) + if err != nil { + return megapool.FinalBalanceProof{}, 0, err + } // Convert []common.Hash to [][32]byte witnesses := make([][32]byte, len(withdrawalProofResponse.Witnesses)) @@ -884,9 +863,8 @@ func FindWithdrawalBlockAndArrayPosition(slot uint64, validatorIndex uint64, bc return 0, nil, 0, nil, nil, fmt.Errorf("2 epochs of missing slots detected. It is likely that the Beacon Client was checkpoint synced after the most recent withdrawal to slot %d, and does not have the history required to generate a withdrawal proof", slot) } continue - } else { - notFounds = 0 } + notFounds = 0 beaconBlock, err := eth2.NewSignedBeaconBlock(blockResponse.Data, blockResponse.Fork) if err != nil { diff --git a/shared/services/requirements.go b/shared/services/requirements.go index 8a9646131..c3be4384a 100644 --- a/shared/services/requirements.go +++ b/shared/services/requirements.go @@ -473,7 +473,10 @@ func waitEthClientSynced(c *cli.Command, verbose bool, timeout int64) (bool, err return false, err } if synced { - alerting.AlertExecutionClientSyncComplete(cfg) + err = alerting.AlertExecutionClientSyncComplete(cfg) + if err != nil { + log.Printf("error alerting execution client sync complete: %v\n", err) + } return true, nil } } @@ -505,7 +508,10 @@ func waitEthClientSynced(c *cli.Command, verbose bool, timeout int64) (bool, err } // Only return true if the last reportedly known block is within our defined threshold if isUpToDate { - alerting.AlertExecutionClientSyncComplete(cfg) + err = alerting.AlertExecutionClientSyncComplete(cfg) + if err != nil { + log.Printf("error alerting execution client sync complete: %v\n", err) + } return true, nil } } @@ -569,7 +575,10 @@ func waitBeaconClientSynced(c *cli.Command, verbose bool, timeout int64) (bool, return false, err } if synced { - alerting.AlertBeaconClientSyncComplete(cfg) + err = alerting.AlertBeaconClientSyncComplete(cfg) + if err != nil { + log.Printf("error alerting beacon client sync complete: %v\n", err) + } return true, nil } } @@ -586,7 +595,10 @@ func waitBeaconClientSynced(c *cli.Command, verbose bool, timeout int64) (bool, log.Printf("Eth 2.0 node syncing: %.2f%%\n", syncStatus.Progress*100) } } else { - alerting.AlertBeaconClientSyncComplete(cfg) + err = alerting.AlertBeaconClientSyncComplete(cfg) + if err != nil { + log.Printf("error alerting beacon client sync complete: %v\n", err) + } return true, nil } diff --git a/shared/services/rewards/execution-client.go b/shared/services/rewards/execution-client.go index a494b71f6..3e4d4892f 100644 --- a/shared/services/rewards/execution-client.go +++ b/shared/services/rewards/execution-client.go @@ -28,7 +28,7 @@ type defaultRewardsExecutionClient struct { *rocketpool.RocketPool } -func NewRewardsExecutionClient(rp *rocketpool.RocketPool) *defaultRewardsExecutionClient { +func NewRewardsExecutionClient(rp *rocketpool.RocketPool) RewardsExecutionClient { out := new(defaultRewardsExecutionClient) out.RocketPool = rp return out diff --git a/shared/services/rewards/generator-impl-v11.go b/shared/services/rewards/generator-impl-v11.go index 14ca5aba3..f67da8589 100644 --- a/shared/services/rewards/generator-impl-v11.go +++ b/shared/services/rewards/generator-impl-v11.go @@ -1214,7 +1214,7 @@ func (r *treeGeneratorImpl_v11) processEpoch(duringInterval bool, epoch uint64) } -func (r *treeGeneratorImpl_v11) checkAttestations(attestations []beacon.AttestationInfo) error { +func (r *treeGeneratorImpl_v11) checkAttestations(attestations []beacon.AttestationInfo) { // Go through the attestations for the block for _, attestation := range attestations { @@ -1328,8 +1328,6 @@ func (r *treeGeneratorImpl_v11) checkAttestations(attestations []beacon.Attestat } } - return nil - } // Maps out the attestation duties for the given epoch diff --git a/shared/services/rewards/generator-impl-v9-v10.go b/shared/services/rewards/generator-impl-v9-v10.go index b74a38a4c..2aef4d57e 100644 --- a/shared/services/rewards/generator-impl-v9-v10.go +++ b/shared/services/rewards/generator-impl-v9-v10.go @@ -935,7 +935,7 @@ func (r *treeGeneratorImpl_v9_v10) processEpoch(duringInterval bool, epoch uint6 } -func (r *treeGeneratorImpl_v9_v10) checkAttestations(attestations []beacon.AttestationInfo, inclusionSlot uint64) error { +func (r *treeGeneratorImpl_v9_v10) checkAttestations(attestations []beacon.AttestationInfo, inclusionSlot uint64) { // Go through the attestations for the block for _, attestation := range attestations { @@ -1006,8 +1006,6 @@ func (r *treeGeneratorImpl_v9_v10) checkAttestations(attestations []beacon.Attes } } - return nil - } // Maps out the attestation duties for the given epoch @@ -1134,8 +1132,8 @@ func (r *treeGeneratorImpl_v9_v10) createMinipoolIndexMap() error { } -var farFutureTimestamp int64 = 1000000000000000000 // Far into the future -var farPastTimestamp int64 = 0 +var farFutureTimestamp = int64(1000000000000000000) // Far into the future +var farPastTimestamp = int64(0) // Get the details for every node that was opted into the Smoothing Pool for at least some portion of this interval func (r *treeGeneratorImpl_v9_v10) getSmoothingPoolNodeDetails() error { diff --git a/shared/services/rewards/ssz_types/rewards-file-v4.go b/shared/services/rewards/ssz_types/rewards-file-v4.go index 9b21742d3..4b519fad2 100644 --- a/shared/services/rewards/ssz_types/rewards-file-v4.go +++ b/shared/services/rewards/ssz_types/rewards-file-v4.go @@ -25,7 +25,7 @@ const ( FormatSSZ ) -var Magic [4]byte = [4]byte{0x52, 0x50, 0x52, 0x54} +var Magic = [4]byte{0x52, 0x50, 0x52, 0x54} type Address [20]byte type Hash [32]byte diff --git a/shared/services/rewards/ssz_types/rewards-file-v5.go b/shared/services/rewards/ssz_types/rewards-file-v5.go index 4e5468de9..457ebc0b2 100644 --- a/shared/services/rewards/ssz_types/rewards-file-v5.go +++ b/shared/services/rewards/ssz_types/rewards-file-v5.go @@ -18,7 +18,7 @@ import ( "github.com/wealdtech/go-merkletree/keccak256" ) -var Magicv2 [4]byte = [4]byte{0x52, 0x50, 0x52, 0x55} +var Magicv2 = [4]byte{0x52, 0x50, 0x52, 0x55} type NodeRewards_v2 []*NodeReward_v2 diff --git a/shared/services/rewards/test/assets/assets.go b/shared/services/rewards/test/assets/assets.go index 99c79a05a..cccc371a6 100644 --- a/shared/services/rewards/test/assets/assets.go +++ b/shared/services/rewards/test/assets/assets.go @@ -29,7 +29,9 @@ func GetMainnet20RewardsJSON() []byte { if err != nil { panic(err) } - defer gz.Close() + defer func() { + _ = gz.Close() + }() mainnet20RewardsJSON, err = io.ReadAll(gz) if err != nil { panic(err) @@ -50,7 +52,9 @@ func GetMainnet20MinipoolPerformanceJSON() []byte { if err != nil { panic(err) } - defer gz.Close() + defer func() { + _ = gz.Close() + }() Mainnet20MinipoolPerformanceJSON, err = io.ReadAll(gz) if err != nil { panic(err) @@ -73,7 +77,9 @@ func GetMainnet20RewardsState() *state.NetworkState { if err != nil { panic(err) } - defer gz.Close() + defer func() { + _ = gz.Close() + }() // Create a JSON decoder dec := json.NewDecoder(gz) @@ -124,7 +130,9 @@ func GetMainnet20CriticalDutiesSlots() *state.CriticalDutiesSlots { if err != nil { panic(err) } - defer jsonReader.Close() + defer func() { + _ = jsonReader.Close() + }() // Create a JSON decoder dec := json.NewDecoder(jsonReader) diff --git a/shared/services/rewards/test/mock.go b/shared/services/rewards/test/mock.go index 2bbc6059d..f4c51c4fc 100644 --- a/shared/services/rewards/test/mock.go +++ b/shared/services/rewards/test/mock.go @@ -49,7 +49,6 @@ func (h *MockHistory) GetNodeAddress() common.Address { } var oneEth = big.NewInt(1000000000000000000) -var thirtyTwoEth = big.NewInt(0).Mul(oneEth, big.NewInt(32)) type MockMinipool struct { Address common.Address @@ -945,9 +944,9 @@ func (h *MockHistory) GetPreviousRewardSnapshotEvent() rprewards.RewardsEvent { } } -type nodeSummary map[string][]*MockNode +type NodeSummary map[string][]*MockNode -func (h *MockHistory) GetNodeSummary() nodeSummary { +func (h *MockHistory) GetNodeSummary() NodeSummary { out := make(map[string][]*MockNode) for _, node := range h.Nodes { out[node.Class] = append(out[node.Class], node) @@ -955,12 +954,12 @@ func (h *MockHistory) GetNodeSummary() nodeSummary { return out } -func (s nodeSummary) GetClass(class string) ([]*MockNode, bool) { +func (s NodeSummary) GetClass(class string) ([]*MockNode, bool) { nodes, ok := s[class] return nodes, ok } -func (s nodeSummary) MustGetClass(t *testing.T, class string) []*MockNode { +func (s NodeSummary) MustGetClass(t *testing.T, class string) []*MockNode { nodes, ok := s.GetClass(class) if !ok { t.Fatalf("Class %s not found", class) diff --git a/shared/services/rewards/utils.go b/shared/services/rewards/utils.go index c413d4613..b41d66a3c 100644 --- a/shared/services/rewards/utils.go +++ b/shared/services/rewards/utils.go @@ -19,15 +19,11 @@ import ( "github.com/mitchellh/go-homedir" "github.com/rocket-pool/smartnode/bindings/rewards" "github.com/rocket-pool/smartnode/bindings/rocketpool" - rpstate "github.com/rocket-pool/smartnode/bindings/utils/state" "github.com/rocket-pool/smartnode/shared/services/beacon" "github.com/rocket-pool/smartnode/shared/services/config" cfgtypes "github.com/rocket-pool/smartnode/shared/types/config" ) -// Simple container for the zero value so it doesn't have to be recreated over and over -var zero *big.Int - // Gets the intervals the node can claim and the intervals that have already been claimed func GetClaimStatus(rp *rocketpool.RocketPool, nodeAddress common.Address) (unclaimed []uint64, claimed []uint64, err error) { // Get the current interval @@ -193,7 +189,6 @@ func (i *IntervalInfo) DownloadRewardsFile(cfg *config.RocketPoolConfig, isDaemo errBuilder.WriteString("Downloading " + url + " failed (" + err.Error() + ")\n") continue } - defer resp.Body.Close() if resp.StatusCode != http.StatusOK { errBuilder.WriteString("Downloading " + url + " failed with status " + resp.Status + "\n") @@ -205,6 +200,11 @@ func (i *IntervalInfo) DownloadRewardsFile(cfg *config.RocketPoolConfig, isDaemo errBuilder.WriteString("Error reading response bytes from " + url + ": " + err.Error() + "\n") continue } + err = resp.Body.Close() + if err != nil { + errBuilder.WriteString("Error closing response body from " + url + ": " + err.Error() + "\n") + continue + } writeBytes := bytes if strings.HasSuffix(url, config.RewardsTreeIpfsExtension) { // Decompress it @@ -224,7 +224,10 @@ func (i *IntervalInfo) DownloadRewardsFile(cfg *config.RocketPoolConfig, isDaemo downloadedRoot := deserializedRewardsFile.GetMerkleRoot() // Reconstruct the merkle tree from the file data, this should overwrite the stored Merkle Root with a new one - deserializedRewardsFile.GenerateMerkleTree() + err = deserializedRewardsFile.GenerateMerkleTree() + if err != nil { + return fmt.Errorf("error generating merkle tree: %w", err) + } // Get the resulting merkle root calculatedRoot := deserializedRewardsFile.GetMerkleRoot() @@ -350,34 +353,3 @@ func decompressFile(compressedBytes []byte) ([]byte, error) { return decompressedBytes, nil } - -// Get the bond and node fee of a minipool for the specified time -func getMinipoolBondAndNodeFee(details *rpstate.NativeMinipoolDetails, blockTime time.Time) (*big.Int, *big.Int) { - currentBond := details.NodeDepositBalance - currentFee := details.NodeFee - previousBond := details.LastBondReductionPrevValue - previousFee := details.LastBondReductionPrevNodeFee - - // Init the zero wrapper - if zero == nil { - zero = big.NewInt(0) - } - - reductionTimeBig := details.LastBondReductionTime - if reductionTimeBig.Cmp(zero) == 0 { - // Never reduced - return currentBond, currentFee - } else { - reductionTime := time.Unix(reductionTimeBig.Int64(), 0) - if reductionTime.Sub(blockTime) > 0 { - // This block occurred before the reduction - if previousFee.Cmp(zero) == 0 { - // Catch for minipools that were created before this call existed - return previousBond, currentFee - } - return previousBond, previousFee - } - } - - return currentBond, currentFee -} diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index 1dcae83b6..5d5ef8b21 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -50,9 +50,6 @@ const ( defaultFeeRecipientFile string = "fr-default.tmpl" defaultNativeFeeRecipientFile string = "fr-default-env.tmpl" - templateSuffix string = ".tmpl" - composeFileSuffix string = ".yml" - nethermindAdminUrl string = "http://127.0.0.1:7434" pruneStarterContainerSuffix string = "_nm_prune_starter" @@ -287,7 +284,10 @@ func (c *Client) runScript(script assets.ScriptWithContext, verbose bool, flags if verbose { fmt.Printf("Verbose mode enabled, tmpdir %s will not be removed\n", tmpdir) } else { - defer os.RemoveAll(tmpdir) + defer func() { + // It's fine if this fails, tmpreaper will handle it + _ = os.RemoveAll(tmpdir) + }() } // Create a file in the tmpdir @@ -896,14 +896,14 @@ func (c *Client) RunNethermindPruneStarter(executionContainerName string) error if errObject, ok := response["error"].(map[string]any); ok { fmt.Printf("Error starting prune: code %d, message = %s, data = %s\n", errObject["code"], errObject["message"], errObject["data"]) continue - } else { - fmt.Printf("Success: Pruning is now \"%s\"\n", response["result"]) - fmt.Println("Your main execution client is now pruning. You can follow its progress with `rocketpool service logs eth1`.") - fmt.Println("NOTE: While pruning, you **cannot** interrupt the client (e.g. by restarting) or you risk corrupting the database!") - fmt.Println("You must let it run to completion!") - break } + fmt.Printf("Success: Pruning is now \"%s\"\n", response["result"]) + fmt.Println("Your main execution client is now pruning. You can follow its progress with `rocketpool service logs eth1`.") + fmt.Println("NOTE: While pruning, you **cannot** interrupt the client (e.g. by restarting) or you risk corrupting the database!") + fmt.Println("You must let it run to completion!") + break + } return nil } @@ -1013,16 +1013,13 @@ func (c *Client) checkIfCommandExists(command string) (bool, error) { if isExitErr && exitErr.ExitCode() == 127 { // Command not found return false, nil - } else { - return false, fmt.Errorf("error checking if %s exists: %w", command, err) - } - } else { - if strings.Contains(string(output), fmt.Sprintf("%s is", command)) { - return true, nil - } else { - return false, fmt.Errorf("unexpected output when checking for %s: %s", command, string(output)) } + return false, fmt.Errorf("error checking if %s exists: %w", command, err) + } + if strings.Contains(string(output), fmt.Sprintf("%s is", command)) { + return true, nil } + return false, fmt.Errorf("unexpected output when checking for %s: %s", command, string(output)) } // Build a docker compose command @@ -1315,7 +1312,9 @@ func (c *Client) callHTTPAPICtx(ctx context.Context, method, path string, params if err != nil { return nil, fmt.Errorf("error calling HTTP API %s %s: %w", method, path, err) } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() responseBytes, err := io.ReadAll(resp.Body) if err != nil { @@ -1348,7 +1347,7 @@ func (c *Client) printOutput(cmdText string) error { if err != nil { return err } - defer cmd.Close() + defer cmd.Close() //nolint:errcheck cmd.SetStdout(os.Stdout) cmd.SetStderr(os.Stderr) diff --git a/shared/services/rocketpool/fee-recipient.go b/shared/services/rocketpool/fee-recipient.go index d2e43d4d1..f786f646e 100644 --- a/shared/services/rocketpool/fee-recipient.go +++ b/shared/services/rocketpool/fee-recipient.go @@ -113,11 +113,13 @@ func UpdateFeeRecipientPerKey(pubkeys []types.ValidatorPubkey, megapoolAddress c return fmt.Errorf("error making GET request for pubkey %s: %w", pubkeyHex, err) } body, err := io.ReadAll(resp.Body) - resp.Body.Close() if err != nil { return fmt.Errorf("error reading GET response body for pubkey %s: %w", pubkeyHex, err) } + defer func() { + _ = resp.Body.Close() + }() type FeeRecipientResp struct { Data struct { @@ -153,7 +155,9 @@ func UpdateFeeRecipientPerKey(pubkeys []types.ValidatorPubkey, megapoolAddress c if err != nil { return fmt.Errorf("error making request for pubkey %s: %w", pubkeyHex, err) } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() if resp.StatusCode < 200 || resp.StatusCode >= 300 { bodyBytes, _ := io.ReadAll(resp.Body) diff --git a/shared/services/rocketpool/queue.go b/shared/services/rocketpool/queue.go index d62ee04af..0e4592a20 100644 --- a/shared/services/rocketpool/queue.go +++ b/shared/services/rocketpool/queue.go @@ -33,8 +33,8 @@ func (c *Client) QueueStatus() (api.QueueStatusResponse, error) { } // Check whether the queue can be processed -func (c *Client) CanProcessQueue(max uint32) (api.CanProcessQueueResponse, error) { - responseBytes, err := c.callHTTPAPI("GET", "/api/queue/can-process", url.Values{"max": {fmt.Sprintf("%d", max)}}) +func (c *Client) CanProcessQueue(m uint32) (api.CanProcessQueueResponse, error) { + responseBytes, err := c.callHTTPAPI("GET", "/api/queue/can-process", url.Values{"max": {fmt.Sprintf("%d", m)}}) if err != nil { return api.CanProcessQueueResponse{}, fmt.Errorf("Could not get can process queue status: %w", err) } @@ -49,8 +49,8 @@ func (c *Client) CanProcessQueue(max uint32) (api.CanProcessQueueResponse, error } // Process the queue -func (c *Client) ProcessQueue(max uint32) (api.ProcessQueueResponse, error) { - responseBytes, err := c.callHTTPAPI("POST", "/api/queue/process", url.Values{"max": {fmt.Sprintf("%d", max)}}) +func (c *Client) ProcessQueue(m uint32) (api.ProcessQueueResponse, error) { + responseBytes, err := c.callHTTPAPI("POST", "/api/queue/process", url.Values{"max": {fmt.Sprintf("%d", m)}}) if err != nil { return api.ProcessQueueResponse{}, fmt.Errorf("Could not process queue: %w", err) } @@ -65,8 +65,8 @@ func (c *Client) ProcessQueue(max uint32) (api.ProcessQueueResponse, error) { } // Check whether deposits can be assigned -func (c *Client) CanAssignDeposits(max uint32) (api.CanAssignDepositsResponse, error) { - responseBytes, err := c.callHTTPAPI("GET", "/api/queue/can-assign-deposits", url.Values{"max": {fmt.Sprintf("%d", max)}}) +func (c *Client) CanAssignDeposits(m uint32) (api.CanAssignDepositsResponse, error) { + responseBytes, err := c.callHTTPAPI("GET", "/api/queue/can-assign-deposits", url.Values{"max": {fmt.Sprintf("%d", m)}}) if err != nil { return api.CanAssignDepositsResponse{}, fmt.Errorf("Could not get can assign deposits status: %w", err) } @@ -81,8 +81,8 @@ func (c *Client) CanAssignDeposits(max uint32) (api.CanAssignDepositsResponse, e } // Assign deposits to queued validators -func (c *Client) AssignDeposits(max uint32) (api.AssignDepositsResponse, error) { - responseBytes, err := c.callHTTPAPI("POST", "/api/queue/assign-deposits", url.Values{"max": {fmt.Sprintf("%d", max)}}) +func (c *Client) AssignDeposits(m uint32) (api.AssignDepositsResponse, error) { + responseBytes, err := c.callHTTPAPI("POST", "/api/queue/assign-deposits", url.Values{"max": {fmt.Sprintf("%d", m)}}) if err != nil { return api.AssignDepositsResponse{}, fmt.Errorf("Could not assign deposits: %w", err) } diff --git a/shared/services/services.go b/shared/services/services.go index 17619af2d..28bffe210 100644 --- a/shared/services/services.go +++ b/shared/services/services.go @@ -47,7 +47,6 @@ var ( bcManager *BeaconClientManager rocketPool *rocketpool.RocketPool rocketSignerRegistry *contracts.RocketSignerRegistry - beaconClient beacon.Client docker *client.Client initCfg sync.Once @@ -57,9 +56,7 @@ var ( initECManager sync.Once initBCManager sync.Once initRocketPool sync.Once - initOneInchOracle sync.Once initRocketSignerRegistry sync.Once - initBeaconClient sync.Once initDocker sync.Once ) @@ -149,12 +146,12 @@ func GetEthClient(c *cli.Command) (*ExecutionClientManager, error) { return ec, nil } -func dialProtectedEthClient(url string) (*ethClient, error) { +func dialProtectedEthClient(url string) (*EthClient, error) { ec, err := ethclient.Dial(url) if err != nil { return nil, err } - return ðClient{ec}, nil + return &EthClient{ec}, nil } func GetRocketPool(c *cli.Command) (*rocketpool.RocketPool, error) { diff --git a/shared/services/wallet/masquerade-wallet.go b/shared/services/wallet/masquerade-wallet.go index d7b80b82b..e99e4cf64 100644 --- a/shared/services/wallet/masquerade-wallet.go +++ b/shared/services/wallet/masquerade-wallet.go @@ -90,8 +90,7 @@ func (w *masqueradeWallet) EndMasquerade() error { // Gets the wallet's chain ID func (w *masqueradeWallet) GetChainID() *big.Int { - copy := big.NewInt(0).Set(w.chainID) - return copy + return big.NewInt(0).Set(w.chainID) } // Add a keystore to the wallet diff --git a/shared/services/wallet/validator.go b/shared/services/wallet/validator.go index 03b2b6731..2a908f51f 100644 --- a/shared/services/wallet/validator.go +++ b/shared/services/wallet/validator.go @@ -128,10 +128,9 @@ func (w *hdWallet) LoadValidatorKey(pubkey types.ValidatorPubkey) (*eth2types.BL if len(errors) > 0 { // If there were errors, return them return nil, fmt.Errorf("encountered the following errors while trying to load the key for validator %s:\n%s", pubkey.Hex(), strings.Join(errors, "\n")) - } else { - // If there were no errors, the key just didn't exist - return nil, fmt.Errorf("couldn't find the key for validator %s in any of the wallet's keystores", pubkey.Hex()) } + // If there were no errors, the key just didn't exist + return nil, fmt.Errorf("couldn't find the key for validator %s in any of the wallet's keystores", pubkey.Hex()) } diff --git a/shared/services/wallet/wallet.go b/shared/services/wallet/wallet.go index 044e09ba7..1c5d813c7 100644 --- a/shared/services/wallet/wallet.go +++ b/shared/services/wallet/wallet.go @@ -217,8 +217,7 @@ func (w *hdWallet) EndMasquerade() error { // Gets the wallet's chain ID func (w *hdWallet) GetChainID() *big.Int { - copy := big.NewInt(0).Set(w.chainID) - return copy + return big.NewInt(0).Set(w.chainID) } // Add a keystore to the wallet diff --git a/shared/types/eth2/generic/state.go b/shared/types/eth2/generic/state.go index 51760e90c..3a1d90ca1 100644 --- a/shared/types/eth2/generic/state.go +++ b/shared/types/eth2/generic/state.go @@ -11,8 +11,6 @@ const beaconStateValidatorsMaxLength uint64 = 1 << 40 const BeaconStateHistoricalSummariesFieldIndex uint64 = 27 const BeaconStateHistoricalSummariesMaxLength uint64 = 1 << 24 -const beaconStateHistoricalSummaryChunkCeil uint64 = 2 -const beaconStateHistoricalSummaryBlockSummaryRootIndex uint64 = 0 const BeaconStateBlockRootsMaxLength uint64 = 1 << 13 const BeaconStateBlockRootsFieldIndex uint64 = 5 diff --git a/shared/utils/eth2/eth2.go b/shared/utils/eth2/eth2.go index ee29f29b3..55a84c593 100644 --- a/shared/utils/eth2/eth2.go +++ b/shared/utils/eth2/eth2.go @@ -20,7 +20,7 @@ import ( const MinipoolBalanceDetailsBatchSize = 20 // Beacon chain balance info for a minipool -type minipoolBalanceDetails struct { +type MinipoolBalanceDetails struct { IsStaking bool NodeDeposit *big.Int NodeBalance *big.Int @@ -33,16 +33,16 @@ func EpochAt(config beacon.Eth2Config, time uint64) uint64 { } // Get the balances of the minipools on the beacon chain -func GetBeaconBalances(rp *rocketpool.RocketPool, bc beacon.Client, addresses []common.Address, beaconHead beacon.BeaconHead, opts *bind.CallOpts) ([]minipoolBalanceDetails, error) { +func GetBeaconBalances(rp *rocketpool.RocketPool, bc beacon.Client, addresses []common.Address, beaconHead beacon.BeaconHead, opts *bind.CallOpts) ([]MinipoolBalanceDetails, error) { // Get minipool validator statuses validators, err := rputils.GetMinipoolValidators(rp, bc, addresses, opts, &beacon.ValidatorStatusOptions{Epoch: &beaconHead.Epoch}) if err != nil { - return []minipoolBalanceDetails{}, err + return []MinipoolBalanceDetails{}, err } // Load details in batches - details := make([]minipoolBalanceDetails, len(addresses)) + details := make([]MinipoolBalanceDetails, len(addresses)) for bsi := 0; bsi < len(addresses); bsi += MinipoolBalanceDetailsBatchSize { // Get batch start & end index @@ -56,7 +56,7 @@ func GetBeaconBalances(rp *rocketpool.RocketPool, bc beacon.Client, addresses [] wg.Go(func() error { address := addresses[mi] validator := validators[address] - mpDetails, err := GetMinipoolBalanceDetails(rp, address, opts, validator, beaconHead.Epoch) + mpDetails, err := getMinipoolBalanceDetails(rp, address, opts, validator, beaconHead.Epoch) if err == nil { details[mi] = mpDetails } @@ -64,7 +64,7 @@ func GetBeaconBalances(rp *rocketpool.RocketPool, bc beacon.Client, addresses [] }) } if err := wg.Wait(); err != nil { - return []minipoolBalanceDetails{}, err + return []MinipoolBalanceDetails{}, err } } @@ -74,10 +74,10 @@ func GetBeaconBalances(rp *rocketpool.RocketPool, bc beacon.Client, addresses [] } // Get the balances of the minipools on the beacon chain -func GetBeaconBalancesFromState(rp *rocketpool.RocketPool, mpds []*rpstate.NativeMinipoolDetails, state *state.NetworkState, beaconHead beacon.BeaconHead, opts *bind.CallOpts) ([]minipoolBalanceDetails, error) { +func GetBeaconBalancesFromState(rp *rocketpool.RocketPool, mpds []*rpstate.NativeMinipoolDetails, state *state.NetworkState, beaconHead beacon.BeaconHead, opts *bind.CallOpts) ([]MinipoolBalanceDetails, error) { // Load details in batches - details := make([]minipoolBalanceDetails, len(mpds)) + details := make([]MinipoolBalanceDetails, len(mpds)) for bsi := 0; bsi < len(mpds); bsi += MinipoolBalanceDetailsBatchSize { // Get batch start & end index @@ -89,7 +89,7 @@ func GetBeaconBalancesFromState(rp *rocketpool.RocketPool, mpds []*rpstate.Nativ for mi := msi; mi < mei; mi++ { mi := mi wg.Go(func() error { - mpDetails, err := GetMinipoolBalanceDetailsFromState(rp, mpds[mi], state, opts, beaconHead.Epoch) + mpDetails, err := getMinipoolBalanceDetailsFromState(rp, mpds[mi], state, opts, beaconHead.Epoch) if err == nil { details[mi] = mpDetails } @@ -97,7 +97,7 @@ func GetBeaconBalancesFromState(rp *rocketpool.RocketPool, mpds []*rpstate.Nativ }) } if err := wg.Wait(); err != nil { - return []minipoolBalanceDetails{}, err + return []MinipoolBalanceDetails{}, err } } @@ -107,12 +107,12 @@ func GetBeaconBalancesFromState(rp *rocketpool.RocketPool, mpds []*rpstate.Nativ } // Get minipool balance details -func GetMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common.Address, opts *bind.CallOpts, validator beacon.ValidatorStatus, blockEpoch uint64) (minipoolBalanceDetails, error) { +func getMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common.Address, opts *bind.CallOpts, validator beacon.ValidatorStatus, blockEpoch uint64) (MinipoolBalanceDetails, error) { // Create minipool mp, err := minipool.NewMinipool(rp, minipoolAddress, opts) if err != nil { - return minipoolBalanceDetails{}, err + return MinipoolBalanceDetails{}, err } blockBalance := eth.GweiToWei(float64(validator.Balance)) @@ -141,7 +141,7 @@ func GetMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common // Wait for data if err := wg.Wait(); err != nil { - return minipoolBalanceDetails{}, err + return MinipoolBalanceDetails{}, err } // Deal with pools that haven't received deposits yet so their balance is still 0 @@ -151,7 +151,7 @@ func GetMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common // Ignore finalized minipools if finalized { - return minipoolBalanceDetails{ + return MinipoolBalanceDetails{ NodeDeposit: big.NewInt(0), NodeBalance: big.NewInt(0), TotalBalance: big.NewInt(0), @@ -160,7 +160,7 @@ func GetMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common // Use node deposit balance if initialized or prelaunch if status == types.Initialized || status == types.Prelaunch { - return minipoolBalanceDetails{ + return MinipoolBalanceDetails{ NodeDeposit: nodeDepositBalance, NodeBalance: nodeDepositBalance, TotalBalance: blockBalance, @@ -169,7 +169,7 @@ func GetMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common // Use node deposit balance if validator not yet active on beacon chain at block if !validator.Exists || validator.ActivationEpoch >= blockEpoch { - return minipoolBalanceDetails{ + return MinipoolBalanceDetails{ NodeDeposit: nodeDepositBalance, NodeBalance: nodeDepositBalance, TotalBalance: blockBalance, @@ -179,11 +179,11 @@ func GetMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common // Get node balance at block nodeBalance, err := mp.CalculateNodeShare(blockBalance, opts) if err != nil { - return minipoolBalanceDetails{}, err + return MinipoolBalanceDetails{}, err } // Return - return minipoolBalanceDetails{ + return MinipoolBalanceDetails{ IsStaking: (validator.ExitEpoch > blockEpoch), NodeDeposit: nodeDepositBalance, NodeBalance: nodeBalance, @@ -193,12 +193,12 @@ func GetMinipoolBalanceDetails(rp *rocketpool.RocketPool, minipoolAddress common } // Get minipool balance details -func GetMinipoolBalanceDetailsFromState(rp *rocketpool.RocketPool, mpd *rpstate.NativeMinipoolDetails, state *state.NetworkState, opts *bind.CallOpts, blockEpoch uint64) (minipoolBalanceDetails, error) { +func getMinipoolBalanceDetailsFromState(rp *rocketpool.RocketPool, mpd *rpstate.NativeMinipoolDetails, state *state.NetworkState, opts *bind.CallOpts, blockEpoch uint64) (MinipoolBalanceDetails, error) { // Create minipool mp, err := minipool.NewMinipoolFromVersion(rp, mpd.MinipoolAddress, mpd.Version, opts) if err != nil { - return minipoolBalanceDetails{}, err + return MinipoolBalanceDetails{}, err } validator := state.MinipoolValidatorDetails[mpd.Pubkey] blockBalance := eth.GweiToWei(float64(validator.Balance)) @@ -215,7 +215,7 @@ func GetMinipoolBalanceDetailsFromState(rp *rocketpool.RocketPool, mpd *rpstate. // Ignore finalized minipools if finalized { - return minipoolBalanceDetails{ + return MinipoolBalanceDetails{ NodeDeposit: big.NewInt(0), NodeBalance: big.NewInt(0), TotalBalance: big.NewInt(0), @@ -224,7 +224,7 @@ func GetMinipoolBalanceDetailsFromState(rp *rocketpool.RocketPool, mpd *rpstate. // Use node deposit balance if initialized or prelaunch if status == types.Initialized || status == types.Prelaunch { - return minipoolBalanceDetails{ + return MinipoolBalanceDetails{ NodeDeposit: nodeDepositBalance, NodeBalance: nodeDepositBalance, TotalBalance: blockBalance, @@ -233,7 +233,7 @@ func GetMinipoolBalanceDetailsFromState(rp *rocketpool.RocketPool, mpd *rpstate. // Use node deposit balance if validator not yet active on beacon chain at block if !validator.Exists || validator.ActivationEpoch >= blockEpoch { - return minipoolBalanceDetails{ + return MinipoolBalanceDetails{ NodeDeposit: nodeDepositBalance, NodeBalance: nodeDepositBalance, TotalBalance: blockBalance, @@ -243,11 +243,11 @@ func GetMinipoolBalanceDetailsFromState(rp *rocketpool.RocketPool, mpd *rpstate. // Get node balance at block nodeBalance, err := mp.CalculateNodeShare(blockBalance, opts) if err != nil { - return minipoolBalanceDetails{}, err + return MinipoolBalanceDetails{}, err } // Return - return minipoolBalanceDetails{ + return MinipoolBalanceDetails{ IsStaking: (validator.ExitEpoch > blockEpoch), NodeDeposit: nodeDepositBalance, NodeBalance: nodeBalance, diff --git a/shared/utils/rp/config.go b/shared/utils/rp/config.go index af410d13a..fc0711adf 100644 --- a/shared/utils/rp/config.go +++ b/shared/utils/rp/config.go @@ -66,7 +66,7 @@ func SaveConfig(cfg *config.RocketPoolConfig, directory, filename string) error } for _, match := range oldFiles { - os.RemoveAll(match) + _ = os.RemoveAll(match) } }() 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/treegen/voting-power.go b/treegen/voting-power.go index 2b809b065..13837e08a 100644 --- a/treegen/voting-power.go +++ b/treegen/voting-power.go @@ -34,7 +34,7 @@ func getNodeVotingPower(s *state.NetworkState, nodeIdx int) *big.Int { continue } - activeMinipoolCount += 1 + activeMinipoolCount++ } // Get provided ETH (32 * minipoolCount - matched)