Skip to content

Commit

Permalink
feat(seqset): add finalizedBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
ericlee42 committed Mar 5, 2024
1 parent 0a47999 commit acd9446
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 25 deletions.
56 changes: 42 additions & 14 deletions contracts/SequencerSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ contract MetisSequencerSet is OwnableUpgradeable {
// initial epoch
uint256 epochId = 0;

// We do not check if the length between the start and end block matches the epoch length
// the epoch length can only be used for next epoch
require(
_firstStartBlock > block.number &&
_firstEndBlock > _firstStartBlock,
"Invalid block range"
);

// initial epoch item
epochs[epochId] = Epoch({
number: epochId,
Expand Down Expand Up @@ -99,9 +107,9 @@ contract MetisSequencerSet is OwnableUpgradeable {
// get epoch number by block
// It returns Max(uint256) if the height doesn't exist in any epochs
function getEpochByBlock(uint256 _number) public view returns (uint256) {
uint256 lastIndex = currentEpochId;
for (uint256 i = lastIndex; i >= 0; i--) {
Epoch memory epoch = epochs[i];
uint256 lastIndex = currentEpochId + 1;
for (uint256 i = lastIndex; i > 0; i--) {
Epoch memory epoch = epochs[i - 1];
if (epoch.startBlock <= _number && _number <= epoch.endBlock) {
return epoch.number;
}
Expand All @@ -110,11 +118,6 @@ contract MetisSequencerSet is OwnableUpgradeable {
if (i == lastIndex && _number > epoch.endBlock) {
return type(uint256).max;
}

// not in the first epoch
if (i == 0 && _number < epoch.startBlock) {
return type(uint256).max;
}
}

// return default if not found any thing
Expand All @@ -132,12 +135,32 @@ contract MetisSequencerSet is OwnableUpgradeable {

// finalizedEpoch returns the finalized epoch
// the epoch won't be recommitted by `recommitEpoch`
// It will returns zero-value epoch if the epoch doesn't exist
function finalizedEpoch() public view returns (Epoch memory epoch) {
uint256 curEpochId = currentEpochId;
if (curEpochId > 2) {
epoch = epochs[curEpochId - 2];
// if there is no such epoch, the second return value will be false
function finalizedEpoch()
public
view
returns (Epoch memory epoch, bool exist)
{
uint256 lastIndex = currentEpochId + 1;
for (uint256 i = lastIndex; i > 0; i--) {
epoch = epochs[i - 1];
if (block.number > epoch.endBlock) {
return (epoch, true);
}
}
// It's epoch 0 but not exist
return (epoch, false);
}

// finalizedBlock returns the finalized block number
function finalizedBlock() public view returns (uint256) {
(Epoch memory epoch, bool exist) = finalizedEpoch();
if (exist) {
return epoch.endBlock;
}
// the last block of epoch 0
// since the startBlock must not be 0, so it's safe to minus 1
return epoch.startBlock - 1;
}

// get metis sequencer by block number
Expand Down Expand Up @@ -210,7 +233,7 @@ contract MetisSequencerSet is OwnableUpgradeable {
require(_startBlock == block.number, "Invalid start block");
require(_newSigner != address(0), "Invalid signer");

// Note: We don't check if the startBlock and endBlock match with epochLength
// Note: We do not check if the length between the start and end block matches the epoch length

uint256 curEpochId = currentEpochId;
// recommitEpoch occurs in the latest epoch
Expand All @@ -236,6 +259,11 @@ contract MetisSequencerSet is OwnableUpgradeable {
// recommitEpoch occurs in last but one epoch
else if (_oldEpochId + 1 == curEpochId) {
Epoch storage epoch = epochs[_oldEpochId];
// ensure that finilized epoch can't be changed
require(
epoch.endBlock > block.number,
"The last epoch is finished"
);
epoch.endBlock = block.number - 1;

// update latest epoch
Expand Down
39 changes: 28 additions & 11 deletions ts-src/test/SequencerSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
mineUpTo,
} from "@nomicfoundation/hardhat-toolbox/network-helpers";

const initStartBlock = 1n;
const initStartBlock = 400n;
const initEndBlock = 599n;
const initEpochLen = 200n;

Expand Down Expand Up @@ -102,38 +102,51 @@ describe("MetisSequencerSet", async () => {

await seqset.connect(mpc).commitEpoch(nextEpochNumber, 600, 799, seq1);

// epoch 0 but not exists
{
const { number, startBlock, endBlock, signer } =
const [{ number, startBlock, endBlock, signer }, valid] =
await seqset.finalizedEpoch();
expect(number).eq(0);
expect(startBlock).eq(0);
expect(endBlock).eq(0);
expect(signer).eq(ethers.ZeroAddress);
expect(startBlock).eq(initStartBlock);
expect(endBlock).eq(initEndBlock);
expect(signer).eq(seq0.address);
expect(valid).eq(false);

expect(await seqset.finalizedBlock(), "finalizedBlock-0").eq(
initStartBlock - 1n,
);
}

await mineUpTo(700);
nextEpochNumber++;
await seqset.connect(mpc).commitEpoch(nextEpochNumber, 800, 999, seq0);

// epoch 0 and exists
{
const { number, startBlock, endBlock, signer } =
const [{ number, startBlock, endBlock, signer }, valid] =
await seqset.finalizedEpoch();
expect(number).eq(0);
expect(startBlock).eq(0);
expect(endBlock).eq(0);
expect(signer).eq(ethers.ZeroAddress);
expect(startBlock).eq(initStartBlock);
expect(endBlock).eq(initEndBlock);
expect(signer).eq(seq0.address);
expect(valid).eq(true);
expect(await seqset.finalizedBlock(), "finalizedBlock-1").eq(
initEndBlock,
);
}

await mineUpTo(900);
nextEpochNumber++;
await seqset.connect(mpc).commitEpoch(nextEpochNumber, 1000, 1199, seq1);
{
const { number, startBlock, endBlock, signer } =
const [{ number, startBlock, endBlock, signer }, valid] =
await seqset.finalizedEpoch();
expect(number).eq(nextEpochNumber - 2n);
expect(startBlock).eq(600);
expect(endBlock).eq(799);
expect(signer).eq(seq1.address);
expect(valid).eq(true);
expect(await seqset.finalizedBlock(), "finalizedBlock-2").eq(799);
}
});

Expand Down Expand Up @@ -326,7 +339,11 @@ describe("MetisSequencerSet", async () => {
await mineUpTo(1200);
// block 1201, add epoch 5, 1300-1499
await seqset.connect(mpc).commitEpoch(5, 1300, 1499, seq1);
await mineUpTo(1320);
await mineUpTo(1319);
// block 1320 the epoch 4 has been finished
await expect(
seqset.connect(mpc).recommitEpoch(4, 5, 1321, 1700, seq1),
).to.be.revertedWith("The last epoch is finished");
// block 1321, add epoch 5, 1500-1699
await seqset.connect(mpc).commitEpoch(6, 1500, 1699, seq1);

Expand Down

0 comments on commit acd9446

Please sign in to comment.