Skip to content

Commit

Permalink
make status significantly faster
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrower95 committed Sep 5, 2024
1 parent ad25e3f commit e53e4e9
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 81 deletions.
7 changes: 6 additions & 1 deletion cli/core/checkpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,13 @@ func GenerateCheckpointProofForState(ctx context.Context, eigenpodAddress string
color.Yellow("You have a total of %d validators pointed to this pod.", len(allValidators))
}

allValidatorsWithInfo, err := FetchMultipleOnchainValidatorInfo(eth, eigenpodAddress, allValidators)
if err != nil {
return nil, err
}

tracing.OnStartSection("SelectCheckpointableValidators", map[string]string{})
checkpointValidators, err := SelectCheckpointableValidators(eth, eigenpodAddress, allValidators, currentCheckpointTimestamp)
checkpointValidators, err := SelectCheckpointableValidators(eth, eigenpodAddress, allValidatorsWithInfo, currentCheckpointTimestamp)
if err != nil {
return nil, err
}
Expand Down
33 changes: 15 additions & 18 deletions cli/core/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ type EigenpodStatus struct {
MustForceCheckpoint bool
}

func getRegularBalancesGwei(allValidators []ValidatorWithIndex, state *spec.VersionedBeaconState) []phase0.Gwei {
func getRegularBalancesGwei(state *spec.VersionedBeaconState) []phase0.Gwei {
validatorBalances, err := state.ValidatorBalances()
PanicOnError("failed to load validator balances", err)

return validatorBalances
}

func sumActiveValidatorBeaconBalancesGwei(allValidators []ValidatorWithIndex, allBalances []phase0.Gwei, state *spec.VersionedBeaconState) phase0.Gwei {
func sumActiveValidatorBeaconBalancesGwei(allValidators []ValidatorWithOnchainInfo, allBalances []phase0.Gwei, state *spec.VersionedBeaconState) phase0.Gwei {
var sumGwei phase0.Gwei = 0

for i := 0; i < len(allValidators); i++ {
Expand All @@ -75,18 +75,12 @@ func sumActiveValidatorBeaconBalancesGwei(allValidators []ValidatorWithIndex, al
return sumGwei
}

func sumRestakedBalancesGwei(eth *ethclient.Client, eigenpodAddress string, activeValidators []ValidatorWithIndex) (phase0.Gwei, error) {
func sumRestakedBalancesGwei(eth *ethclient.Client, eigenpodAddress string, activeValidators []ValidatorWithOnchainInfo) (phase0.Gwei, error) {
var sumGwei phase0.Gwei = 0

validatorInfos, err := GetOnchainValidatorInfo(eth, eigenpodAddress, activeValidators)
if err != nil {
return 0, err
}

for i := 0; i < len(activeValidators); i++ {
validatorInfo := validatorInfos[i]

sumGwei += phase0.Gwei(validatorInfo.RestakedBalanceGwei)
validator := activeValidators[i]
sumGwei += phase0.Gwei(validator.Info.RestakedBalanceGwei)
}

return sumGwei, nil
Expand All @@ -106,15 +100,18 @@ func GetStatus(ctx context.Context, eigenpodAddress string, eth *ethclient.Clien
checkpointTimestamp, state, err := GetCheckpointTimestampAndBeaconState(ctx, eigenpodAddress, eth, beaconClient)
PanicOnError("failed to fetch checkpoint and beacon state", err)

allValidators, err := FindAllValidatorsForEigenpod(eigenpodAddress, state)
allValidatorsForEigenpod, err := FindAllValidatorsForEigenpod(eigenpodAddress, state)
PanicOnError("failed to find validators", err)

allBeaconBalances := getRegularBalancesGwei(allValidators, state)
allValidatorsWithInfoForEigenpod, err := FetchMultipleOnchainValidatorInfo(eth, eigenpodAddress, allValidatorsForEigenpod)
PanicOnError("failed to fetch validator info", err)

activeValidators, err := SelectActiveValidators(eth, eigenpodAddress, allValidators)
allBeaconBalances := getRegularBalancesGwei(state)

activeValidators, err := SelectActiveValidators(eth, eigenpodAddress, allValidatorsWithInfoForEigenpod)
PanicOnError("failed to find active validators", err)

checkpointableValidators, err := SelectCheckpointableValidators(eth, eigenpodAddress, allValidators, checkpointTimestamp)
checkpointableValidators, err := SelectCheckpointableValidators(eth, eigenpodAddress, allValidatorsWithInfoForEigenpod, checkpointTimestamp)
PanicOnError("failed to find checkpointable validators", err)

sumBeaconBalancesGwei := new(big.Float).SetUint64(uint64(sumActiveValidatorBeaconBalancesGwei(activeValidators, allBeaconBalances, state)))
Expand All @@ -123,9 +120,9 @@ func GetStatus(ctx context.Context, eigenpodAddress string, eth *ethclient.Clien
PanicOnError("failed to calculate sum of onchain validator balances", err)
sumRestakedBalancesGwei := new(big.Float).SetUint64(uint64(sumRestakedBalancesU64))

for i := 0; i < len(allValidators); i++ {
validator := allValidators[i].Validator
validatorIndex := allValidators[i].Index
for i := 0; i < len(allValidatorsForEigenpod); i++ {
validator := allValidatorsForEigenpod[i].Validator
validatorIndex := allValidatorsForEigenpod[i].Index

validatorInfo, err := eigenPod.ValidatorPubkeyToInfo(nil, validator.PublicKey[:])
PanicOnError("failed to fetch validator info", err)
Expand Down
88 changes: 30 additions & 58 deletions cli/core/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
gethCommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
Expand Down Expand Up @@ -98,26 +97,14 @@ type ValidatorWithIndex = struct {
Index uint64
}

func withDryRun(opts *bind.TransactOpts) *bind.TransactOpts {
// golang doesn't have a spread operator for structs smh
return &bind.TransactOpts{
From: opts.From,
Nonce: opts.Nonce,
Signer: opts.Signer,

Value: opts.Value,
GasPrice: opts.GasPrice,
GasFeeCap: opts.GasFeeCap,
GasTipCap: opts.GasTipCap,
GasLimit: 0, // Gas limit to set for the transaction execution (0 = estimate)

Context: opts.Context, // Network context to support cancellation and timeouts (nil = no timeout)
NoSend: true, // Do all transact steps but do not send the transaction
}
type ValidatorWithOnchainInfo = struct {
Info onchain.IEigenPodValidatorInfo
Validator *phase0.Validator
Index uint64
}

type Owner = struct {
FromAddress gethCommon.Address
FromAddress common.Address
PublicKey *ecdsa.PublicKey
TransactionOptions *bind.TransactOpts
IsDryRun bool
Expand All @@ -129,7 +116,7 @@ func StartCheckpoint(ctx context.Context, eigenpodAddress string, ownerPrivateKe
return nil, fmt.Errorf("failed to parse private key: %w", err)
}

eigenPod, err := onchain.NewEigenPod(gethCommon.HexToAddress(eigenpodAddress), eth)
eigenPod, err := onchain.NewEigenPod(common.HexToAddress(eigenpodAddress), eth)
if err != nil {
return nil, fmt.Errorf("failed to reach eigenpod: %w", err)
}
Expand Down Expand Up @@ -293,13 +280,13 @@ func FindAllValidatorsForEigenpod(eigenpodAddress string, beaconState *spec.Vers
return outputValidators, nil
}

func GetOnchainValidatorInfo(client *ethclient.Client, eigenpodAddress string, allValidators []ValidatorWithIndex) ([]onchain.IEigenPodValidatorInfo, error) {
func FetchMultipleOnchainValidatorInfo(client *ethclient.Client, eigenpodAddress string, allValidators []ValidatorWithIndex) ([]ValidatorWithOnchainInfo, error) {
eigenPod, err := onchain.NewEigenPod(common.HexToAddress(eigenpodAddress), client)
if err != nil {
return nil, fmt.Errorf("failed to locate Eigenpod. Is your address correct?: %w", err)
}

var validatorInfo []onchain.IEigenPodValidatorInfo = []onchain.IEigenPodValidatorInfo{}
var validators []ValidatorWithOnchainInfo = []ValidatorWithOnchainInfo{}

// TODO: batch/multicall
zeroes := [16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
Expand All @@ -316,10 +303,14 @@ func GetOnchainValidatorInfo(client *ethclient.Client, eigenpodAddress string, a
if err != nil {
return nil, fmt.Errorf("failed to fetch validator eigeninfo: %w", err)
}
validatorInfo = append(validatorInfo, info)
validators = append(validators, ValidatorWithOnchainInfo{
Index: allValidators[i].Index,
Validator: allValidators[i].Validator,
Info: info,
})
}

return validatorInfo, nil
return validators, nil
}

func GetCurrentCheckpointBlockRoot(eigenpodAddress string, eth *ethclient.Client) (*[32]byte, error) {
Expand Down Expand Up @@ -510,21 +501,15 @@ func WriteOutputToFileOrStdout(output []byte, out *string) error {
func SelectCheckpointableValidators(
client *ethclient.Client,
eigenpodAddress string,
validators []ValidatorWithIndex,
validators []ValidatorWithOnchainInfo,
lastCheckpoint uint64,
) ([]ValidatorWithIndex, error) {
validatorInfos, err := GetOnchainValidatorInfo(client, eigenpodAddress, validators)
if err != nil {
return nil, err
}

var checkpointValidators = []ValidatorWithIndex{}
) ([]ValidatorWithOnchainInfo, error) {
var checkpointValidators = []ValidatorWithOnchainInfo{}
for i := 0; i < len(validators); i++ {
validator := validators[i]
validatorInfo := validatorInfos[i]

notCheckpointed := (validatorInfo.LastCheckpointedAt != lastCheckpoint) || (validatorInfo.LastCheckpointedAt == 0)
isActive := validatorInfo.Status == ValidatorStatusActive
notCheckpointed := (validator.Info.LastCheckpointedAt != lastCheckpoint) || (validator.Info.LastCheckpointedAt == 0)
isActive := validator.Info.Status == ValidatorStatusActive

if notCheckpointed && isActive {
checkpointValidators = append(checkpointValidators, validator)
Expand All @@ -541,9 +526,9 @@ const FAR_FUTURE_EPOCH = math.MaxUint64
func SelectAwaitingActivationValidators(
client *ethclient.Client,
eigenpodAddress string,
validators []ValidatorWithIndex,
) ([]ValidatorWithIndex, error) {
var awaitingActivationValidators = []ValidatorWithIndex{}
validators []ValidatorWithOnchainInfo,
) ([]ValidatorWithOnchainInfo, error) {
var awaitingActivationValidators = []ValidatorWithOnchainInfo{}
for i := 0; i < len(validators); i++ {
validator := validators[i]

Expand All @@ -557,19 +542,13 @@ func SelectAwaitingActivationValidators(
func SelectAwaitingCredentialValidators(
client *ethclient.Client,
eigenpodAddress string,
validators []ValidatorWithIndex,
) ([]ValidatorWithIndex, error) {
validatorInfos, err := GetOnchainValidatorInfo(client, eigenpodAddress, validators)
if err != nil {
return nil, err
}

var awaitingCredentialValidators = []ValidatorWithIndex{}
validators []ValidatorWithOnchainInfo,
) ([]ValidatorWithOnchainInfo, error) {
var awaitingCredentialValidators = []ValidatorWithOnchainInfo{}
for i := 0; i < len(validators); i++ {
validator := validators[i]
validatorInfo := validatorInfos[i]

if (validatorInfo.Status == ValidatorStatusInactive) &&
if (validator.Info.Status == ValidatorStatusInactive) &&
(validator.Validator.ExitEpoch == FAR_FUTURE_EPOCH) &&
(validator.Validator.ActivationEpoch != FAR_FUTURE_EPOCH) {
awaitingCredentialValidators = append(awaitingCredentialValidators, validator)
Expand All @@ -581,19 +560,12 @@ func SelectAwaitingCredentialValidators(
func SelectActiveValidators(
client *ethclient.Client,
eigenpodAddress string,
validators []ValidatorWithIndex,
) ([]ValidatorWithIndex, error) {
validatorInfos, err := GetOnchainValidatorInfo(client, eigenpodAddress, validators)
if err != nil {
return nil, err
}

var activeValidators = []ValidatorWithIndex{}
validators []ValidatorWithOnchainInfo,
) ([]ValidatorWithOnchainInfo, error) {
var activeValidators = []ValidatorWithOnchainInfo{}
for i := 0; i < len(validators); i++ {
validator := validators[i]
validatorInfo := validatorInfos[i]

if validatorInfo.Status == ValidatorStatusActive {
if validator.Info.Status == ValidatorStatusActive {
activeValidators = append(activeValidators, validator)
}
}
Expand Down
17 changes: 13 additions & 4 deletions cli/core/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

eigenpodproofs "github.com/Layr-Labs/eigenpod-proofs-generation"
"github.com/Layr-Labs/eigenpod-proofs-generation/cli/core/onchain"
"github.com/Layr-Labs/eigenpod-proofs-generation/cli/utils"
v1 "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/go-eth2-client/spec"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -176,11 +177,19 @@ func GenerateValidatorProofAtState(proofs *eigenpodproofs.EigenPodProofs, eigenp
}
} else {
// default behavior -- load any validators that are inactive / need a credential proof
awaitingCredentialValidators, err = SelectAwaitingCredentialValidators(eth, eigenpodAddress, allValidators)
}
allValidatorsWithInfo, err := FetchMultipleOnchainValidatorInfo(eth, eigenpodAddress, allValidators)
if err != nil {
return nil, fmt.Errorf("failed to load validator information: %s", err.Error())
}

if err != nil {
return nil, fmt.Errorf("failed to find validators awaiting credential proofs: %w", err)
_awaitingCredentialValidators, err := SelectAwaitingCredentialValidators(eth, eigenpodAddress, allValidatorsWithInfo)
if err != nil {
return nil, fmt.Errorf("failed to select awaiting credential validators: %s", err.Error())
}

awaitingCredentialValidators = utils.Map(_awaitingCredentialValidators, func(validator ValidatorWithOnchainInfo, index uint64) ValidatorWithIndex {
return ValidatorWithIndex{Index: validator.Index, Validator: validator.Validator}
})
}

if len(awaitingCredentialValidators) == 0 {
Expand Down

0 comments on commit e53e4e9

Please sign in to comment.