Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v0.2.0] Major CLI Refactor / Cleanup #127

Merged
merged 3 commits into from
Aug 14, 2024
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
75 changes: 75 additions & 0 deletions cli/commands/assignSubmitter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package commands

import (
"context"
"fmt"

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

type TAssignSubmitterArgs struct {
Node string
TargetAddress string
Sender string
EigenpodAddress string
NoPrompt bool
Verbose bool
}

func AssignSubmitterCommand(args TAssignSubmitterArgs) error {
ctx := context.Background()

if len(args.TargetAddress) == 0 {
return fmt.Errorf("usage: `assign-submitter <0xsubmitter>`")
} else if !common.IsHexAddress(args.TargetAddress) {
return fmt.Errorf("invalid address for 0xsubmitter: %s", args.TargetAddress)
}

eth, err := ethclient.Dial(args.Node)
if err != nil {
return fmt.Errorf("failed to reach eth --node: %w", err)
}

chainId, err := eth.ChainID(ctx)
if err != nil {
return fmt.Errorf("failed to reach eth node for chain id: %w", err)
}

ownerAccount, err := core.PrepareAccount(&args.Sender, chainId, false /* noSend */)
if err != nil {
return fmt.Errorf("failed to parse --sender: %w", err)
}

pod, err := onchain.NewEigenPod(common.HexToAddress(args.EigenpodAddress), eth)
if err != nil {
return fmt.Errorf("error contacting eigenpod: %w", err)
}

// Check that the existing submitter is not the current submitter
newSubmitter := common.HexToAddress(args.TargetAddress)
currentSubmitter, err := pod.ProofSubmitter(nil)
if err != nil {
return fmt.Errorf("error fetching current proof submitter: %w", err)
} else if currentSubmitter.Cmp(newSubmitter) == 0 {
return fmt.Errorf("error: new proof submitter is existing proof submitter (%s)", currentSubmitter)
}

if !args.NoPrompt {
fmt.Printf("Your pod's current proof submitter is %s.\n", currentSubmitter)
core.PanicIfNoConsent(fmt.Sprintf("This will update your EigenPod to allow %s to submit proofs on its behalf. As the EigenPod's owner, you can always change this later.", newSubmitter))
}

txn, err := pod.SetProofSubmitter(ownerAccount.TransactionOptions, newSubmitter)
if err != nil {
return fmt.Errorf("error updating submitter role: %w", err)
}

color.Green("submitted txn: %s", txn.Hash())
color.Green("updated!")

return nil
}
110 changes: 110 additions & 0 deletions cli/commands/checkpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package commands

import (
"context"

"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/ethereum/go-ethereum/core/types"
"github.com/fatih/color"
"github.com/pkg/errors"
)

type TCheckpointCommandArgs struct {
EigenpodAddress string
Node string
BeaconNode string
Sender string
DisableColor bool
NoPrompt bool
SimulateTransaction bool
BatchSize uint64
ForceCheckpoint bool
Verbose bool
}

func CheckpointCommand(args TCheckpointCommandArgs) error {
ctx := context.Background()

if args.DisableColor {
color.NoColor = true
}

isVerbose := !args.SimulateTransaction || args.Verbose

if args.SimulateTransaction && len(args.Sender) > 0 {
core.Panic("if using `--print-calldata`, please do not specify a sender.")
return nil
}

eth, beaconClient, chainId, err := core.GetClients(ctx, args.Node, args.BeaconNode, isVerbose)
core.PanicOnError("failed to reach ethereum clients", err)

currentCheckpoint, err := core.GetCurrentCheckpoint(args.EigenpodAddress, eth)
core.PanicOnError("failed to load checkpoint", err)

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

if currentCheckpoint == 0 {
if len(args.Sender) > 0 || args.SimulateTransaction {
if !args.NoPrompt && !args.SimulateTransaction {
core.PanicIfNoConsent(core.StartCheckpointProofConsent())
}
Comment on lines +53 to +55
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do the inverse of this boolean statement?

if args.NoPrompt || args.SimulateTransaction

The current version is making my head hurt :(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dam this is what i get for coding past 11


txn, err := core.StartCheckpoint(ctx, args.EigenpodAddress, args.Sender, chainId, eth, args.ForceCheckpoint, args.SimulateTransaction)
core.PanicOnError("failed to start checkpoint", err)

if !args.SimulateTransaction {
color.Green("starting checkpoint: %s.. (waiting for txn to be mined)", txn.Hash().Hex())
bind.WaitMined(ctx, eth, txn)
color.Green("started checkpoint! txn: %s", txn.Hash().Hex())
} else {
printProofs([]Transaction{
{
Type: "checkpoint_start",
To: txn.To().Hex(),
CallData: common.Bytes2Hex(txn.Data()),
},
})

return nil
}

newCheckpoint, err := eigenpod.CurrentCheckpointTimestamp(nil)
core.PanicOnError("failed to fetch current checkpoint", err)

currentCheckpoint = newCheckpoint
} else {
core.PanicOnError("no checkpoint active and no private key provided to start one", errors.New("no checkpoint"))
}
}

if isVerbose {
color.Green("pod has active checkpoint! checkpoint timestamp: %d", currentCheckpoint)
}

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

txns, err := core.SubmitCheckpointProof(ctx, args.Sender, args.EigenpodAddress, chainId, proof, eth, args.BatchSize, args.NoPrompt, args.SimulateTransaction)
if args.SimulateTransaction {
printableTxns := aMap(txns, func(txn *types.Transaction) Transaction {
return Transaction{
To: txn.To().Hex(),
CallData: common.Bytes2Hex(txn.Data()),
Type: "checkpoint_proof",
}
})
printProofs(printableTxns)
} else {
for i, txn := range txns {
color.Green("transaction(%d): %s", i, txn.Hash().Hex())
}
}
core.PanicOnError("an error occurred while submitting your checkpoint proofs", err)

return nil
}
92 changes: 92 additions & 0 deletions cli/commands/credentials.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package commands

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

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

type TCredentialCommandArgs struct {
EigenpodAddress string

DisableColor bool
UseJSON bool
SimulateTransaction bool
Node string
BeaconNode string
Sender string
SpecificValidator uint64
BatchSize uint64
NoPrompt bool
Verbose bool
}

func CredentialsCommand(args TCredentialCommandArgs) error {
ctx := context.Background()
if args.DisableColor {
color.NoColor = true
}

isVerbose := (!args.UseJSON && !args.SimulateTransaction) || args.Verbose

eth, beaconClient, chainId, err := core.GetClients(ctx, args.Node, args.BeaconNode, isVerbose)
core.PanicOnError("failed to reach ethereum clients", err)

if args.SimulateTransaction && len(args.Sender) > 0 {
core.Panic("if using --print-calldata, please do not specify a --sender.")
return nil
}

var specificValidatorIndex *big.Int = nil
if args.SpecificValidator != math.MaxUint64 && args.SpecificValidator != 0 {
specificValidatorIndex = new(big.Int).SetUint64(args.SpecificValidator)
if isVerbose {
fmt.Printf("Using specific validator: %d", args.SpecificValidator)
}
}

validatorProofs, oracleBeaconTimestamp, err := core.GenerateValidatorProof(ctx, args.EigenpodAddress, eth, chainId, beaconClient, specificValidatorIndex, isVerbose)

if err != nil || validatorProofs == nil {
core.PanicOnError("Failed to generate validator proof", err)
core.Panic("no inactive validators")
}

if len(args.Sender) != 0 || args.SimulateTransaction {
txns, indices, err := core.SubmitValidatorProof(ctx, args.Sender, args.EigenpodAddress, chainId, eth, args.BatchSize, validatorProofs, oracleBeaconTimestamp, args.NoPrompt, args.SimulateTransaction, isVerbose)
core.PanicOnError(fmt.Sprintf("failed to %s validator proof", func() string {
if args.SimulateTransaction {
return "simulate"
} else {
return "submit"
}
}()), err)

if args.SimulateTransaction {
out := aMap(txns, func(txn *types.Transaction) CredentialProofTransaction {
return CredentialProofTransaction{
Transaction: Transaction{
Type: "credential_proof",
To: txn.To().Hex(),
CallData: common.Bytes2Hex(txn.Data()),
},
ValidatorIndices: aMap(aFlatten(indices), func(index *big.Int) uint64 {
return index.Uint64()
}),
}
})
printProofs(out)
} else {
for i, txn := range txns {
color.Green("transaction(%d): %s", i, txn.Hash().Hex())
}
}
}
return nil
}
Loading
Loading