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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions bindings/legacy/v1.4.0/megapool/megapool-manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package megapool

import (
"fmt"
"sync"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"

"github.com/rocket-pool/smartnode/bindings/megapool"
"github.com/rocket-pool/smartnode/bindings/rocketpool"
"github.com/rocket-pool/smartnode/bindings/transactions/gaslimit"
)

// Estimate the gas of Stake
func EstimateStakeGas(rp *rocketpool.RocketPool, megapoolAddress common.Address, validatorId uint32, slotTimestamp uint64, validatorProof megapool.ValidatorProof, slotProof megapool.SlotProof, opts *bind.TransactOpts) (gaslimit.Limits, error) {
megapoolManager, err := getRocketMegapoolManager(rp, nil)
if err != nil {
return gaslimit.Limits{}, err
}
return megapoolManager.GetTransactionGasInfo(opts, "stake", megapoolAddress, validatorId, slotTimestamp, validatorProof, slotProof)
}

// Progress the prelaunch megapool to staking
func Stake(rp *rocketpool.RocketPool, megapoolAddress common.Address, validatorId uint32, slotTimestamp uint64, validatorProof megapool.ValidatorProof, slotProof megapool.SlotProof, opts *bind.TransactOpts) (*types.Transaction, error) {
megapoolManager, err := getRocketMegapoolManager(rp, nil)
if err != nil {
return nil, err
}
tx, err := megapoolManager.Transact(opts, "stake", megapoolAddress, validatorId, slotTimestamp, validatorProof, slotProof)
if err != nil {
return nil, fmt.Errorf("error staking megapool %s: %w", megapoolAddress, err)
}
return tx, nil
}

// Estimate the gas to call NotifyExit
func EstimateNotifyExitGas(rp *rocketpool.RocketPool, megapoolAddress common.Address, validatorId uint32, slotTimestamp uint64, validatorProof megapool.ValidatorProof, slotProof megapool.SlotProof, opts *bind.TransactOpts) (gaslimit.Limits, error) {
megapoolManager, err := getRocketMegapoolManager(rp, nil)
if err != nil {
return gaslimit.Limits{}, err
}
return megapoolManager.GetTransactionGasInfo(opts, "notifyExit", megapoolAddress, validatorId, slotTimestamp, validatorProof, slotProof)
}

// Notify the megapool that one of its validators is exiting
func NotifyExit(rp *rocketpool.RocketPool, megapoolAddress common.Address, validatorId uint32, slotTimestamp uint64, validatorProof megapool.ValidatorProof, slotProof megapool.SlotProof, opts *bind.TransactOpts) (*types.Transaction, error) {
megapoolManager, err := getRocketMegapoolManager(rp, nil)
if err != nil {
return nil, err
}
tx, err := megapoolManager.Transact(opts, "notifyExit", megapoolAddress, validatorId, slotTimestamp, validatorProof, slotProof)
if err != nil {
return nil, fmt.Errorf("error calling notify exit: %w", err)
}
return tx, nil
}

// Estimate the gas to call NotifyNotExit
func EstimateNotifyNotExitGas(rp *rocketpool.RocketPool, megapoolAddress common.Address, validatorId uint32, slotTimestamp uint64, validatorProof megapool.ValidatorProof, slotProof megapool.SlotProof, opts *bind.TransactOpts) (gaslimit.Limits, error) {
megapoolManager, err := getRocketMegapoolManager(rp, nil)
if err != nil {
return gaslimit.Limits{}, err
}
return megapoolManager.GetTransactionGasInfo(opts, "notifyNotExit", megapoolAddress, validatorId, slotTimestamp, validatorProof, slotProof)
}

// Used to prove a validator is not exiting after a challenge-exit
func NotifyNotExit(rp *rocketpool.RocketPool, megapoolAddress common.Address, validatorId uint32, slotTimestamp uint64, validatorProof megapool.ValidatorProof, slotProof megapool.SlotProof, opts *bind.TransactOpts) (*types.Transaction, error) {
megapoolManager, err := getRocketMegapoolManager(rp, nil)
if err != nil {
return nil, err
}
tx, err := megapoolManager.Transact(opts, "notifyNotExit", megapoolAddress, validatorId, slotTimestamp, validatorProof, slotProof)
if err != nil {
return nil, fmt.Errorf("error calling notify not exit: %w", err)
}
return tx, nil
}

// Estimate the gas to call NotifyFinalBalance
func EstimateNotifyFinalBalance(rp *rocketpool.RocketPool, megapoolAddress common.Address, validatorId uint32, slotTimestamp uint64, withdrawalProof megapool.WithdrawalProof, validatorProof megapool.ValidatorProof, slotProof megapool.SlotProof, opts *bind.TransactOpts) (gaslimit.Limits, error) {
megapoolManager, err := getRocketMegapoolManager(rp, nil)
if err != nil {
return gaslimit.Limits{}, err
}
return megapoolManager.GetTransactionGasInfo(opts, "notifyFinalBalance", megapoolAddress, validatorId, slotTimestamp, withdrawalProof, validatorProof, slotProof)
}

// Notify the megapool of the final balance of an exited validator
func NotifyFinalBalance(rp *rocketpool.RocketPool, megapoolAddress common.Address, validatorId uint32, slotTimestamp uint64, withdrawalProof megapool.WithdrawalProof, validatorProof megapool.ValidatorProof, slotProof megapool.SlotProof, opts *bind.TransactOpts) (*types.Transaction, error) {
megapoolManager, err := getRocketMegapoolManager(rp, nil)
if err != nil {
return nil, err
}
tx, err := megapoolManager.Transact(opts, "notifyFinalBalance", megapoolAddress, validatorId, slotTimestamp, withdrawalProof, validatorProof, slotProof)
if err != nil {
return nil, fmt.Errorf("error calling notify final balance: %w", err)
}
return tx, nil
}

// Estimate the gas to call DissolveWithProof
func EstimateDissolveWithProof(rp *rocketpool.RocketPool, megapoolAddress common.Address, validatorId uint32, slotTimestamp uint64, validatorProof megapool.ValidatorProof, slotProof megapool.SlotProof, opts *bind.TransactOpts) (gaslimit.Limits, error) {
megapoolManager, err := getRocketMegapoolManager(rp, nil)
if err != nil {
return gaslimit.Limits{}, err
}
return megapoolManager.GetTransactionGasInfo(opts, "dissolve", megapoolAddress, validatorId, slotTimestamp, validatorProof, slotProof)
}

// Dissolve a validator using a proof that it used wrong credentials
func DissolveWithProof(rp *rocketpool.RocketPool, megapoolAddress common.Address, validatorId uint32, slotTimestamp uint64, validatorProof megapool.ValidatorProof, slotProof megapool.SlotProof, opts *bind.TransactOpts) (*types.Transaction, error) {
megapoolManager, err := getRocketMegapoolManager(rp, nil)
if err != nil {
return nil, err
}
tx, err := megapoolManager.Transact(opts, "dissolve", megapoolAddress, validatorId, slotTimestamp, validatorProof, slotProof)
if err != nil {
return nil, fmt.Errorf("error calling dissolve with proof: %w", err)
}
return tx, nil
}

var rocketMegapoolManagerLock sync.Mutex

func getRocketMegapoolManager(rp *rocketpool.RocketPool, opts *bind.CallOpts) (*rocketpool.Contract, error) {
rocketMegapoolManagerLock.Lock()
defer rocketMegapoolManagerLock.Unlock()
return rp.GetContract("rocketMegapoolManager", opts)
}
12 changes: 12 additions & 0 deletions bindings/megapool/beacon-state-verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,15 @@ func GetBeaconStateVerifierVersion(rp *rocketpool.RocketPool, opts *bind.CallOpt
}
return rocketpool.GetContractVersion(rp, *beaconStateVerifier.Address, opts)
}

func UsesProofBundles(rp *rocketpool.RocketPool, opts *bind.CallOpts) (bool, error) {
version, err := GetBeaconStateVerifierVersion(rp, opts)
if err != nil {
return false, err
}
return usesProofBundles(version), nil
}

func usesProofBundles(beaconStateVerifierVersion uint8) bool {
return beaconStateVerifierVersion >= 2
}
11 changes: 2 additions & 9 deletions rocketpool-cli/megapool/notify-final-balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func getNotifiableValidator() (uint64, uint64, bool, error) {
continue
}
if validator.Exiting {
if validator.BeaconStatus.Status == beacon.ValidatorState_WithdrawalDone {
if beacon.HasFinalBalanceWithdrawal(validator.BeaconStatus) {
readyValidators = append(readyValidators, validator)
} else {
pendingValidators = append(pendingValidators, validator)
Expand Down Expand Up @@ -139,14 +139,7 @@ func printPendingFinalBalanceValidator(v api.MegapoolValidatorDetails, currentEp
if withdrawableEpoch != 0 && withdrawableEpoch != FarFutureEpoch {
fmt.Printf(" withdrawable_epoch: %d%s\n", withdrawableEpoch, epochTimingSuffix(withdrawableEpoch, currentEpoch, secondsPerEpoch))
if currentEpoch >= withdrawableEpoch {
switch bs.Status {
case beacon.ValidatorState_WithdrawalPossible:
fmt.Printf(" note: withdrawable; waiting for the beacon withdrawal sweep (full balance)\n")
case beacon.ValidatorState_ExitedUnslashed, beacon.ValidatorState_ExitedSlashed:
fmt.Printf(" note: exited; waiting to become withdrawal_possible, then for the sweep\n")
default:
fmt.Printf(" note: withdrawable epoch reached; waiting for full withdrawal (status %s)\n", bs.Status)
}
fmt.Printf(" note: %s\n", beacon.FinalBalanceSweepNote(bs))
}
} else {
fmt.Printf(" withdrawable_epoch: not yet set on finalized state\n")
Expand Down
12 changes: 2 additions & 10 deletions rocketpool/api/megapool/dissolve-with-proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ func canDissolveWithProof(c *cli.Command, validatorId uint32) (*api.CanDissolveW
if err != nil {
return nil, err
}
proofData, err := megapool.EncodeValidatorProofBundleV1(proof, slotProof)
if err != nil {
return nil, err
}

if !validatorInfo.InPrestake {
response.CanDissolve = false
Expand All @@ -105,7 +101,7 @@ func canDissolveWithProof(c *cli.Command, validatorId uint32) (*api.CanDissolveW
if err != nil {
return nil, err
}
gasLimits, err := megapool.EstimateDissolveWithProof(rp, megapoolAddress, validatorId, slotTimestamp, megapool.ValidatorProofVersion1, proofData, opts)
gasLimits, err := services.EstimateMegapoolDissolveWithProofGas(rp, megapoolAddress, validatorId, slotTimestamp, proof, slotProof, opts)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -171,13 +167,9 @@ func dissolveWithProof(c *cli.Command, validatorId uint32, t *snroute.TransactOp
if err != nil {
return nil, err
}
proofData, err := megapool.EncodeValidatorProofBundleV1(validatorProof, slotProof)
if err != nil {
return nil, err
}

// Dissolve
tx, err := megapool.DissolveWithProof(rp, megapoolAddress, validatorId, slotTimestamp, megapool.ValidatorProofVersion1, proofData, opts)
tx, err := services.DissolveMegapoolWithProof(rp, megapoolAddress, validatorId, slotTimestamp, validatorProof, slotProof, opts)
if err != nil {
return nil, err
}
Expand Down
11 changes: 5 additions & 6 deletions rocketpool/api/megapool/notify-final-balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,18 @@ func canNotifyFinalBalance(c *cli.Command, validatorId uint32, withdrawalSlot ui
withdrawalSlot = validatorStatus.WithdrawableEpoch * 32
}

proofVersion, proofData, slotTimestamp, err := services.GetFinalBalanceProofBundle(c, withdrawalSlot, validatorIndex, types.ValidatorPubkey(validatorInfo.Pubkey), megapoolAddress, w)
opts, err := w.GetNodeAccountTransactor()
if err != nil {
return nil, err
}

opts, err := w.GetNodeAccountTransactor()
proof, err := services.BuildMegapoolFinalBalanceProof(c, rp, megapoolAddress, withdrawalSlot, validatorIndex, types.ValidatorPubkey(validatorInfo.Pubkey), w)
if err != nil {
return nil, err
}

// Notify the validator exit
gasLimits, err := megapool.EstimateNotifyFinalBalance(rp, megapoolAddress, validatorId, slotTimestamp, proofVersion, proofData, opts)
gasLimits, err := services.EstimateMegapoolNotifyFinalBalanceGas(rp, megapoolAddress, validatorId, proof, opts)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -157,13 +157,12 @@ func notifyFinalBalance(c *cli.Command, validatorId uint32, withdrawalSlot uint6
withdrawalSlot = validatorStatus.WithdrawableEpoch * 32
}

proofVersion, proofData, slotTimestamp, err := services.GetFinalBalanceProofBundle(c, withdrawalSlot, validatorIndex, types.ValidatorPubkey(validatorInfo.Pubkey), megapoolAddress, w)
proof, err := services.BuildMegapoolFinalBalanceProof(c, rp, megapoolAddress, withdrawalSlot, validatorIndex, types.ValidatorPubkey(validatorInfo.Pubkey), w)
if err != nil {
return nil, err
}

// Notify the validator exit
tx, err := megapool.NotifyFinalBalance(rp, megapoolAddress, validatorId, slotTimestamp, proofVersion, proofData, opts)
tx, err := services.NotifyMegapoolFinalBalance(rp, megapoolAddress, validatorId, proof, opts)
if err != nil {
return nil, err
}
Expand Down
12 changes: 2 additions & 10 deletions rocketpool/api/megapool/notify-validator-exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,18 +126,14 @@ func canNotifyValidatorExit(c *cli.Command, validatorId uint32) (*api.CanNotifyV
if err != nil {
return nil, err
}
proofData, err := megapool.EncodeValidatorProofBundleV1(proof, slotProof)
if err != nil {
return nil, err
}

opts, err := w.GetNodeAccountTransactor()
if err != nil {
return nil, err
}

// Notify the validator exit
gasLimits, err := megapool.EstimateNotifyExitGas(rp, megapoolAddress, validatorId, slotTimestamp, megapool.ValidatorProofVersion1, proofData, opts)
gasLimits, err := services.EstimateMegapoolNotifyExitGas(rp, megapoolAddress, validatorId, slotTimestamp, proof, slotProof, opts)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -215,13 +211,9 @@ func notifyValidatorExit(c *cli.Command, validatorId uint32, t *snroute.Transact
if err != nil {
return nil, err
}
proofData, err := megapool.EncodeValidatorProofBundleV1(validatorProof, slotProof)
if err != nil {
return nil, err
}

// Notify the validator exit
tx, err := megapool.NotifyExit(rp, megapoolAddress, validatorId, slotTimetamp, megapool.ValidatorProofVersion1, proofData, opts)
tx, err := services.NotifyMegapoolExit(rp, megapoolAddress, validatorId, slotTimetamp, validatorProof, slotProof, opts)
if err != nil {
return nil, err
}
Expand Down
12 changes: 2 additions & 10 deletions rocketpool/api/megapool/stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,13 @@ func canStake(c *cli.Command, validatorId uint64) (*api.CanStakeResponse, error)
}
return nil, err
}
proofData, err := megapool.EncodeValidatorProofBundleV1(validatorProof, slotProof)
if err != nil {
return nil, err
}

// Get gas estimate
opts, err := w.GetNodeAccountTransactor()
if err != nil {
return nil, err
}
gasLimits, err := megapool.EstimateStakeGas(rp, megapoolAddress, uint32(validatorId), slotTimestamp, megapool.ValidatorProofVersion1, proofData, opts)
gasLimits, err := services.EstimateMegapoolStakeGas(rp, megapoolAddress, uint32(validatorId), slotTimestamp, validatorProof, slotProof, opts)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -175,13 +171,9 @@ func stake(c *cli.Command, validatorId uint64, t *snroute.TransactOpts) (*api.St
if err != nil {
return nil, err
}
proofData, err := megapool.EncodeValidatorProofBundleV1(validatorProof, slotProof)
if err != nil {
return nil, err
}

// Stake
tx, err := megapool.Stake(rp, megapoolAddress, uint32(validatorId), slotTimestamp, megapool.ValidatorProofVersion1, proofData, opts)
tx, err := services.StakeMegapool(rp, megapoolAddress, uint32(validatorId), slotTimestamp, validatorProof, slotProof, opts)
if err != nil {
return nil, err
}
Expand Down
16 changes: 6 additions & 10 deletions rocketpool/node/defend-challenge-exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,29 +156,25 @@ func (t *defendChallengeExit) defendChallenge(rp *rocketpool.RocketPool, mp mega
return err
}

t.log.Printlnf("[STARTED] Crafting a validator proof. This process can take several seconds and is CPU and memory intensive. If you don't see a [FINISHED] log entry your system may not have enough resources to perform this operation.")
t.log.Printlnf("Crafting a validator proof.")

validatorProof, slotTimestamp, slotProof, err := services.GetValidatorProof(t.c, 0, t.w, state.BeaconConfig, mp.GetAddress(), validatorPubkey, nil)
if err != nil {
t.log.Printlnf("[ERROR] There was an error during the proof creation process: %w", err)
return err
}
proofData, err := megapool.EncodeValidatorProofBundleV1(validatorProof, slotProof)
if err != nil {
return err
}

t.log.Printlnf("[FINISHED] The beacon state proof has been successfully created.")
t.log.Printlnf("The beacon state proof has been successfully created.")
var gasLimits gaslimit.Limits

if !exiting {
// Get the gas limit
gasLimits, err = megapool.EstimateNotifyNotExitGas(rp, mp.GetAddress(), validatorId, slotTimestamp, megapool.ValidatorProofVersion1, proofData, opts)
gasLimits, err = services.EstimateMegapoolNotifyNotExitGas(rp, mp.GetAddress(), validatorId, slotTimestamp, validatorProof, slotProof, opts)
if err != nil {
return err
}
} else {
gasLimits, err = megapool.EstimateNotifyExitGas(rp, mp.GetAddress(), validatorId, slotTimestamp, megapool.ValidatorProofVersion1, proofData, opts)
gasLimits, err = services.EstimateMegapoolNotifyExitGas(rp, mp.GetAddress(), validatorId, slotTimestamp, validatorProof, slotProof, opts)
if err != nil {
return err
}
Expand Down Expand Up @@ -206,13 +202,13 @@ func (t *defendChallengeExit) defendChallenge(rp *rocketpool.RocketPool, mp mega
var tx *coretypes.Transaction
if !exiting {
t.log.Printlnf("Notifying that validator %d is not exiting.", validatorId)
tx, err = megapool.NotifyNotExit(rp, mp.GetAddress(), validatorId, slotTimestamp, megapool.ValidatorProofVersion1, proofData, opts)
tx, err = services.NotifyMegapoolNotExit(rp, mp.GetAddress(), validatorId, slotTimestamp, validatorProof, slotProof, opts)
if err != nil {
return err
}
} else {
t.log.Printlnf("Notifying that validator %d is exiting.", validatorId)
tx, err = megapool.NotifyExit(rp, mp.GetAddress(), validatorId, slotTimestamp, megapool.ValidatorProofVersion1, proofData, opts)
tx, err = services.NotifyMegapoolExit(rp, mp.GetAddress(), validatorId, slotTimestamp, validatorProof, slotProof, opts)
if err != nil {
return err
}
Expand Down
Loading
Loading