diff --git a/aggregator/aggregator.go b/aggregator/aggregator.go index 806fa7dea..eac2a301e 100644 --- a/aggregator/aggregator.go +++ b/aggregator/aggregator.go @@ -2,6 +2,9 @@ package aggregator import ( "context" + "github.com/Layr-Labs/eigensdk-go/chainio/clients/eth" + "github.com/Layr-Labs/eigensdk-go/chainio/txmgr" + "github.com/Layr-Labs/eigensdk-go/signerv2" "sync" "time" @@ -89,49 +92,67 @@ type Aggregator struct { // NewAggregator creates a new Aggregator with the provided config. // TODO: Remove this context once OperatorPubkeysServiceInMemory's API is // changed and we can gracefully exit otherwise -func NewAggregator(ctx context.Context, c *config.Config) (*Aggregator, error) { - avsReader, err := chainio.BuildAvsReaderFromConfig(c) +func NewAggregator(config *config.Config, logger logging.Logger, ctx context.Context) (*Aggregator, error) { + ethHttpClient, err := eth.NewClient(config.EthHttpRpcUrl) if err != nil { - c.Logger.Error("Cannot create avsReader", "err", err) + logger.Errorf("Cannot create http ethclient", "err", err) return nil, err } - avsWriter, err := chainio.BuildAvsWriterFromConfig(c) + avsReader, err := chainio.BuildAvsReader(config.SFFLRegistryCoordinatorAddr, config.OperatorStateRetrieverAddr, ethHttpClient, logger) if err != nil { - c.Logger.Errorf("Cannot create avsWriter", "err", err) + logger.Error("Cannot create avsReader", "err", err) + return nil, err + } + + chainId, err := ethHttpClient.ChainID(context.Background()) + if err != nil { + logger.Error("Cannot get chainId", "err", err) + return nil, err + } + + signerV2, _, err := signerv2.SignerFromConfig(signerv2.Config{PrivateKey: config.EcdsaPrivateKey}, chainId) + if err != nil { + panic(err) + } + txMgr := txmgr.NewSimpleTxManager(ethHttpClient, logger, signerV2, config.AggregatorAddress) + + avsWriter, err := chainio.BuildAvsWriter(txMgr, config.SFFLRegistryCoordinatorAddr, config.OperatorStateRetrieverAddr, ethHttpClient, logger) + if err != nil { + logger.Errorf("Cannot create avsWriter", "err", err) return nil, err } chainioConfig := sdkclients.BuildAllConfig{ - EthHttpUrl: c.EthHttpRpcUrl, - EthWsUrl: c.EthWsRpcUrl, - RegistryCoordinatorAddr: c.SFFLRegistryCoordinatorAddr.String(), - OperatorStateRetrieverAddr: c.OperatorStateRetrieverAddr.String(), + EthHttpUrl: config.EthHttpRpcUrl, + EthWsUrl: config.EthWsRpcUrl, + RegistryCoordinatorAddr: config.SFFLRegistryCoordinatorAddr.String(), + OperatorStateRetrieverAddr: config.OperatorStateRetrieverAddr.String(), AvsName: avsName, PromMetricsIpPortAddress: ":9090", } - clients, err := clients.BuildAll(chainioConfig, c.AggregatorAddress, c.SignerFn, c.Logger) + clients, err := clients.BuildAll(chainioConfig, config.AggregatorAddress, signerV2, logger) if err != nil { - c.Logger.Errorf("Cannot create sdk clients", "err", err) + logger.Errorf("Cannot create sdk clients", "err", err) return nil, err } - msgDb, err := NewMessageDatabase(c.AggregatorDatabasePath) + msgDb, err := NewMessageDatabase(config.AggregatorDatabasePath) if err != nil { - c.Logger.Errorf("Cannot create database", "err", err) + logger.Errorf("Cannot create database", "err", err) return nil, err } - operatorPubkeysService := oppubkeysserv.NewOperatorPubkeysServiceInMemory(ctx, clients.AvsRegistryChainSubscriber, clients.AvsRegistryChainReader, c.Logger) - avsRegistryService := avsregistry.NewAvsRegistryServiceChainCaller(avsReader, operatorPubkeysService, c.Logger) - taskBlsAggregationService := blsagg.NewBlsAggregatorService(avsRegistryService, c.Logger) - stateRootUpdateBlsAggregationService := NewMessageBlsAggregatorService(avsRegistryService, clients.EthHttpClient, c.Logger) - operatorSetUpdateBlsAggregationService := NewMessageBlsAggregatorService(avsRegistryService, clients.EthHttpClient, c.Logger) + operatorPubkeysService := oppubkeysserv.NewOperatorPubkeysServiceInMemory(ctx, clients.AvsRegistryChainSubscriber, clients.AvsRegistryChainReader, logger) + avsRegistryService := avsregistry.NewAvsRegistryServiceChainCaller(avsReader, operatorPubkeysService, logger) + taskBlsAggregationService := blsagg.NewBlsAggregatorService(avsRegistryService, logger) + stateRootUpdateBlsAggregationService := NewMessageBlsAggregatorService(avsRegistryService, clients.EthHttpClient, logger) + operatorSetUpdateBlsAggregationService := NewMessageBlsAggregatorService(avsRegistryService, clients.EthHttpClient, logger) return &Aggregator{ - logger: c.Logger, - serverIpPortAddr: c.AggregatorServerIpPortAddr, - restServerIpPortAddr: c.AggregatorRestServerIpPortAddr, + logger: logger, + serverIpPortAddr: config.AggregatorServerIpPortAddr, + restServerIpPortAddr: config.AggregatorRestServerIpPortAddr, avsWriter: avsWriter, avsReader: avsReader, taskBlsAggregationService: taskBlsAggregationService, diff --git a/aggregator/cmd/main.go b/aggregator/cmd/main.go index 1f9b2415b..43aa5c6fd 100644 --- a/aggregator/cmd/main.go +++ b/aggregator/cmd/main.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + sdklogging "github.com/Layr-Labs/eigensdk-go/logging" "log" "os" @@ -37,19 +38,29 @@ func main() { func aggregatorMain(ctx *cli.Context) error { log.Println("Initializing Aggregator") - config, err := config.NewConfig(ctx) + + rawConfig := config.NewRawConfig(ctx) + logger, err := sdklogging.NewZapLogger(rawConfig.Environment) if err != nil { return err } - configJson, err := json.MarshalIndent(config, "", " ") + + config, err := config.NewConfig(rawConfig, ctx) if err != nil { - config.Logger.Fatalf(err.Error()) + logger.Error("Error creating config", "err", err) + return err } - fmt.Println("Config:", string(configJson)) - bgCtx := context.Background() + { + configJson, err := json.MarshalIndent(config, "", " ") + if err != nil { + logger.Fatalf(err.Error()) + } + fmt.Println("Config:", string(configJson)) + } - agg, err := aggregator.NewAggregator(bgCtx, config) + bgCtx := context.Background() + agg, err := aggregator.NewAggregator(config, logger, bgCtx) if err != nil { return err } diff --git a/core/chainio/avs_reader.go b/core/chainio/avs_reader.go index bfffbbe2c..73a1e85cf 100644 --- a/core/chainio/avs_reader.go +++ b/core/chainio/avs_reader.go @@ -15,7 +15,6 @@ import ( erc20mock "github.com/NethermindEth/near-sffl/contracts/bindings/ERC20Mock" opsetupdatereg "github.com/NethermindEth/near-sffl/contracts/bindings/SFFLOperatorSetUpdateRegistry" taskmanager "github.com/NethermindEth/near-sffl/contracts/bindings/SFFLTaskManager" - "github.com/NethermindEth/near-sffl/core/config" ) type AvsReaderer interface { @@ -37,9 +36,6 @@ type AvsReader struct { var _ AvsReaderer = (*AvsReader)(nil) -func BuildAvsReaderFromConfig(c *config.Config) (*AvsReader, error) { - return BuildAvsReader(c.SFFLRegistryCoordinatorAddr, c.OperatorStateRetrieverAddr, c.EthHttpClient, c.Logger) -} func BuildAvsReader(registryCoordinatorAddr, operatorStateRetrieverAddr gethcommon.Address, ethHttpClient eth.EthClient, logger logging.Logger) (*AvsReader, error) { avsManagersBindings, err := NewAvsManagersBindings(registryCoordinatorAddr, operatorStateRetrieverAddr, ethHttpClient, logger) if err != nil { diff --git a/core/chainio/avs_subscriber.go b/core/chainio/avs_subscriber.go index ed0135061..ed0327764 100644 --- a/core/chainio/avs_subscriber.go +++ b/core/chainio/avs_subscriber.go @@ -11,7 +11,6 @@ import ( opsetupdatereg "github.com/NethermindEth/near-sffl/contracts/bindings/SFFLOperatorSetUpdateRegistry" taskmanager "github.com/NethermindEth/near-sffl/contracts/bindings/SFFLTaskManager" - "github.com/NethermindEth/near-sffl/core/config" ) type AvsSubscriberer interface { @@ -30,15 +29,6 @@ type AvsSubscriber struct { logger sdklogging.Logger } -func BuildAvsSubscriberFromConfig(config *config.Config) (*AvsSubscriber, error) { - return BuildAvsSubscriber( - config.SFFLRegistryCoordinatorAddr, - config.OperatorStateRetrieverAddr, - config.EthWsClient, - config.Logger, - ) -} - func BuildAvsSubscriber(registryCoordinatorAddr, blsOperatorStateRetrieverAddr gethcommon.Address, ethclient eth.EthClient, logger sdklogging.Logger) (*AvsSubscriber, error) { avsContractBindings, err := NewAvsManagersBindings(registryCoordinatorAddr, blsOperatorStateRetrieverAddr, ethclient, logger) if err != nil { diff --git a/core/chainio/avs_writer.go b/core/chainio/avs_writer.go index 21d027a3c..060568333 100644 --- a/core/chainio/avs_writer.go +++ b/core/chainio/avs_writer.go @@ -12,7 +12,6 @@ import ( logging "github.com/Layr-Labs/eigensdk-go/logging" taskmanager "github.com/NethermindEth/near-sffl/contracts/bindings/SFFLTaskManager" - "github.com/NethermindEth/near-sffl/core/config" ) type AvsWriterer interface { @@ -49,10 +48,6 @@ type AvsWriter struct { var _ AvsWriterer = (*AvsWriter)(nil) -func BuildAvsWriterFromConfig(c *config.Config) (*AvsWriter, error) { - return BuildAvsWriter(c.TxMgr, c.SFFLRegistryCoordinatorAddr, c.OperatorStateRetrieverAddr, c.EthHttpClient, c.Logger) -} - func BuildAvsWriter(txMgr txmgr.TxManager, registryCoordinatorAddr, operatorStateRetrieverAddr gethcommon.Address, ethHttpClient eth.EthClient, logger logging.Logger) (*AvsWriter, error) { avsServiceBindings, err := NewAvsManagersBindings(registryCoordinatorAddr, operatorStateRetrieverAddr, ethHttpClient, logger) if err != nil { diff --git a/core/config/config.go b/core/config/config.go index 10afa3f73..3b96d8aef 100644 --- a/core/config/config.go +++ b/core/config/config.go @@ -1,20 +1,17 @@ package config import ( - "context" "crypto/ecdsa" "errors" + "fmt" "os" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/urfave/cli" - "github.com/Layr-Labs/eigensdk-go/chainio/clients/eth" - "github.com/Layr-Labs/eigensdk-go/chainio/txmgr" "github.com/Layr-Labs/eigensdk-go/crypto/bls" sdklogging "github.com/Layr-Labs/eigensdk-go/logging" - "github.com/Layr-Labs/eigensdk-go/signerv2" sdkutils "github.com/Layr-Labs/eigensdk-go/utils" ) @@ -23,14 +20,11 @@ import ( type Config struct { EcdsaPrivateKey *ecdsa.PrivateKey BlsPrivateKey *bls.PrivateKey - Logger sdklogging.Logger EigenMetricsIpPortAddress string // we need the url for the eigensdk currently... eventually standardize api so as to // only take an ethclient or an rpcUrl (and build the ethclient at each constructor site) EthHttpRpcUrl string EthWsRpcUrl string - EthHttpClient eth.EthClient - EthWsClient eth.EthClient OperatorStateRetrieverAddr common.Address SFFLRegistryCoordinatorAddr common.Address AggregatorServerIpPortAddr string @@ -38,8 +32,6 @@ type Config struct { AggregatorDatabasePath string RegisterOperatorOnStartup bool // json:"-" skips this field when marshaling (only used for logging to stdout), since SignerFn doesnt implement marshalJson - SignerFn signerv2.SignerFn `json:"-"` - TxMgr txmgr.TxManager AggregatorAddress common.Address } @@ -63,17 +55,20 @@ type SFFLContractsRaw struct { OperatorStateRetrieverAddr string `json:"operatorStateRetriever"` } -// NewConfig parses config file to read from from flags or environment variables -// Note: This config is shared by challenger and aggregator and so we put in the core. -// Operator has a different config and is meant to be used by the operator CLI. -func NewConfig(ctx *cli.Context) (*Config, error) { - - var configRaw ConfigRaw +func NewRawConfig(ctx *cli.Context) ConfigRaw { + var rawConfig ConfigRaw configFilePath := ctx.GlobalString(ConfigFileFlag.Name) if configFilePath != "" { - sdkutils.ReadYamlConfig(configFilePath, &configRaw) + sdkutils.ReadYamlConfig(configFilePath, &rawConfig) } + return rawConfig +} + +// NewConfig parses config file to read from from flags or environment variables +// Note: This config is shared by challenger and aggregator and so we put in the core. +// Operator has a different config and is meant to be used by the operator CLI. +func NewConfig(configRaw ConfigRaw, ctx *cli.Context) (*Config, error) { var sfflDeploymentRaw SFFLDeploymentRaw sfflDeploymentFilePath := ctx.GlobalString(SFFLDeploymentFileFlag.Name) if _, err := os.Stat(sfflDeploymentFilePath); errors.Is(err, os.ErrNotExist) { @@ -81,75 +76,41 @@ func NewConfig(ctx *cli.Context) (*Config, error) { } sdkutils.ReadJsonConfig(sfflDeploymentFilePath, &sfflDeploymentRaw) - logger, err := sdklogging.NewZapLogger(configRaw.Environment) - if err != nil { - return nil, err - } - - ethRpcClient, err := eth.NewClient(configRaw.EthRpcUrl) - if err != nil { - logger.Errorf("Cannot create http ethclient", "err", err) - return nil, err - } - - ethWsClient, err := eth.NewClient(configRaw.EthWsUrl) - if err != nil { - logger.Errorf("Cannot create ws ethclient", "err", err) - return nil, err - } - ecdsaPrivateKeyString := ctx.GlobalString(EcdsaPrivateKeyFlag.Name) if ecdsaPrivateKeyString[:2] == "0x" { ecdsaPrivateKeyString = ecdsaPrivateKeyString[2:] } + ecdsaPrivateKey, err := crypto.HexToECDSA(ecdsaPrivateKeyString) if err != nil { - logger.Errorf("Cannot parse ecdsa private key", "err", err) - return nil, err + return nil, fmt.Errorf("Cannot parse ecdsa private key: %w", err) } aggregatorAddr, err := sdkutils.EcdsaPrivateKeyToAddress(ecdsaPrivateKey) if err != nil { - logger.Error("Cannot get operator address", "err", err) - return nil, err + return nil, fmt.Errorf("cannot parse ecdsa private key: %w", err) } - chainId, err := ethRpcClient.ChainID(context.Background()) - if err != nil { - logger.Error("Cannot get chainId", "err", err) - return nil, err - } - - signerV2, _, err := signerv2.SignerFromConfig(signerv2.Config{PrivateKey: ecdsaPrivateKey}, chainId) - if err != nil { - panic(err) - } - txMgr := txmgr.NewSimpleTxManager(ethRpcClient, logger, signerV2, aggregatorAddr) - config := &Config{ EcdsaPrivateKey: ecdsaPrivateKey, - Logger: logger, EthWsRpcUrl: configRaw.EthWsUrl, EthHttpRpcUrl: configRaw.EthRpcUrl, - EthHttpClient: ethRpcClient, - EthWsClient: ethWsClient, OperatorStateRetrieverAddr: common.HexToAddress(sfflDeploymentRaw.Addresses.OperatorStateRetrieverAddr), SFFLRegistryCoordinatorAddr: common.HexToAddress(sfflDeploymentRaw.Addresses.RegistryCoordinatorAddr), AggregatorServerIpPortAddr: configRaw.AggregatorServerIpPortAddr, RegisterOperatorOnStartup: configRaw.RegisterOperatorOnStartup, - SignerFn: signerV2, - TxMgr: txMgr, AggregatorAddress: aggregatorAddr, } config.validate() + return config, nil } func (c *Config) validate() { - // TODO: make sure every pointer is non-nil if c.OperatorStateRetrieverAddr == common.HexToAddress("") { panic("Config: BLSOperatorStateRetrieverAddr is required") } + if c.SFFLRegistryCoordinatorAddr == common.HexToAddress("") { panic("Config: SFFLRegistryCoordinatorAddr is required") } diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 88bf5a17a..e912900d2 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -17,11 +17,9 @@ import ( "time" "github.com/Layr-Labs/eigensdk-go/chainio/clients/eth" - "github.com/Layr-Labs/eigensdk-go/chainio/txmgr" "github.com/Layr-Labs/eigensdk-go/crypto/bls" sdkEcdsa "github.com/Layr-Labs/eigensdk-go/crypto/ecdsa" sdklogging "github.com/Layr-Labs/eigensdk-go/logging" - "github.com/Layr-Labs/eigensdk-go/signerv2" sdkutils "github.com/Layr-Labs/eigensdk-go/utils" "github.com/docker/docker/api/types/container" "github.com/docker/go-connections/nat" @@ -145,13 +143,19 @@ func setupTestEnv(t *testing.T, ctx context.Context) *testEnv { sfflDeploymentRaw := readSfflDeploymentRaw() - nodeConfig := genOperatorConfig(t, ctx, mainnetAnvil, rollupAnvils, rabbitMq) - config := buildConfig(t, sfflDeploymentRaw, mainnetAnvil) + configRaw := buildConfigRaw(mainnetAnvil) + logger, err := sdklogging.NewZapLogger(configRaw.Environment) + if err != nil { + t.Fatalf("Failed to create logger: %s", err.Error()) + } + config := buildConfig(t, sfflDeploymentRaw, configRaw, logger) + aggregator := startAggregator(t, ctx, config, logger) + + nodeConfig := genOperatorConfig(t, ctx, mainnetAnvil, rollupAnvils, rabbitMq) operator := startOperator(t, ctx, nodeConfig) - aggregator := startAggregator(t, ctx, config) - avsReader, err := chainio.BuildAvsReaderFromConfig(config) + avsReader, err := chainio.BuildAvsReader(config.SFFLRegistryCoordinatorAddr, config.OperatorStateRetrieverAddr, mainnetAnvil.HttpClient, logger) if err != nil { t.Fatalf("Cannot create AVS Reader: %s", err.Error()) } @@ -208,10 +212,10 @@ func startOperator(t *testing.T, ctx context.Context, nodeConfig types.NodeConfi return operator } -func startAggregator(t *testing.T, ctx context.Context, config *config.Config) *aggregator.Aggregator { +func startAggregator(t *testing.T, ctx context.Context, config *config.Config, logger sdklogging.Logger) *aggregator.Aggregator { t.Log("starting aggregator for integration tests") - agg, err := aggregator.NewAggregator(ctx, config) + agg, err := aggregator.NewAggregator(config, logger, ctx) if err != nil { t.Fatalf("Failed to create aggregator: %s", err.Error()) } @@ -327,19 +331,18 @@ func genOperatorConfig(t *testing.T, ctx context.Context, mainnetAnvil *AnvilIns return nodeConfig } -func buildConfig(t *testing.T, sfflDeploymentRaw config.SFFLDeploymentRaw, mainnetAnvil *AnvilInstance) *config.Config { - var aggConfigRaw config.ConfigRaw +func buildConfigRaw(mainnetAnvil *AnvilInstance) config.ConfigRaw { + var configRaw config.ConfigRaw aggConfigFilePath := "../../config-files/aggregator.yaml" - sdkutils.ReadYamlConfig(aggConfigFilePath, &aggConfigRaw) - aggConfigRaw.EthRpcUrl = mainnetAnvil.HttpUrl - aggConfigRaw.EthWsUrl = mainnetAnvil.WsUrl - aggConfigRaw.AggregatorDatabasePath = "" + sdkutils.ReadYamlConfig(aggConfigFilePath, &configRaw) + configRaw.EthRpcUrl = mainnetAnvil.HttpUrl + configRaw.EthWsUrl = mainnetAnvil.WsUrl + configRaw.AggregatorDatabasePath = "" - logger, err := sdklogging.NewZapLogger(aggConfigRaw.Environment) - if err != nil { - t.Fatalf("Failed to create logger: %s", err.Error()) - } + return configRaw +} +func buildConfig(t *testing.T, sfflDeploymentRaw config.SFFLDeploymentRaw, aggConfigRaw config.ConfigRaw, logeer sdklogging.Logger) *config.Config { aggregatorEcdsaPrivateKeyString := "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6" if aggregatorEcdsaPrivateKeyString[:2] == "0x" { aggregatorEcdsaPrivateKeyString = aggregatorEcdsaPrivateKeyString[2:] @@ -353,26 +356,16 @@ func buildConfig(t *testing.T, sfflDeploymentRaw config.SFFLDeploymentRaw, mainn t.Fatalf("Cannot get operator address: %s", err.Error()) } - privateKeySigner, _, err := signerv2.SignerFromConfig(signerv2.Config{PrivateKey: aggregatorEcdsaPrivateKey}, mainnetAnvil.ChainID) - if err != nil { - t.Fatalf("Cannot create signer: %s", err.Error()) - } - txMgr := txmgr.NewSimpleTxManager(mainnetAnvil.HttpClient, logger, privateKeySigner, aggregatorAddr) - return &config.Config{ EcdsaPrivateKey: aggregatorEcdsaPrivateKey, - Logger: logger, EthHttpRpcUrl: aggConfigRaw.EthRpcUrl, - EthHttpClient: mainnetAnvil.HttpClient, EthWsRpcUrl: aggConfigRaw.EthWsUrl, - EthWsClient: mainnetAnvil.WsClient, OperatorStateRetrieverAddr: common.HexToAddress(sfflDeploymentRaw.Addresses.OperatorStateRetrieverAddr), SFFLRegistryCoordinatorAddr: common.HexToAddress(sfflDeploymentRaw.Addresses.RegistryCoordinatorAddr), AggregatorServerIpPortAddr: aggConfigRaw.AggregatorServerIpPortAddr, AggregatorRestServerIpPortAddr: aggConfigRaw.AggregatorRestServerIpPortAddr, AggregatorDatabasePath: aggConfigRaw.AggregatorDatabasePath, RegisterOperatorOnStartup: aggConfigRaw.RegisterOperatorOnStartup, - TxMgr: txMgr, AggregatorAddress: aggregatorAddr, } }