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

Operator opt-out #171

Merged
merged 13 commits into from
May 23, 2024
22 changes: 20 additions & 2 deletions operator/avs_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/Layr-Labs/eigensdk-go/crypto/bls"
sdklogging "github.com/Layr-Labs/eigensdk-go/logging"
eigentypes "github.com/Layr-Labs/eigensdk-go/types"
eigenutils "github.com/Layr-Labs/eigensdk-go/chainio/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
Expand All @@ -35,7 +36,7 @@ type AvsManagerer interface {
operatorEcdsaKeyPair *ecdsa.PrivateKey,
blsKeyPair *bls.KeyPair,
) error

DeregisterOperator(blsKeyPair *bls.KeyPair) error
GetOperatorId(options *bind.CallOpts, address common.Address) ([32]byte, error)
GetCheckpointTaskCreatedChan() <-chan *taskmanager.ContractSFFLTaskManagerCheckpointTaskCreated
GetOperatorSetUpdateChan() <-chan messages.OperatorSetUpdateMessage
Expand All @@ -58,7 +59,9 @@ type AvsManager struct {
logger sdklogging.Logger
}

func NewAvsManager(config *optypes.NodeConfig, ethRpcClient eth.Client, ethWsClient eth.Client, sdkClients *clients.Clients, txManager *txmgr.SimpleTxManager, logger sdklogging.Logger) (*AvsManager, error) {
var _ AvsManagerer = (*AvsManager)(nil)

func NewAvsManager(config *optypes.NodeConfig, ethRpcClient eth.Client, ethWsClient eth.Client, sdkClients *clients.Clients, txManager txmgr.TxManager, logger sdklogging.Logger) (*AvsManager, error) {
avsWriter, err := chainio.BuildAvsWriter(
txManager, common.HexToAddress(config.AVSRegistryCoordinatorAddress),
common.HexToAddress(config.OperatorStateRetrieverAddress), ethRpcClient, logger,
Expand Down Expand Up @@ -285,6 +288,21 @@ func (avsManager *AvsManager) RegisterOperatorWithAvs(
return nil
}

func (avsManager *AvsManager) DeregisterOperator(blsKeyPair *bls.KeyPair) error {
// TODO: 'QuorumNums' is hardcoded for now
quorumNumbers := eigentypes.QuorumNums{0}
pubKey := eigenutils.ConvertToBN254G1Point(blsKeyPair.GetPubKeyG1())

_, err := avsManager.avsWriter.DeregisterOperator(context.Background(), quorumNumbers, pubKey)
if err != nil {
avsManager.logger.Errorf("Unable to deregister operator with avs registry coordinator: %v", err)
return err
}
avsManager.logger.Infof("Deregistered operator with avs registry coordinator.")
emlautarom1 marked this conversation as resolved.
Show resolved Hide resolved

return nil
}

func (avsManager *AvsManager) IsOperatorRegistered(options *bind.CallOpts, address common.Address) (bool, error) {
return avsManager.avsReader.IsOperatorRegistered(options, address)
}
Expand Down
3 changes: 1 addition & 2 deletions operator/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"github.com/Layr-Labs/eigensdk-go/nodeapi"
"github.com/Layr-Labs/eigensdk-go/signerv2"
eigentypes "github.com/Layr-Labs/eigensdk-go/types"
sdktypes "github.com/Layr-Labs/eigensdk-go/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -184,7 +183,7 @@ func NewOperatorFromConfig(c optypes.NodeConfig) (*Operator, error) {

// We must register the economic metrics separately because they are exported metrics (from jsonrpc or subgraph calls)
// and not instrumented metrics: see https://prometheus.io/docs/instrumenting/writing_clientlibs/#overall-structure
quorumNames := map[sdktypes.QuorumNum]string{
quorumNames := map[eigentypes.QuorumNum]string{
0: "quorum0",
}
economicMetricsCollector := economic.NewCollector(
Expand Down
72 changes: 40 additions & 32 deletions plugin/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/Layr-Labs/eigensdk-go/chainio/clients/eth"
"github.com/Layr-Labs/eigensdk-go/chainio/clients/wallet"
"github.com/Layr-Labs/eigensdk-go/chainio/txmgr"
regcoord "github.com/Layr-Labs/eigensdk-go/contracts/bindings/RegistryCoordinator"
"github.com/Layr-Labs/eigensdk-go/crypto/bls"
sdkecdsa "github.com/Layr-Labs/eigensdk-go/crypto/ecdsa"
"github.com/Layr-Labs/eigensdk-go/logging"
Expand Down Expand Up @@ -78,7 +77,7 @@ func main() {
}
}

func plugin(ctx *cli.Context) {
func plugin(ctx *cli.Context) error {
goCtx := context.Background()
logger, _ := logging.NewZapLogger(logging.Development)

Expand All @@ -89,7 +88,7 @@ func plugin(ctx *cli.Context) {
err := utils.ReadYamlConfig(configPath, &avsConfig)
if err != nil {
logger.Error("Failed to read config", "err", err)
return
return err
}

logger.Info("Starting with config", "avsConfig", avsConfig)
Expand All @@ -107,30 +106,30 @@ func plugin(ctx *cli.Context) {
ethHttpClient, err := eth.NewClient(avsConfig.EthRpcUrl)
if err != nil {
logger.Error("Failed to connect to eth client", "err", err)
return
return err
}
chainID, err := ethHttpClient.ChainID(goCtx)
if err != nil {
logger.Error("Failed to get chain ID", "err", err)
return
return err
}
signerV2, _, err := signerv2.SignerFromConfig(signerv2.Config{
KeystorePath: avsConfig.EcdsaPrivateKeyStorePath,
Password: ecdsaKeyPassword,
}, chainID)
if err != nil {
logger.Error("Failed to create signer", "err", err)
return
return err
}
ecdsaPrivateKey, err := sdkecdsa.ReadKey(avsConfig.EcdsaPrivateKeyStorePath, ecdsaKeyPassword)
if err != nil {
logger.Error("Failed to read ecdsa private key", "err", err)
return
return err
}
clients, err := sdkclients.BuildAll(buildClientConfig, ecdsaPrivateKey, logger)
if err != nil {
logger.Error("Failed to create sdk clients", "err", err)
return
return err
}
avsReader, err := chainio.BuildAvsReader(
common.HexToAddress(avsConfig.AVSRegistryCoordinatorAddress),
Expand All @@ -140,12 +139,12 @@ func plugin(ctx *cli.Context) {
)
if err != nil {
logger.Error("Failed to create avs reader", "err", err)
return
return err
}
txSender, err := wallet.NewPrivateKeyWallet(ethHttpClient, signerV2, common.HexToAddress(avsConfig.OperatorAddress), logger)
if err != nil {
logger.Error("Failed to create tx sender", "err", err)
return
return err
}
txMgr := txmgr.NewSimpleTxManager(txSender, ethHttpClient, logger, common.HexToAddress(avsConfig.OperatorAddress)).WithGasLimitMultiplier(1.5)
avsWriter, err := chainio.BuildAvsWriter(
Expand All @@ -157,12 +156,12 @@ func plugin(ctx *cli.Context) {
)
if err != nil {
logger.Error("Failed to create avs writer", "err", err)
return
return err
}
avsManager, err := operator.NewAvsManager(&avsConfig, clients.EthHttpClient, clients.EthWsClient, clients, txMgr, logger)
if err != nil {
logger.Error("Failed to create avs manager", "err", err)
return
return err
}

if operationType == "opt-in" {
Expand All @@ -171,7 +170,7 @@ func plugin(ctx *cli.Context) {
blsKeypair, err := bls.ReadPrivateKeyFromFile(avsConfig.BlsPrivateKeyStorePath, blsKeyPassword)
if err != nil {
logger.Error("Failed to read bls private key", "err", err)
return
return err
}

operatorEcdsaPrivateKey, err := sdkecdsa.ReadKey(
Expand All @@ -180,60 +179,69 @@ func plugin(ctx *cli.Context) {
)
if err != nil {
logger.Error("Failed to read operator ecdsa private key", "err", err)
return
return err
}

avsManager.RegisterOperatorWithAvs(ethHttpClient, operatorEcdsaPrivateKey, blsKeypair)
err = avsManager.RegisterOperatorWithAvs(ethHttpClient, operatorEcdsaPrivateKey, blsKeypair)
if (err != nil) {
logger.Error("Failed to register operator with avs", "err", err)
return err
}
} else if operationType == "opt-out" {
fmt.Println("Opting out of slashing - unimplemented")
blsKeyPassword := ctx.GlobalString(BlsKeyPasswordFlag.Name)

blsKeypair, err := bls.ReadPrivateKeyFromFile(avsConfig.BlsPrivateKeyStorePath, blsKeyPassword)
if err != nil {
logger.Error("Failed to read bls private key", "err", err)
return err
}

err = avsManager.DeregisterOperator(blsKeypair)
if (err != nil) {
logger.Error("Failed to deregister operator", "err", err)
return err
}
} else if operationType == "deposit" {
starategyAddrString := ctx.GlobalString(StrategyAddrFlag.Name)
if len(starategyAddrString) == 0 {
logger.Error("Strategy address is required for deposit operation")
return
return err
}
strategyAddr := common.HexToAddress(ctx.GlobalString(StrategyAddrFlag.Name))
_, tokenAddr, err := clients.ElChainReader.GetStrategyAndUnderlyingToken(&bind.CallOpts{}, strategyAddr)
if err != nil {
logger.Error("Failed to fetch strategy contract", "err", err)
return
return err
}
contractErc20Mock, err := avsReader.GetErc20Mock(context.Background(), tokenAddr)
if err != nil {
logger.Error("Failed to fetch ERC20Mock contract", "err", err)
return
return err
}
txOpts, err := avsWriter.TxMgr.GetNoSendTxOpts()
if err != nil {
logger.Error("Failed to get tx opts", "err", err)
return
return err
}
amount := big.NewInt(1000)
tx, err := contractErc20Mock.Mint(txOpts, common.HexToAddress(avsConfig.OperatorAddress), amount)
if err != nil {
logger.Error("Failed to assemble Mint tx", "err", err)
return
return err
}
_, err = avsWriter.TxMgr.Send(context.Background(), tx)
if err != nil {
logger.Error("Failed to submit Mint tx", "err", err)
return
return err
}

_, err = clients.ElChainWriter.DepositERC20IntoStrategy(context.Background(), strategyAddr, amount)
if err != nil {
logger.Error("Failed to deposit into strategy", "err", err)
return
return err
}
return
} else {
logger.Error("Invalid operation type")
}
}

func pubKeyG1ToBN254G1Point(p *bls.G1Point) regcoord.BN254G1Point {
return regcoord.BN254G1Point{
X: p.X.BigInt(new(big.Int)),
Y: p.Y.BigInt(new(big.Int)),
return cli.NewExitError(fmt.Sprintf("Invalid operation type: %v", operationType), 1)
}
return nil
}
Loading