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

currently everything is broken because interfaces live in core and fixing it is a pain
  • Loading branch information
wadealexc committed Oct 26, 2023
1 parent b5afb7d commit 596f20f
Show file tree
Hide file tree
Showing 11 changed files with 622 additions and 383 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 @@ -337,16 +352,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 @@ -535,9 +561,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
47 changes: 33 additions & 14 deletions src/IndexRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,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 @@ -92,6 +95,11 @@ contract IndexRegistry is IndexRegistryStorage {

for (uint256 i = 0; i < quorumNumbers.length; i++) {
uint8 quorumNumber = uint8(quorumNumbers[i]);

// Check that the quorum exists
uint256 historyLength = _totalOperatorsHistory[quorumNumber].length;
require(historyLength != 0, "IndexRegistry.registerOperator: quorum does not exist");

uint32 indexOfOperatorToRemove = _operatorIdToIndexHistory[operatorId][quorumNumber][_operatorIdToIndexHistory[operatorId][quorumNumber].length - 1].index;
_processOperatorRemoval({
operatorId: operatorId,
Expand All @@ -101,11 +109,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 @@ -116,12 +137,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 All @@ -130,10 +149,10 @@ contract IndexRegistry is IndexRegistryStorage {
* @param index the latest index of that operator in the list of operators registered for this quorum
*/
function _updateOperatorIdToIndexHistory(bytes32 operatorId, uint8 quorumNumber, uint32 index) internal {
OperatorIndexUpdate memory latestOperatorIndex;
latestOperatorIndex.index = index;
latestOperatorIndex.fromBlockNumber = uint32(block.number);
_operatorIdToIndexHistory[operatorId][quorumNumber].push(latestOperatorIndex);
_operatorIdToIndexHistory[operatorId][quorumNumber].push(OperatorIndexUpdate({
index: index,
fromBlockNumber: uint32(block.number)
}));

emit QuorumIndexUpdate(operatorId, quorumNumber, index);
}
Expand Down
Loading

0 comments on commit 596f20f

Please sign in to comment.