Skip to content

Commit 6c7f37d

Browse files
committed
add blockDataHash
1 parent 4aaca56 commit 6c7f37d

File tree

2 files changed

+35
-20
lines changed

2 files changed

+35
-20
lines changed

src/Zenith.sol

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ contract Zenith is HostPassage, AccessControlDefaultAdminRules {
4444
/// @notice Emitted when a new rollup block is successfully submitted.
4545
/// @param sequencer - the address of the sequencer that signed the block.
4646
/// @param header - the block header information for the block.
47-
event BlockSubmitted(address indexed sequencer, BlockHeader indexed header);
47+
/// @param blockDataHash - keccak256(blockData). the Node will discard the block if the hash doens't match.
48+
event BlockSubmitted(address indexed sequencer, BlockHeader indexed header, bytes32 blockDataHash);
4849

4950
/// @notice Emit the entire block data for easy visibility
5051
event BlockData(bytes blockData);
@@ -59,23 +60,32 @@ contract Zenith is HostPassage, AccessControlDefaultAdminRules {
5960
/// @notice Submit a rollup block with block data submitted via calldata.
6061
/// @dev Blocks are submitted by Builders, with an attestation to the block data signed by a Sequencer.
6162
/// @param header - the header information for the rollup block.
62-
/// @param blockData - block data information. could be blob hashes / indices, or direct rlp-encoded transctions. blockData is ignored by the contract logic.
63+
/// @param blockDataHash - keccak256(blockData). the Node will discard the block if the hash doens't match.
64+
/// @dev including blockDataHash allows the sequencer to sign over finalized block data, without needing to calldatacopy the `blockData` param.
6365
/// @param v - the v component of the Sequencer's ECSDA signature over the block header.
6466
/// @param r - the r component of the Sequencer's ECSDA signature over the block header.
6567
/// @param s - the s component of the Sequencer's ECSDA signature over the block header.
68+
/// @param blockData - block data information. could be packed blob hashes, or direct rlp-encoded transctions. blockData is ignored by the contract logic.
6669
/// @custom:reverts BadSequence if the sequence number is not the next block for the given rollup chainId.
6770
/// @custom:reverts BlockExpired if the confirmBy time has passed.
6871
/// @custom:reverts BadSignature if the signer is not a permissioned sequencer,
6972
/// OR if the signature provided commits to a different header.
7073
/// @custom:reverts OneRollupBlockPerHostBlock if attempting to submit a second rollup block within one host block.
7174
/// @custom:emits BlockSubmitted if the block is successfully submitted.
7275
/// @custom:emits BlockData to expose the block calldata; as a convenience until calldata tracing is implemented in the Node.
73-
function submitBlock(BlockHeader memory header, uint8 v, bytes32 r, bytes32 s, bytes calldata blockData) external {
74-
_submitBlock(header, v, r, s);
76+
function submitBlock(
77+
BlockHeader memory header,
78+
bytes32 blockDataHash,
79+
uint8 v,
80+
bytes32 r,
81+
bytes32 s,
82+
bytes calldata blockData
83+
) external {
84+
_submitBlock(header, blockDataHash, v, r, s);
7585
emit BlockData(blockData);
7686
}
7787

78-
function _submitBlock(BlockHeader memory header, uint8 v, bytes32 r, bytes32 s) internal {
88+
function _submitBlock(BlockHeader memory header, bytes32 blockDataHash, uint8 v, bytes32 r, bytes32 s) internal {
7989
// assert that the sequence number is valid and increment it
8090
uint256 _nextSequence = nextSequence[header.rollupChainId]++;
8191
if (_nextSequence != header.sequence) revert BadSequence(_nextSequence);
@@ -84,29 +94,30 @@ contract Zenith is HostPassage, AccessControlDefaultAdminRules {
8494
if (block.timestamp > header.confirmBy) revert BlockExpired();
8595

8696
// derive sequencer from signature over block header
87-
bytes32 blockCommit = blockCommitment(header);
97+
bytes32 blockCommit = blockCommitment(header, blockDataHash);
8898
address sequencer = ecrecover(blockCommit, v, r, s);
8999

90100
// assert that signature is valid && sequencer is permissioned
91101
if (!hasRole(SEQUENCER_ROLE, sequencer)) revert BadSignature(sequencer);
92102

93103

94104
// emit event
95-
emit BlockSubmitted(sequencer, header);
105+
emit BlockSubmitted(sequencer, header, blockDataHash);
96106
}
97107

98108
/// @notice Construct hash of block details that the sequencer signs.
99109
/// @param header - the header information for the rollup block.
100110
/// @return commit - the hash of the encoded block details.
101-
function blockCommitment(BlockHeader memory header) public view returns (bytes32 commit) {
111+
function blockCommitment(BlockHeader memory header, bytes32 blockDataHash) public view returns (bytes32 commit) {
102112
bytes memory encoded = abi.encodePacked(
103113
"init4.sequencer.v0",
104114
block.chainid,
105115
header.rollupChainId,
106116
header.sequence,
107117
header.gasLimit,
108118
header.confirmBy,
109-
header.rewardAddress
119+
header.rewardAddress,
120+
blockDataHash
110121
);
111122
commit = keccak256(encoded);
112123
}

test/Zenith.t.sol

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ contract ZenithTest is Test {
1111
bytes32 commit;
1212
/// @dev blockData is ignored by the contract. it's included for the purpose of DA for the node.
1313
bytes blockData = "0x1234567890abcdef";
14+
bytes32 blockDataHash;
1415

1516
uint256 sequencerKey = 123;
1617
uint256 notSequencerKey = 300;
1718

18-
event BlockSubmitted(address indexed sequencer, Zenith.BlockHeader indexed header);
19+
event BlockSubmitted(address indexed sequencer, Zenith.BlockHeader indexed header, bytes32 blockDataHash);
1920

2021
function setUp() public {
2122
target = new Zenith(address(this));
@@ -28,34 +29,36 @@ contract ZenithTest is Test {
2829
header.gasLimit = 30_000_000;
2930
header.rewardAddress = address(this);
3031

32+
blockDataHash = keccak256(blockData);
33+
3134
// derive block commitment from the header
32-
commit = target.blockCommitment(header);
35+
commit = target.blockCommitment(header, blockDataHash);
3336
}
3437

3538
// cannot submit block with incorrect sequence number
3639
function test_badSequence() public {
3740
// change to incorrect sequence number
3841
header.sequence = 1;
39-
commit = target.blockCommitment(header);
42+
commit = target.blockCommitment(header, blockDataHash);
4043

4144
// sign block commitmenet with sequencer key
4245
(uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit);
4346

4447
vm.expectRevert(abi.encodeWithSelector(Zenith.BadSequence.selector, 0));
45-
target.submitBlock(header, v, r, s, blockData);
48+
target.submitBlock(header, blockDataHash, v, r, s, blockData);
4649
}
4750

4851
// cannot submit block with expired confirmBy time
4952
function test_blockExpired() public {
5053
// change to expired confirmBy time
5154
header.confirmBy = block.timestamp - 1;
52-
commit = target.blockCommitment(header);
55+
commit = target.blockCommitment(header, blockDataHash);
5356

5457
// sign block commitmenet with sequencer key
5558
(uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit);
5659

5760
vm.expectRevert(abi.encodeWithSelector(Zenith.BlockExpired.selector));
58-
target.submitBlock(header, v, r, s, blockData);
61+
target.submitBlock(header, blockDataHash, v, r, s, blockData);
5962
}
6063

6164
// can submit block successfully with acceptable header & correct signature provided
@@ -65,8 +68,8 @@ contract ZenithTest is Test {
6568

6669
// should emit BlockSubmitted event
6770
vm.expectEmit();
68-
emit BlockSubmitted(vm.addr(sequencerKey), header);
69-
target.submitBlock(header, v, r, s, blockData);
71+
emit BlockSubmitted(vm.addr(sequencerKey), header, blockDataHash);
72+
target.submitBlock(header, blockDataHash, v, r, s, blockData);
7073

7174
// should increment sequence number
7275
assertEq(target.nextSequence(header.rollupChainId), header.sequence + 1);
@@ -78,7 +81,7 @@ contract ZenithTest is Test {
7881
(uint8 v, bytes32 r, bytes32 s) = vm.sign(notSequencerKey, commit);
7982

8083
vm.expectRevert(abi.encodeWithSelector(Zenith.BadSignature.selector, vm.addr(notSequencerKey)));
81-
target.submitBlock(header, v, r, s, blockData);
84+
target.submitBlock(header, blockDataHash, v, r, s, blockData);
8285
}
8386

8487
// cannot submit block with sequencer signature over different block header data
@@ -88,10 +91,11 @@ contract ZenithTest is Test {
8891

8992
// change header data from what was signed by sequencer
9093
header.confirmBy = block.timestamp + 15 minutes;
91-
bytes32 newCommit = target.blockCommitment(header);
94+
bytes32 newCommit = target.blockCommitment(header, blockDataHash);
9295
address derivedSigner = ecrecover(newCommit, v, r, s);
9396

9497
vm.expectRevert(abi.encodeWithSelector(Zenith.BadSignature.selector, derivedSigner));
95-
target.submitBlock(header, v, r, s, blockData);
98+
target.submitBlock(header, blockDataHash, v, r, s, blockData);
99+
}
96100
}
97101
}

0 commit comments

Comments
 (0)