Skip to content

Commit

Permalink
Merge branch 'multiquorums' into edit-bls-sig-checker
Browse files Browse the repository at this point in the history
  • Loading branch information
gpsanant authored Jun 27, 2023
2 parents 85f87e8 + 609c55d commit 648a590
Show file tree
Hide file tree
Showing 7 changed files with 9 additions and 133 deletions.
2 changes: 1 addition & 1 deletion src/contracts/interfaces/IBLSPubkeyRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ interface IBLSPubkeyRegistry is IRegistry {
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already deregistered
* 5) `quorumNumbers` is the same as the parameter use when registering
* 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for
* 6) `pubkey` is the same as the parameter used when registering
*/
function deregisterOperator(address operator, bool completeDeregistration, bytes calldata quorumNumbers, BN254.G1Point memory pubkey) external returns(bytes32);
Expand Down
2 changes: 1 addition & 1 deletion src/contracts/interfaces/IIndexRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ interface IIndexRegistry is IRegistry {
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already deregistered
* 5) `quorumNumbers` is the same as the parameter use when registering
* 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for
*/
function deregisterOperator(bytes32 operatorId, bool completeDeregistration, bytes calldata quorumNumbers, bytes32[] memory operatorIdsToSwap, uint32 globalOperatorListIndex) external;

Expand Down
2 changes: 1 addition & 1 deletion src/contracts/interfaces/IRegistryCoordinator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ interface IRegistryCoordinator {
// the id of the operator, which is likely the keccak256 hash of the operator's public key if using BLSRegsitry
bytes32 operatorId;
// start taskNumber from which the operator has been registered
uint32 fromTaskNumber;
uint32 fromTaskNumber; // TODO: REMOVE
// indicates whether the operator is actively registered for serving the middleware or not
OperatorStatus status;
}
Expand Down
46 changes: 1 addition & 45 deletions src/contracts/interfaces/IStakeRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ interface IStakeRegistry is IRegistry {
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already deregistered
* 5) `quorumNumbers` is the same as the parameter use when registering
* 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for
*/
function deregisterOperator(bytes32 operatorId, bytes memory quorumNumbers) external;

Expand Down Expand Up @@ -136,50 +136,6 @@ interface IStakeRegistry is IRegistry {
*/
function getCurrentTotalStakeForQuorum(uint8 quorumNumber) external view returns (uint96);

/**
* @notice Checks that the `operator` was active at the `blockNumber`, using the specified `stakeHistoryIndex` as proof.
* @param operatorId is the id of the operator of interest
* @param blockNumber is the block number of interest
* @param quorumNumber is the quorum number which the operator had stake in
* @param stakeHistoryIndex specifies the index in `operatorIdToStakeHistory[operatorId]` at which to check the claim of the operator's activity
* @return 'true' if it is succesfully proven that the `operator` was active at the `blockNumber`, and 'false' otherwise
* @dev In order for this function to return 'true', the inputs must satisfy all of the following list:
* 1) `operatorIdToStakeHistory[operatorId][quorumNumber][index].updateBlockNumber <= blockNumber`
* 2) `operatorIdToStakeHistory[operatorId][quorumNumber][index].nextUpdateBlockNumber` must be either `0` (signifying no next update) or
* is must be strictly greater than `blockNumber`
* 3) `operatorIdToStakeHistory[operatorId][quorumNumber][index].stake > 0` i.e. the operator had nonzero stake
* @dev Note that a return value of 'false' does not guarantee that the `operator` was inactive at `blockNumber`, since a
* bad `stakeHistoryIndex` can be supplied in order to obtain a response of 'false'.
*/
function checkOperatorActiveAtBlockNumber(
bytes32 operatorId,
uint256 blockNumber,
uint8 quorumNumber,
uint256 stakeHistoryIndex
) external view returns (bool);

/**
* @notice Checks that the `operator` was inactive at the `blockNumber`, using the specified `stakeHistoryIndex` for `quorumNumber` as proof.
* @param operatorId is the id of the operator of interest
* @param blockNumber is the block number of interest
* @param quorumNumber is the quorum number which the operator had no stake in
* @param stakeHistoryIndex specifies the index in `operatorIdToStakeHistory[operatorId]` at which to check the claim of the operator's inactivity
* @return 'true' if it is succesfully proven that the `operator` was inactive at the `blockNumber`, and 'false' otherwise
* @dev In order for this function to return 'true', the inputs must satisfy all of the following list:
* 1) `operatorIdToStakeHistory[operatorId][quorumNumber][index].updateBlockNumber <= blockNumber`
* 2) `operatorIdToStakeHistory[operatorId][quorumNumber][index].nextUpdateBlockNumber` must be either `0` (signifying no next update) or
* is must be strictly greater than `blockNumber`
* 3) `operatorIdToStakeHistory[operatorId][quorumNumber][index].stake == 0` i.e. the operator had zero stake
* @dev Note that a return value of 'false' does not guarantee that the `operator` was active at `blockNumber`, since a
* bad `stakeHistoryIndex` can be supplied in order to obtain a response of 'false'.
*/
function checkOperatorInactiveAtBlockNumber(
bytes32 operatorId,
uint256 blockNumber,
uint8 quorumNumber,
uint256 stakeHistoryIndex
) external view returns (bool);

/**
* @notice Used for updating information on deposits of nodes.
* @param operators are the addresses of the operators whose stake information is getting updated
Expand Down
2 changes: 1 addition & 1 deletion src/contracts/middleware/BLSPubkeyRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ contract BLSPubkeyRegistry is IBLSPubkeyRegistry, Test {
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already deregistered
* 5) `quorumNumbers` is the same as the parameter use when registering
* 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for
* 6) `pubkey` is the same as the parameter used when registering
*/
function deregisterOperator(address operator, bool completeDeregistration, bytes memory quorumNumbers, BN254.G1Point memory pubkey) external onlyRegistryCoordinator returns(bytes32){
Expand Down
2 changes: 1 addition & 1 deletion src/contracts/middleware/IndexRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ contract IndexRegistry is IIndexRegistry {
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already deregistered
* 5) `quorumNumbers` is the same as the parameter use when registering
* 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for
*/
function deregisterOperator(bytes32 operatorId, bool completeDeregistration, bytes calldata quorumNumbers, bytes32[] memory operatorIdsToSwap, uint32 globalOperatorListIndex) external onlyRegistryCoordinator {
require(quorumNumbers.length == operatorIdsToSwap.length, "IndexRegistry.deregisterOperator: quorumNumbers and operatorIdsToSwap must be the same length");
Expand Down
86 changes: 3 additions & 83 deletions src/contracts/middleware/StakeRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -196,85 +196,6 @@ contract StakeRegistry is StakeRegistryStorage {
return _totalStakeHistory[quorumNumber].length;
}

/**
* @notice Checks that the `operator` was active at the `blockNumber`, using the specified `stakeHistoryIndex` as proof.
* @param operatorId is the id of the operator of interest
* @param blockNumber is the block number of interest
* @param quorumNumber is the quorum number which the operator had stake in
* @param stakeHistoryIndex specifies the index in `operatorIdToStakeHistory[operatorId]` at which to check the claim of the operator's activity
* @return 'true' if it is succesfully proven that the `operator` was active at the `blockNumber`, and 'false' otherwise
* @dev In order for this function to return 'true', the inputs must satisfy all of the following list:
* 1) `operatorIdToStakeHistory[operatorId][quorumNumber][index].updateBlockNumber <= blockNumber`
* 2) `operatorIdToStakeHistory[operatorId][quorumNumber][index].nextUpdateBlockNumber` must be either `0` (signifying no next update) or
* is must be strictly greater than `blockNumber`
* 3) `operatorIdToStakeHistory[operatorId][quorumNumber][index].stake > 0` i.e. the operator had nonzero stake
* @dev Note that a return value of 'false' does not guarantee that the `operator` was inactive at `blockNumber`, since a
* bad `stakeHistoryIndex` can be supplied in order to obtain a response of 'false'.
*/
function checkOperatorActiveAtBlockNumber(
bytes32 operatorId,
uint256 blockNumber,
uint8 quorumNumber,
uint256 stakeHistoryIndex
) external view returns (bool)
{
// pull the stake history entry specified by `stakeHistoryIndex`
OperatorStakeUpdate memory operatorStakeUpdate = operatorIdToStakeHistory[operatorId][quorumNumber][stakeHistoryIndex];
return (
// check that the update specified by `stakeHistoryIndex` occurred at or prior to `blockNumber`
(operatorStakeUpdate.updateBlockNumber <= blockNumber)
&&
// if there is a next update, then check that the next update occurred strictly after `blockNumber`
(operatorStakeUpdate.nextUpdateBlockNumber == 0 || operatorStakeUpdate.nextUpdateBlockNumber > blockNumber)
&&
/// verify that the stake was non-zero at the time (note: here was use the assumption that the operator was 'inactive'
/// once their stake fell to zero)
operatorStakeUpdate.stake != 0 // this implicitly checks that the operator was a part of the quorum of interest
);
}

/**
* @notice Checks that the `operator` was inactive at the `blockNumber`, using the specified `stakeHistoryIndex` for `quorumNumber` as proof.
* @param operatorId is the id of the operator of interest
* @param blockNumber is the block number of interest
* @param quorumNumber is the quorum number which the operator had no stake in
* @param stakeHistoryIndex specifies the index in `operatorIdToStakeHistory[operatorId]` at which to check the claim of the operator's inactivity
* @return 'true' if it is succesfully proven that the `operator` was inactive at the `blockNumber`, and 'false' otherwise
* @dev In order for this function to return 'true', the inputs must satisfy all of the following list:
* 1) `operatorIdToStakeHistory[operatorId][quorumNumber][index].updateBlockNumber <= blockNumber`
* 2) `operatorIdToStakeHistory[operatorId][quorumNumber][index].nextUpdateBlockNumber` must be either `0` (signifying no next update) or
* is must be strictly greater than `blockNumber`
* 3) `operatorIdToStakeHistory[operatorId][quorumNumber][index].stake == 0` i.e. the operator had zero stake
* @dev Note that a return value of 'false' does not guarantee that the `operator` was active at `blockNumber`, since a
* bad `stakeHistoryIndex` can be supplied in order to obtain a response of 'false'.
* @dev One precondition that must be checked is that the operator is a part of the given `quorumNumber`
*/
function checkOperatorInactiveAtBlockNumber(
bytes32 operatorId,
uint256 blockNumber,
uint8 quorumNumber,
uint256 stakeHistoryIndex
) external view returns (bool)
{
// special case for `operatorIdToStakeHistory[operatorId]` having length zero -- in which case we know the operator was never registered
if (operatorIdToStakeHistory[operatorId][quorumNumber].length == 0) {
return true;
}
// pull the stake history entry specified by `stakeHistoryIndex`
OperatorStakeUpdate memory operatorStakeUpdate = operatorIdToStakeHistory[operatorId][quorumNumber][stakeHistoryIndex];
return (
// check that the update specified by `stakeHistoryIndex` occurred at or prior to `blockNumber`
(operatorStakeUpdate.updateBlockNumber <= blockNumber)
&&
// if there is a next update, then check that the next update occurred strictly after `blockNumber`
(operatorStakeUpdate.nextUpdateBlockNumber == 0 || operatorStakeUpdate.nextUpdateBlockNumber > blockNumber)
&&
/// verify that the stake was zero at the time (note: here was use the assumption that the operator was 'inactive'
/// once their stake fell to zero)
operatorStakeUpdate.stake == 0
);
}

// MUTATING FUNCTIONS

/// @notice Adjusts the `minimumStakeFirstQuorum` -- i.e. the node stake (weight) requirement for inclusion in the 1st quorum.
Expand Down Expand Up @@ -308,7 +229,7 @@ contract StakeRegistry is StakeRegistryStorage {
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already deregistered
* 5) `quorumNumbers` is the same as the parameter use when registering
* 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for
*/
function deregisterOperator(bytes32 operatorId, bytes calldata quorumNumbers) external virtual onlyRegistryCoordinator {
_deregisterOperator(operatorId, quorumNumbers);
Expand Down Expand Up @@ -418,17 +339,15 @@ contract StakeRegistry is StakeRegistryStorage {
* stake updates. These operator's individual stake updates will have a 0 stake value for the latest update.
*/
function _deregisterOperator(bytes32 operatorId, bytes memory quorumNumbers) internal {
uint8 quorumNumbersLength = uint8(quorumNumbers.length);
// check the operator is deregistering from only valid quorums
require(uint8(quorumNumbers[quorumNumbersLength - 1]) < quorumCount, "StakeRegistry._registerOperator: greatest quorumNumber must be less than quorumCount");
OperatorStakeUpdate memory _operatorStakeUpdate;
// add the `updateBlockNumber` info
_operatorStakeUpdate.updateBlockNumber = uint32(block.number);
OperatorStakeUpdate memory _newTotalStakeUpdate;
// add the `updateBlockNumber` info
_newTotalStakeUpdate.updateBlockNumber = uint32(block.number);
// loop through the operator's quorums and remove the operator's stake for each quorum
for (uint8 quorumNumbersIndex = 0; quorumNumbersIndex < quorumNumbersLength;) {
for (uint8 quorumNumbersIndex = 0; quorumNumbersIndex < quorumNumbers.length;) {
uint8 quorumNumber = uint8(quorumNumbers[quorumNumbersIndex]);
// update the operator's stake
uint96 stakeBeforeUpdate = _recordOperatorStakeUpdate(operatorId, quorumNumber, _operatorStakeUpdate);
Expand Down Expand Up @@ -465,6 +384,7 @@ contract StakeRegistry is StakeRegistryStorage {

// check if minimum requirements have been met
if (operatorStakeUpdate.stake < minimumStakeForQuorum[quorumNumber]) {
// set staker to 0
operatorStakeUpdate.stake = uint96(0);
}
// get stakeBeforeUpdate and update with new stake
Expand Down

0 comments on commit 648a590

Please sign in to comment.