Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make epoch period flexible #118

Merged
merged 4 commits into from
Jun 12, 2024
Merged
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
5 changes: 0 additions & 5 deletions contracts/interfaces/ILagrangeCommittee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,6 @@ interface ILagrangeCommittee {
// Fired on successful rotation of committee
event UpdateCommittee(uint256 indexed chainID, uint256 indexed epochNumber, bytes32 current);

// Event fired on updating epoch period
event EpochPeriodUpdated(
uint32 indexed chainID, uint32 indexed epochPeriodIndex, uint256 flagBlock, uint256 flagEpoch, uint256 duration
);

// Event fired on updating sign address
event SignAddressUpdated(address indexed operator, address indexed signAddress);
}
132 changes: 50 additions & 82 deletions contracts/protocol/LagrangeCommittee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,6 @@ contract LagrangeCommittee is Initializable, OwnableUpgradeable, ILagrangeCommit
// ChainID => Committee
mapping(uint32 => CommitteeDef) public committeeParams;

// committees is also used for external storage for epoch period modification
// committees[chainID][uint256.max].leafCount = current index of epoch period
// committees[chainID][uint256.max - 1] : 1-index
// updatedBlock: (flagBlock << 112) | flagEpoch
// leafCount: epochPeriod
// committees[chainID][uint256.max - 2] : 2-index
// committees[chainID][uint256.max - 3] : 3-index
// ... ... ...
// ChainID => Epoch => CommitteeData
mapping(uint32 => mapping(uint256 => CommitteeData)) public committees;

Expand Down Expand Up @@ -67,16 +59,6 @@ contract LagrangeCommittee is Initializable, OwnableUpgradeable, ILagrangeCommit
_transferOwnership(initialOwner);
}

// Initializes epoch period
// @dev This function can be called for the chainID registered in the previous version
function setFirstEpochPeriod(uint32 chainID) public onlyOwner {
uint32 _count = getEpochPeriodCount(chainID);
if (_count != 0) return; // already initialized
CommitteeDef memory _committeeParam = committeeParams[chainID];

_writeEpochPeriod(chainID, _committeeParam.startBlock, 0, _committeeParam.duration);
}

// Adds a new operator to the committee
function addOperator(address operator, address signAddress, uint256[2][] calldata blsPubKeys)
external
Expand Down Expand Up @@ -366,7 +348,7 @@ contract LagrangeCommittee is Initializable, OwnableUpgradeable, ILagrangeCommit

epochNumber = _getEpochNumber(chainID, blockNumber);
// All the prior blocks belong to epoch 1
if (epochNumber == 0) epochNumber = 1;
if (epochNumber == 0 && blockNumber >= committeeParams[chainID].genesisBlock) epochNumber = 1;
}

// Get the operator's voting power for the given chainID
Expand Down Expand Up @@ -424,8 +406,6 @@ contract LagrangeCommittee is Initializable, OwnableUpgradeable, ILagrangeCommit

chainIDs.push(_chainID);

setFirstEpochPeriod(_chainID);

emit InitCommittee(_chainID, _quorumNumber, _genesisBlock, _duration, _freezeDuration, _minWeight, _maxWeight);
}

Expand All @@ -441,12 +421,6 @@ contract LagrangeCommittee is Initializable, OwnableUpgradeable, ILagrangeCommit
uint96 _minWeight,
uint96 _maxWeight
) internal {
if (committeeParams[_chainID].duration != _duration) {
uint256 _flagEpoch = _getEpochNumber(_chainID, block.number - 1) + 1;
(,, uint256 _endBlockPrv) = getEpochInterval(_chainID, _flagEpoch - 1);
_writeEpochPeriod(_chainID, _endBlockPrv, _flagEpoch, _duration);
}

committeeParams[_chainID] = CommitteeDef(
_startBlock, _l1Bias, _genesisBlock, _duration, _freezeDuration, _quorumNumber, _minWeight, _maxWeight
);
Expand All @@ -456,74 +430,68 @@ contract LagrangeCommittee is Initializable, OwnableUpgradeable, ILagrangeCommit
);
}

// ----------------- Functions for Epoch Number ----------------- //
function getEpochPeriodCount(uint32 chainID) public view returns (uint32) {
return committees[chainID][type(uint256).max].leafCount;
}

function getEpochPeriodByIndex(uint32 chainID, uint32 index)
public
view
returns (uint256 flagBlock, uint256 flagEpoch, uint256 duration)
{
CommitteeData memory _epochPeriodContext = committees[chainID][type(uint256).max - index];
return (
_epochPeriodContext.updatedBlock >> 112,
(_epochPeriodContext.updatedBlock << 112) >> 112,
_epochPeriodContext.leafCount
);
}

function getEpochInterval(uint32 _chainID, uint256 _epochNumber)
// Get epoch interval for a given chain
function getEpochInterval(uint32 chainID, uint256 epochNumber)
public
view
returns (uint256 _startBlock, uint256 _freezeBlock, uint256 _endBlock)
returns (uint256 startBlock, uint256 freezeBlock, uint256 endBlock)
{
// epoch period would be updated rarely
uint32 _index = getEpochPeriodCount(_chainID);
while (_index > 0) {
(uint256 _flagBlock, uint256 _flagEpoch, uint256 _duration) = getEpochPeriodByIndex(_chainID, _index);
if (_epochNumber >= _flagEpoch) {
_startBlock = (_epochNumber - _flagEpoch) * _duration + _flagBlock;
_endBlock = _startBlock + _duration;
_freezeBlock = _endBlock - committeeParams[_chainID].freezeDuration;
break;
}
unchecked {
_index--;
}
CommitteeDef memory committeeParam = committeeParams[chainID];
uint256 _lastEpoch = updatedEpoch[chainID];

if (epochNumber == 0) {
startBlock = committeeParam.startBlock;
endBlock = _lastEpoch == 0
? committeeParam.startBlock + committeeParam.duration
: committees[chainID][1].updatedBlock;
freezeBlock = endBlock - committeeParam.freezeDuration;
return (startBlock, freezeBlock, endBlock);
}
}

function _writeEpochPeriod(uint32 _chainID, uint256 _flagBlock, uint256 _flagEpoch, uint256 _duration) internal {
uint32 _index = committees[_chainID][type(uint256).max].leafCount + 1;
committees[_chainID][type(uint256).max - _index] = CommitteeData(
0,
(uint224(SafeCast.toUint112(_flagBlock)) << 112) + uint224(SafeCast.toUint112(_flagEpoch)),
SafeCast.toUint32(_duration)
);
committees[_chainID][type(uint256).max].leafCount = _index;
emit EpochPeriodUpdated(_chainID, _index, _flagBlock, _flagEpoch, _duration);
if (epochNumber <= _lastEpoch) {
startBlock = committees[chainID][epochNumber].updatedBlock;
endBlock = _lastEpoch == epochNumber
? startBlock + committeeParam.duration
: committees[chainID][epochNumber + 1].updatedBlock;
freezeBlock = endBlock - committeeParam.freezeDuration;
} else {
uint256 _lastEpochBlock =
_lastEpoch > 0 ? committees[chainID][_lastEpoch].updatedBlock : committeeParam.startBlock;
startBlock = _lastEpochBlock + (epochNumber - _lastEpoch) * committeeParam.duration;
endBlock = startBlock + committeeParam.duration;
freezeBlock = endBlock - committeeParam.freezeDuration;
}
}

function _getEpochNumber(uint32 _chainID, uint256 _blockNumber) internal view returns (uint256 _epochNumber) {
if (_blockNumber < committeeParams[_chainID].genesisBlock) {
CommitteeDef memory committeeParam = committeeParams[_chainID];
if (_blockNumber < committeeParam.startBlock) {
return 0;
}
// epoch period would be updated rarely
uint32 _index = getEpochPeriodCount(_chainID);
while (_index > 0) {
(uint256 _flagBlock, uint256 _flagEpoch, uint256 _duration) = getEpochPeriodByIndex(_chainID, _index);
if (_blockNumber >= _flagBlock) {
_epochNumber = _flagEpoch + (_blockNumber - _flagBlock) / _duration;
break;
}
unchecked {
_index--;

uint256 _lastEpoch = updatedEpoch[_chainID];
uint256 _lastEpochBlock =
_lastEpoch > 0 ? committees[_chainID][_lastEpoch].updatedBlock : committeeParam.startBlock;

if (_blockNumber >= _lastEpochBlock) {
_epochNumber = _lastEpoch + (_blockNumber - _lastEpochBlock) / committeeParam.duration;
} else if (_lastEpoch == 0) {
return 0;
} else {
// binary search
uint256 _low = 0;
uint256 _high = _lastEpoch;
while (_low < _high - 1) {
uint256 _mid = (_low + _high + 1) >> 1;
if (_blockNumber < committees[_chainID][_mid].updatedBlock) {
_high = _mid;
} else {
_low = _mid + 1;
}
}
_epochNumber = _high - 1;
}
}
// ------------------------------------------------------------- //

function _registerOperator(address _operator, address _signAddress, uint256[2][] memory _blsPubKeys) internal {
delete operatorsStatus[_operator];
Expand Down
30 changes: 0 additions & 30 deletions script/update/Redeploy_For_UpdateEpoch.s.sol

This file was deleted.

Loading
Loading