Skip to content

feat: v3 codec #4

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

Merged
merged 13 commits into from
Jul 31, 2024
Merged
22 changes: 21 additions & 1 deletion src/L1/rollup/IL1MessageQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ interface IL1MessageQueue {
/// @param skippedBitmap A bitmap indicates whether a message is skipped.
event DequeueTransaction(uint256 startIndex, uint256 count, uint256 skippedBitmap);

event ResetDequeuedTransaction(uint256 startIndex, uint256 count);

event FinalizedDequeuedTransaction(uint256 finalizedIndex);

/// @notice Emitted when a message is dropped from L1.
/// @param index The index of message dropped.
event DropTransaction(uint256 index);
Expand Down Expand Up @@ -57,6 +61,10 @@ interface IL1MessageQueue {
/// @notice The start index of all pending inclusion messages.
function pendingQueueIndex() external view returns (uint256);

/// @notice The last index of all finalized messages plus one.
/// @dev All messages from `finalizedQueueIndexPlusOne` to `pendingQueueIndex-1` are committed but not finalized.
function finalizedQueueIndexPlusOne() external view returns (uint256);

/// @notice Return the index of next appended message.
/// @dev Also the total number of appended messages.
function nextCrossDomainMessageIndex() external view returns (uint256);
Expand Down Expand Up @@ -126,7 +134,7 @@ interface IL1MessageQueue {
bytes calldata data
) external;

/// @notice Pop finalized messages from queue.
/// @notice Pop messages from queue.
///
/// @dev We can pop at most 256 messages each time. And if the message is not skipped,
/// the corresponding entry will be cleared.
Expand All @@ -140,6 +148,18 @@ interface IL1MessageQueue {
uint256 skippedBitmap
) external;

/// @notice Reset status of popped messages.
///
/// @dev We can only reset unfinalized popped messages.
///
/// @param startIndex The start index to reset.
/// @param count The number of messages to reset.
function resetPoppedCrossDomainMessage(uint256 startIndex, uint256 count) external;

/// @notice Finalize status of popped messages.
/// @param newFinalizedQueueIndexPlusOne The index of message to finalize plus one.
function finalizePoppedCrossDomainMessage(uint256 newFinalizedQueueIndexPlusOne) external;

/// @notice Drop a skipped message from the queue.
function dropCrossDomainMessage(uint256 index) external;
}
40 changes: 36 additions & 4 deletions src/L1/rollup/IScrollChain.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,31 @@ interface IScrollChain {
bytes calldata skippedL1MessageBitmap
) external;

/// @notice Revert a pending batch.
/// @notice Commit a batch of transactions on layer 1 with blob data proof.
///
/// @dev Memory layout of `blobDataProof`:
/// | z | y | kzg_commitment | kzg_proof |
/// |---------|---------|----------------|-----------|
/// | bytes32 | bytes32 | bytes48 | bytes48 |
///
/// @param version The version of current batch.
/// @param parentBatchHeader The header of parent batch, see the comments of `BatchHeaderV0Codec`.
/// @param chunks The list of encoded chunks, see the comments of `ChunkCodec`.
/// @param skippedL1MessageBitmap The bitmap indicates whether each L1 message is skipped or not.
/// @param blobDataProof The proof for blob data.
function commitBatchWithBlobProof(
uint8 version,
bytes calldata parentBatchHeader,
bytes[] memory chunks,
bytes calldata skippedL1MessageBitmap,
bytes calldata blobDataProof
) external;

/// @notice Revert pending batches.
/// @dev one can only revert unfinalized batches.
/// @param batchHeader The header of current batch, see the encoding in comments of `commitBatch`.
/// @param count The number of subsequent batches to revert, including current batch.
function revertBatch(bytes calldata batchHeader, uint256 count) external;
/// @param firstBatchHeader The header of first batch to revert, see the encoding in comments of `commitBatch`.
/// @param lastBatchHeader The header of last batch to revert, see the encoding in comments of `commitBatch`.
function revertBatch(bytes calldata firstBatchHeader, bytes calldata lastBatchHeader) external;

/// @notice Finalize a committed batch on layer 1.
/// @param batchHeader The header of current batch, see the encoding in comments of `commitBatch.
Expand Down Expand Up @@ -122,4 +142,16 @@ interface IScrollChain {
bytes calldata blobDataProof,
bytes calldata aggrProof
) external;

/// @notice Finalize a list of committed batches (i.e. bundle) on layer 1.
/// @param batchHeader The header of last batch in current bundle, see the encoding in comments of `commitBatch.
/// @param postStateRoot The state root after current bundle.
/// @param withdrawRoot The withdraw trie root after current batch.
/// @param aggrProof The aggregation proof for current bundle.
function finalizeBundleWithProof(
bytes calldata batchHeader,
bytes32 postStateRoot,
bytes32 withdrawRoot,
bytes calldata aggrProof
) external;
}
57 changes: 52 additions & 5 deletions src/L1/rollup/L1MessageQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
/// @dev The bitmap for skipped messages, where `skippedMessageBitmap[i]` keeps the bits from `[i*256, (i+1)*256)`.
mapping(uint256 => uint256) private skippedMessageBitmap;

/// @inheritdoc IL1MessageQueue
uint256 public finalizedQueueIndexPlusOne;

/// @dev The storage slots for future usage.
uint256[41] private __gap;
uint256[40] private __gap;

/**********************
* Function Modifiers *
Expand All @@ -76,6 +79,11 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
_;
}

modifier onlyScrollChain() {
require(_msgSender() == scrollChain, "Only callable by the ScrollChain");
_;
}

/***************
* Constructor *
***************/
Expand Down Expand Up @@ -343,9 +351,7 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
uint256 _startIndex,
uint256 _count,
uint256 _skippedBitmap
) external {
require(_msgSender() == scrollChain, "Only callable by the ScrollChain");

) external override onlyScrollChain {
require(_count <= 256, "pop too many messages");
require(pendingQueueIndex == _startIndex, "start index mismatch");

Expand All @@ -367,9 +373,50 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
emit DequeueTransaction(_startIndex, _count, _skippedBitmap);
}

/// @inheritdoc IL1MessageQueue
/// @dev Caller should make sure `_count > 0` to reduce unnecessary contract call.
function resetPoppedCrossDomainMessage(uint256 _startIndex, uint256 _count) external override onlyScrollChain {
if (_count == 0) return;
require(_startIndex >= finalizedQueueIndexPlusOne, "reset finalized messages");
require(_startIndex + _count <= pendingQueueIndex, "reset non-popped messages");

unchecked {
uint256 bucket = _startIndex >> 8;
uint256 offset = _startIndex & 0xff;
skippedMessageBitmap[bucket] &= (1 << offset) - 1;
uint256 numResetMessages = 256 - offset;
while (numResetMessages < _count) {
bucket += 1;
uint256 bitmap = skippedMessageBitmap[bucket];
if (bitmap > 0) skippedMessageBitmap[bucket] = 0;
numResetMessages += 256;
}
}

pendingQueueIndex = _startIndex;
emit ResetDequeuedTransaction(_startIndex, _count);
}

/// @inheritdoc IL1MessageQueue
function finalizePoppedCrossDomainMessage(uint256 _newFinalizedQueueIndexPlusOne)
external
override
onlyScrollChain
{
uint256 cachedFinalizedQueueIndexPlusOne = finalizedQueueIndexPlusOne;
if (_newFinalizedQueueIndexPlusOne == cachedFinalizedQueueIndexPlusOne) return;
require(_newFinalizedQueueIndexPlusOne > cachedFinalizedQueueIndexPlusOne, "finalized index too small");
require(_newFinalizedQueueIndexPlusOne <= pendingQueueIndex, "finalized index too large");

finalizedQueueIndexPlusOne = _newFinalizedQueueIndexPlusOne;
unchecked {
emit FinalizedDequeuedTransaction(_newFinalizedQueueIndexPlusOne - 1);
}
}

/// @inheritdoc IL1MessageQueue
function dropCrossDomainMessage(uint256 _index) external onlyMessenger {
require(_index < pendingQueueIndex, "cannot drop pending message");
require(_index < finalizedQueueIndexPlusOne, "cannot drop pending message");

require(_isMessageSkipped(_index), "drop non-skipped message");
require(!droppedMessageBitmap.get(_index), "message already dropped");
Expand Down
4 changes: 4 additions & 0 deletions src/L1/rollup/L1MessageQueueWithGasPriceOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ contract L1MessageQueueWithGasPriceOracle is L1MessageQueue, IL1MessageQueueWith
whitelistChecker = IL2GasPriceOracle(gasOracle).whitelist();
}

function initializeV3() external reinitializer(3) {
finalizedQueueIndexPlusOne = pendingQueueIndex;
}

/*************************
* Public View Functions *
*************************/
Expand Down
18 changes: 15 additions & 3 deletions src/L1/rollup/MultipleVersionRollupVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pragma solidity =0.8.24;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

import {IRollupVerifier} from "../../libraries/verifier/IRollupVerifier.sol";
import {IZkEvmVerifier} from "../../libraries/verifier/IZkEvmVerifier.sol";
import {IZkEvmVerifierV1, IZkEvmVerifierV2} from "../../libraries/verifier/IZkEvmVerifier.sol";

/// @title MultipleVersionRollupVerifier
/// @notice Verifies aggregate zk proofs using the appropriate verifier.
Expand Down Expand Up @@ -111,7 +111,7 @@ contract MultipleVersionRollupVerifier is IRollupVerifier, Ownable {
) external view override {
address _verifier = getVerifier(0, _batchIndex);

IZkEvmVerifier(_verifier).verify(_aggrProof, _publicInputHash);
IZkEvmVerifierV1(_verifier).verify(_aggrProof, _publicInputHash);
}

/// @inheritdoc IRollupVerifier
Expand All @@ -123,7 +123,19 @@ contract MultipleVersionRollupVerifier is IRollupVerifier, Ownable {
) external view override {
address _verifier = getVerifier(_version, _batchIndex);

IZkEvmVerifier(_verifier).verify(_aggrProof, _publicInputHash);
IZkEvmVerifierV1(_verifier).verify(_aggrProof, _publicInputHash);
}

/// @inheritdoc IRollupVerifier
function verifyAggregateProof(
uint256 _version,
uint256 _batchIndex,
bytes calldata _aggrProof,
bytes calldata _publicInput
) external view override {
address _verifier = getVerifier(_version, _batchIndex);

IZkEvmVerifierV2(_verifier).verify(_aggrProof, _publicInput);
}

/************************
Expand Down
Loading