Skip to content

Commit

Permalink
squash
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrower95 committed Aug 20, 2024
1 parent 224588b commit 30fb7b3
Show file tree
Hide file tree
Showing 9 changed files with 493 additions and 2 deletions.
46 changes: 46 additions & 0 deletions cli/commands/findStalePods.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package commands

import (
"context"
"encoding/json"
"fmt"

"github.com/Layr-Labs/eigenpod-proofs-generation/cli/core"
"github.com/fatih/color"
)

type TFindStalePodsCommandArgs struct {
EthNode string
BeaconNode string
Verbose bool
}

func FindStalePodsCommand(args TFindStalePodsCommandArgs) error {
ctx := context.Background()
eth, beacon, chainId, err := core.GetClients(ctx, args.EthNode, args.BeaconNode /* verbose */, args.Verbose)
core.PanicOnError("failed to dial clients", err)

results, err := core.FindStaleEigenpods(ctx, eth, args.EthNode, beacon, chainId, args.Verbose)
core.PanicOnError("failed to find stale eigenpods", err)

if !args.Verbose {
// just print json and be done
jsonStr, _ := json.MarshalIndent(results, "", " ")
fmt.Println(string(jsonStr))
return nil
}

for pod, res := range results {
color.Red("pod %s\n", pod)
for _, validator := range res {
fmt.Printf("\t[#%d] (%s) - %d\n", validator.Index, func() string {
if validator.Validator.Slashed {
return "slashed"
} else {
return "not slashed"
}
}(), validator.Validator.EffectiveBalance)
}
}
return nil
}
106 changes: 106 additions & 0 deletions cli/commands/staleBalance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package commands

import (
"context"
"fmt"
"math/big"

eigenpodproofs "github.com/Layr-Labs/eigenpod-proofs-generation"
"github.com/Layr-Labs/eigenpod-proofs-generation/cli/core"
"github.com/Layr-Labs/eigenpod-proofs-generation/cli/core/onchain"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/fatih/color"
)

type TFixStaleBalanceArgs struct {
EthNode string
BeaconNode string
Sender string
EigenpodAddress string
SlashedValidatorIndex int64
Verbose bool
CheckpointBatchSize uint64
NoPrompt bool
}

// another fun cast brought to you by golang!
func proofCast(proof []eigenpodproofs.Bytes32) [][32]byte {
res := make([][32]byte, len(proof))
for i, elt := range proof {
res[i] = elt
}
return res
}

func FixStaleBalance(args TFixStaleBalanceArgs) error {
ctx := context.Background()

eth, beacon, chainId, err := core.GetClients(ctx, args.EthNode, args.BeaconNode, args.Verbose)
core.PanicOnError("failed to get clients", err)

validator, err := beacon.GetValidator(ctx, uint64(args.SlashedValidatorIndex))
core.PanicOnError("failed to fetch validator state", err)

if !validator.Validator.Slashed {
core.Panic("Provided validator was not slashed.")
return nil
}

ownerAccount, err := core.PrepareAccount(&args.Sender, chainId, false /* noSend */)
core.PanicOnError("failed to parse sender PK", err)

eigenpod, err := onchain.NewEigenPod(common.HexToAddress(args.EigenpodAddress), eth)
core.PanicOnError("failed to reach eigenpod", err)

currentCheckpointTimestamp, err := eigenpod.CurrentCheckpointTimestamp(nil)
core.PanicOnError("failed to fetch any existing checkpoint info", err)

if currentCheckpointTimestamp > 0 {
if args.Verbose {
color.Red("This eigenpod has an outstanding checkpoint (since %d). You must complete it before continuing.", currentCheckpointTimestamp)
}

proofs, err := core.GenerateCheckpointProof(ctx, args.EigenpodAddress, eth, chainId, beacon)
core.PanicOnError("failed to generate checkpoint proofs", err)

txns, err := core.SubmitCheckpointProof(ctx, args.Sender, args.EigenpodAddress, chainId, proofs, eth, args.CheckpointBatchSize, args.NoPrompt /* noSend */, false)
core.PanicOnError("failed to submit checkpoint proofs", err)

for i, txn := range txns {
if args.Verbose {
fmt.Printf("sending txn[%d/%d]: %s (waiting)...", i, len(txns), txn.Hash())
}
bind.WaitMined(ctx, eth, txn)
}
}

proof, oracleBeaconTimesetamp, err := core.GenerateValidatorProof(ctx, args.EigenpodAddress, eth, chainId, beacon, new(big.Int).SetUint64(uint64(args.SlashedValidatorIndex)), args.Verbose)
core.PanicOnError("failed to generate credential proof for slashed validator", err)

if !args.NoPrompt {
core.PanicIfNoConsent("This will invoke `EigenPod.verifyStaleBalance()` on the given eigenpod, which will start a checkpoint. Once started, this checkpoint must be completed.")
}

if args.Verbose {
color.Black("Calling verifyStaleBalance() to update pod.")
}

txn, err := eigenpod.VerifyStaleBalance(
ownerAccount.TransactionOptions,
oracleBeaconTimesetamp,
onchain.BeaconChainProofsStateRootProof{
Proof: proof.StateRootProof.Proof.ToByteSlice(),
BeaconStateRoot: proof.StateRootProof.BeaconStateRoot,
},
onchain.BeaconChainProofsValidatorProof{
ValidatorFields: proofCast(proof.ValidatorFields[0]),
Proof: proof.ValidatorFieldsProofs[0].ToByteSlice(),
},
)
core.PanicOnError("failed to call verifyStaleBalance()", err)

fmt.Printf("txn: %s\n", txn.Hash())

return nil
}
26 changes: 26 additions & 0 deletions cli/core/beaconClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
v1 "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/go-eth2-client/http"
"github.com/attestantio/go-eth2-client/spec"
"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
Expand All @@ -23,6 +24,7 @@ var (
type BeaconClient interface {
GetBeaconHeader(ctx context.Context, blockId string) (*v1.BeaconBlockHeader, error)
GetBeaconState(ctx context.Context, stateId string) (*spec.VersionedBeaconState, error)
GetValidator(ctx context.Context, index uint64) (*v1.Validator, error)
}

type beaconClient struct {
Expand Down Expand Up @@ -65,6 +67,30 @@ func (b *beaconClient) GetBeaconHeader(ctx context.Context, blockId string) (*v1
return nil, ErrBeaconClientNotSupported
}

func (b *beaconClient) GetValidator(ctx context.Context, index uint64) (*v1.Validator, error) {
if provider, ok := b.eth2client.(eth2client.ValidatorsProvider); ok {
opts := api.ValidatorsOpts{
State: "head",
Indices: []phase0.ValidatorIndex{phase0.ValidatorIndex(index)},
}
singleValidorInfoResponse, err := provider.Validators(ctx, &opts)
if err != nil {
return nil, err
}

if singleValidorInfoResponse == nil {
return nil, errors.New("beacon state is nil")
}

if b.verbose {
log.Info().Msg("finished download")
}
return singleValidorInfoResponse.Data[phase0.ValidatorIndex(index)], nil
}

return nil, ErrBeaconClientNotSupported
}

func (b *beaconClient) GetBeaconState(ctx context.Context, stateId string) (*spec.VersionedBeaconState, error) {
timeout, _ := time.ParseDuration("200s")
if provider, ok := b.eth2client.(eth2client.BeaconStateProvider); ok {
Expand Down
Loading

0 comments on commit 30fb7b3

Please sign in to comment.