Skip to content

Commit

Permalink
split up operatorIndexUpdate struct into two
Browse files Browse the repository at this point in the history
  • Loading branch information
ypatil12 committed Oct 19, 2023
1 parent a226a89 commit b503dc3
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 74 deletions.
17 changes: 13 additions & 4 deletions docs/middleware/IndexRegistry.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,27 @@ This contract assigns each operator an index (0 indexed) within each of its quor
The RegistryCoordinator for the AVS makes call to the IndexRegistry to register an operator for a certain set of quorums. The IndexRegistry will assign the next index in each of the quorums the operator is registering for to the operator storing the following struct:
```solidity
// struct used to give definitive ordering to operators at each blockNumber.
// NOTE: this struct is slightly abused for also storing the total number of operators for each quorum over time
struct OperatorIndexUpdate {
// blockNumber number from which `index` was the operators index
// the operator's index or the total number of operators at a `blockNumber` is the first entry such that `blockNumber >= entry.fromBlockNumber`
// the operator's index is the first entry such that `blockNumber >= entry.fromBlockNumber`
uint32 fromBlockNumber;
// index of the operator in array of operators, or the total number of operators if in the 'totalOperatorsHistory'
// index of the operator in array of operators
// index = type(uint32).max = OPERATOR_DEREGISTERED_INDEX implies the operator was deregistered
uint32 index;
}
```

The IndexRegistry also adds the operator's id to the append only list of operators that have registered for the middleware and it stores the total number of operators after the registering operator has registered for each of the quorums the operator is registering for by pushing the above struct to a growing array.
The IndexRegistry also adds the operator's id to the append only list of operators that have registered for the middleware and it stores the total number of operators after the registering operator has registered for each of the quorums the operator is registering for by pushing the below struct to a growing array.

```solidity
// struct used to denote the number of operators in a quorum at a given blockNumber
struct QuorumUpdate {
// The total number of operators at a `blockNumber` is the first entry such that `blockNumber >= entry.fromBlockNumber`
uint32 fromBlockNumber;
// The number of operators at `fromBlockNumber`
uint32 numOperators;
}
```

### deregisterOperator

Expand Down
38 changes: 19 additions & 19 deletions src/IndexRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ contract IndexRegistry is IndexRegistryStorage {

//this is the would-be index of the operator being registered, the total number of operators for that quorum (which is last index + 1)
uint256 quorumHistoryLength = _totalOperatorsHistory[quorumNumber].length;
uint32 numOperators = quorumHistoryLength > 0 ? _totalOperatorsHistory[quorumNumber][quorumHistoryLength - 1].index : 0;
uint32 numOperators = quorumHistoryLength > 0 ? _totalOperatorsHistory[quorumNumber][quorumHistoryLength - 1].numOperators : 0;
_updateOperatorIdToIndexHistory({
operatorId: operatorId,
quorumNumber: quorumNumber,
Expand Down Expand Up @@ -101,7 +101,7 @@ contract IndexRegistry is IndexRegistryStorage {
});
_updateTotalOperatorHistory({
quorumNumber: quorumNumber,
numOperators: _totalOperatorsHistory[quorumNumber][_totalOperatorsHistory[quorumNumber].length - 1].index - 1
numOperators: _totalOperatorsHistory[quorumNumber][_totalOperatorsHistory[quorumNumber].length - 1].numOperators - 1
});
}
}
Expand All @@ -116,12 +116,12 @@ contract IndexRegistry is IndexRegistryStorage {
* @param numOperators is the number of operators in the quorum
*/
function _updateTotalOperatorHistory(uint8 quorumNumber, uint32 numOperators) internal {
OperatorIndexUpdate memory totalOperatorUpdate;
QuorumUpdate memory quorumUpdate;
// In the case of totalOperatorsHistory, the index parameter is the number of operators in the quorum
totalOperatorUpdate.index = numOperators;
totalOperatorUpdate.fromBlockNumber = uint32(block.number);
quorumUpdate.numOperators = numOperators;
quorumUpdate.fromBlockNumber = uint32(block.number);

_totalOperatorsHistory[quorumNumber].push(totalOperatorUpdate);
_totalOperatorsHistory[quorumNumber].push(quorumUpdate);
}

/**
Expand Down Expand Up @@ -152,7 +152,7 @@ contract IndexRegistry is IndexRegistryStorage {
) internal {
uint32 operatorIdToSwapIndex = _operatorIdToIndexHistory[operatorIdToSwap][quorumNumber][_operatorIdToIndexHistory[operatorIdToSwap][quorumNumber].length - 1].index;
require(
_totalOperatorsHistory[quorumNumber][_totalOperatorsHistory[quorumNumber].length - 1].index - 1 == operatorIdToSwapIndex,
_totalOperatorsHistory[quorumNumber][_totalOperatorsHistory[quorumNumber].length - 1].numOperators - 1 == operatorIdToSwapIndex,
"IndexRegistry._processOperatorRemoval: operatorIdToSwap is not the last operator in the quorum"
);

Expand Down Expand Up @@ -198,13 +198,13 @@ contract IndexRegistry is IndexRegistryStorage {
// loop backwards through the total operator history to find the total number of operators at the given block number
for (uint256 i = 0; i <= totalOperatorsHistoryLength - 1; i++) {
uint256 listIndex = (totalOperatorsHistoryLength - 1) - i;
OperatorIndexUpdate memory totalOperatorUpdate = _totalOperatorsHistory[quorumNumber][listIndex];
QuorumUpdate memory quorumUpdate = _totalOperatorsHistory[quorumNumber][listIndex];
// look for the first update that began before or at `blockNumber`
if (totalOperatorUpdate.fromBlockNumber <= blockNumber) {
return _totalOperatorsHistory[quorumNumber][listIndex].index;
if (quorumUpdate.fromBlockNumber <= blockNumber) {
return _totalOperatorsHistory[quorumNumber][listIndex].numOperators;
}
}
return _totalOperatorsHistory[quorumNumber][0].index;
return _totalOperatorsHistory[quorumNumber][0].numOperators;
}

/**
Expand Down Expand Up @@ -251,10 +251,10 @@ contract IndexRegistry is IndexRegistryStorage {
}

/// @notice Returns the _totalOperatorsHistory entry for the specified `quorumNumber` at the specified `index`
function getTotalOperatorsUpdateForQuorumAtIndex(
function getQuorumUpdateAtIndex(
uint8 quorumNumber,
uint32 index
) external view returns (OperatorIndexUpdate memory) {
) external view returns (QuorumUpdate memory) {
return _totalOperatorsHistory[quorumNumber][index];
}

Expand Down Expand Up @@ -305,23 +305,23 @@ contract IndexRegistry is IndexRegistryStorage {
uint32 blockNumber,
uint32 index
) external view returns (uint32){
OperatorIndexUpdate memory operatorIndexToCheck = _totalOperatorsHistory[quorumNumber][index];
QuorumUpdate memory quorumUpdate = _totalOperatorsHistory[quorumNumber][index];

// blocknumber must be at or after the "index'th" entry's fromBlockNumber
require(
blockNumber >= operatorIndexToCheck.fromBlockNumber,
blockNumber >= quorumUpdate.fromBlockNumber,
"IndexRegistry.getTotalOperatorsForQuorumAtBlockNumberByIndex: provided index is too far in the past for provided block number"
);

// if there is an index update after the "index'th" update, the blocknumber must be before the next entry's fromBlockNumber
if (index != _totalOperatorsHistory[quorumNumber].length - 1){
OperatorIndexUpdate memory nextOperatorIndex = _totalOperatorsHistory[quorumNumber][index + 1];
QuorumUpdate memory nextQuorumUpdate = _totalOperatorsHistory[quorumNumber][index + 1];
require(
blockNumber < nextOperatorIndex.fromBlockNumber,
blockNumber < nextQuorumUpdate.fromBlockNumber,
"IndexRegistry.getTotalOperatorsForQuorumAtBlockNumberByIndex: provided index is too far in the future for provided block number"
);
}
return operatorIndexToCheck.index;
return quorumUpdate.numOperators;
}

/// @notice Returns an ordered list of operators of the services for the given `quorumNumber` at the given `blockNumber`
Expand All @@ -347,6 +347,6 @@ contract IndexRegistry is IndexRegistryStorage {
if (totalOperatorsHistoryLength == 0) {
return 0;
}
return _totalOperatorsHistory[quorumNumber][totalOperatorsHistoryLength - 1].index;
return _totalOperatorsHistory[quorumNumber][totalOperatorsHistoryLength - 1].numOperators;
}
}
2 changes: 1 addition & 1 deletion src/IndexRegistryStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ abstract contract IndexRegistryStorage is Initializable, IIndexRegistry {
/// @notice mapping of operatorId => quorumNumber => index history of that operator
mapping(bytes32 => mapping(uint8 => OperatorIndexUpdate[])) internal _operatorIdToIndexHistory;
/// @notice mapping of quorumNumber => history of numbers of unique registered operators
mapping(uint8 => OperatorIndexUpdate[]) internal _totalOperatorsHistory;
mapping(uint8 => QuorumUpdate[]) internal _totalOperatorsHistory;

constructor(
IRegistryCoordinator _registryCoordinator
Expand Down
15 changes: 11 additions & 4 deletions src/interfaces/IIndexRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,23 @@ interface IIndexRegistry is IRegistry {
// DATA STRUCTURES

// struct used to give definitive ordering to operators at each blockNumber.
// NOTE: this struct is slightly abused for also storing the total number of operators for each quorum over time
struct OperatorIndexUpdate {
// blockNumber number from which `index` was the operators index
// the operator's index or the total number of operators at a `blockNumber` is the first entry such that `blockNumber >= entry.fromBlockNumber`
// the operator's index is the first entry such that `blockNumber >= entry.fromBlockNumber`
uint32 fromBlockNumber;
// index of the operator in array of operators, or the total number of operators if in the 'totalOperatorsHistory'
// index of the operator in array of operators
// index = type(uint32).max = OPERATOR_DEREGISTERED_INDEX implies the operator was deregistered
uint32 index;
}

// struct used to denote the number of operators in a quorum at a given blockNumber
struct QuorumUpdate {
// The total number of operators at a `blockNumber` is the first entry such that `blockNumber >= entry.fromBlockNumber`
uint32 fromBlockNumber;
// The number of operators at `fromBlockNumber`
uint32 numOperators;
}

/**
* @notice Registers the operator with the specified `operatorId` for the quorums specified by `quorumNumbers`.
* @param operatorId is the id of the operator that is being registered
Expand Down Expand Up @@ -63,7 +70,7 @@ interface IIndexRegistry is IRegistry {
function getOperatorIndexUpdateOfOperatorIdForQuorumAtIndex(bytes32 operatorId, uint8 quorumNumber, uint32 index) external view returns (OperatorIndexUpdate memory);

/// @notice Returns the _totalOperatorsHistory entry for the specified `quorumNumber` at the specified `index`
function getTotalOperatorsUpdateForQuorumAtIndex(uint8 quorumNumber, uint32 index) external view returns (OperatorIndexUpdate memory);
function getQuorumUpdateAtIndex(uint8 quorumNumber, uint32 index) external view returns (QuorumUpdate memory);

/**
* @notice Looks up the `operator`'s index for `quorumNumber` at the specified `blockNumber` using the `index`.
Expand Down
Loading

0 comments on commit b503dc3

Please sign in to comment.