Skip to content

Commit

Permalink
refactor: wip refactor to move "createQuorum" to the registry coordin…
Browse files Browse the repository at this point in the history
…ator
  • Loading branch information
wadealexc committed Oct 30, 2023
1 parent a0d2c34 commit b4709cb
Show file tree
Hide file tree
Showing 8 changed files with 350 additions and 376 deletions.
42 changes: 30 additions & 12 deletions src/BLSPubkeyRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,20 @@ contract BLSPubkeyRegistry is BLSPubkeyRegistryStorage {
emit OperatorRemovedFromQuorums(operator, quorumNumbers);
}

/**
* @notice Creates a new quorum by pushing its first apk update
* @param quorumNumber The number of the new quorum
*/
function createQuorum(uint8 quorumNumber) public virtual onlyRegistryCoordinator {
require(quorumApkUpdates[quorumNumber].length == 0, "BLSPubkeyRegistry.createQuorum: quorum already exists");

quorumApkUpdates[quorumNumber].push(ApkUpdate({
apkHash: bytes24(0),
updateBlockNumber: uint32(block.number),
nextUpdateBlockNumber: 0
}));
}

/*******************************************************************************
INTERNAL FUNCTIONS
*******************************************************************************/
Expand All @@ -103,28 +117,32 @@ contract BLSPubkeyRegistry is BLSPubkeyRegistryStorage {
for (uint i = 0; i < quorumNumbers.length; ) {
uint8 quorumNumber = uint8(quorumNumbers[i]);

uint256 quorumApkUpdatesLength = quorumApkUpdates[quorumNumber].length;
if (quorumApkUpdatesLength > 0) {
// update nextUpdateBlockNumber of the current latest ApkUpdate
quorumApkUpdates[quorumNumber][quorumApkUpdatesLength - 1].nextUpdateBlockNumber = uint32(block.number);
}
// Validate quorumNumber
uint256 historyLength = quorumApkUpdates[quorumNumber].length;
require(historyLength != 0, "BLSPubkeyRegistry._processQuorumApkUpdate: quorum does not exist");

apkAfterUpdate = quorumApk[quorumNumber].plus(point);
// Update the last entry to point at the current block
// TODO - if the last entry was made in this block, update the entry instead
quorumApkUpdates[quorumNumber][historyLength - 1].nextUpdateBlockNumber = uint32(block.number);

//update aggregate public key for this quorum
// Update aggregate public key for this quorum
apkAfterUpdate = quorumApk[quorumNumber].plus(point);
quorumApk[quorumNumber] = apkAfterUpdate;
//create new ApkUpdate to add to the mapping
ApkUpdate memory latestApkUpdate;
latestApkUpdate.apkHash = bytes24(BN254.hashG1Point(apkAfterUpdate));
latestApkUpdate.updateBlockNumber = uint32(block.number);
quorumApkUpdates[quorumNumber].push(latestApkUpdate);

// Push update to history
quorumApkUpdates[quorumNumber].push(ApkUpdate({
apkHash: bytes24(BN254.hashG1Point(apkAfterUpdate)),
updateBlockNumber: uint32(block.number),
nextUpdateBlockNumber: 0
}));

unchecked {
++i;
}
}
}

// TODO - should this fail if apkUpdate.apkHash == 0? This will be the case for the first entry in each quorum
function _validateApkHashForQuorumAtBlockNumber(ApkUpdate memory apkUpdate, uint32 blockNumber) internal pure {
require(
blockNumber >= apkUpdate.updateBlockNumber,
Expand Down
95 changes: 72 additions & 23 deletions src/BLSRegistryCoordinatorWithIndices.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import "src/interfaces/IStakeRegistry.sol";
import "src/interfaces/IIndexRegistry.sol";
import "src/interfaces/IRegistryCoordinator.sol";



/**
* @title A `RegistryCoordinator` that has three registries:
* 1) a `StakeRegistry` that keeps track of operators' stakes
Expand All @@ -44,18 +42,22 @@ contract BLSRegistryCoordinatorWithIndices is EIP712, Initializable, IBLSRegistr
uint8 internal constant PAUSED_REGISTER_OPERATOR = 0;
/// @notice Index for flag that pauses operator deregistration
uint8 internal constant PAUSED_DEREGISTER_OPERATOR = 1;
/// @notice The maximum number of quorums this contract supports
uint8 internal constant MAX_QUORUM_COUNT = 192;

/// @notice the EigenLayer Slasher
ISlasher public immutable slasher;
/// @notice the Service Manager for the service that this contract is coordinating
IServiceManager public immutable serviceManager;
/// @notice the BLS Pubkey Registry contract that will keep track of operators' BLS public keys
IBLSPubkeyRegistry public immutable blsPubkeyRegistry;
BLSPubkeyRegistry public immutable blsPubkeyRegistry;
/// @notice the Stake Registry contract that will keep track of operators' stakes
IStakeRegistry public immutable stakeRegistry;
StakeRegistry public immutable stakeRegistry;
/// @notice the Index Registry contract that will keep track of operators' indexes
IIndexRegistry public immutable indexRegistry;
IndexRegistry public immutable indexRegistry;

/// @notice the current number of quorums supported by the registry coordinator
uint8 public quorumCount;
/// @notice the mapping from quorum number to a quorums operator cap and kick parameters
mapping(uint8 => OperatorSetParam) internal _quorumOperatorSetParams;
/// @notice the mapping from operator's operatorId to the updates of the bitmap of quorums they are registered for
Expand All @@ -82,6 +84,14 @@ contract BLSRegistryCoordinatorWithIndices is EIP712, Initializable, IBLSRegistr
_;
}

modifier quorumExists(uint8 quorumNumber) {
require(
quorumNumber < quorumCount,
"BLSRegistryCoordinatorWithIndices.quorumExists: quorum does not exist"
);
_;
}

constructor(
ISlasher _slasher,
IServiceManager _serviceManager,
Expand All @@ -99,25 +109,30 @@ contract BLSRegistryCoordinatorWithIndices is EIP712, Initializable, IBLSRegistr
function initialize(
address _churnApprover,
address _ejector,
OperatorSetParam[] memory _operatorSetParams,
IPauserRegistry _pauserRegistry,
uint256 _initialPausedStatus
uint256 _initialPausedStatus,
OperatorSetParam[] memory _operatorSetParams,
uint96[] memory _minimumStakes,
IVoteWeigher.StrategyAndWeightingMultiplier[][] memory _strategyParams
) external initializer {
// set initial paused status
require(
_operatorSetParams.length == _minimumStakes.length && _minimumStakes.length == _strategyParams.length,
"BLSRegistryCoordinatorWithIndices.initialize: input length mismatch"
);

// Initialize roles
_initializePauser(_pauserRegistry, _initialPausedStatus);
// set the churnApprover
_setChurnApprover(_churnApprover);
// set the ejector
_setEjector(_ejector);
// add registry contracts to the registries array

// Add registry contracts to the registries array
registries.push(address(stakeRegistry));
registries.push(address(blsPubkeyRegistry));
registries.push(address(indexRegistry));

// set the operator set params
require(IVoteWeigher(address(stakeRegistry)).quorumCount() == _operatorSetParams.length, "BLSRegistryCoordinatorWithIndices: operator set params length mismatch");
for (uint8 i = 0; i < _operatorSetParams.length; i++) {
_setOperatorSetParams(i, _operatorSetParams[i]);
// Create quorums
for (uint256 i = 0; i < _operatorSetParams.length; i++) {
_createQuorum(_operatorSetParams[i], _minimumStakes[i], _strategyParams[i]);
}
}

Expand Down Expand Up @@ -322,16 +337,27 @@ contract BLSRegistryCoordinatorWithIndices is EIP712, Initializable, IBLSRegistr
*******************************************************************************/

/**
* @notice Sets parameters of the operator set for the given `quorumNumber`
* @notice Creates a quorum and initializes it in each registry contract
*/
function createQuorum(
OperatorSetParam memory operatorSetParams,
uint96 minimumStake,
IVoteWeigher.StrategyAndWeightingMultiplier[] memory strategyParams
) external virtual onlyServiceManagerOwner {
_createQuorum(operatorSetParams, minimumStake, strategyParams);
}

/**
* @notice Updates a quorum's OperatorSetParams
* @param quorumNumber is the quorum number to set the maximum number of operators for
* @param operatorSetParam is the parameters of the operator set for the `quorumNumber`
* @param operatorSetParams is the parameters of the operator set for the `quorumNumber`
* @dev only callable by the service manager owner
*/
function setOperatorSetParams(
uint8 quorumNumber,
OperatorSetParam memory operatorSetParam
) external onlyServiceManagerOwner {
_setOperatorSetParams(quorumNumber, operatorSetParam);
OperatorSetParam memory operatorSetParams
) external onlyServiceManagerOwner quorumExists(quorumNumber) {
_setOperatorSetParams(quorumNumber, operatorSetParams);
}

/**
Expand Down Expand Up @@ -521,9 +547,32 @@ contract BLSRegistryCoordinatorWithIndices is EIP712, Initializable, IBLSRegistr
EIP1271SignatureUtils.checkSignature_EIP1271(churnApprover, calculateOperatorChurnApprovalDigestHash(registeringOperatorId, operatorKickParams, signatureWithSaltAndExpiry.salt, signatureWithSaltAndExpiry.expiry), signatureWithSaltAndExpiry.signature);
}

function _setOperatorSetParams(uint8 quorumNumber, OperatorSetParam memory operatorSetParam) internal {
_quorumOperatorSetParams[quorumNumber] = operatorSetParam;
emit OperatorSetParamsUpdated(quorumNumber, operatorSetParam);
/**
* @notice Creates and initializes a quorum in each registry contract
*/
function _createQuorum(
OperatorSetParam memory operatorSetParams,
uint96 minimumStake,
IVoteWeigher.StrategyAndWeightingMultiplier[] memory strategyParams
) internal {
// Increment the total quorum count. Fails if we're already at the max
uint8 prevQuorumCount = quorumCount;
require(prevQuorumCount < MAX_QUORUM_COUNT, "BLSRegistryCoordinatorWithIndicies.createQuorum: max quorums reached");
quorumCount = prevQuorumCount + 1;

// The previous count is the new quorum's number
uint8 quorumNumber = prevQuorumCount;

// Initialize the quorum here and in each registry
_setOperatorSetParams(quorumNumber, operatorSetParams);
stakeRegistry.createQuorum(quorumNumber, minimumStake, strategyParams);
indexRegistry.createQuorum(quorumNumber);
blsPubkeyRegistry.createQuorum(quorumNumber);
}

function _setOperatorSetParams(uint8 quorumNumber, OperatorSetParam memory operatorSetParams) internal {
_quorumOperatorSetParams[quorumNumber] = operatorSetParams;
emit OperatorSetParamsUpdated(quorumNumber, operatorSetParams);
}

function _setChurnApprover(address newChurnApprover) internal {
Expand Down
34 changes: 24 additions & 10 deletions src/IndexRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,12 @@ contract IndexRegistry is IndexRegistryStorage {
for (uint256 i = 0; i < quorumNumbers.length; i++) {
uint8 quorumNumber = uint8(quorumNumbers[i]);

//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].numOperators : 0;
// Check that the quorum exists
uint256 historyLength = _totalOperatorsHistory[quorumNumber].length;
require(historyLength != 0, "IndexRegistry.registerOperator: quorum does not exist");

// Get the number of operators currently in the quorum, which will be operator's new index
uint32 numOperators = historyLength > 0 ? _totalOperatorsHistory[quorumNumber][historyLength - 1].numOperators : 0;
_updateOperatorIdToIndexHistory({
operatorId: operatorId,
quorumNumber: quorumNumber,
Expand Down Expand Up @@ -90,11 +93,24 @@ contract IndexRegistry is IndexRegistryStorage {
});
_updateTotalOperatorHistory({
quorumNumber: quorumNumber,
numOperators: _totalOperatorsHistory[quorumNumber][_totalOperatorsHistory[quorumNumber].length - 1].numOperators - 1
numOperators: _totalOperatorsHistory[quorumNumber][historyLength - 1].numOperators - 1
});
}
}

/**
* @notice Creates a new quorum by pushing its first quorum update
* @param quorumNumber The number of the new quorum
*/
function createQuorum(uint8 quorumNumber) public virtual onlyRegistryCoordinator {
require(_totalOperatorsHistory[quorumNumber].length == 0, "IndexRegistry.createQuorum: quorum already exists");

_totalOperatorsHistory[quorumNumber].push(QuorumUpdate({
numOperators: 0,
fromBlockNumber: uint32(block.number)
}));
}

/*******************************************************************************
INTERNAL FUNCTIONS
*******************************************************************************/
Expand All @@ -105,12 +121,10 @@ contract IndexRegistry is IndexRegistryStorage {
* @param numOperators is the number of operators in the quorum
*/
function _updateTotalOperatorHistory(uint8 quorumNumber, uint32 numOperators) internal {
QuorumUpdate memory quorumUpdate;
// In the case of totalOperatorsHistory, the index parameter is the number of operators in the quorum
quorumUpdate.numOperators = numOperators;
quorumUpdate.fromBlockNumber = uint32(block.number);

_totalOperatorsHistory[quorumNumber].push(quorumUpdate);
_totalOperatorsHistory[quorumNumber].push(QuorumUpdate({
numOperators: numOperators,
fromBlockNumber: uint32(block.number)
}));
}

/**
Expand Down
Loading

0 comments on commit b4709cb

Please sign in to comment.