Skip to content

Commit

Permalink
Merge branch 'dev' into test--cleanup-operator-test-local-calls-only
Browse files Browse the repository at this point in the history
  • Loading branch information
pablodeymo authored Nov 20, 2024
2 parents 00a95da + 27225c8 commit 9982848
Show file tree
Hide file tree
Showing 47 changed files with 2,725 additions and 1,654 deletions.
1 change: 1 addition & 0 deletions .github/workflows/check-fmt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
branches:
- dev
pull_request:
merge_group:

permissions:
contents: read
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/check-mocks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
branches:
- dev
pull_request:
merge_group:

permissions:
contents: read
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- dev
pull_request:
merge_group:

jobs:
Lint:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- dev
pull_request:
merge_group:

jobs:
Test:
Expand Down
6 changes: 3 additions & 3 deletions aws/secretmanager/secretmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package secretmanager

import (
"context"
"log"

"github.com/Layr-Labs/eigensdk-go/utils"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
Expand All @@ -12,7 +12,7 @@ import (
func ReadStringFromSecretManager(ctx context.Context, secretName, region string) (string, error) {
config, err := config.LoadDefaultConfig(ctx, config.WithRegion(region))
if err != nil {
log.Fatal(err)
return "", utils.WrapError("error while loading default config", err)
}

// Create Secrets Manager client
Expand All @@ -27,7 +27,7 @@ func ReadStringFromSecretManager(ctx context.Context, secretName, region string)
if err != nil {
// For a list of exceptions thrown, see
// https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
return "", err
return "", utils.WrapError("error while loading default config", err)
}

// Decrypts secret using the associated KMS key.
Expand Down
28 changes: 22 additions & 6 deletions chainio/clients/avsregistry/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,11 @@ func (r *ChainReader) GetOperatorsStakeInQuorumsOfOperatorAtCurrentBlock(
return r.GetOperatorsStakeInQuorumsOfOperatorAtBlock(opts, operatorId, uint32(curBlock))
}

// GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock could have race conditions
// it currently makes a bunch of calls to fetch "current block" information,
// so some of them could actually return information from different blocks
// To avoid a possible race condition, this method must assure that all the calls
// are made with the same blockNumber.
// So, if the blockNumber and blockHash are not set in opts, blockNumber will be set
// to the latest block.
// All calls to the chain use `opts` parameter.
func (r *ChainReader) GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock(
opts *bind.CallOpts,
operatorId types.OperatorId,
Expand All @@ -267,6 +269,20 @@ func (r *ChainReader) GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock(
return nil, errors.New("StakeRegistry contract not provided")
}

// check if opts parameter has not a block number set (BlockNumber)
var defaultHash common.Hash
if opts.BlockNumber == nil && opts.BlockHash == defaultHash {
// if not, set the block number to the latest block
if opts.Context == nil {
opts.Context = context.Background()
}
latestBlock, err := r.ethClient.BlockNumber(opts.Context)
if err != nil {
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 {
return nil, utils.WrapError("Failed to get operator quorums", err)
Expand All @@ -275,7 +291,7 @@ func (r *ChainReader) GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock(
quorumStakes := make(map[types.QuorumNum]types.StakeAmount)
for _, quorum := range quorums {
stake, err := r.stakeRegistry.GetCurrentStake(
&bind.CallOpts{},
opts,
operatorId,
uint8(quorum),
)
Expand Down Expand Up @@ -421,7 +437,7 @@ func (r *ChainReader) QueryExistingRegisteredOperatorPubKeys(
if err != nil {
return nil, nil, utils.WrapError("Cannot get current block number", err)
}
stopBlock = big.NewInt(int64(curBlockNum))
stopBlock = new(big.Int).SetUint64(curBlockNum)
}
if blockRange == nil {
blockRange = DefaultQueryBlockRange
Expand Down Expand Up @@ -519,7 +535,7 @@ func (r *ChainReader) QueryExistingRegisteredOperatorSockets(
if err != nil {
return nil, utils.WrapError("Cannot get current block number", err)
}
stopBlock = big.NewInt(int64(curBlockNum))
stopBlock = new(big.Int).SetUint64(curBlockNum)
}
if blockRange == nil {
blockRange = DefaultQueryBlockRange
Expand Down
138 changes: 138 additions & 0 deletions chainio/clients/avsregistry/reader_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package avsregistry_test

import (
"context"
"math/big"
"testing"

"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"
"github.com/stretchr/testify/require"
)

func TestReaderMethods(t *testing.T) {
clients, _ := testclients.BuildTestClients(t)
chainReader := clients.ReadClients.AvsRegistryChainReader

quorumNumbers := types.QuorumNums{0}

t.Run("get quorum state", func(t *testing.T) {
count, err := chainReader.GetQuorumCount(&bind.CallOpts{})
require.NoError(t, err)
require.NotNil(t, count)
})

t.Run("get operator stake in quorums at current block", func(t *testing.T) {
stake, err := chainReader.GetOperatorsStakeInQuorumsAtCurrentBlock(&bind.CallOpts{}, quorumNumbers)
require.NoError(t, err)
require.NotNil(t, stake)
})

t.Run("get operator stake in quorums at block", func(t *testing.T) {
stake, err := chainReader.GetOperatorsStakeInQuorumsAtBlock(&bind.CallOpts{}, quorumNumbers, 100)
require.NoError(t, err)
require.NotNil(t, stake)
})

t.Run("get operator address in quorums at current block", func(t *testing.T) {
addresses, err := chainReader.GetOperatorAddrsInQuorumsAtCurrentBlock(&bind.CallOpts{}, quorumNumbers)
require.NoError(t, err)
require.NotNil(t, addresses)
})

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)
require.NoError(t, err)

_, _, err = chainReader.GetOperatorsStakeInQuorumsOfOperatorAtBlock(&bind.CallOpts{}, operatorId, 100)
require.Error(t, err)
require.Contains(t, err.Error(), "Failed to get operators state")
})

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)
require.NoError(t, err)

stakes, err := chainReader.GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock(&bind.CallOpts{}, operatorId)
require.NoError(t, err)
require.Equal(t, 0, len(stakes))
})

t.Run("get check signatures indices returns error for non-registered operator", func(t *testing.T) {
operatorAddress := common.Address{0x1}
operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)

_, err = chainReader.GetCheckSignaturesIndices(
&bind.CallOpts{},
100,
quorumNumbers,
[]types.OperatorId{operatorId},
)
require.Contains(t, err.Error(), "Failed to get check signatures indices")
})

t.Run("get operator id", func(t *testing.T) {
operatorAddress := common.Address{0x1}
operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)
require.NotNil(t, operatorId)
})

t.Run("get operator from id returns zero address for non-registered operator", func(t *testing.T) {
operatorAddress := common.HexToAddress("0x1234567890123456789012345678901234567890")
operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)

retrievedAddress, err := chainReader.GetOperatorFromId(&bind.CallOpts{}, operatorId)
require.NoError(t, err)
require.Equal(t, retrievedAddress, common.Address{0x0})
})

t.Run("query registration detail", func(t *testing.T) {
operatorAddress := common.HexToAddress("0x1234567890123456789012345678901234567890")
quorums, err := chainReader.QueryRegistrationDetail(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)
require.Equal(t, 1, len(quorums))
})

t.Run("is operator registered", func(t *testing.T) {
operatorAddress := common.HexToAddress("0x1234567890123456789012345678901234567890")
isRegistered, err := chainReader.IsOperatorRegistered(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)
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 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))
})
}
12 changes: 7 additions & 5 deletions chainio/clients/avsregistry/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (

type eLReader interface {
CalculateOperatorAVSRegistrationDigestHash(
opts *bind.CallOpts,
ctx context.Context,
operatorAddr gethcommon.Address,
serviceManagerAddr gethcommon.Address,
operatorToAvsRegistrationSigSalt [32]byte,
Expand Down Expand Up @@ -233,7 +233,7 @@ func (w *ChainWriter) RegisterOperatorInQuorumWithAVSRegistryCoordinator(

// params to register operator in delegation manager's operator-avs mapping
msgToSign, err := w.elReader.CalculateOperatorAVSRegistrationDigestHash(
&bind.CallOpts{},
ctx,
operatorAddr,
w.serviceManagerAddr,
operatorToAvsRegistrationSigSalt,
Expand Down Expand Up @@ -344,16 +344,18 @@ func (w *ChainWriter) RegisterOperator(
if err != nil {
return nil, err
}
curBlock, err := w.ethClient.BlockByNumber(context.Background(), big.NewInt(int64(curBlockNum)))
curBlock, err := w.ethClient.BlockByNumber(context.Background(), new(big.Int).SetUint64(curBlockNum))
if err != nil {
return nil, err
}
sigValidForSeconds := int64(60 * 60) // 1 hour
operatorToAvsRegistrationSigExpiry := big.NewInt(int64(curBlock.Time()) + sigValidForSeconds)
operatorToAvsRegistrationSigExpiry := new(
big.Int,
).Add(new(big.Int).SetUint64(curBlock.Time()), big.NewInt(sigValidForSeconds))

// params to register operator in delegation manager's operator-avs mapping
msgToSign, err := w.elReader.CalculateOperatorAVSRegistrationDigestHash(
&bind.CallOpts{},
ctx,
operatorAddr,
w.serviceManagerAddr,
operatorToAvsRegistrationSigSalt,
Expand Down
74 changes: 74 additions & 0 deletions chainio/clients/avsregistry/writer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package avsregistry_test

import (
"context"
"testing"

chainioutils "github.com/Layr-Labs/eigensdk-go/chainio/utils"
"github.com/Layr-Labs/eigensdk-go/crypto/bls"
"github.com/Layr-Labs/eigensdk-go/testutils/testclients"
"github.com/Layr-Labs/eigensdk-go/types"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
)

func TestWriterMethods(t *testing.T) {
clients, _ := testclients.BuildTestClients(t)
chainWriter := clients.AvsRegistryChainWriter

keypair, err := bls.NewKeyPairFromString("0x01")
require.NoError(t, err)

addr := gethcommon.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266")
ecdsaPrivKeyHex := "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
ecdsaPrivateKey, err := crypto.HexToECDSA(ecdsaPrivKeyHex)
require.NoError(t, err)

quorumNumbers := types.QuorumNums{0}

t.Run("register operator", func(t *testing.T) {
receipt, err := chainWriter.RegisterOperator(
context.Background(),
ecdsaPrivateKey,
keypair,
quorumNumbers,
"",
true,
)
require.NoError(t, err)
require.NotNil(t, receipt)
})

t.Run("update stake of operator subset", func(t *testing.T) {
receipt, err := chainWriter.UpdateStakesOfOperatorSubsetForAllQuorums(
context.Background(),
[]gethcommon.Address{addr},
true,
)
require.NoError(t, err)
require.NotNil(t, receipt)
})

t.Run("update stake of entire operator set", func(t *testing.T) {
receipt, err := chainWriter.UpdateStakesOfEntireOperatorSetForQuorums(
context.Background(),
[][]gethcommon.Address{{addr}},
quorumNumbers,
true,
)
require.NoError(t, err)
require.NotNil(t, receipt)
})

t.Run("deregister operator", func(t *testing.T) {
receipt, err := chainWriter.DeregisterOperator(
context.Background(),
quorumNumbers,
chainioutils.ConvertToBN254G1Point(keypair.PubKey),
true,
)
require.NoError(t, err)
require.NotNil(t, receipt)
})
}
2 changes: 1 addition & 1 deletion chainio/clients/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func BuildAll(
}
signerV2, addr, err := signerv2.SignerFromConfig(signerv2.Config{PrivateKey: ecdsaPrivateKey}, chainid)
if err != nil {
panic(err)
return nil, utils.WrapError("Failed to create the signer from the given config", err)
}

pkWallet, err := wallet.NewPrivateKeyWallet(ethHttpClient, signerV2, addr, logger)
Expand Down
Loading

0 comments on commit 9982848

Please sign in to comment.