Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 25 additions & 23 deletions src/OperatorStateRetriever.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,36 @@ contract OperatorStateRetriever {
address operator;
bytes32 operatorId;
uint96 stake;
uint96 slashableStake;
}

struct CheckSignaturesIndices {
uint32[] nonSignerQuorumBitmapIndices;
uint32[] quorumApkIndices;
uint32[] totalStakeIndices;
uint32[] totalStakeIndices;
uint32[][] nonSignerStakeIndices; // nonSignerStakeIndices[quorumNumberIndex][nonSignerIndex]
}

/**
* @notice This function is intended to to be called by AVS operators every time a new task is created (i.e.)
* the AVS coordinator makes a request to AVS operators. Since all of the crucial information is kept onchain,
* the AVS coordinator makes a request to AVS operators. Since all of the crucial information is kept onchain,
* operators don't need to run indexers to fetch the data.
* @param registryCoordinator is the registry coordinator to fetch the AVS registry information from
* @param operatorId the id of the operator to fetch the quorums lists
* @param operatorId the id of the operator to fetch the quorums lists
* @param blockNumber is the block number to get the operator state for
* @return 1) the quorumBitmap of the operator at the given blockNumber
* 2) 2d array of Operator structs. For each quorum the provided operator
* 2) 2d array of Operator structs. For each quorum the provided operator
* was a part of at `blockNumber`, an ordered list of operators.
*/
function getOperatorState(
IRegistryCoordinator registryCoordinator,
bytes32 operatorId,
IRegistryCoordinator registryCoordinator,
bytes32 operatorId,
uint32 blockNumber
) external view returns (uint256, Operator[][] memory) {
bytes32[] memory operatorIds = new bytes32[](1);
operatorIds[0] = operatorId;
uint256 index = registryCoordinator.getQuorumBitmapIndicesAtBlockNumber(blockNumber, operatorIds)[0];

uint256 quorumBitmap = registryCoordinator.getQuorumBitmapAtBlockNumberByIndex(operatorId, blockNumber, index);

bytes memory quorumNumbers = BitmapUtils.bitmapToBytesArray(quorumBitmap);
Expand All @@ -54,16 +55,16 @@ contract OperatorStateRetriever {
}

/**
* @notice returns the ordered list of operators (id and stake) for each quorum. The AVS coordinator
* @notice returns the ordered list of operators (id and stake) for each quorum. The AVS coordinator
* may call this function directly to get the operator state for a given block number
* @param registryCoordinator is the registry coordinator to fetch the AVS registry information from
* @param quorumNumbers are the ids of the quorums to get the operator state for
* @param blockNumber is the block number to get the operator state for
* @return 2d array of Operators. For each quorum, an ordered list of Operators
*/
function getOperatorState(
IRegistryCoordinator registryCoordinator,
bytes memory quorumNumbers,
IRegistryCoordinator registryCoordinator,
bytes memory quorumNumbers,
uint32 blockNumber
) public view returns(Operator[][] memory) {
IStakeRegistry stakeRegistry = registryCoordinator.stakeRegistry();
Expand All @@ -79,32 +80,33 @@ contract OperatorStateRetriever {
operators[i][j] = Operator({
operator: blsApkRegistry.getOperatorFromPubkeyHash(operatorIds[j]),
operatorId: bytes32(operatorIds[j]),
stake: stakeRegistry.getStakeAtBlockNumber(bytes32(operatorIds[j]), quorumNumber, blockNumber)
stake: stakeRegistry.getStakeAtBlockNumber(bytes32(operatorIds[j]), quorumNumber, blockNumber),
slashableStake: stakeRegistry.getStakeAtBlockNumber(bytes32(operatorIds[j]), quorumNumber, blockNumber) /// TODO: Fix this when view added
});
}
}

return operators;
}

/**
* @notice this is called by the AVS operator to get the relevant indices for the checkSignatures function
* if they are not running an indexer
* if they are not running an indexer
* @param registryCoordinator is the registry coordinator to fetch the AVS registry information from
* @param referenceBlockNumber is the block number to get the indices for
* @param quorumNumbers are the ids of the quorums to get the operator state for
* @param nonSignerOperatorIds are the ids of the nonsigning operators
* @return 1) the indices of the quorumBitmaps for each of the operators in the @param nonSignerOperatorIds array at the given blocknumber
* 2) the indices of the total stakes entries for the given quorums at the given blocknumber
* 3) the indices of the stakes of each of the nonsigners in each of the quorums they were a
* 3) the indices of the stakes of each of the nonsigners in each of the quorums they were a
* part of (for each nonsigner, an array of length the number of quorums they were a part of
* that are also part of the provided quorumNumbers) at the given blocknumber
* 4) the indices of the quorum apks for each of the provided quorums at the given blocknumber
*/
function getCheckSignaturesIndices(
IRegistryCoordinator registryCoordinator,
uint32 referenceBlockNumber,
bytes calldata quorumNumbers,
uint32 referenceBlockNumber,
bytes calldata quorumNumbers,
bytes32[] calldata nonSignerOperatorIds
) external view returns (CheckSignaturesIndices memory) {
IStakeRegistry stakeRegistry = registryCoordinator.stakeRegistry();
Expand All @@ -115,7 +117,7 @@ contract OperatorStateRetriever {

// get the indices of the totalStake updates for each of the quorums in the quorumNumbers array
checkSignaturesIndices.totalStakeIndices = stakeRegistry.getTotalStakeIndicesAtBlockNumber(referenceBlockNumber, quorumNumbers);

checkSignaturesIndices.nonSignerStakeIndices = new uint32[][](quorumNumbers.length);
for (uint8 quorumNumberIndex = 0; quorumNumberIndex < quorumNumbers.length; quorumNumberIndex++) {
uint256 numNonSignersForQuorum = 0;
Expand All @@ -124,15 +126,15 @@ contract OperatorStateRetriever {

for (uint i = 0; i < nonSignerOperatorIds.length; i++) {
// get the quorumBitmap for the operator at the given blocknumber and index
uint192 nonSignerQuorumBitmap =
uint192 nonSignerQuorumBitmap =
registryCoordinator.getQuorumBitmapAtBlockNumberByIndex(
nonSignerOperatorIds[i],
referenceBlockNumber,
nonSignerOperatorIds[i],
referenceBlockNumber,
checkSignaturesIndices.nonSignerQuorumBitmapIndices[i]
);

require(nonSignerQuorumBitmap != 0, "OperatorStateRetriever.getCheckSignaturesIndices: operator must be registered at blocknumber");

// if the operator was a part of the quorum and the quorum is a part of the provided quorumNumbers
if ((nonSignerQuorumBitmap >> uint8(quorumNumbers[quorumNumberIndex])) & 1 == 1) {
// get the index of the stake update for the operator at the given blocknumber and quorum number
Expand Down Expand Up @@ -210,5 +212,5 @@ contract OperatorStateRetriever {
operators[i] = registryCoordinator.getOperatorFromId(operatorIds[i]);
}
}

}
11 changes: 11 additions & 0 deletions src/RegistryCoordinator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,17 @@ contract RegistryCoordinator is
}
}

function updateOperatorAllocationsForQuorum(
address[] memory operators,
uint8 quorumNumber
) external onlyWhenNotPaused(PAUSED_UPDATE_OPERATOR) {
bytes32[] memory operatorIds = new bytes32[](operators.length);
for (uint256 i = 0; i < operators.length; i++) {
operatorIds[i] = _operatorInfo[operators[i]].operatorId;
}
stakeRegistry.updateOperatorsAllocations(operators, operatorIds, quorumNumber);
}

/**
* @notice For each quorum in `quorumNumbers`, updates the StakeRegistry's view of ALL its registered operators' stakes.
* Each quorum's `quorumUpdateBlockNumber` is also updated, which tracks the most recent block number when ALL registered
Expand Down
Loading
Loading