Skip to content

Commit 0dda7fa

Browse files
authored
refactor: move blockDataHash into BlockHeader (#43)
1 parent be70144 commit 0dda7fa

File tree

2 files changed

+28
-34
lines changed

2 files changed

+28
-34
lines changed

src/Zenith.sol

+13-17
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@ contract Zenith is Passage {
1313
/// @param confirmBy - the timestamp by which the block must be submitted. Enforced by the contract.
1414
/// @param gasLimit - the gas limit for the rollup block. Ignored by the contract; enforced by the Node.
1515
/// @param rewardAddress - the address to receive the rollup block reward. Ignored by the contract; enforced by the Node.
16+
/// @param blockDataHash - keccak256(rlp-encoded transactions). the Node will discard the block if the hash doens't match.
17+
/// this allows the sequencer to sign over finalized set of transactions,
18+
/// without the Zenith contract needing to interact with raw transaction data (which may be provided via blobs or calldata).
1619
struct BlockHeader {
1720
uint256 rollupChainId;
1821
uint256 sequence;
1922
uint256 confirmBy;
2023
uint256 gasLimit;
2124
address rewardAddress;
25+
bytes32 blockDataHash;
2226
}
2327

2428
/// @notice The sequence number of the next block that can be submitted for a given rollup chainId.
@@ -43,8 +47,8 @@ contract Zenith is Passage {
4347
error BlockExpired();
4448

4549
/// @notice Thrown when a block submission is attempted with a signature by a non-permissioned sequencer,
46-
/// OR when signature is produced over different data than is provided.
47-
/// @param derivedSequencer - the derived signer of the block data that is not a permissioned sequencer.
50+
/// OR when signature is produced over different block header than is provided.
51+
/// @param derivedSequencer - the derived signer of the block header that is not a permissioned sequencer.
4852
error BadSignature(address derivedSequencer);
4953

5054
/// @notice Thrown when attempting to submit more than one rollup block per host block
@@ -60,7 +64,8 @@ contract Zenith is Passage {
6064
/// @param confirmBy - the timestamp by which the block must be submitted.
6165
/// @param gasLimit - the gas limit for the rollup block.
6266
/// @param rewardAddress - the address to receive the rollup block reward.
63-
/// @param blockDataHash - keccak256(blockData). the Node will discard the block if the hash doens't match.
67+
/// @param blockDataHash - keccak256(rlp-encoded transactions). the Node will discard the block if the hash doens't match transactions provided.
68+
/// @dev including blockDataHash allows the sequencer to sign over finalized block data, without needing to calldatacopy the `blockData` param.
6469
event BlockSubmitted(
6570
address indexed sequencer,
6671
uint256 indexed rollupChainId,
@@ -121,8 +126,6 @@ contract Zenith is Passage {
121126
/// @notice Submit a rollup block.
122127
/// @dev Blocks are submitted by Builders, with an attestation to the block signed by a Sequencer.
123128
/// @param header - the header information for the rollup block.
124-
/// @param blockDataHash - keccak256(rlp-encoded transactions). the Node will discard the block if the hash doens't match transactions provided.
125-
/// @dev including blockDataHash allows the sequencer to sign over finalized block data, without needing to calldatacopy the `blockData` param.
126129
/// @param v - the v component of the Sequencer's ECSDA signature over the block header.
127130
/// @param r - the r component of the Sequencer's ECSDA signature over the block header.
128131
/// @param s - the s component of the Sequencer's ECSDA signature over the block header.
@@ -132,14 +135,7 @@ contract Zenith is Passage {
132135
/// OR if the signature provided commits to a different header.
133136
/// @custom:reverts OneRollupBlockPerHostBlock if attempting to submit a second rollup block within one host block.
134137
/// @custom:emits BlockSubmitted if the block is successfully submitted.
135-
function submitBlock(
136-
BlockHeader memory header,
137-
bytes32 blockDataHash,
138-
uint8 v,
139-
bytes32 r,
140-
bytes32 s,
141-
bytes calldata
142-
) external {
138+
function submitBlock(BlockHeader memory header, uint8 v, bytes32 r, bytes32 s, bytes calldata) external {
143139
// assert that the sequence number is valid and increment it
144140
uint256 _nextSequence = incrementSequence(header.rollupChainId);
145141
if (_nextSequence != header.sequence) revert BadSequence(_nextSequence);
@@ -148,7 +144,7 @@ contract Zenith is Passage {
148144
if (block.timestamp > header.confirmBy) revert BlockExpired();
149145

150146
// derive sequencer from signature over block header
151-
bytes32 blockCommit = blockCommitment(header, blockDataHash);
147+
bytes32 blockCommit = blockCommitment(header);
152148
address sequencer = ecrecover(blockCommit, v, r, s);
153149

154150
// assert that signature is valid && sequencer is permissioned
@@ -166,14 +162,14 @@ contract Zenith is Passage {
166162
header.confirmBy,
167163
header.gasLimit,
168164
header.rewardAddress,
169-
blockDataHash
165+
header.blockDataHash
170166
);
171167
}
172168

173169
/// @notice Construct hash of block details that the sequencer signs.
174170
/// @param header - the header information for the rollup block.
175171
/// @return commit - the hash of the encoded block details.
176-
function blockCommitment(BlockHeader memory header, bytes32 blockDataHash) public view returns (bytes32 commit) {
172+
function blockCommitment(BlockHeader memory header) public view returns (bytes32 commit) {
177173
bytes memory encoded = abi.encodePacked(
178174
"init4.sequencer.v0",
179175
block.chainid,
@@ -182,7 +178,7 @@ contract Zenith is Passage {
182178
header.gasLimit,
183179
header.confirmBy,
184180
header.rewardAddress,
185-
blockDataHash
181+
header.blockDataHash
186182
);
187183
commit = keccak256(encoded);
188184
}

test/Zenith.t.sol

+15-17
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ contract ZenithTest is Test {
1010
Zenith.BlockHeader header;
1111
bytes32 commit;
1212
/// @dev blockData is ignored by the contract. it's included for the purpose of DA for the node.
13-
bytes32 blockDataHash;
1413
bytes blockData = "";
1514

1615
uint256 sequencerKey = 123;
@@ -36,37 +35,36 @@ contract ZenithTest is Test {
3635
header.confirmBy = block.timestamp + 10 minutes;
3736
header.gasLimit = 30_000_000;
3837
header.rewardAddress = address(this);
39-
40-
blockDataHash = keccak256(blockData);
38+
header.blockDataHash = keccak256(blockData);
4139

4240
// derive block commitment from the header
43-
commit = target.blockCommitment(header, blockDataHash);
41+
commit = target.blockCommitment(header);
4442
}
4543

4644
// cannot submit block with incorrect sequence number
4745
function test_badSequence() public {
4846
// change to incorrect sequence number
4947
header.sequence = 100;
50-
commit = target.blockCommitment(header, blockDataHash);
48+
commit = target.blockCommitment(header);
5149

5250
// sign block commitmenet with sequencer key
5351
(uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit);
5452

5553
vm.expectRevert(abi.encodeWithSelector(Zenith.BadSequence.selector, 1));
56-
target.submitBlock(header, blockDataHash, v, r, s, blockData);
54+
target.submitBlock(header, v, r, s, blockData);
5755
}
5856

5957
// cannot submit block with expired confirmBy time
6058
function test_blockExpired() public {
6159
// change to expired confirmBy time
6260
header.confirmBy = block.timestamp - 1;
63-
commit = target.blockCommitment(header, blockDataHash);
61+
commit = target.blockCommitment(header);
6462

6563
// sign block commitmenet with sequencer key
6664
(uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit);
6765

6866
vm.expectRevert(abi.encodeWithSelector(Zenith.BlockExpired.selector));
69-
target.submitBlock(header, blockDataHash, v, r, s, blockData);
67+
target.submitBlock(header, v, r, s, blockData);
7068
}
7169

7270
// can submit block successfully with acceptable header & correct signature provided
@@ -83,9 +81,9 @@ contract ZenithTest is Test {
8381
header.confirmBy,
8482
header.gasLimit,
8583
header.rewardAddress,
86-
blockDataHash
84+
header.blockDataHash
8785
);
88-
target.submitBlock(header, blockDataHash, v, r, s, blockData);
86+
target.submitBlock(header, v, r, s, blockData);
8987

9088
// should increment sequence number
9189
assertEq(target.nextSequence(header.rollupChainId), header.sequence + 1);
@@ -97,7 +95,7 @@ contract ZenithTest is Test {
9795
(uint8 v, bytes32 r, bytes32 s) = vm.sign(notSequencerKey, commit);
9896

9997
vm.expectRevert(abi.encodeWithSelector(Zenith.BadSignature.selector, vm.addr(notSequencerKey)));
100-
target.submitBlock(header, blockDataHash, v, r, s, blockData);
98+
target.submitBlock(header, v, r, s, blockData);
10199
}
102100

103101
// cannot submit block with sequencer signature over different block header data
@@ -107,11 +105,11 @@ contract ZenithTest is Test {
107105

108106
// change header data from what was signed by sequencer
109107
header.confirmBy = block.timestamp + 15 minutes;
110-
bytes32 newCommit = target.blockCommitment(header, blockDataHash);
108+
bytes32 newCommit = target.blockCommitment(header);
111109
address derivedSigner = ecrecover(newCommit, v, r, s);
112110

113111
vm.expectRevert(abi.encodeWithSelector(Zenith.BadSignature.selector, derivedSigner));
114-
target.submitBlock(header, blockDataHash, v, r, s, blockData);
112+
target.submitBlock(header, v, r, s, blockData);
115113
}
116114

117115
// cannot submit two rollup blocks within one host block
@@ -128,18 +126,18 @@ contract ZenithTest is Test {
128126
header.confirmBy,
129127
header.gasLimit,
130128
header.rewardAddress,
131-
blockDataHash
129+
header.blockDataHash
132130
);
133-
target.submitBlock(header, blockDataHash, v, r, s, blockData);
131+
target.submitBlock(header, v, r, s, blockData);
134132

135133
// incerement the header sequence
136134
header.sequence += 1;
137-
commit = target.blockCommitment(header, blockDataHash);
135+
commit = target.blockCommitment(header);
138136
(v, r, s) = vm.sign(sequencerKey, commit);
139137

140138
// should revert with OneRollupBlockPerHostBlock
141139
// (NOTE: this test works because forge does not increment block.number when it mines a transaction)
142140
vm.expectRevert(abi.encodeWithSelector(Zenith.OneRollupBlockPerHostBlock.selector));
143-
target.submitBlock(header, blockDataHash, v, r, s, blockData);
141+
target.submitBlock(header, v, r, s, blockData);
144142
}
145143
}

0 commit comments

Comments
 (0)