From c1b0717888eac88882c8e728b3d7cfb340403c96 Mon Sep 17 00:00:00 2001 From: Damian Ramirez Date: Wed, 22 Jan 2025 12:49:17 -0300 Subject: [PATCH 01/14] Create a test reader for avsregistry --- testutils/testclients/testclients.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/testutils/testclients/testclients.go b/testutils/testclients/testclients.go index 28e1b48ea..d6ecce5a1 100644 --- a/testutils/testclients/testclients.go +++ b/testutils/testclients/testclients.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/Layr-Labs/eigensdk-go/chainio/clients" + "github.com/Layr-Labs/eigensdk-go/chainio/clients/avsregistry" "github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts" "github.com/Layr-Labs/eigensdk-go/chainio/clients/wallet" "github.com/Layr-Labs/eigensdk-go/chainio/txmgr" @@ -193,3 +194,26 @@ func NewTestTxManager(httpEndpoint string, privateKeyHex string) (*txmgr.SimpleT txManager := txmgr.NewSimpleTxManager(pkWallet, ethHttpClient, logger, addr) return txManager, nil } + +// Creates a testing AVSRegistrer ChainReader from an httpEndpoint, private key and config. +func NewTestAVSChainReaderFromConfig( + httpEndpoint string, + config avsregistry.Config, +) (*avsregistry.ChainReader, error) { + testConfig := testutils.GetDefaultTestConfig() + logger := logging.NewTextSLogger(os.Stdout, &logging.SLoggerOptions{Level: testConfig.LogLevel}) + ethHttpClient, err := ethclient.Dial(httpEndpoint) + if err != nil { + return nil, utils.WrapError("Failed to create eth client", err) + } + + testReader, err := avsregistry.NewReaderFromConfig( + config, + ethHttpClient, + logger, + ) + if err != nil { + return nil, utils.WrapError("Failed to create chain reader from config", err) + } + return testReader, nil +} From 7ebbb37e5ef5fd7c652f618a708cd38133ee2db6 Mon Sep 17 00:00:00 2001 From: Damian Ramirez Date: Wed, 22 Jan 2025 12:49:31 -0300 Subject: [PATCH 02/14] Add test case for reader when config is invalid --- chainio/clients/avsregistry/reader_test.go | 66 ++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/chainio/clients/avsregistry/reader_test.go b/chainio/clients/avsregistry/reader_test.go index 375551a2d..b6e32573e 100644 --- a/chainio/clients/avsregistry/reader_test.go +++ b/chainio/clients/avsregistry/reader_test.go @@ -2,9 +2,11 @@ package avsregistry_test import ( "context" + "fmt" "math/big" "testing" + "github.com/Layr-Labs/eigensdk-go/chainio/clients/avsregistry" "github.com/Layr-Labs/eigensdk-go/testutils/testclients" "github.com/Layr-Labs/eigensdk-go/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -136,3 +138,67 @@ func TestReaderMethods(t *testing.T) { require.Equal(t, 0, len(address_to_sockets)) }) } + +// Test that the reader returns an error when the configuration is invalid. +func TestReaderWithInvalidConfiguration(t *testing.T) { + _, anvilHttpEndpoint := testclients.BuildTestClients(t) + + config := avsregistry.Config{} + chainReader, err := testclients.NewTestAVSChainReaderFromConfig(anvilHttpEndpoint, config) + require.NoError(t, err) + + quorumNumbers := types.QuorumNums{0} + + tests := []struct { + name string + runFunc func() error + expectError bool + }{ + { + name: "get quorum state", + runFunc: func() error { + _, err := chainReader.GetQuorumCount(&bind.CallOpts{}) + return err + }, + expectError: true, + }, + { + name: "get operator stake in quorums at current block", + runFunc: func() error { + _, err := chainReader.GetOperatorsStakeInQuorumsAtBlock(&bind.CallOpts{}, quorumNumbers, 100) + return err + }, + expectError: true, + }, + { + name: "get operator address in quorums at current block", + runFunc: func() error { + _, err := chainReader.GetOperatorAddrsInQuorumsAtCurrentBlock(&bind.CallOpts{}, quorumNumbers) + return err + }, + expectError: true, + }, + { + name: "get operators stake in quorums of operator at block", + runFunc: func() error { + randomOperatorId := types.OperatorId{99} + _, _, err := chainReader.GetOperatorsStakeInQuorumsOfOperatorAtBlock( + &bind.CallOpts{}, + randomOperatorId, + 100, + ) + return err + }, + expectError: true, + }, + } + + for _, tc := range tests { + t.Run(fmt.Sprintf("%s with invalid config", tc.name), func(t *testing.T) { + err := tc.runFunc() + if tc.expectError { + require.Error(t, err, "Expected error for %s", tc.name) + } + }) + } +} From 8b2c87616141fcf8fea1b6e7862c097c686f28fe Mon Sep 17 00:00:00 2001 From: Damian Ramirez Date: Wed, 22 Jan 2025 14:16:24 -0300 Subject: [PATCH 03/14] Add more methods with invalid config --- chainio/clients/avsregistry/reader_test.go | 62 +++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/chainio/clients/avsregistry/reader_test.go b/chainio/clients/avsregistry/reader_test.go index b6e32573e..eda0c3fe5 100644 --- a/chainio/clients/avsregistry/reader_test.go +++ b/chainio/clients/avsregistry/reader_test.go @@ -148,12 +148,37 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { require.NoError(t, err) quorumNumbers := types.QuorumNums{0} + randomOperatorId := types.OperatorId{99} tests := []struct { name string runFunc func() error expectError bool }{ + { + name: "get operator id", + runFunc: func() error { + _, err := chainReader.GetOperatorId(&bind.CallOpts{}, common.Address{}) + return err + }, + expectError: true, + }, + { + name: "get operator from id", + runFunc: func() error { + _, err := chainReader.GetOperatorFromId(&bind.CallOpts{}, randomOperatorId) + return err + }, + expectError: true, + }, + { + name: "check if operator is registered", + runFunc: func() error { + _, err := chainReader.IsOperatorRegistered(&bind.CallOpts{}, common.Address{}) + return err + }, + expectError: true, + }, { name: "get quorum state", runFunc: func() error { @@ -181,7 +206,6 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { { name: "get operators stake in quorums of operator at block", runFunc: func() error { - randomOperatorId := types.OperatorId{99} _, _, err := chainReader.GetOperatorsStakeInQuorumsOfOperatorAtBlock( &bind.CallOpts{}, randomOperatorId, @@ -191,6 +215,42 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { }, expectError: true, }, + { + name: "get single operator stake in quorums of operator at current block", + runFunc: func() error { + _, err := chainReader.GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock( + &bind.CallOpts{}, + randomOperatorId, + ) + return err + }, + expectError: true, + }, { + name: "check signatures indices", + runFunc: func() error { + _, err := chainReader.GetCheckSignaturesIndices( + &bind.CallOpts{}, + 100, + quorumNumbers, + []types.OperatorId{randomOperatorId}, + ) + return err + }, + expectError: true, + }, + { + name: "query registered operator sockets", + runFunc: func() error { + _, err := chainReader.QueryExistingRegisteredOperatorSockets( + context.Background(), + big.NewInt(0), + nil, + nil, + ) + return err + }, + expectError: true, + }, } for _, tc := range tests { From 012c7b166766e005a40c5b01b2b7604aafd6bae2 Mon Sep 17 00:00:00 2001 From: Damian Ramirez Date: Wed, 22 Jan 2025 14:37:07 -0300 Subject: [PATCH 04/14] Add test for GetOperatorsStakeInQuorumsOfOperator --- chainio/clients/avsregistry/reader_test.go | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/chainio/clients/avsregistry/reader_test.go b/chainio/clients/avsregistry/reader_test.go index eda0c3fe5..9c497bbfb 100644 --- a/chainio/clients/avsregistry/reader_test.go +++ b/chainio/clients/avsregistry/reader_test.go @@ -7,16 +7,28 @@ import ( "testing" "github.com/Layr-Labs/eigensdk-go/chainio/clients/avsregistry" + "github.com/Layr-Labs/eigensdk-go/crypto/bls" + "github.com/Layr-Labs/eigensdk-go/testutils" "github.com/Layr-Labs/eigensdk-go/testutils/testclients" "github.com/Layr-Labs/eigensdk-go/types" "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/crypto" "github.com/stretchr/testify/require" ) func TestReaderMethods(t *testing.T) { clients, _ := testclients.BuildTestClients(t) chainReader := clients.ReadClients.AvsRegistryChainReader + chainWriter := clients.AvsRegistryChainWriter + + keypair, err := bls.NewKeyPairFromString("0x01") + require.NoError(t, err) + + operatorAddr := gethcommon.HexToAddress(testutils.ANVIL_FIRST_ADDRESS) + ecdsaPrivateKey, err := crypto.HexToECDSA(testutils.ANVIL_FIRST_PRIVATE_KEY) + require.NoError(t, err) quorumNumbers := types.QuorumNums{0} @@ -137,6 +149,40 @@ func TestReaderMethods(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, len(address_to_sockets)) }) + + t.Run("get operators stake in quorums", func(t *testing.T) { + receipt, err := chainWriter.RegisterOperator( + context.Background(), + ecdsaPrivateKey, + keypair, + quorumNumbers, + "", + true, + ) + require.NoError(t, err) + require.NotNil(t, receipt) + + operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddr) + require.NoError(t, err) + + quorums, operators, err := chainReader.GetOperatorsStakeInQuorumsOfOperatorAtBlock( + &bind.CallOpts{}, + operatorId, + uint32(receipt.BlockNumber.Uint64()), + ) + require.NoError(t, err) + require.Equal(t, 1, len(quorums)) + require.Equal(t, 1, len(operators)) + + quorums, operators, err = chainReader.GetOperatorsStakeInQuorumsOfOperatorAtCurrentBlock( + &bind.CallOpts{}, + operatorId, + ) + require.NoError(t, err) + t.Logf("quorums: %+v \n operators: %+v", quorums, operators) + require.Equal(t, 1, len(quorums)) + require.Equal(t, 1, len(operators)) + }) } // Test that the reader returns an error when the configuration is invalid. From 1c19f1959fc770944e7dfef38335a00d20f5d023 Mon Sep 17 00:00:00 2001 From: Damian Ramirez Date: Wed, 22 Jan 2025 14:42:03 -0300 Subject: [PATCH 05/14] Remove t.Log --- chainio/clients/avsregistry/reader_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/chainio/clients/avsregistry/reader_test.go b/chainio/clients/avsregistry/reader_test.go index 9c497bbfb..694595845 100644 --- a/chainio/clients/avsregistry/reader_test.go +++ b/chainio/clients/avsregistry/reader_test.go @@ -179,7 +179,6 @@ func TestReaderMethods(t *testing.T) { operatorId, ) require.NoError(t, err) - t.Logf("quorums: %+v \n operators: %+v", quorums, operators) require.Equal(t, 1, len(quorums)) require.Equal(t, 1, len(operators)) }) From fc2b46c43d1b81167bf819b64a50bcef0b3b8a41 Mon Sep 17 00:00:00 2001 From: Damian Ramirez Date: Wed, 22 Jan 2025 15:06:56 -0300 Subject: [PATCH 06/14] Refactor in operators stake in quorums --- chainio/clients/avsregistry/reader_test.go | 53 ++++++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/chainio/clients/avsregistry/reader_test.go b/chainio/clients/avsregistry/reader_test.go index 694595845..b1e723b11 100644 --- a/chainio/clients/avsregistry/reader_test.go +++ b/chainio/clients/avsregistry/reader_test.go @@ -162,25 +162,48 @@ func TestReaderMethods(t *testing.T) { require.NoError(t, err) require.NotNil(t, receipt) + blockNumber := uint32(receipt.BlockNumber.Uint64()) + operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddr) require.NoError(t, err) - quorums, operators, err := chainReader.GetOperatorsStakeInQuorumsOfOperatorAtBlock( - &bind.CallOpts{}, - operatorId, - uint32(receipt.BlockNumber.Uint64()), - ) - require.NoError(t, err) - require.Equal(t, 1, len(quorums)) - require.Equal(t, 1, len(operators)) + t.Run("get operators stake in quorums at block", func(t *testing.T) { + stake, operators, err := chainReader.GetOperatorsStakeInQuorumsOfOperatorAtBlock( + &bind.CallOpts{}, + operatorId, + blockNumber, + ) + require.NoError(t, err) + require.Equal(t, 1, len(stake)) + require.Equal(t, 1, len(operators)) + }) - quorums, operators, err = chainReader.GetOperatorsStakeInQuorumsOfOperatorAtCurrentBlock( - &bind.CallOpts{}, - operatorId, - ) - require.NoError(t, err) - require.Equal(t, 1, len(quorums)) - require.Equal(t, 1, len(operators)) + t.Run("get operators stake in quorums at current block", func(t *testing.T) { + stake, operators, err := chainReader.GetOperatorsStakeInQuorumsOfOperatorAtCurrentBlock( + &bind.CallOpts{}, + operatorId, + ) + require.NoError(t, err) + require.Equal(t, 1, len(stake)) + require.Equal(t, 1, len(operators)) + }) + + t.Run("get operator stake in quoryms at current block", func(t *testing.T) { + stakeMap, err := chainReader.GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock(&bind.CallOpts{}, operatorId) + require.NoError(t, err) + require.Equal(t, 1, len(stakeMap)) + }) + + t.Run("get check signatures indices ", func(t *testing.T) { + indices, err := chainReader.GetCheckSignaturesIndices( + &bind.CallOpts{}, + blockNumber, + quorumNumbers, + []types.OperatorId{operatorId}, + ) + require.NoError(t, err) + require.NotNil(t, indices) + }) }) } From 755148a5d265bea8160e0052214c275346498e47 Mon Sep 17 00:00:00 2001 From: Damian Ramirez Date: Wed, 22 Jan 2025 15:50:46 -0300 Subject: [PATCH 07/14] Add case for QueryExistingRegisteredOperatorPubKeys --- chainio/clients/avsregistry/reader_test.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/chainio/clients/avsregistry/reader_test.go b/chainio/clients/avsregistry/reader_test.go index b1e723b11..f81fec336 100644 --- a/chainio/clients/avsregistry/reader_test.go +++ b/chainio/clients/avsregistry/reader_test.go @@ -188,7 +188,7 @@ func TestReaderMethods(t *testing.T) { require.Equal(t, 1, len(operators)) }) - t.Run("get operator stake in quoryms at current block", func(t *testing.T) { + t.Run("get operator stake in quorums at current block", func(t *testing.T) { stakeMap, err := chainReader.GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock(&bind.CallOpts{}, operatorId) require.NoError(t, err) require.Equal(t, 1, len(stakeMap)) @@ -204,6 +204,19 @@ func TestReaderMethods(t *testing.T) { require.NoError(t, err) require.NotNil(t, indices) }) + + t.Run( + "query existing registered operator pub keys", func(t *testing.T) { + addresses, pubKeys, err := chainReader.QueryExistingRegisteredOperatorPubKeys( + context.Background(), + big.NewInt(0), + nil, + nil, + ) + require.NoError(t, err) + require.Equal(t, 1, len(pubKeys)) + require.Equal(t, 1, len(addresses)) + }) }) } From c86b82f691afd3d1d433806ad1ec65b2fed1555f Mon Sep 17 00:00:00 2001 From: Damian Ramirez Date: Wed, 22 Jan 2025 17:17:35 -0300 Subject: [PATCH 08/14] Change helper function name --- chainio/clients/avsregistry/reader_test.go | 2 +- testutils/testclients/testclients.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chainio/clients/avsregistry/reader_test.go b/chainio/clients/avsregistry/reader_test.go index f81fec336..366800880 100644 --- a/chainio/clients/avsregistry/reader_test.go +++ b/chainio/clients/avsregistry/reader_test.go @@ -225,7 +225,7 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { _, anvilHttpEndpoint := testclients.BuildTestClients(t) config := avsregistry.Config{} - chainReader, err := testclients.NewTestAVSChainReaderFromConfig(anvilHttpEndpoint, config) + chainReader, err := testclients.NewTestAvsRegistryReaderFromConfig(anvilHttpEndpoint, config) require.NoError(t, err) quorumNumbers := types.QuorumNums{0} diff --git a/testutils/testclients/testclients.go b/testutils/testclients/testclients.go index e2ce29af1..6a5fbf767 100644 --- a/testutils/testclients/testclients.go +++ b/testutils/testclients/testclients.go @@ -240,7 +240,7 @@ func NewTestAvsRegistryWriterFromConfig( } // Creates a testing AVSRegistrer ChainReader from an httpEndpoint, private key and config. -func NewTestAVSChainReaderFromConfig( +func NewTestAvsRegistryReaderFromConfig( httpEndpoint string, config avsregistry.Config, ) (*avsregistry.ChainReader, error) { From 3b6bacaef66879a8eba93b8cbc272bbdfc8e7007 Mon Sep 17 00:00:00 2001 From: maximopalopoli Date: Wed, 29 Jan 2025 16:02:00 -0300 Subject: [PATCH 09/14] Add error interface from #477 --- chainio/clients/elcontracts/error.go | 50 ++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 chainio/clients/elcontracts/error.go diff --git a/chainio/clients/elcontracts/error.go b/chainio/clients/elcontracts/error.go new file mode 100644 index 000000000..432f38fc5 --- /dev/null +++ b/chainio/clients/elcontracts/error.go @@ -0,0 +1,50 @@ +package elcontracts + +import "fmt" + +type Error struct { + code int + message string + description string + cause error +} + +func (e Error) Error() string { + if e.cause != nil { + return fmt.Sprintf("%s(%d) - %s: %s", e.message, e.code, e.description, e.cause.Error()) + } + return fmt.Sprintf("%s(%d) - %s", e.message, e.code, e.description) +} + +func (e Error) Unwrap() error { + return e.cause +} + +func CreateErrorForMissingContract(contractName string) Error { + errDescription := fmt.Sprintf("%s contract not provided", contractName) + return Error{1, "Missing needed contract", errDescription, nil} +} + +func CreateForBindingError(bindingName string, errorCause error) Error { + errDescription := fmt.Sprintf("Error happened while calling %s", bindingName) + return Error{ + 0, + "Binding error", + errDescription, + errorCause, + } +} + +func CreateForNestedError(functionName string, errorCause error) Error { + errDescription := fmt.Sprintf("Error happened while calling %s", functionName) + return Error{ + 2, + "Nested error", + errDescription, + errorCause, + } +} + +func CommonErrorMissingContract(contractName string) string { + return fmt.Sprintf("Missing needed contract(1) - %s contract not provided", contractName) +} From 4bdffb62b6aa452663a8cc5957f0f89ea150ff5c Mon Sep 17 00:00:00 2001 From: maximopalopoli Date: Wed, 29 Jan 2025 17:22:46 -0300 Subject: [PATCH 10/14] Use missing contract custom error and tag errors with comments --- chainio/clients/avsregistry/reader.go | 108 ++++++++++++++++---------- 1 file changed, 67 insertions(+), 41 deletions(-) diff --git a/chainio/clients/avsregistry/reader.go b/chainio/clients/avsregistry/reader.go index 382cb27ba..d646bda7c 100644 --- a/chainio/clients/avsregistry/reader.go +++ b/chainio/clients/avsregistry/reader.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts" "github.com/Layr-Labs/eigensdk-go/chainio/clients/eth" apkreg "github.com/Layr-Labs/eigensdk-go/contracts/bindings/BLSApkRegistry" opstateretriever "github.com/Layr-Labs/eigensdk-go/contracts/bindings/OperatorStateRetriever" @@ -70,7 +71,8 @@ func NewReaderFromConfig( ) (*ChainReader, error) { bindings, err := NewBindingsFromConfig(cfg, client, logger) if err != nil { - return nil, err + wrappedError := elcontracts.CreateForNestedError("NewBindingsFromConfig", err) + return nil, wrappedError } return NewChainReader( @@ -86,9 +88,16 @@ func NewReaderFromConfig( func (r *ChainReader) GetQuorumCount(opts *bind.CallOpts) (uint8, error) { if r.registryCoordinator == nil { - return 0, errors.New("RegistryCoordinator contract not provided") + wrappedError := elcontracts.CreateErrorForMissingContract("RegistryCoordinator") + return 0, wrappedError + } + + cont, err := r.registryCoordinator.QuorumCount(opts) + if err != nil { // Binding error + return 0, err } - return r.registryCoordinator.QuorumCount(opts) + + return cont, nil } func (r *ChainReader) GetOperatorsStakeInQuorumsAtCurrentBlock( @@ -99,13 +108,19 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsAtCurrentBlock( opts.Context = context.Background() } curBlock, err := r.ethClient.BlockNumber(opts.Context) - if err != nil { + if err != nil { // binding error return nil, utils.WrapError("Cannot get current block number", err) } - if curBlock > math.MaxUint32 { + if curBlock > math.MaxUint32 { // other error return nil, utils.WrapError("Current block number is too large to be converted to uint32", err) } - return r.GetOperatorsStakeInQuorumsAtBlock(opts, quorumNumbers, uint32(curBlock)) + + operatorStakes, err := r.GetOperatorsStakeInQuorumsAtBlock(opts, quorumNumbers, uint32(curBlock)) + if err != nil { // Nested error + return nil, err + } + + return operatorStakes, nil } // the contract stores historical state, so blockNumber should be the block number of the state you want to query @@ -135,17 +150,18 @@ func (r *ChainReader) GetOperatorAddrsInQuorumsAtCurrentBlock( quorumNumbers types.QuorumNums, ) ([][]common.Address, error) { if r.operatorStateRetriever == nil { - return nil, errors.New("OperatorStateRetriever contract not provided") + wrappedError := elcontracts.CreateErrorForMissingContract("OperatorStateRetriever") + return nil, wrappedError } if opts.Context == nil { opts.Context = context.Background() } curBlock, err := r.ethClient.BlockNumber(opts.Context) - if err != nil { + if err != nil { // Binding error return nil, utils.WrapError("Failed to get current block number", err) } - if curBlock > math.MaxUint32 { + if curBlock > math.MaxUint32 { // other error return nil, utils.WrapError("Current block number is too large to be converted to uint32", err) } operatorStakes, err := r.operatorStateRetriever.GetOperatorState( @@ -154,7 +170,7 @@ func (r *ChainReader) GetOperatorAddrsInQuorumsAtCurrentBlock( quorumNumbers.UnderlyingType(), uint32(curBlock), ) - if err != nil { + if err != nil { // Binding error return nil, utils.WrapError("Failed to get operators state", err) } var quorumOperatorAddrs [][]common.Address @@ -166,7 +182,6 @@ func (r *ChainReader) GetOperatorAddrsInQuorumsAtCurrentBlock( quorumOperatorAddrs = append(quorumOperatorAddrs, operatorAddrs) } return quorumOperatorAddrs, nil - } func (r *ChainReader) GetOperatorsStakeInQuorumsOfOperatorAtBlock( @@ -175,7 +190,8 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsOfOperatorAtBlock( blockNumber uint32, ) (types.QuorumNums, [][]opstateretriever.OperatorStateRetrieverOperator, error) { if r.operatorStateRetriever == nil { - return nil, nil, errors.New("OperatorStateRetriever contract not provided") + wrappedError := elcontracts.CreateErrorForMissingContract("OperatorStateRetriever") + return nil, nil, wrappedError } quorumBitmap, operatorStakes, err := r.operatorStateRetriever.GetOperatorState0( @@ -183,7 +199,7 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsOfOperatorAtBlock( r.registryCoordinatorAddr, operatorId, blockNumber) - if err != nil { + if err != nil { // Binding error return nil, nil, utils.WrapError("Failed to get operators state", err) } quorums := types.BitmapToQuorumIds(quorumBitmap) @@ -200,14 +216,19 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsOfOperatorAtCurrentBlock( opts.Context = context.Background() } curBlock, err := r.ethClient.BlockNumber(opts.Context) - if err != nil { + if err != nil { // Binding error return nil, nil, utils.WrapError("Failed to get current block number", err) } - if curBlock > math.MaxUint32 { + if curBlock > math.MaxUint32 { // other error return nil, nil, utils.WrapError("Current block number is too large to be converted to uint32", err) } opts.BlockNumber = big.NewInt(int64(curBlock)) - return r.GetOperatorsStakeInQuorumsOfOperatorAtBlock(opts, operatorId, uint32(curBlock)) + quorums, operatorsStake, err := r.GetOperatorsStakeInQuorumsOfOperatorAtBlock(opts, operatorId, uint32(curBlock)) + if err != nil { + return nil, nil, err + } + + return quorums, operatorsStake, nil } // To avoid a possible race condition, this method must assure that all the calls @@ -220,11 +241,13 @@ func (r *ChainReader) GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock( operatorId types.OperatorId, ) (map[types.QuorumNum]types.StakeAmount, error) { if r.registryCoordinator == nil { - return nil, errors.New("RegistryCoordinator contract not provided") + wrappedError := elcontracts.CreateErrorForMissingContract("RegistryCoordinator") + return nil, wrappedError } if r.stakeRegistry == nil { - return nil, errors.New("StakeRegistry contract not provided") + wrappedError := elcontracts.CreateErrorForMissingContract("StakeRegistry") + return nil, wrappedError } // check if opts parameter has not a block number set (BlockNumber) @@ -235,14 +258,14 @@ func (r *ChainReader) GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock( opts.Context = context.Background() } latestBlock, err := r.ethClient.BlockNumber(opts.Context) - if err != nil { + if err != nil { // Binding error return nil, utils.WrapError("Failed to get latest block number", err) } opts.BlockNumber = big.NewInt(int64(latestBlock)) } quorumBitmap, err := r.registryCoordinator.GetCurrentQuorumBitmap(opts, operatorId) - if err != nil { + if err != nil { // Binding error return nil, utils.WrapError("Failed to get operator quorums", err) } quorums := types.BitmapToQuorumIds(quorumBitmap) @@ -253,7 +276,7 @@ func (r *ChainReader) GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock( operatorId, uint8(quorum), ) - if err != nil { + if err != nil { // Binding error return nil, utils.WrapError("Failed to get operator stake", err) } quorumStakes[quorum] = stake @@ -268,9 +291,8 @@ func (r *ChainReader) GetCheckSignaturesIndices( nonSignerOperatorIds []types.OperatorId, ) (opstateretriever.OperatorStateRetrieverCheckSignaturesIndices, error) { if r.operatorStateRetriever == nil { - return opstateretriever.OperatorStateRetrieverCheckSignaturesIndices{}, errors.New( - "OperatorStateRetriever contract not provided", - ) + wrappedError := elcontracts.CreateErrorForMissingContract("OperatorStateRetriever") + return opstateretriever.OperatorStateRetrieverCheckSignaturesIndices{}, wrappedError } nonSignerOperatorIdsBytes := make([][32]byte, len(nonSignerOperatorIds)) @@ -284,7 +306,7 @@ func (r *ChainReader) GetCheckSignaturesIndices( quorumNumbers.UnderlyingType(), nonSignerOperatorIdsBytes, ) - if err != nil { + if err != nil { // Binding error return opstateretriever.OperatorStateRetrieverCheckSignaturesIndices{}, utils.WrapError( "Failed to get check signatures indices", err, @@ -298,14 +320,15 @@ func (r *ChainReader) GetOperatorId( operatorAddress common.Address, ) ([32]byte, error) { if r.registryCoordinator == nil { - return [32]byte{}, errors.New("RegistryCoordinator contract not provided") + wrappedError := elcontracts.CreateErrorForMissingContract("RegistryCoordinator") + return [32]byte{}, wrappedError } operatorId, err := r.registryCoordinator.GetOperatorId( opts, operatorAddress, ) - if err != nil { + if err != nil { // Binding error return [32]byte{}, utils.WrapError("Failed to get operator id", err) } return operatorId, nil @@ -316,14 +339,15 @@ func (r *ChainReader) GetOperatorFromId( operatorId types.OperatorId, ) (common.Address, error) { if r.registryCoordinator == nil { - return common.Address{}, errors.New("RegistryCoordinator contract not provided") + wrappedError := elcontracts.CreateErrorForMissingContract("RegistryCoordinator") + return common.Address{}, wrappedError } operatorAddress, err := r.registryCoordinator.GetOperatorFromId( opts, operatorId, ) - if err != nil { + if err != nil { // Binding error return common.Address{}, utils.WrapError("Failed to get operator address", err) } return operatorAddress, nil @@ -334,11 +358,11 @@ func (r *ChainReader) QueryRegistrationDetail( operatorAddress common.Address, ) ([]bool, error) { operatorId, err := r.GetOperatorId(opts, operatorAddress) - if err != nil { + if err != nil { // Nested error return nil, utils.WrapError("Failed to get operator id", err) } value, err := r.registryCoordinator.GetCurrentQuorumBitmap(opts, operatorId) - if err != nil { + if err != nil { // Binding error return nil, utils.WrapError("Failed to get operator quorums", err) } numBits := value.BitLen() @@ -348,7 +372,7 @@ func (r *ChainReader) QueryRegistrationDetail( } if len(quorums) == 0 { numQuorums, err := r.GetQuorumCount(opts) - if err != nil { + if err != nil { // Nested error return nil, utils.WrapError("Failed to get quorum count", err) } for i := uint8(0); i < numQuorums; i++ { @@ -363,11 +387,12 @@ func (r *ChainReader) IsOperatorRegistered( operatorAddress common.Address, ) (bool, error) { if r.registryCoordinator == nil { - return false, errors.New("RegistryCoordinator contract not provided") + wrappedError := elcontracts.CreateErrorForMissingContract("RegistryCoordinator") + return false, wrappedError } operatorStatus, err := r.registryCoordinator.GetOperatorStatus(opts, operatorAddress) - if err != nil { + if err != nil { // Binding error return false, utils.WrapError("Failed to get operator status", err) } @@ -383,7 +408,7 @@ func (r *ChainReader) QueryExistingRegisteredOperatorPubKeys( blockRange *big.Int, ) ([]types.OperatorAddr, []types.OperatorPubkeys, error) { blsApkRegistryAbi, err := apkreg.ContractBLSApkRegistryMetaData.GetAbi() - if err != nil { + if err != nil { // other error ? return nil, nil, utils.WrapError("Cannot get Abi", err) } @@ -392,7 +417,7 @@ func (r *ChainReader) QueryExistingRegisteredOperatorPubKeys( } if stopBlock == nil { curBlockNum, err := r.ethClient.BlockNumber(ctx) - if err != nil { + if err != nil { // Binding error return nil, nil, utils.WrapError("Cannot get current block number", err) } stopBlock = new(big.Int).SetUint64(curBlockNum) @@ -424,7 +449,7 @@ func (r *ChainReader) QueryExistingRegisteredOperatorPubKeys( } logs, err := r.ethClient.FilterLogs(ctx, query) - if err != nil { + if err != nil { // Binding error return nil, nil, utils.WrapError("Cannot filter logs", err) } r.logger.Debug( @@ -443,7 +468,7 @@ func (r *ChainReader) QueryExistingRegisteredOperatorPubKeys( operatorAddresses = append(operatorAddresses, operatorAddr) event, err := blsApkRegistryAbi.Unpack("NewPubkeyRegistration", vLog.Data) - if err != nil { + if err != nil { // other error return nil, nil, utils.WrapError("Cannot unpack event data", err) } @@ -482,7 +507,8 @@ func (r *ChainReader) QueryExistingRegisteredOperatorSockets( blockRange *big.Int, ) (map[types.OperatorId]types.Socket, error) { if r.registryCoordinator == nil { - return nil, errors.New("RegistryCoordinator contract not provided") + wrappedError := elcontracts.CreateErrorForMissingContract("RegistryCoordinator") + return nil, wrappedError } if startBlock == nil { @@ -490,7 +516,7 @@ func (r *ChainReader) QueryExistingRegisteredOperatorSockets( } if stopBlock == nil { curBlockNum, err := r.ethClient.BlockNumber(ctx) - if err != nil { + if err != nil { // Binding error return nil, utils.WrapError("Cannot get current block number", err) } stopBlock = new(big.Int).SetUint64(curBlockNum) @@ -519,7 +545,7 @@ func (r *ChainReader) QueryExistingRegisteredOperatorSockets( End: &end, } socketUpdates, err := r.registryCoordinator.FilterOperatorSocketUpdate(filterOpts, nil) - if err != nil { + if err != nil { // Binding error return nil, utils.WrapError("Cannot filter operator socket updates", err) } From e8c1131ae163f36a369d6fe01ececad89c135812 Mon Sep 17 00:00:00 2001 From: maximopalopoli Date: Wed, 29 Jan 2025 17:40:50 -0300 Subject: [PATCH 11/14] Use custom binding error in binding calls failures --- chainio/clients/avsregistry/reader.go | 93 ++++++++++++++++----------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/chainio/clients/avsregistry/reader.go b/chainio/clients/avsregistry/reader.go index d646bda7c..45aa6ee52 100644 --- a/chainio/clients/avsregistry/reader.go +++ b/chainio/clients/avsregistry/reader.go @@ -93,8 +93,9 @@ func (r *ChainReader) GetQuorumCount(opts *bind.CallOpts) (uint8, error) { } cont, err := r.registryCoordinator.QuorumCount(opts) - if err != nil { // Binding error - return 0, err + if err != nil { + wrappedError := elcontracts.CreateForBindingError("registryCoordinator.QuorumCount", err) + return 0, wrappedError } return cont, nil @@ -108,8 +109,9 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsAtCurrentBlock( opts.Context = context.Background() } curBlock, err := r.ethClient.BlockNumber(opts.Context) - if err != nil { // binding error - return nil, utils.WrapError("Cannot get current block number", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("ethClient.BlockNumber", err) + return nil, wrappedError } if curBlock > math.MaxUint32 { // other error return nil, utils.WrapError("Current block number is too large to be converted to uint32", err) @@ -158,8 +160,9 @@ func (r *ChainReader) GetOperatorAddrsInQuorumsAtCurrentBlock( opts.Context = context.Background() } curBlock, err := r.ethClient.BlockNumber(opts.Context) - if err != nil { // Binding error - return nil, utils.WrapError("Failed to get current block number", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("ethClient.BlockNumber", err) + return nil, wrappedError } if curBlock > math.MaxUint32 { // other error return nil, utils.WrapError("Current block number is too large to be converted to uint32", err) @@ -170,8 +173,9 @@ func (r *ChainReader) GetOperatorAddrsInQuorumsAtCurrentBlock( quorumNumbers.UnderlyingType(), uint32(curBlock), ) - if err != nil { // Binding error - return nil, utils.WrapError("Failed to get operators state", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("operatorStateRetriever.GetOperatorState", err) + return nil, wrappedError } var quorumOperatorAddrs [][]common.Address for _, quorum := range operatorStakes { @@ -199,8 +203,9 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsOfOperatorAtBlock( r.registryCoordinatorAddr, operatorId, blockNumber) - if err != nil { // Binding error - return nil, nil, utils.WrapError("Failed to get operators state", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("operatorStateRetriever.GetOperatorState0", err) + return nil, nil, wrappedError } quorums := types.BitmapToQuorumIds(quorumBitmap) return quorums, operatorStakes, nil @@ -216,8 +221,9 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsOfOperatorAtCurrentBlock( opts.Context = context.Background() } curBlock, err := r.ethClient.BlockNumber(opts.Context) - if err != nil { // Binding error - return nil, nil, utils.WrapError("Failed to get current block number", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("ethClient.BlockNumber", err) + return nil, nil, wrappedError } if curBlock > math.MaxUint32 { // other error return nil, nil, utils.WrapError("Current block number is too large to be converted to uint32", err) @@ -258,15 +264,17 @@ func (r *ChainReader) GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock( opts.Context = context.Background() } latestBlock, err := r.ethClient.BlockNumber(opts.Context) - if err != nil { // Binding error - return nil, utils.WrapError("Failed to get latest block number", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("ethClient.BlockNumber", err) + return nil, wrappedError } opts.BlockNumber = big.NewInt(int64(latestBlock)) } quorumBitmap, err := r.registryCoordinator.GetCurrentQuorumBitmap(opts, operatorId) - if err != nil { // Binding error - return nil, utils.WrapError("Failed to get operator quorums", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("registryCoordinator.GetCurrentQuorumBitmap", err) + return nil, wrappedError } quorums := types.BitmapToQuorumIds(quorumBitmap) quorumStakes := make(map[types.QuorumNum]types.StakeAmount) @@ -276,8 +284,9 @@ func (r *ChainReader) GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock( operatorId, uint8(quorum), ) - if err != nil { // Binding error - return nil, utils.WrapError("Failed to get operator stake", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("stakeRegistry.GetCurrentStake", err) + return nil, wrappedError } quorumStakes[quorum] = stake } @@ -306,11 +315,9 @@ func (r *ChainReader) GetCheckSignaturesIndices( quorumNumbers.UnderlyingType(), nonSignerOperatorIdsBytes, ) - if err != nil { // Binding error - return opstateretriever.OperatorStateRetrieverCheckSignaturesIndices{}, utils.WrapError( - "Failed to get check signatures indices", - err, - ) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("operatorStateRetriever.GetCheckSignaturesIndices", err) + return opstateretriever.OperatorStateRetrieverCheckSignaturesIndices{}, wrappedError } return checkSignatureIndices, nil } @@ -328,8 +335,9 @@ func (r *ChainReader) GetOperatorId( opts, operatorAddress, ) - if err != nil { // Binding error - return [32]byte{}, utils.WrapError("Failed to get operator id", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("registryCoordinator.GetOperatorId", err) + return [32]byte{}, wrappedError } return operatorId, nil } @@ -347,8 +355,9 @@ func (r *ChainReader) GetOperatorFromId( opts, operatorId, ) - if err != nil { // Binding error - return common.Address{}, utils.WrapError("Failed to get operator address", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("registryCoordinator.GetOperatorFromId", err) + return common.Address{}, wrappedError } return operatorAddress, nil } @@ -362,8 +371,9 @@ func (r *ChainReader) QueryRegistrationDetail( return nil, utils.WrapError("Failed to get operator id", err) } value, err := r.registryCoordinator.GetCurrentQuorumBitmap(opts, operatorId) - if err != nil { // Binding error - return nil, utils.WrapError("Failed to get operator quorums", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("registryCoordinator.GetCurrentQuorumBitmap", err) + return nil, wrappedError } numBits := value.BitLen() var quorums []bool @@ -392,8 +402,9 @@ func (r *ChainReader) IsOperatorRegistered( } operatorStatus, err := r.registryCoordinator.GetOperatorStatus(opts, operatorAddress) - if err != nil { // Binding error - return false, utils.WrapError("Failed to get operator status", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("registryCoordinator.GetOperatorStatus", err) + return false, wrappedError } // 0 = NEVER_REGISTERED, 1 = REGISTERED, 2 = DEREGISTERED @@ -417,8 +428,9 @@ func (r *ChainReader) QueryExistingRegisteredOperatorPubKeys( } if stopBlock == nil { curBlockNum, err := r.ethClient.BlockNumber(ctx) - if err != nil { // Binding error - return nil, nil, utils.WrapError("Cannot get current block number", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("ethClient.BlockNumber", err) + return nil, nil, wrappedError } stopBlock = new(big.Int).SetUint64(curBlockNum) } @@ -449,8 +461,9 @@ func (r *ChainReader) QueryExistingRegisteredOperatorPubKeys( } logs, err := r.ethClient.FilterLogs(ctx, query) - if err != nil { // Binding error - return nil, nil, utils.WrapError("Cannot filter logs", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("ethClient.FilterLogs", err) + return nil, nil, wrappedError } r.logger.Debug( "avsRegistryChainReader.QueryExistingRegisteredOperatorPubKeys", @@ -516,8 +529,9 @@ func (r *ChainReader) QueryExistingRegisteredOperatorSockets( } if stopBlock == nil { curBlockNum, err := r.ethClient.BlockNumber(ctx) - if err != nil { // Binding error - return nil, utils.WrapError("Cannot get current block number", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("ethClient.BlockNumber", err) + return nil, wrappedError } stopBlock = new(big.Int).SetUint64(curBlockNum) } @@ -545,8 +559,9 @@ func (r *ChainReader) QueryExistingRegisteredOperatorSockets( End: &end, } socketUpdates, err := r.registryCoordinator.FilterOperatorSocketUpdate(filterOpts, nil) - if err != nil { // Binding error - return nil, utils.WrapError("Cannot filter operator socket updates", err) + if err != nil { + wrappedError := elcontracts.CreateForBindingError("registryCoordinator.FilterOperatorSocketUpdate", err) + return nil, wrappedError } numSocketUpdates := 0 From d7c55f148be59df09248df360813f34e9f3cb16c Mon Sep 17 00:00:00 2001 From: maximopalopoli Date: Wed, 29 Jan 2025 18:09:38 -0300 Subject: [PATCH 12/14] Use existent custom errors to cover all cases --- chainio/clients/avsregistry/reader.go | 51 ++++++++++++++++----------- chainio/clients/elcontracts/error.go | 9 +++++ 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/chainio/clients/avsregistry/reader.go b/chainio/clients/avsregistry/reader.go index 45aa6ee52..0a7e82db4 100644 --- a/chainio/clients/avsregistry/reader.go +++ b/chainio/clients/avsregistry/reader.go @@ -2,7 +2,6 @@ package avsregistry import ( "context" - "errors" "math" "math/big" @@ -19,7 +18,6 @@ import ( "github.com/Layr-Labs/eigensdk-go/crypto/bls" "github.com/Layr-Labs/eigensdk-go/logging" "github.com/Layr-Labs/eigensdk-go/types" - "github.com/Layr-Labs/eigensdk-go/utils" ) // DefaultQueryBlockRange different node providers have different eth_getLogs range limits. @@ -113,13 +111,15 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsAtCurrentBlock( wrappedError := elcontracts.CreateForBindingError("ethClient.BlockNumber", err) return nil, wrappedError } - if curBlock > math.MaxUint32 { // other error - return nil, utils.WrapError("Current block number is too large to be converted to uint32", err) + if curBlock > math.MaxUint32 { + wrappedError := elcontracts.CreateForOtherError("Current block number is too large to fit into an uint32", err) + return nil, wrappedError } operatorStakes, err := r.GetOperatorsStakeInQuorumsAtBlock(opts, quorumNumbers, uint32(curBlock)) - if err != nil { // Nested error - return nil, err + if err != nil { + wrappedError := elcontracts.CreateForNestedError("GetOperatorsStakeInQuorumsAtBlock", err) + return nil, wrappedError } return operatorStakes, nil @@ -133,7 +133,8 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsAtBlock( blockNumber uint32, ) ([][]opstateretriever.OperatorStateRetrieverOperator, error) { if r.operatorStateRetriever == nil { - return nil, errors.New("OperatorStateRetriever contract not provided") + wrappedError := elcontracts.CreateErrorForMissingContract("OperatorStateRetriever") + return nil, wrappedError } operatorStakes, err := r.operatorStateRetriever.GetOperatorState( @@ -142,7 +143,8 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsAtBlock( quorumNumbers.UnderlyingType(), blockNumber) if err != nil { - return nil, utils.WrapError("Failed to get operators state", err) + wrappedError := elcontracts.CreateForBindingError("operatorStateRetriever.GetOperatorState", err) + return nil, wrappedError } return operatorStakes, nil } @@ -164,8 +166,9 @@ func (r *ChainReader) GetOperatorAddrsInQuorumsAtCurrentBlock( wrappedError := elcontracts.CreateForBindingError("ethClient.BlockNumber", err) return nil, wrappedError } - if curBlock > math.MaxUint32 { // other error - return nil, utils.WrapError("Current block number is too large to be converted to uint32", err) + if curBlock > math.MaxUint32 { + wrappedError := elcontracts.CreateForOtherError("Current block number is too large to fit into an uint32", err) + return nil, wrappedError } operatorStakes, err := r.operatorStateRetriever.GetOperatorState( opts, @@ -225,13 +228,15 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsOfOperatorAtCurrentBlock( wrappedError := elcontracts.CreateForBindingError("ethClient.BlockNumber", err) return nil, nil, wrappedError } - if curBlock > math.MaxUint32 { // other error - return nil, nil, utils.WrapError("Current block number is too large to be converted to uint32", err) + if curBlock > math.MaxUint32 { + wrappedError := elcontracts.CreateForOtherError("Current block number is too large to fit into an uint32", err) + return nil, nil, wrappedError } opts.BlockNumber = big.NewInt(int64(curBlock)) quorums, operatorsStake, err := r.GetOperatorsStakeInQuorumsOfOperatorAtBlock(opts, operatorId, uint32(curBlock)) if err != nil { - return nil, nil, err + wrappedError := elcontracts.CreateForNestedError("GetOperatorsStakeInQuorumsOfOperatorAtBlock", err) + return nil, nil, wrappedError } return quorums, operatorsStake, nil @@ -367,8 +372,9 @@ func (r *ChainReader) QueryRegistrationDetail( operatorAddress common.Address, ) ([]bool, error) { operatorId, err := r.GetOperatorId(opts, operatorAddress) - if err != nil { // Nested error - return nil, utils.WrapError("Failed to get operator id", err) + if err != nil { + wrappedError := elcontracts.CreateForNestedError("GetOperatorId", err) + return nil, wrappedError } value, err := r.registryCoordinator.GetCurrentQuorumBitmap(opts, operatorId) if err != nil { @@ -382,8 +388,9 @@ func (r *ChainReader) QueryRegistrationDetail( } if len(quorums) == 0 { numQuorums, err := r.GetQuorumCount(opts) - if err != nil { // Nested error - return nil, utils.WrapError("Failed to get quorum count", err) + if err != nil { + wrappedError := elcontracts.CreateForNestedError("GetQuorumCount", err) + return nil, wrappedError } for i := uint8(0); i < numQuorums; i++ { quorums = append(quorums, false) @@ -419,8 +426,9 @@ func (r *ChainReader) QueryExistingRegisteredOperatorPubKeys( blockRange *big.Int, ) ([]types.OperatorAddr, []types.OperatorPubkeys, error) { blsApkRegistryAbi, err := apkreg.ContractBLSApkRegistryMetaData.GetAbi() - if err != nil { // other error ? - return nil, nil, utils.WrapError("Cannot get Abi", err) + if err != nil { + wrappedError := elcontracts.CreateForOtherError("Failed to get bls apk registry ABI", err) + return nil, nil, wrappedError } if startBlock == nil { @@ -481,8 +489,9 @@ func (r *ChainReader) QueryExistingRegisteredOperatorPubKeys( operatorAddresses = append(operatorAddresses, operatorAddr) event, err := blsApkRegistryAbi.Unpack("NewPubkeyRegistration", vLog.Data) - if err != nil { // other error - return nil, nil, utils.WrapError("Cannot unpack event data", err) + if err != nil { + wrappedError := elcontracts.CreateForOtherError("Failed to unpack event data", err) + return nil, nil, wrappedError } G1Pubkey := event[0].(struct { diff --git a/chainio/clients/elcontracts/error.go b/chainio/clients/elcontracts/error.go index 432f38fc5..e662955ac 100644 --- a/chainio/clients/elcontracts/error.go +++ b/chainio/clients/elcontracts/error.go @@ -45,6 +45,15 @@ func CreateForNestedError(functionName string, errorCause error) Error { } } +func CreateForOtherError(errDescription string, errorCause error) Error { + return Error{ + 3, + "Other error", + errDescription, + errorCause, + } +} + func CommonErrorMissingContract(contractName string) string { return fmt.Sprintf("Missing needed contract(1) - %s contract not provided", contractName) } From 0062953e638e50c297a1c5c826a23e7f09757dc7 Mon Sep 17 00:00:00 2001 From: maximopalopoli Date: Wed, 29 Jan 2025 18:15:07 -0300 Subject: [PATCH 13/14] Fix err description asserts --- chainio/clients/avsregistry/reader_test.go | 62 ++++++++++++---------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/chainio/clients/avsregistry/reader_test.go b/chainio/clients/avsregistry/reader_test.go index 375551a2d..dc2aea84e 100644 --- a/chainio/clients/avsregistry/reader_test.go +++ b/chainio/clients/avsregistry/reader_test.go @@ -42,8 +42,7 @@ func TestReaderMethods(t *testing.T) { require.NotNil(t, addresses) }) - t.Run( - "get operators stake in quorums of operator at block returns error for non-registered operator", + t.Run("get operators stake in quorums of operator at block returns error for non-registered operator", func(t *testing.T) { operatorAddress := common.Address{0x1} operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddress) @@ -51,11 +50,14 @@ func TestReaderMethods(t *testing.T) { _, _, err = chainReader.GetOperatorsStakeInQuorumsOfOperatorAtBlock(&bind.CallOpts{}, operatorId, 100) require.Error(t, err) - require.Contains(t, err.Error(), "Failed to get operators state") + require.Equal( + t, + err.Error(), + "Binding error(0) - Error happened while calling operatorStateRetriever.GetOperatorState0: execution reverted: revert: RegistryCoordinator.getQuorumBitmapIndexAtBlockNumber: no bitmap update found for operatorId", + ) }) - t.Run( - "get single operator stake in quorums of operator at current block returns error for non-registered operator", + t.Run("get single operator stake in quorums of operator at current block returns error for non-registered operator", func(t *testing.T) { operatorAddress := common.Address{0x1} operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddress) @@ -77,7 +79,11 @@ func TestReaderMethods(t *testing.T) { quorumNumbers, []types.OperatorId{operatorId}, ) - require.Contains(t, err.Error(), "Failed to get check signatures indices") + require.Contains( + t, + err.Error(), + "Binding error(0) - Error happened while calling operatorStateRetriever.GetCheckSignaturesIndices: execution reverted: revert: RegistryCoordinator.getQuorumBitmapIndexAtBlockNumber: no bitmap update found for operatorId", + ) }) t.Run("get operator id", func(t *testing.T) { @@ -111,28 +117,26 @@ func TestReaderMethods(t *testing.T) { require.False(t, isRegistered) }) - t.Run( - "query existing registered operator pub keys", func(t *testing.T) { - addresses, pubKeys, err := chainReader.QueryExistingRegisteredOperatorPubKeys( - context.Background(), - big.NewInt(0), - nil, - nil, - ) - require.NoError(t, err) - require.Equal(t, 0, len(pubKeys)) - require.Equal(t, 0, len(addresses)) - }) + t.Run("query existing registered operator pub keys", func(t *testing.T) { + addresses, pubKeys, err := chainReader.QueryExistingRegisteredOperatorPubKeys( + context.Background(), + big.NewInt(0), + nil, + nil, + ) + require.NoError(t, err) + require.Equal(t, 0, len(pubKeys)) + require.Equal(t, 0, len(addresses)) + }) - t.Run( - "query existing registered operator sockets", func(t *testing.T) { - address_to_sockets, err := chainReader.QueryExistingRegisteredOperatorSockets( - context.Background(), - big.NewInt(0), - nil, - nil, - ) - require.NoError(t, err) - require.Equal(t, 0, len(address_to_sockets)) - }) + t.Run("query existing registered operator sockets", func(t *testing.T) { + address_to_sockets, err := chainReader.QueryExistingRegisteredOperatorSockets( + context.Background(), + big.NewInt(0), + nil, + nil, + ) + require.NoError(t, err) + require.Equal(t, 0, len(address_to_sockets)) + }) } From 07452748e3adbab22c94659cb0e8b89d102cb747 Mon Sep 17 00:00:00 2001 From: maximopalopoli Date: Thu, 30 Jan 2025 09:45:13 -0300 Subject: [PATCH 14/14] Add expected error message assert --- chainio/clients/avsregistry/reader_test.go | 39 ++++++++++++++-------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/chainio/clients/avsregistry/reader_test.go b/chainio/clients/avsregistry/reader_test.go index 89c30511b..f3ae53676 100644 --- a/chainio/clients/avsregistry/reader_test.go +++ b/chainio/clients/avsregistry/reader_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/Layr-Labs/eigensdk-go/chainio/clients/avsregistry" + "github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts" "github.com/Layr-Labs/eigensdk-go/crypto/bls" "github.com/Layr-Labs/eigensdk-go/testutils" "github.com/Layr-Labs/eigensdk-go/testutils/testclients" @@ -236,9 +237,10 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { randomOperatorId := types.OperatorId{99} tests := []struct { - name string - runFunc func() error - expectError bool + name string + runFunc func() error + expectError bool + expectedErrorString string }{ { name: "get operator id", @@ -246,7 +248,8 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { _, err := chainReader.GetOperatorId(&bind.CallOpts{}, common.Address{}) return err }, - expectError: true, + expectError: true, + expectedErrorString: elcontracts.CommonErrorMissingContract("RegistryCoordinator"), }, { name: "get operator from id", @@ -254,7 +257,8 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { _, err := chainReader.GetOperatorFromId(&bind.CallOpts{}, randomOperatorId) return err }, - expectError: true, + expectError: true, + expectedErrorString: elcontracts.CommonErrorMissingContract("RegistryCoordinator"), }, { name: "check if operator is registered", @@ -262,7 +266,8 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { _, err := chainReader.IsOperatorRegistered(&bind.CallOpts{}, common.Address{}) return err }, - expectError: true, + expectError: true, + expectedErrorString: elcontracts.CommonErrorMissingContract("RegistryCoordinator"), }, { name: "get quorum state", @@ -270,7 +275,8 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { _, err := chainReader.GetQuorumCount(&bind.CallOpts{}) return err }, - expectError: true, + expectError: true, + expectedErrorString: elcontracts.CommonErrorMissingContract("RegistryCoordinator"), }, { name: "get operator stake in quorums at current block", @@ -278,7 +284,8 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { _, err := chainReader.GetOperatorsStakeInQuorumsAtBlock(&bind.CallOpts{}, quorumNumbers, 100) return err }, - expectError: true, + expectError: true, + expectedErrorString: elcontracts.CommonErrorMissingContract("OperatorStateRetriever"), }, { name: "get operator address in quorums at current block", @@ -286,7 +293,8 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { _, err := chainReader.GetOperatorAddrsInQuorumsAtCurrentBlock(&bind.CallOpts{}, quorumNumbers) return err }, - expectError: true, + expectError: true, + expectedErrorString: elcontracts.CommonErrorMissingContract("OperatorStateRetriever"), }, { name: "get operators stake in quorums of operator at block", @@ -298,7 +306,8 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { ) return err }, - expectError: true, + expectError: true, + expectedErrorString: elcontracts.CommonErrorMissingContract("OperatorStateRetriever"), }, { name: "get single operator stake in quorums of operator at current block", @@ -309,7 +318,8 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { ) return err }, - expectError: true, + expectError: true, + expectedErrorString: elcontracts.CommonErrorMissingContract("RegistryCoordinator"), }, { name: "check signatures indices", runFunc: func() error { @@ -321,7 +331,8 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { ) return err }, - expectError: true, + expectError: true, + expectedErrorString: elcontracts.CommonErrorMissingContract("OperatorStateRetriever"), }, { name: "query registered operator sockets", @@ -334,7 +345,8 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { ) return err }, - expectError: true, + expectError: true, + expectedErrorString: elcontracts.CommonErrorMissingContract("RegistryCoordinator"), }, } @@ -343,6 +355,7 @@ func TestReaderWithInvalidConfiguration(t *testing.T) { err := tc.runFunc() if tc.expectError { require.Error(t, err, "Expected error for %s", tc.name) + require.Equal(t, err.Error(), tc.expectedErrorString) } }) }