From 0042b1a0dd502bb03c6bf1da85fc096c5c8e8f1b Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Fri, 18 Oct 2024 18:34:29 -0300 Subject: [PATCH] Get operator stake in quorums of operator at current block race condition (#371) Co-authored-by: tomasarrachea --- chainio/clients/avsregistry/reader.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/chainio/clients/avsregistry/reader.go b/chainio/clients/avsregistry/reader.go index 8733fe9c..f4ba2156 100644 --- a/chainio/clients/avsregistry/reader.go +++ b/chainio/clients/avsregistry/reader.go @@ -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, @@ -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) @@ -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), )