mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-01-10 22:48:14 -05:00
fix(contracts): fix chunk hash computation (#546)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
This commit is contained in:
@@ -402,11 +402,13 @@ contract ScrollChain is OwnableUpgradeable, IScrollChain {
|
||||
bytes calldata _skippedL1MessageBitmap
|
||||
) internal view returns (uint256 _totalNumL1MessagesInChunk) {
|
||||
uint256 chunkPtr;
|
||||
uint256 startDataPtr;
|
||||
uint256 dataPtr;
|
||||
uint256 blockPtr;
|
||||
|
||||
assembly {
|
||||
dataPtr := mload(0x40)
|
||||
startDataPtr := dataPtr
|
||||
chunkPtr := add(_chunk, 0x20) // skip chunkLength
|
||||
blockPtr := add(chunkPtr, 1) // skip numBlocks
|
||||
}
|
||||
@@ -414,15 +416,23 @@ contract ScrollChain is OwnableUpgradeable, IScrollChain {
|
||||
uint256 _numBlocks = ChunkCodec.validateChunkLength(chunkPtr, _chunk.length);
|
||||
|
||||
// concatenate block contexts
|
||||
uint256 _totalTransactionsInChunk;
|
||||
for (uint256 i = 0; i < _numBlocks; i++) {
|
||||
dataPtr = ChunkCodec.copyBlockContext(chunkPtr, dataPtr, i);
|
||||
uint256 _numTransactionsInBlock = ChunkCodec.numTransactions(blockPtr);
|
||||
unchecked {
|
||||
_totalTransactionsInChunk += _numTransactionsInBlock;
|
||||
blockPtr += ChunkCodec.BLOCK_CONTEXT_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
assembly {
|
||||
mstore(0x40, add(dataPtr, mul(_totalTransactionsInChunk, 0x20))) // reserve memory for tx hashes
|
||||
blockPtr := add(chunkPtr, 1) // reset block ptr
|
||||
}
|
||||
|
||||
// concatenate tx hashes
|
||||
uint256 l2TxPtr = ChunkCodec.l2TxPtr(chunkPtr, _numBlocks);
|
||||
|
||||
// avoid stack too deep on forge coverage
|
||||
uint256 _totalTransactionsInChunk;
|
||||
while (_numBlocks > 0) {
|
||||
// concatenate l1 message hashes
|
||||
uint256 _numL1MessagesInBlock = ChunkCodec.numL1Messages(blockPtr);
|
||||
@@ -446,7 +456,6 @@ contract ScrollChain is OwnableUpgradeable, IScrollChain {
|
||||
}
|
||||
|
||||
unchecked {
|
||||
_totalTransactionsInChunk += _numTransactionsInBlock;
|
||||
_totalNumL1MessagesInChunk += _numL1MessagesInBlock;
|
||||
_totalL1MessagesPoppedInBatch += _numL1MessagesInBlock;
|
||||
_totalL1MessagesPoppedOverall += _numL1MessagesInBlock;
|
||||
@@ -467,9 +476,7 @@ contract ScrollChain is OwnableUpgradeable, IScrollChain {
|
||||
|
||||
// compute data hash and store to memory
|
||||
assembly {
|
||||
let startPtr := mload(0x40)
|
||||
let dataHash := keccak256(startPtr, sub(dataPtr, startPtr))
|
||||
|
||||
let dataHash := keccak256(startDataPtr, sub(dataPtr, startDataPtr))
|
||||
mstore(memPtr, dataHash)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ import {ScrollChain, IScrollChain} from "../L1/rollup/ScrollChain.sol";
|
||||
import {MockScrollChain} from "./mocks/MockScrollChain.sol";
|
||||
import {MockRollupVerifier} from "./mocks/MockRollupVerifier.sol";
|
||||
|
||||
// solhint-disable no-inline-assembly
|
||||
|
||||
contract ScrollChainTest is DSTestPlus {
|
||||
// from ScrollChain
|
||||
event UpdateSequencer(address indexed account, bool status);
|
||||
@@ -42,35 +44,6 @@ contract ScrollChainTest is DSTestPlus {
|
||||
rollup.initialize(address(messageQueue), address(0), 100);
|
||||
}
|
||||
|
||||
/*
|
||||
function testPublicInputHash() public {
|
||||
IScrollChain.Batch memory batch;
|
||||
batch.prevStateRoot = bytes32(0x000000000000000000000000000000000000000000000000000000000000cafe);
|
||||
batch.newStateRoot = bytes32(0);
|
||||
batch.withdrawTrieRoot = bytes32(0);
|
||||
batch
|
||||
.l2Transactions = hex"0000007402f8710582fd14808506e38dccc9825208944d496ccc28058b1d74b7a19541663e21154f9c848801561db11e24a43380c080a0d890606d7a35b2ab0f9b866d62c092d5b163f3e6a55537ae1485aac08c3f8ff7a023997be2d32f53e146b160fff0ba81e81dbb4491c865ab174d15c5b3d28c41ae";
|
||||
|
||||
batch.blocks = new IScrollChain.BlockContext[](1);
|
||||
batch.blocks[0].blockHash = bytes32(0);
|
||||
batch.blocks[0].parentHash = bytes32(0);
|
||||
batch.blocks[0].blockNumber = 51966;
|
||||
batch.blocks[0].timestamp = 123456789;
|
||||
batch.blocks[0].baseFee = 0;
|
||||
batch.blocks[0].gasLimit = 10000000000000000;
|
||||
batch.blocks[0].numTransactions = 1;
|
||||
batch.blocks[0].numL1Messages = 0;
|
||||
|
||||
(bytes32 hash, , , ) = chain.computePublicInputHash(0, batch);
|
||||
assertEq(hash, bytes32(0xa9f2ca3175794f91226a410ba1e60fff07a405c957562675c4149b77e659d805));
|
||||
|
||||
batch
|
||||
.l2Transactions = hex"00000064f8628001830f424094000000000000000000000000000000000000bbbb8080820a97a064e07cd8f939e2117724bdcbadc80dda421381cbc2a1f4e0d093d9cc5c5cf68ea03e264227f80852d88743cd9e43998f2746b619180366a87e4531debf9c3fa5dc";
|
||||
(hash, , , ) = chain.computePublicInputHash(0, batch);
|
||||
assertEq(hash, bytes32(0x398cb22bbfa1665c1b342b813267538a4c933d7f92d8bd9184aba0dd1122987b));
|
||||
}
|
||||
*/
|
||||
|
||||
function testCommitBatch() public {
|
||||
bytes memory batchHeader0 = new bytes(89);
|
||||
|
||||
@@ -260,13 +233,34 @@ contract ScrollChainTest is DSTestPlus {
|
||||
bytes memory chunk1;
|
||||
|
||||
// commit batch1, one chunk with one block, 1 tx, 1 L1 message, no skip
|
||||
// => payload for data hash of chunk0
|
||||
// 0000000000000000
|
||||
// 0000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000
|
||||
// 0001
|
||||
// 50c3caa727394b95dc4885b7d25033ed22ac772b985fb274f2a7c0699a11346d
|
||||
// => data hash for chunk0
|
||||
// bb88f47194a07d59ed17bc9b2015f83d0afea8f7892d9c5f0b6565563bf06b26
|
||||
// => data hash for all chunks
|
||||
// 038433daac85a0b03cd443ed50bc85e832c883061651ae2182b2984751e0b340
|
||||
// => payload for batch header
|
||||
// 00
|
||||
// 0000000000000002
|
||||
// 0000000000000001
|
||||
// 0000000000000001
|
||||
// 038433daac85a0b03cd443ed50bc85e832c883061651ae2182b2984751e0b340
|
||||
// 119b828c2a2798d2c957228ebeaff7e10bb099ae0d4e224f3eeb779ff61cba61
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// => hash for batch header
|
||||
// cef70bf80683c4d9b8b2813e90c314e8c56648e231300b8cfed9d666b0caf14e
|
||||
bytes memory batchHeader1 = new bytes(89 + 32);
|
||||
assembly {
|
||||
mstore(add(batchHeader1, 0x20), 0) // version
|
||||
mstore(add(batchHeader1, add(0x20, 1)), shl(192, 1)) // batchIndex = 1
|
||||
mstore(add(batchHeader1, add(0x20, 9)), shl(192, 1)) // l1MessagePopped = 1
|
||||
mstore(add(batchHeader1, add(0x20, 17)), shl(192, 1)) // totalL1MessagePopped = 1
|
||||
mstore(add(batchHeader1, add(0x20, 25)), 0xfe21c37fa013c76f86b8593ddf15d685a04b55061d06797597ee866f6ff2edf8) // dataHash
|
||||
mstore(add(batchHeader1, add(0x20, 25)), 0x038433daac85a0b03cd443ed50bc85e832c883061651ae2182b2984751e0b340) // dataHash
|
||||
mstore(add(batchHeader1, add(0x20, 57)), batchHash0) // parentBatchHash
|
||||
mstore(add(batchHeader1, add(0x20, 89)), 0) // bitmap0
|
||||
}
|
||||
@@ -280,9 +274,9 @@ contract ScrollChainTest is DSTestPlus {
|
||||
chunks[0] = chunk0;
|
||||
bitmap = new bytes(32);
|
||||
rollup.commitBatch(0, batchHeader0, chunks, bitmap);
|
||||
assertGt(uint256(rollup.committedBatches(1)), 0);
|
||||
assertBoolEq(rollup.isBatchFinalized(1), false);
|
||||
bytes32 batchHash1 = rollup.committedBatches(1);
|
||||
assertEq(batchHash1, bytes32(0xcef70bf80683c4d9b8b2813e90c314e8c56648e231300b8cfed9d666b0caf14e));
|
||||
|
||||
// finalize batch1
|
||||
rollup.finalizeBatchWithProof(
|
||||
@@ -301,17 +295,57 @@ contract ScrollChainTest is DSTestPlus {
|
||||
|
||||
// commit batch2 with two chunks, correctly
|
||||
// 1. chunk0 has one block, 3 tx, no L1 messages
|
||||
// => payload for chunk0
|
||||
// 0000000000000000
|
||||
// 0000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000
|
||||
// 0003
|
||||
// ... (some tx hashes)
|
||||
// => data hash for chunk0
|
||||
// 2ac1dad3f3696e5581dfc10f2c7a7a8fc5b344285f7d332c7895a8825fca609a
|
||||
// 2. chunk1 has three blocks
|
||||
// 2.1 block0 has 5 tx, 3 L1 messages, no skips
|
||||
// 2.2 block1 has 10 tx, 5 L1 messages, even is skipped.
|
||||
// 2.2 block1 has 300 tx, 256 L1 messages, odd position is skipped.
|
||||
// => payload for chunk1
|
||||
// 0000000000000000
|
||||
// 0000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000
|
||||
// 0005
|
||||
// 0000000000000000
|
||||
// 0000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000
|
||||
// 000a
|
||||
// 0000000000000000
|
||||
// 0000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000
|
||||
// 012c
|
||||
// ... (some tx hashes)
|
||||
// => data hash for chunk2
|
||||
// 5c91563ee8be18cb94accfc83728f883ff5e3aa600fd0799e0a4e39afc7970b9
|
||||
// => data hash for all chunks
|
||||
// bf38f308e0a87ed7bf92fa2da038fa1d59a7b9801eb0f6d487f8eef528632145
|
||||
// => payload for batch header
|
||||
// 00
|
||||
// 0000000000000002
|
||||
// 0000000000000108
|
||||
// 0000000000000109
|
||||
// bf38f308e0a87ed7bf92fa2da038fa1d59a7b9801eb0f6d487f8eef528632145
|
||||
// cef70bf80683c4d9b8b2813e90c314e8c56648e231300b8cfed9d666b0caf14e
|
||||
// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa800000000000000000000000000000000000000000000000000000000000000aa
|
||||
// => hash for batch header
|
||||
// 17fe6c12739f3a6261ae6db6486f41758dbd5d0508f19a5ca9ac37df67bbfec2
|
||||
bytes memory batchHeader2 = new bytes(89 + 32 + 32);
|
||||
assembly {
|
||||
mstore(add(batchHeader2, 0x20), 0) // version
|
||||
mstore(add(batchHeader2, add(0x20, 1)), shl(192, 2)) // batchIndex = 2
|
||||
mstore(add(batchHeader2, add(0x20, 9)), shl(192, 264)) // l1MessagePopped = 264
|
||||
mstore(add(batchHeader2, add(0x20, 17)), shl(192, 265)) // totalL1MessagePopped = 265
|
||||
mstore(add(batchHeader2, add(0x20, 25)), 0xa447b3c80bc6c3ee1aebc1af746c7c6b35a05c4a7af89d2103e9e0788b54375c) // dataHash
|
||||
mstore(add(batchHeader2, add(0x20, 25)), 0xbf38f308e0a87ed7bf92fa2da038fa1d59a7b9801eb0f6d487f8eef528632145) // dataHash
|
||||
mstore(add(batchHeader2, add(0x20, 57)), batchHash1) // parentBatchHash
|
||||
mstore(
|
||||
add(batchHeader2, add(0x20, 89)),
|
||||
@@ -358,9 +392,9 @@ contract ScrollChainTest is DSTestPlus {
|
||||
}
|
||||
|
||||
rollup.commitBatch(0, batchHeader1, chunks, bitmap);
|
||||
assertGt(uint256(rollup.committedBatches(2)), 0);
|
||||
assertBoolEq(rollup.isBatchFinalized(2), false);
|
||||
bytes32 batchHash2 = rollup.committedBatches(2);
|
||||
assertEq(batchHash2, bytes32(0x17fe6c12739f3a6261ae6db6486f41758dbd5d0508f19a5ca9ac37df67bbfec2));
|
||||
|
||||
// verify committed batch correctly
|
||||
rollup.finalizeBatchWithProof(
|
||||
|
||||
Reference in New Issue
Block a user