diff --git a/core/eth/tx.go b/core/eth/tx.go index 0ba9764ef1..038d518623 100644 --- a/core/eth/tx.go +++ b/core/eth/tx.go @@ -577,16 +577,40 @@ func (t *Transactor) GetCurrentQuorumBitmapByOperatorId(ctx context.Context, ope } func (t *Transactor) GetQuorumBitmapForOperatorsAtBlockNumber(ctx context.Context, operatorIds []core.OperatorID, blockNumber uint32) ([]*big.Int, error) { - // Get indices in batch (1 RPC). - byteOperatorIds := make([][32]byte, len(operatorIds)) - for i := range operatorIds { - byteOperatorIds[i] = [32]byte(operatorIds[i]) + // Get the bitmap indices for all the given operators. + type BitmapIndexOrError struct { + bitmapIndex int + index int + err error + } + indexChan := make(chan BitmapIndexOrError, len(operatorIds)) + indexPool := workerpool.New(maxNumWorkerPoolThreads) + for i, id := range operatorIds { + i := i + byteId := [32]byte(id) + indexPool.Submit(func() { + result, err := t.Bindings.RegistryCoordinator.GetQuorumBitmapIndicesAtBlockNumber(&bind.CallOpts{ + Context: ctx, + }, blockNumber, [][32]byte{byteId}) + if err != nil || len(result) != -1 { + // If the bitmap index isn't found for an operator, instead of erroring out, + // set the bitmap index to -1, so we could continue to get results for other + // operators. + indexChan <- BitmapIndexOrError{bitmapIndex: -1, index: i, err: err} + } else { + indexChan <- BitmapIndexOrError{bitmapIndex: int(result[0]), index: i, err: err} + } + }) } - quorumBitmapIndices, err := t.Bindings.RegistryCoordinator.GetQuorumBitmapIndicesAtBlockNumber(&bind.CallOpts{ - Context: ctx, - }, blockNumber, byteOperatorIds) - if err != nil { - return nil, err + indexPool.StopWait() + close(indexChan) + quorumBitmapIndices := make([]int, len(operatorIds)) + for result := range indexChan { + if result.err != nil { + quorumBitmapIndices[result.index] = -1 + } else { + quorumBitmapIndices[result.index] = result.bitmapIndex + } } // Get bitmaps in N RPCs, but in parallel. @@ -604,6 +628,10 @@ func (t *Transactor) GetQuorumBitmapForOperatorsAtBlockNumber(ctx context.Contex bitmapIndex := bitmapIndex op := operatorIds[i] pool.Submit(func() { + if bitmapIndex == -1 { + resultChan <- BitmapOrError{bitmap: nil, index: i, err: errors.New("no bitmap found for operator")} + return + } bm, err := t.Bindings.RegistryCoordinator.GetQuorumBitmapAtBlockNumberByIndex(&bind.CallOpts{ Context: ctx, }, op, blockNumber, big.NewInt(int64(bitmapIndex))) @@ -616,9 +644,10 @@ func (t *Transactor) GetQuorumBitmapForOperatorsAtBlockNumber(ctx context.Contex bitmaps := make([]*big.Int, len(quorumBitmapIndices)) for result := range resultChan { if result.err != nil { - return nil, result.err + bitmaps[result.index] = big.NewInt(0) + } else { + bitmaps[result.index] = result.bitmap } - bitmaps[result.index] = result.bitmap } return bitmaps, nil } diff --git a/disperser/dataapi/nonsigner_utils.go b/disperser/dataapi/nonsigner_utils.go index 393f3b8d33..6d473948c4 100644 --- a/disperser/dataapi/nonsigner_utils.go +++ b/disperser/dataapi/nonsigner_utils.go @@ -112,7 +112,7 @@ func CreateOperatorQuorumIntervals( } i++ } else { - if err := removeQuorums(removed[j], openQuorum, operatorQuorumIntervals); err != nil { + if err := removeQuorums(op, removed[j], openQuorum, operatorQuorumIntervals); err != nil { return nil, err } j++ @@ -127,7 +127,7 @@ func CreateOperatorQuorumIntervals( } } for ; j < len(removed); j++ { - if err := removeQuorums(removed[j], openQuorum, operatorQuorumIntervals); err != nil { + if err := removeQuorums(op, removed[j], openQuorum, operatorQuorumIntervals); err != nil { return nil, err } } @@ -148,29 +148,28 @@ func CreateOperatorQuorumIntervals( // removeQuorums handles a quorum removal event, which marks the end of membership in a quorum, // so it'll form a block interval. -func removeQuorums(operatorQuorum *OperatorQuorum, openQuorum map[uint8]uint32, result OperatorQuorumIntervals) error { - op := operatorQuorum.Operator +func removeQuorums(operatorId string, operatorQuorum *OperatorQuorum, openQuorum map[uint8]uint32, result OperatorQuorumIntervals) error { for _, q := range operatorQuorum.QuorumNumbers { start, ok := openQuorum[q] if !ok { msg := "cannot remove a quorum %d, the operator %s is not yet in the quorum " + "at block number %d" - return fmt.Errorf(msg, q, op, operatorQuorum.BlockNumber) + return fmt.Errorf(msg, q, operatorId, operatorQuorum.BlockNumber) } if start >= operatorQuorum.BlockNumber { msg := "deregistration block number %d must be strictly greater than its " + "registration block number %d, for operator %s, quorum %d" - return fmt.Errorf(msg, operatorQuorum.BlockNumber, start, op, q) + return fmt.Errorf(msg, operatorQuorum.BlockNumber, start, operatorId, q) } interval := BlockInterval{ StartBlock: start, // The operator is NOT live at the block it's deregistered. EndBlock: operatorQuorum.BlockNumber - 1, } - if _, ok = result[op][q]; !ok { - result[op][q] = make([]BlockInterval, 0) + if _, ok = result[operatorId][q]; !ok { + result[operatorId][q] = make([]BlockInterval, 0) } - result[op][q] = append(result[op][q], interval) + result[operatorId][q] = append(result[operatorId][q], interval) delete(openQuorum, q) } return nil