Skip to content
Open
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

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bindings/bin/rollup_deployed.hex

Large diffs are not rendered by default.

97 changes: 95 additions & 2 deletions bindings/bindings/l1messagequeuewithgaspriceoracle.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bindings/bindings/l1messagequeuewithgaspriceoracle_more.go

Large diffs are not rendered by default.

233 changes: 231 additions & 2 deletions bindings/bindings/rollup.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bindings/bindings/rollup_more.go

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions contracts/contracts/l1/rollup/IL1MessageQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ interface IL1MessageQueue {
/// @notice The start index of all pending inclusion messages.
function pendingQueueIndex() external view returns (uint256);

/// @notice Return the enqueue timestamp of the first unfinalized message.
/// @dev Used for checking if L1 messages are being processed within acceptable time.
/// @return timestamp The block.timestamp when the first unfinalized message was enqueued.
function getFirstUnfinalizedMessageEnqueueTime() external view returns (uint256 timestamp);

/// @notice Return the index of next appended message.
/// @dev Also the total number of appended messages.
function nextCrossDomainMessageIndex() external view returns (uint256);
Expand Down
19 changes: 19 additions & 0 deletions contracts/contracts/l1/rollup/IRollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ interface IRollup {
/// @param newPercent The new proofRewardPercent.
event UpdateProofRewardPercent(uint256 oldPercent, uint256 newPercent);

/// @notice Emitted when the rollup delay period is updated.
/// @param oldPeriod The old rollupDelayPeriod.
/// @param newPeriod The new rollupDelayPeriod.
event UpdateRollupDelayPeriod(uint256 oldPeriod, uint256 newPeriod);

/// @notice Emit when prove remaining claimed.
/// @param receiver receiver address.
/// @param amount claimed amount.
Expand Down Expand Up @@ -182,6 +187,20 @@ interface IRollup {
BatchSignatureInput calldata batchSignatureInput
) external payable;

/// @notice Commit a batch with ZKP proof for permissionless submission.
/// @dev This function allows anyone to submit batches when the sequencer is offline or censoring.
///
/// @param batchDataInput The BatchDataInput struct
/// @param batchSignatureInput The BatchSignatureInput struct
/// @param batchHeader The batch header for ZKP verification
/// @param batchProof The ZKP proof data
function commitBatchWithProof(
BatchDataInput calldata batchDataInput,
BatchSignatureInput calldata batchSignatureInput,
bytes calldata batchHeader,
bytes calldata batchProof
) external;

/// @notice Revert a pending batch.
/// @dev one can only revert unfinalized batches.
/// @param batchHeader The header of current batch, see the encoding in comments of `commitBatch`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ contract L1MessageQueueWithGasPriceOracle is OwnableUpgradeable, IL1MessageQueue
/// @inheritdoc IL1MessageQueueWithGasPriceOracle
address public whitelistChecker;

mapping(uint256 => uint256) public messageEnqueueTime;

/**********************
* Function Modifiers *
**********************/
Expand Down Expand Up @@ -149,11 +151,7 @@ contract L1MessageQueueWithGasPriceOracle is OwnableUpgradeable, IL1MessageQueue
len := 1
leave
}
for {

} gt(v, 0) {

} {
for {} gt(v, 0) {} {
len := add(len, 1)
v := shr(8, v)
}
Expand Down Expand Up @@ -260,6 +258,19 @@ contract L1MessageQueueWithGasPriceOracle is OwnableUpgradeable, IL1MessageQueue
return hash;
}

function getFirstUnfinalizedMessageEnqueueTime() external view returns (uint256 timestamp) {
if (pendingQueueIndex < messageQueue.length && messageEnqueueTime[pendingQueueIndex] != 0) {
// has pending messages and return enqueue time
return messageEnqueueTime[pendingQueueIndex];
}
// no pending messages, return current timestamp
return block.timestamp;
}

function getMessageEnqueueTimestamp(uint256 index) external view returns (uint256 timestamp) {
return messageEnqueueTime[index];
}

/*****************************
* Public Mutating Functions *
*****************************/
Expand Down Expand Up @@ -363,6 +374,7 @@ contract L1MessageQueueWithGasPriceOracle is OwnableUpgradeable, IL1MessageQueue
uint256 _queueIndex = messageQueue.length;
bytes32 _hash = computeTransactionHash(_sender, _queueIndex, _value, _target, _gasLimit, _data);
messageQueue.push(_hash);
messageEnqueueTime[_queueIndex] = block.timestamp;

// emit event
emit QueueTransaction(_sender, _target, _value, uint64(_queueIndex), _gasLimit, _data);
Expand Down
83 changes: 80 additions & 3 deletions contracts/contracts/l1/rollup/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable {
/// @notice committedStateRoots
mapping(uint256 batchIndex => bytes32 stateRoot) public committedStateRoots;

/// @notice The delay period for permissionless batch submission.
/// @dev After this period, anyone can submit batches if sequencers are offline or censoring.
uint256 public rollupDelayPeriod;

/**********************
* Function Modifiers *
**********************/
Expand Down Expand Up @@ -183,6 +187,14 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable {
}
}

/// @notice Initializer for upgrade to version 3.
/// @param _rollupDelayPeriod The delay period for permissionless batch submission.
function initialize3(uint256 _rollupDelayPeriod) external reinitializer(3) {
require(_rollupDelayPeriod != 0, "invalid rollup delay period");
rollupDelayPeriod = _rollupDelayPeriod;
emit UpdateRollupDelayPeriod(0, _rollupDelayPeriod);
}

/************************
* Restricted Functions *
************************/
Expand Down Expand Up @@ -220,6 +232,19 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable {
BatchDataInput calldata batchDataInput,
BatchSignatureInput calldata batchSignatureInput
) external payable override onlyActiveStaker nonReqRevert whenNotPaused {
// check l1msg delay - sequencer must process L1 messages when delayed
if (
IL1MessageQueue(messageQueue).getFirstUnfinalizedMessageEnqueueTime() + rollupDelayPeriod < block.timestamp
) {
require(batchDataInput.numL1Messages > 0, "l1msg delay");
}
Comment on lines +235 to +240
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not check rollupDelay?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because commitBatch invalidates rollupDelay, which is exactly what we expect.

_commitBatchWithBatchData(batchDataInput, batchSignatureInput);
}

function _commitBatchWithBatchData(
BatchDataInput calldata batchDataInput,
BatchSignatureInput calldata batchSignatureInput
) internal {
require(batchDataInput.version == 0 || batchDataInput.version == 1, "invalid version");
require(batchDataInput.prevStateRoot != bytes32(0), "previous state root is zero");
require(batchDataInput.postStateRoot != bytes32(0), "new state root is zero");
Expand Down Expand Up @@ -259,7 +284,7 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable {
}
bytes32 _blobVersionedHash = (blobhash(0) == bytes32(0)) ? ZERO_VERSIONED_HASH : blobhash(0);

{
{
uint256 _headerLength = BatchHeaderCodecV0.BATCH_HEADER_LENGTH;
if (batchDataInput.version == 1) {
_headerLength = BatchHeaderCodecV1.BATCH_HEADER_LENGTH;
Expand Down Expand Up @@ -318,6 +343,46 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable {
emit CommitBatch(_batchIndex, committedBatches[_batchIndex]);
}

/// @inheritdoc IRollup
/// @dev Allows permissionless batch submission when sequencers are offline or censoring.
/// Entry conditions: rollup delay OR L1 message queue delay must be met.
function commitBatchWithProof(
BatchDataInput calldata batchDataInput,
BatchSignatureInput calldata batchSignatureInput,
bytes calldata _batchHeader,
bytes calldata _batchProof
) external override nonReqRevert whenNotPaused {
// check delay timing - allow if EITHER batch submission OR L1 message processing is stalled
// This enables permissionless batch submission when sequencers are offline or censoring
bool rollupDelay = batchDataStore[lastCommittedBatchIndex].originTimestamp + rollupDelayPeriod <
block.timestamp;

// Check if L1 message queue is delayed
bool l1MsgQueueDelayed = IL1MessageQueue(messageQueue).getFirstUnfinalizedMessageEnqueueTime() +
rollupDelayPeriod <
block.timestamp;

if (!rollupDelay && l1MsgQueueDelayed) {
require(batchDataInput.numL1Messages > 0, "l1msg delay");
}
require(rollupDelay || l1MsgQueueDelayed, "invalid timing");

_commitBatchWithBatchData(batchDataInput, batchSignatureInput);

// get batch data from batch header
(uint256 memPtr, bytes32 _batchHash) = _loadBatchHeader(_batchHeader);
// check batch hash
uint256 _batchIndex = BatchHeaderCodecV0.getBatchIndex(memPtr);
require(lastCommittedBatchIndex == _batchIndex, "incorrect batch header");
require(committedBatches[_batchIndex] == _batchHash, "incorrect batch hash");

// Override finalizeTimestamp for ZKP-backed immediate finality
batchDataStore[_batchIndex].finalizeTimestamp = block.timestamp;

// verify proof
_verifyProof(memPtr, _batchProof);
}

/// @inheritdoc IRollup
/// @dev If the owner wants to revert a sequence of batches by sending multiple transactions,
/// make sure to revert recent batches first.
Expand Down Expand Up @@ -407,6 +472,15 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable {
emit UpdateFinalizationPeriodSeconds(_oldFinalizationPeriodSeconds, finalizationPeriodSeconds);
}

/// @notice Update rollupDelayPeriod.
/// @param _newPeriod New rollup delay period.
function updateRollupDelayPeriod(uint256 _newPeriod) external onlyOwner {
require(_newPeriod > 0 && _newPeriod != rollupDelayPeriod, "invalid new rollup delay period");
uint256 _oldRollupDelayPeriod = rollupDelayPeriod;
rollupDelayPeriod = _newPeriod;
emit UpdateRollupDelayPeriod(_oldRollupDelayPeriod, rollupDelayPeriod);
}

/// @notice Add an account to the challenger list.
/// @param _account The address of account to add.
function addChallenger(address _account) external onlyOwner {
Expand Down Expand Up @@ -477,7 +551,10 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable {
*****************************/

/// @dev proveState proves a batch by submitting a proof.
function proveState(bytes calldata _batchHeader, bytes calldata _batchProof) external nonReqRevert whenNotPaused onlyActiveStaker{
function proveState(
bytes calldata _batchHeader,
bytes calldata _batchProof
) external nonReqRevert whenNotPaused onlyActiveStaker {
// get batch data from batch header
(uint256 memPtr, bytes32 _batchHash) = _loadBatchHeader(_batchHeader);
// check batch hash
Expand Down Expand Up @@ -727,7 +804,7 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable {
if (_version == 0) {
(_memPtr, _length) = BatchHeaderCodecV0.loadAndValidate(_batchHeader);
} else if (_version == 1) {
(_memPtr, _length) = BatchHeaderCodecV1.loadAndValidate(_batchHeader);
(_memPtr, _length) = BatchHeaderCodecV1.loadAndValidate(_batchHeader);
} else {
revert("Unsupported batch version");
}
Expand Down
Loading
Loading