Skip to content

Commit

Permalink
Handle bitmap lookup for nonexistent operators
Browse files Browse the repository at this point in the history
  • Loading branch information
jianoaix committed Mar 19, 2024
1 parent 7644f61 commit 1a9c51d
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 20 deletions.
51 changes: 40 additions & 11 deletions core/eth/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)))
Expand All @@ -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
}
Expand Down
17 changes: 8 additions & 9 deletions disperser/dataapi/nonsigner_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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++
Expand All @@ -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
}
}
Expand All @@ -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
Expand Down

0 comments on commit 1a9c51d

Please sign in to comment.