Skip to content

Commit

Permalink
[postconfirmation] epoch names (#1052)
Browse files Browse the repository at this point in the history
  • Loading branch information
apenzk authored Feb 18, 2025
1 parent 2ca5e05 commit c0134ae
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 98 deletions.
67 changes: 32 additions & 35 deletions protocol-units/settlement/mcr/contracts/src/settlement/MCR.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,18 @@ contract MCR is Initializable, BaseSettlement, MCRStorage, IMCR {
}

// gets the would be epoch for the current L1Block time
function getEpochByL1BlockTime() public view returns (uint256) {
function getPresentEpoch() public view returns (uint256) {
return stakingContract.getEpochByL1BlockTime(address(this));
}

// gets the current epoch up to which superBlocks have been accepted
function getCurrentEpoch() public view returns (uint256) {
return stakingContract.getCurrentEpoch(address(this));
// gets the epoch up to which superBlocks have been accepted
function getAcceptingEpoch() public view returns (uint256) {
return stakingContract.getAcceptingEpoch(address(this));
}

// gets the next epoch
function getNextEpoch() public view returns (uint256) {
return stakingContract.getNextEpoch(address(this));
function getNextAcceptingEpoch() public view returns (uint256) {
return stakingContract.getNextAcceptingEpoch(address(this));
}

// gets the stake for a given attester at a given epoch
Expand Down Expand Up @@ -113,17 +113,17 @@ contract MCR is Initializable, BaseSettlement, MCRStorage, IMCR {
}

// gets the stake for a given attester at the current epoch
function getCurrentEpochStake(
function getAcceptingEpochStake(
address custodian,
address attester
) public view returns (uint256) {
return getStakeAtEpoch(getCurrentEpoch(), custodian, attester);
return getStakeAtEpoch(getAcceptingEpoch(), custodian, attester);
}

function computeAllCurrentEpochStake(
function computeAllStakeFromAcceptingEpoch(
address attester
) public view returns (uint256) {
return computeAllStakeAtEpoch(getCurrentEpoch(), attester);
return computeAllStakeAtEpoch(getAcceptingEpoch(), attester);
}

// gets the total stake for a given epoch
Expand Down Expand Up @@ -161,19 +161,19 @@ contract MCR is Initializable, BaseSettlement, MCRStorage, IMCR {
return totalStake;
}

// gets the total stake for the current epoch
function getTotalStakeForCurrentEpoch(
// gets the total stake for the current epoch for a given custodian
function getTotalStakeForAcceptingEpoch(
address custodian
) public view returns (uint256) {
return getTotalStakeForEpoch(getCurrentEpoch(), custodian);
return getTotalStakeForEpoch(getAcceptingEpoch(), custodian);
}

function computeAllTotalStakeForCurrentEpoch()
function computeAllTotalStakeForAcceptingEpoch()
public
view
returns (uint256)
{
return computeAllTotalStakeForEpoch(getCurrentEpoch());
return computeAllTotalStakeForEpoch(getAcceptingEpoch());
}

function getValidatorCommitmentAtSuperBlockHeight(
Expand All @@ -189,7 +189,8 @@ contract MCR is Initializable, BaseSettlement, MCRStorage, IMCR {
hasRole(COMMITMENT_ADMIN, msg.sender),
"SET_LAST_ACCEPTED_COMMITMENT_AT_HEIGHT_IS_COMMITMENT_ADMIN_ONLY"
);
versionedAcceptedSuperBlocks[acceptedSuperBlocksVersion][superBlockCommitment.height] = superBlockCommitment;
versionedAcceptedSuperBlocks[acceptedSuperBlocksVersion][superBlockCommitment.height] = superBlockCommitment;
setlastAcceptedSuperBlockHeight(superBlockCommitment.height);
}

// Sets the last accepted superBlock height.
Expand All @@ -204,15 +205,11 @@ contract MCR is Initializable, BaseSettlement, MCRStorage, IMCR {
// Forces the latest attestation by setting the superBlock height
// Note: this only safe when we are running with a single validator as it does not zero out follow-on commitments.
function forceLatestCommitment(SuperBlockCommitment memory superBlockCommitment) public {
/*require(
hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
require(
hasRole(COMMITMENT_ADMIN, msg.sender),
"FORCE_LATEST_COMMITMENT_IS_COMMITMENT_ADMIN_ONLY"
);*/

// increment the acceptedSuperBlocksVersion (effectively removing all other accepted superBlocks)
acceptedSuperBlocksVersion += 1;
versionedAcceptedSuperBlocks[acceptedSuperBlocksVersion][superBlockCommitment.height] = superBlockCommitment;
lastAcceptedSuperBlockHeight = superBlockCommitment.height;
);
setAcceptedCommitmentAtBlockHeight(superBlockCommitment);
}

function getAcceptedCommitmentAtSuperBlockHeight(uint256 height) public view returns (SuperBlockCommitment memory) {
Expand Down Expand Up @@ -244,26 +241,26 @@ contract MCR is Initializable, BaseSettlement, MCRStorage, IMCR {
) revert AttesterAlreadyCommitted();

// assign the superBlock height to the current epoch if it hasn't been assigned yet
if (superBlockHeightEpochAssignments[superBlockCommitment.height] == 0) {
if (superBlockHeightAssignedEpoch[superBlockCommitment.height] == 0) {
// note: this is an intended race condition, but it is benign because of the tolerance
superBlockHeightEpochAssignments[
superBlockHeightAssignedEpoch[
superBlockCommitment.height
] = getEpochByL1BlockTime();
] = getPresentEpoch();
}

// register the attester's commitment
commitments[superBlockCommitment.height][attester] = superBlockCommitment;

// increment the commitment count by stake
uint256 allCurrentEpochStake = computeAllCurrentEpochStake(attester);
uint256 allStakeFromAcceptingEpoch = computeAllStakeFromAcceptingEpoch(attester);
commitmentStakes[superBlockCommitment.height][
superBlockCommitment.commitment
] += allCurrentEpochStake;
] += allStakeFromAcceptingEpoch;

emit SuperBlockCommitmentSubmitted(
superBlockCommitment.blockId,
superBlockCommitment.commitment,
allCurrentEpochStake
allStakeFromAcceptingEpoch
);

// keep ticking through to find accepted superBlocks
Expand All @@ -279,12 +276,12 @@ contract MCR is Initializable, BaseSettlement, MCRStorage, IMCR {
*/
function tickOnSuperBlockHeight(uint256 superBlockHeight) internal returns (bool) {
// get the epoch assigned to the superBlock height
uint256 superBlockEpoch = superBlockHeightEpochAssignments[superBlockHeight];
uint256 superBlockEpoch = superBlockHeightAssignedEpoch[superBlockHeight];

// if the current epoch is far behind, that's okay that just means there weren't superBlocks submitted
// so long as we ensure that we go through the superBlocks in order and that the superBlock to epoch assignment is non-decreasing, we're good
// so, we'll just keep rolling over the epoch until we catch up
while (getCurrentEpoch() < superBlockEpoch) {
while (getAcceptingEpoch() < superBlockEpoch) {
rollOverEpoch();
}

Expand Down Expand Up @@ -360,10 +357,10 @@ contract MCR is Initializable, BaseSettlement, MCRStorage, IMCR {
function _acceptSuperBlockCommitment(
SuperBlockCommitment memory superBlockCommitment
) internal {
uint256 currentEpoch = getCurrentEpoch();
uint256 currentAcceptingEpoch = getAcceptingEpoch();
// get the epoch for the superBlock commitment
// SuperBlock commitment is not in the current epoch, it cannot be accepted. This indicates a bug in the protocol.
if (superBlockHeightEpochAssignments[superBlockCommitment.height] != currentEpoch)
if (superBlockHeightAssignedEpoch[superBlockCommitment.height] != currentAcceptingEpoch)
revert UnacceptableSuperBlockCommitment();

// set accepted superBlock commitment
Expand All @@ -383,7 +380,7 @@ contract MCR is Initializable, BaseSettlement, MCRStorage, IMCR {
);

// if the timestamp epoch is greater than the current epoch, roll over the epoch
if (getEpochByL1BlockTime() > currentEpoch) {
if (getPresentEpoch() > currentAcceptingEpoch) {
rollOverEpoch();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ contract MCRStorage {
}

// map each superBlock height to an epoch
mapping(uint256 superBlockHeight => uint256 epoch) public superBlockHeightEpochAssignments;
mapping(uint256 superBlockHeight => uint256 epoch) public superBlockHeightAssignedEpoch;

// track each commitment from each attester for each superBlock height
mapping(uint256 superBlockHeight => mapping(address attester => SuperBlockCommitment)) public commitments;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ contract MovementStaking is
if (domainGenesisAccepted[domain]) revert GenesisAlreadyAccepted();
domainGenesisAccepted[domain] = true;
// roll over from 0 (genesis) to current epoch by L1Block time
currentEpochByDomain[domain] = getEpochByL1BlockTime(domain);
currentAcceptingEpochByDomain[domain] = getEpochByL1BlockTime(domain);

for (uint256 i = 0; i < attestersByDomain[domain].length(); i++) {
address attester = attestersByDomain[domain].at(i);
Expand All @@ -84,7 +84,7 @@ contract MovementStaking is
// roll over the genesis stake to the current epoch
_addStake(
domain,
getCurrentEpoch(domain),
getAcceptingEpoch(domain),
custodian,
attester,
attesterStake
Expand Down Expand Up @@ -151,20 +151,25 @@ contract MovementStaking is
}

// gets the current epoch up to which superBlocks have been accepted
function getCurrentEpoch(address domain) public view returns (uint256) {
return currentEpochByDomain[domain];
function getAcceptingEpoch(address domain) public view returns (uint256) {
return currentAcceptingEpochByDomain[domain];
}

// gets the next epoch
function getNextEpoch(address domain) public view returns (uint256) {
return getCurrentEpoch(domain) == 0 ? 0 : getCurrentEpoch(domain) + 1;
/// @notice Gets the next accepting epoch number
/// @dev Special handling for genesis state (epoch 0):
/// @dev If getAcceptingEpoch(domain) == 0, returns 0 to stay in genesis until ceremony completes
function getNextAcceptingEpoch(address domain) public view returns (uint256) {
return getAcceptingEpoch(domain) == 0 ? 0 : getAcceptingEpoch(domain) + 1;
}

function getNextEpochByL1BlockTime(
/// @notice Gets the next present epoch number
/// @dev Special handling for genesis state (epoch 0):
/// @dev If getAcceptingEpoch(domain) == 0, returns 0 to stay in genesis until ceremony completes
function getNextPresentEpochWithException(
address domain
) public view returns (uint256) {
return
getCurrentEpoch(domain) == 0 ? 0 : getEpochByL1BlockTime(domain) + 1;
getAcceptingEpoch(domain) == 0 ? 0 : getEpochByL1BlockTime(domain) + 1;
}

// gets the stake for a given attester at a given epoch
Expand All @@ -178,15 +183,15 @@ contract MovementStaking is
}

// gets the stake for a given attester at the current epoch
function getCurrentEpochStake(
function getAcceptingEpochStake(
address domain,
address custodian,
address attester
) public view returns (uint256) {
return
getStakeAtEpoch(
domain,
getCurrentEpoch(domain),
getAcceptingEpoch(domain),
custodian,
attester
);
Expand All @@ -203,15 +208,15 @@ contract MovementStaking is
}

// gets the unstake for a given attester at the current epoch
function getCurrentEpochUnstake(
function getAcceptingEpochUnstake(
address domain,
address custodian,
address attester
) public view returns (uint256) {
return
getUnstakeAtEpoch(
domain,
getCurrentEpoch(domain),
getAcceptingEpoch(domain),
custodian,
attester
);
Expand All @@ -227,12 +232,12 @@ contract MovementStaking is
}

// gets the total stake for the current epoch
function getTotalStakeForCurrentEpoch(
function getTotalStakeForAcceptingEpoch(
address domain,
address custodian
) public view returns (uint256) {
return
getTotalStakeForEpoch(domain, getCurrentEpoch(domain), custodian);
getTotalStakeForEpoch(domain, getAcceptingEpoch(domain), custodian);
}

// stakes for the next epoch
Expand Down Expand Up @@ -263,7 +268,7 @@ contract MovementStaking is
// set the attester to stake for the next epoch
_addStake(
domain,
getNextEpochByL1BlockTime(domain),
getNextPresentEpochWithException(domain),
address(custodian),
msg.sender,
amount
Expand All @@ -272,7 +277,7 @@ contract MovementStaking is
// Let the world know that the attester has staked
emit AttesterStaked(
domain,
getNextEpoch(domain),
getNextAcceptingEpoch(domain),
address(custodian),
msg.sender,
amount
Expand All @@ -290,15 +295,15 @@ contract MovementStaking is
// note: by tracking in the next epoch we need to make sure when we roll over an epoch we check the amount rolled over from stake by the unstake in the next epoch
_addUnstake(
domain,
getNextEpochByL1BlockTime(domain),
getNextPresentEpochWithException(domain),
custodian,
msg.sender,
amount
);

emit AttesterUnstaked(
domain,
getNextEpoch(domain),
getNextAcceptingEpoch(domain),
custodian,
msg.sender,
amount
Expand All @@ -312,7 +317,7 @@ contract MovementStaking is
address custodian,
address attester
) internal {
// the amount of stake rolled over is stake[currentEpoch] - unstake[nextEpoch]
// the amount of stake rolled over is stake[currentAcceptingEpoch] - unstake[nextEpoch]
uint256 stakeAmount = getStakeAtEpoch(
domain,
epochNumber,
Expand Down Expand Up @@ -361,13 +366,13 @@ contract MovementStaking is
}

// increment the current epoch
currentEpochByDomain[domain] = epochNumber + 1;
currentAcceptingEpochByDomain[domain] = epochNumber + 1;

emit EpochRolledOver(domain, epochNumber);
}

function rollOverEpoch() external {
_rollOverEpoch(msg.sender, getCurrentEpoch(msg.sender));
_rollOverEpoch(msg.sender, getAcceptingEpoch(msg.sender));
}

/**
Expand Down Expand Up @@ -462,7 +467,7 @@ contract MovementStaking is
uint256 refundAmount = Math.min(
getStakeAtEpoch(
msg.sender,
getCurrentEpoch(attesters[i]),
getAcceptingEpoch(attesters[i]),
custodians[i],
attesters[i]
),
Expand All @@ -478,15 +483,15 @@ contract MovementStaking is
// slash both stake and unstake so that the weight of the attester is reduced and they can't withdraw the unstake at the next epoch
_slashStake(
msg.sender,
getCurrentEpoch(msg.sender),
getAcceptingEpoch(msg.sender),
custodians[i],
attesters[i],
amounts[i]
);

_slashUnstake(
msg.sender,
getCurrentEpoch(msg.sender),
getAcceptingEpoch(msg.sender),
custodians[i],
attesters[i]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ contract MovementStakingStorage {
IERC20 public token;

mapping(address domain => uint256 epochDuration) public epochDurationByDomain;
mapping(address domain => uint256 currentEpoch) public currentEpochByDomain;
mapping(address domain => uint256 currentAcceptingEpoch) public currentAcceptingEpochByDomain;
mapping(address domain => EnumerableSet.AddressSet attester) internal attestersByDomain;
mapping(address domain => EnumerableSet.AddressSet custodian) internal custodiansByDomain;

Expand Down
Loading

0 comments on commit c0134ae

Please sign in to comment.