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

feat: enforced messages and enforces messages #61

Closed
wants to merge 3 commits into from
Closed
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
12 changes: 6 additions & 6 deletions scripts/foundry/InitializeL1ScrollOwner.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ contract InitializeL1ScrollOwner is Script {
bytes4[] memory _selectors;

// no delay, scroll multisig and emergency multisig
_selectors = new bytes4[](4);
_selectors[0] = ScrollChain.revertBatch.selector;
_selectors[1] = ScrollChain.removeSequencer.selector;
_selectors[2] = ScrollChain.removeProver.selector;
_selectors[3] = ScrollChain.setPause.selector;
_selectors = new bytes4[](3);
// _selectors[0] = ScrollChain.revertBatch.selector;
_selectors[0] = ScrollChain.removeSequencer.selector;
_selectors[1] = ScrollChain.removeProver.selector;
_selectors[2] = ScrollChain.setPause.selector;
owner.updateAccess(L1_SCROLL_CHAIN_PROXY_ADDR, _selectors, SCROLL_MULTISIG_NO_DELAY_ROLE, true);
owner.updateAccess(L1_SCROLL_CHAIN_PROXY_ADDR, _selectors, EMERGENCY_MULTISIG_NO_DELAY_ROLE, true);

Expand All @@ -154,7 +154,7 @@ contract InitializeL1ScrollOwner is Script {

// delay 7 day, scroll multisig
_selectors = new bytes4[](1);
_selectors[0] = ScrollChain.updateMaxNumTxInChunk.selector;
// _selectors[0] = ScrollChain.updateMaxNumTxInChunk.selector;
owner.updateAccess(L1_SCROLL_CHAIN_PROXY_ADDR, _selectors, TIMELOCK_7DAY_DELAY_ROLE, true);
}

Expand Down
28 changes: 11 additions & 17 deletions src/L1/rollup/IL1MessageQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ interface IL1MessageQueue {
* Public View Functions *
*************************/

/// @notice The enqueue timestamp of first un-inclusion message.
function getFirstPendingMessageTimestamp() external view returns (uint256);

/// @notice The enqueue timestamp of first unfinalized message.
function getFirstUnfinalizedMessageTimestamp() external view returns (uint256);

/// @notice The start index of all pending inclusion messages.
function pendingQueueIndex() external view returns (uint256);

Expand All @@ -77,6 +83,10 @@ interface IL1MessageQueue {
/// @param queueIndex The index to query.
function getCrossDomainMessage(uint256 queueIndex) external view returns (bytes32);

/// @notice Return the message enqueue timestamp of in `queueIndex`.
/// @param queueIndex The index to query.
function getMessageTimestamp(uint256 queueIndex) external view returns (uint256);

/// @notice Return the amount of ETH should pay for cross domain message.
/// @param gasLimit Gas limit required to complete the message relay on L2.
function estimateCrossDomainMessageFee(uint256 gasLimit) external view returns (uint256);
Expand Down Expand Up @@ -140,24 +150,8 @@ interface IL1MessageQueue {

/// @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.
///
/// @param startIndex The start index to pop.
/// @param count The number of messages to pop.
/// @param skippedBitmap A bitmap indicates whether a message is skipped.
function popCrossDomainMessage(
uint256 startIndex,
uint256 count,
uint256 skippedBitmap
) external;

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

/// @notice Finalize status of popped messages.
/// @param newFinalizedQueueIndexPlusOne The index of message to finalize plus one.
Expand Down
23 changes: 4 additions & 19 deletions src/L1/rollup/IL1MessageQueueWithGasPriceOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,15 @@ interface IL1MessageQueueWithGasPriceOracle is IL1MessageQueue {
* Events *
**********/

/// @notice Emitted when owner updates whitelist checker contract.
/// @param _oldWhitelistChecker The address of old whitelist checker contract.
/// @param _newWhitelistChecker The address of new whitelist checker contract.
event UpdateWhitelistChecker(address indexed _oldWhitelistChecker, address indexed _newWhitelistChecker);

/// @notice Emitted when current l2 base fee is updated.
/// @param oldL2BaseFee The original l2 base fee before update.
/// @param newL2BaseFee The current l2 base fee updated.
event UpdateL2BaseFee(uint256 oldL2BaseFee, uint256 newL2BaseFee);

/**********
* Errors *
**********/

/// @dev Thrown when the caller is not whitelisted.
error ErrorNotWhitelistedSender();
/// @notice Emitted when current l2 base fee parameters are updated.
/// @param overhead The value of overhead.
/// @param scalar The value of scalar to `block.basefee`.
event UpdateL2BaseFeeParameters(uint256 overhead, uint256 scalar);

/*************************
* Public View Functions *
*************************/

/// @notice Return the latest known l2 base fee.
function l2BaseFee() external view returns (uint256);

/// @notice Return the address of whitelist checker contract.
function whitelistChecker() external view returns (address);
}
79 changes: 43 additions & 36 deletions src/L1/rollup/IScrollChain.sol
Original file line number Diff line number Diff line change
Expand Up @@ -138,19 +138,6 @@ interface IScrollChain {
* Public Mutating Functions *
*****************************/

/// @notice Commit a batch of transactions on layer 1.
///
/// @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.
function commitBatch(
uint8 version,
bytes calldata parentBatchHeader,
bytes[] memory chunks,
bytes calldata skippedL1MessageBitmap
) external;

/// @notice Commit a batch of transactions on layer 1 with blob data proof.
///
/// @dev Memory layout of `blobDataProof`:
Expand All @@ -171,40 +158,28 @@ interface IScrollChain {
bytes calldata blobDataProof
) external;

/// @notice Revert pending batches.
/// @dev one can only revert unfinalized batches.
/// @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;

/* This function will never be used since we already upgrade to Darwin. We comment out the codes for reference.
/// @notice Finalize a committed batch (with blob) on layer 1.
/// @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 batchHeader The header of current batch, see the encoding in comments of `commitBatch.
/// @param prevStateRoot The state root of parent batch.
/// @param postStateRoot The state root of current batch.
/// @param withdrawRoot The withdraw trie root of current batch.
/// @param version The version of current batch.
/// @param parentBatchHeader The header of parent batch, see the comments of `BatchHeaderV0Codec`.
Copy link
Member

@colinlyguo colinlyguo Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// @param parentBatchHeader The header of parent batch, see the comments of `BatchHeaderV0Codec`.
/// @param parentBatchHeader The header of parent batch, see the comments of `BatchHeaderV0Codec`, `BatchHeaderV1Codec` and `BatchHeaderV3Codec.sol`.

/// @param chunks The list of encoded chunks, see the comments of `ChunkCodec`.
/// @param blobDataProof The proof for blob data.
/// @param aggrProof The aggregation proof for current batch.
function finalizeBatchWithProof4844(
bytes calldata batchHeader,
bytes32 prevStateRoot,
bytes32 postStateRoot,
bytes32 withdrawRoot,
bytes calldata blobDataProof,
bytes calldata aggrProof
function commitBatchWithBlobProof(
uint8 version,
bytes calldata parentBatchHeader,
bytes[] memory chunks,
bytes calldata blobDataProof
) 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 withdrawRoot The withdraw trie root after current bundle.
/// @param aggrProof The aggregation proof for current bundle.
function finalizeBundleWithProof(
bytes calldata batchHeader,
Expand All @@ -216,12 +191,44 @@ interface IScrollChain {
/// @notice Finalize a list of committed batches (i.e. bundle) on layer 1 with TEE proof.
/// @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 withdrawRoot The withdraw trie root after current bundle.
/// @param teeProof The tee proof for current bundle.
function finalizeBundleWithTeeProof(
bytes calldata batchHeader,
bytes32 postStateRoot,
bytes32 withdrawRoot,
bytes calldata teeProof
) external;

/// @param The struct for batch committing.
/// @param version The version of current batch.
/// @param parentBatchHeader The header of parent batch, see the comments of `BatchHeaderV0Codec`.
Copy link
Member

@colinlyguo colinlyguo Nov 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// @param parentBatchHeader The header of parent batch, see the comments of `BatchHeaderV0Codec`.
/// @param parentBatchHeader The header of parent batch, see the comments of `BatchHeaderV0Codec`, `BatchHeaderV1Codec` and `BatchHeaderV3Codec.sol`.

/// @param chunks The list of encoded chunks, see the comments of `ChunkCodec`.
/// @param blobDataProof The proof for blob data.
struct CommitStruct {
uint8 version;
bytes parentBatchHeader;
bytes[] chunks;
bytes blobDataProof;
}

/// @param The struct for batch finalization.
/// @param batchHeader The header of current batch, see the encoding in comments of `commitBatch`.
/// @param postStateRoot The state root after current batch.
/// @param withdrawRoot The withdraw trie root after current batch.
/// @param zkProof The zk proof for current batch (single-batch bundle).
/// @param teeProof The tee proof for current batch (single-batch bundle).
struct FinalizeStruct {
bytes batchHeader;
bytes32 postStateRoot;
bytes32 withdrawRoot;
bytes zkProof;
bytes teeProof;
}

/// @notice Commit a batch of transactions on layer 1 with blob data proof and finalize it.
/// @param commitStruct The data needed for commit.
/// @param finalizeStruct The data needed for finalize.
function commitAndFinalizeBatch(CommitStruct calldata commitStruct, FinalizeStruct calldata finalizeStruct)
external;
}
83 changes: 35 additions & 48 deletions src/L1/rollup/L1MessageQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import {AddressAliasHelper} from "../../libraries/common/AddressAliasHelper.sol"
contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
using BitMapsUpgradeable for BitMapsUpgradeable.BitMap;

/// @notice Emitted when the number of messages popped exceed queue length.
error ErrorPopMoreThanQueued();

/*************
* Constants *
*************/
Expand Down Expand Up @@ -67,6 +70,10 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
/// @inheritdoc IL1MessageQueue
uint256 public nextUnfinalizedQueueIndex;

/// @dev Mapping from message queue index to enqueue timestamp.
mapping(uint256 => uint256) private enqueueTimestamp;

// todo change gap slots
colinlyguo marked this conversation as resolved.
Show resolved Hide resolved
/// @dev The storage slots for future usage.
uint256[40] private __gap;

Expand Down Expand Up @@ -138,6 +145,22 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
* Public View Functions *
*************************/

/// @inheritdoc IL1MessageQueue
function getFirstPendingMessageTimestamp() external view returns (uint256) {
uint256 length = messageQueue.length;
uint256 index = pendingQueueIndex;
if (index == length) return block.timestamp;
else return enqueueTimestamp[index];
}

/// @inheritdoc IL1MessageQueue
function getFirstUnfinalizedMessageTimestamp() external view returns (uint256) {
uint256 length = messageQueue.length;
uint256 index = nextUnfinalizedQueueIndex;
if (index == length) return block.timestamp;
else return enqueueTimestamp[index];
}

/// @inheritdoc IL1MessageQueue
function nextCrossDomainMessageIndex() external view returns (uint256) {
return messageQueue.length;
Expand All @@ -148,6 +171,11 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
return messageQueue[_queueIndex];
}

/// @inheritdoc IL1MessageQueue
function getMessageTimestamp(uint256 _queueIndex) external view returns (uint256) {
return enqueueTimestamp[_queueIndex];
}

/// @inheritdoc IL1MessageQueue
function estimateCrossDomainMessageFee(uint256 _gasLimit) external view virtual override returns (uint256) {
address _oracle = gasOracle;
Expand Down Expand Up @@ -347,57 +375,15 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
}

/// @inheritdoc IL1MessageQueue
function popCrossDomainMessage(
uint256 _startIndex,
uint256 _count,
uint256 _skippedBitmap
) external override onlyScrollChain {
require(_count <= 256, "pop too many messages");
require(pendingQueueIndex == _startIndex, "start index mismatch");

function popCrossDomainMessage(uint256 count) external override onlyScrollChain {
unchecked {
// clear extra bits in `_skippedBitmap`, and if _count = 256, it's designed to overflow.
uint256 mask = (1 << _count) - 1;
_skippedBitmap &= mask;

uint256 bucket = _startIndex >> 8;
uint256 offset = _startIndex & 0xff;
skippedMessageBitmap[bucket] |= _skippedBitmap << offset;
if (offset + _count > 256) {
skippedMessageBitmap[bucket + 1] = _skippedBitmap >> (256 - offset);
}
uint256 startIndex = pendingQueueIndex;
uint256 cachedPendingQueueIndex = startIndex + count;
uint256 length = messageQueue.length;
if (cachedPendingQueueIndex > length) revert ErrorPopMoreThanQueued();

pendingQueueIndex = _startIndex + _count;
pendingQueueIndex = cachedPendingQueueIndex;
}

emit DequeueTransaction(_startIndex, _count, _skippedBitmap);
}

/// @inheritdoc IL1MessageQueue
/// @dev Caller should make sure `_startIndex < pendingQueueIndex` to reduce unnecessary contract call.
function resetPoppedCrossDomainMessage(uint256 _startIndex) external override onlyScrollChain {
uint256 cachedPendingQueueIndex = pendingQueueIndex;
if (_startIndex == cachedPendingQueueIndex) return;

require(_startIndex >= nextUnfinalizedQueueIndex, "reset finalized messages");
require(_startIndex < cachedPendingQueueIndex, "reset pending messages");

unchecked {
uint256 count = cachedPendingQueueIndex - _startIndex;
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);
}

/// @inheritdoc IL1MessageQueue
Expand Down Expand Up @@ -472,6 +458,7 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
// compute transaction hash
uint256 _queueIndex = messageQueue.length;
bytes32 _hash = computeTransactionHash(_sender, _queueIndex, _value, _target, _gasLimit, _data);
enqueueTimestamp[_queueIndex] = block.timestamp;
messageQueue.push(_hash);

// emit event
Expand Down
Loading