Skip to content

Commit 4aaca56

Browse files
committed
refactor: ignore blockData entirely, just emit it; unify codepaths
1 parent 3f5ddb1 commit 4aaca56

File tree

2 files changed

+38
-157
lines changed

2 files changed

+38
-157
lines changed

src/Zenith.sol

Lines changed: 20 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,12 @@ import {AccessControlDefaultAdminRules} from
77
"openzeppelin-contracts/contracts/access/extensions/AccessControlDefaultAdminRules.sol";
88

99
contract Zenith is HostPassage, AccessControlDefaultAdminRules {
10-
/// @notice The location where the block data was submitted.
11-
/// @param Blobs - the block data was submitted as 4844 blobs. the `submitBlock` calldata contains `blobIndices` which can be used to pull the blobs / blob hashes.
12-
/// @param Calldata - the block data was submitted directly via the `submitBlock` calldata.
13-
enum DataLocation {
14-
Blobs,
15-
Calldata
16-
}
1710
/// @notice Block header information for the rollup block, signed by the sequencer.
1811
/// @param rollupChainId - the chainId of the rollup chain. Any chainId is accepted by the contract.
1912
/// @param sequence - the sequence number of the rollup block. Must be monotonically increasing. Enforced by the contract.
2013
/// @param confirmBy - the timestamp by which the block must be submitted. Enforced by the contract.
2114
/// @param gasLimit - the gas limit for the rollup block. Ignored by the contract; enforced by the Node.
2215
/// @param rewardAddress - the address to receive the rollup block reward. Ignored by the contract; enforced by the Node.
23-
2416
struct BlockHeader {
2517
uint256 rollupChainId;
2618
uint256 sequence;
@@ -50,17 +42,13 @@ contract Zenith is HostPassage, AccessControlDefaultAdminRules {
5042
error BadSignature(address derivedSequencer);
5143

5244
/// @notice Emitted when a new rollup block is successfully submitted.
53-
/// @param location - the location where the block data was submitted.
5445
/// @param sequencer - the address of the sequencer that signed the block.
5546
/// @param header - the block header information for the block.
56-
event BlockSubmitted(DataLocation indexed location, address indexed sequencer, BlockHeader indexed header);
47+
event BlockSubmitted(address indexed sequencer, BlockHeader indexed header);
5748

5849
/// @notice Emit the entire block data for easy visibility
5950
event BlockData(bytes blockData);
6051

61-
/// @notice Emit the blob indices for easy visibility
62-
event BlobIndices(uint32[] blobIndices);
63-
6452
/// @notice Initializes the Admin role.
6553
/// @dev See `AccessControlDefaultAdminRules` for information on contract administration.
6654
/// - Admin role can grant and revoke Sequencer roles.
@@ -69,132 +57,56 @@ contract Zenith is HostPassage, AccessControlDefaultAdminRules {
6957
constructor(address admin) AccessControlDefaultAdminRules(1 days, admin) {}
7058

7159
/// @notice Submit a rollup block with block data submitted via calldata.
72-
/// @param header - see _submitBlock.
73-
/// @param blockData - full data for the block supplied directly.
74-
/// @param v - see _submitBlock.
75-
/// @param r - see _submitBlock.
76-
/// @param s - see _submitBlock.
77-
/// @custom:reverts see _submitBlock.
78-
/// @custom:emits see _submitBlock.
79-
function submitBlock(BlockHeader memory header, bytes calldata blockData, uint8 v, bytes32 r, bytes32 s) external {
80-
bytes32 blockCommit = blockCommitment(header, blockData);
81-
82-
_submitBlock(DataLocation.Calldata, header, blockCommit, v, r, s);
83-
84-
emit BlockData(blockData);
85-
}
86-
87-
/// @notice Submit a rollup block with block data stored in 4844 blobs.
88-
/// @param header - see _submitBlock.
89-
/// @param blobIndices - the indices of the 4844 blob hashes for the block data.
90-
/// @param v - see _submitBlock.
91-
/// @param r - see _submitBlock.
92-
/// @param s - see _submitBlock.
93-
/// @custom:reverts see _submitBlock.
94-
/// @custom:emits see _submitBlock.
95-
function submitBlock(BlockHeader memory header, uint32[] calldata blobIndices, uint8 v, bytes32 r, bytes32 s)
96-
external
97-
{
98-
bytes32 blockCommit = blockCommitment(header, blobIndices);
99-
100-
_submitBlock(DataLocation.Blobs, header, blockCommit, v, r, s);
101-
102-
emit BlobIndices(blobIndices);
103-
}
104-
105-
/// @notice Submit a rollup block.
10660
/// @dev Blocks are submitted by Builders, with an attestation to the block data signed by a Sequencer.
10761
/// @param header - the header information for the rollup block.
108-
/// @param blockCommit - the hashes `blockCommitment` signed by the Sequencer.
109-
/// @param v - the v component of the Sequencer's ECSDA signature over the block commitment.
110-
/// @param r - the r component of the Sequencer's ECSDA signature over the block commitment.
111-
/// @param s - the s component of the Sequencer's ECSDA signature over the block commitment.
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 v - the v component of the Sequencer's ECSDA signature over the block header.
64+
/// @param r - the r component of the Sequencer's ECSDA signature over the block header.
65+
/// @param s - the s component of the Sequencer's ECSDA signature over the block header.
11266
/// @custom:reverts BadSequence if the sequence number is not the next block for the given rollup chainId.
11367
/// @custom:reverts BlockExpired if the confirmBy time has passed.
11468
/// @custom:reverts BadSignature if the signer is not a permissioned sequencer,
115-
/// OR if the signature provided commits to different block data.
69+
/// OR if the signature provided commits to a different header.
70+
/// @custom:reverts OneRollupBlockPerHostBlock if attempting to submit a second rollup block within one host block.
11671
/// @custom:emits BlockSubmitted if the block is successfully submitted.
117-
function _submitBlock(
118-
DataLocation location,
119-
BlockHeader memory header,
120-
bytes32 blockCommit,
121-
uint8 v,
122-
bytes32 r,
123-
bytes32 s
124-
) internal {
72+
/// @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);
75+
emit BlockData(blockData);
76+
}
77+
78+
function _submitBlock(BlockHeader memory header, uint8 v, bytes32 r, bytes32 s) internal {
12579
// assert that the sequence number is valid and increment it
12680
uint256 _nextSequence = nextSequence[header.rollupChainId]++;
12781
if (_nextSequence != header.sequence) revert BadSequence(_nextSequence);
12882

12983
// assert that confirmBy time has not passed
13084
if (block.timestamp > header.confirmBy) revert BlockExpired();
13185

132-
// derive sequencer from signature
86+
// derive sequencer from signature over block header
87+
bytes32 blockCommit = blockCommitment(header);
13388
address sequencer = ecrecover(blockCommit, v, r, s);
13489

13590
// assert that signature is valid && sequencer is permissioned
13691
if (!hasRole(SEQUENCER_ROLE, sequencer)) revert BadSignature(sequencer);
13792

138-
// emit event
139-
emit BlockSubmitted(location, sequencer, header);
140-
}
141-
142-
/// @notice Encode an array of blob hashes, given their indices in the transaction.
143-
/// @param blobIndices - the indices of the 4844 blob hashes for the block data.
144-
/// @return encodedHashes - the encoded blob hashes.
145-
function getHashes(uint32[] calldata blobIndices) internal view returns (bytes memory encodedHashes) {
146-
for (uint32 i = 0; i < blobIndices.length; i++) {
147-
encodedHashes = abi.encodePacked(encodedHashes, blobhash(blobIndices[i]));
148-
}
149-
}
15093

151-
/// @notice Construct hash of block details that the sequencer signs.
152-
/// @dev NOTE: we have separate blockCommitment functions in order to keep `blockData` as `calldata`, which is not possible for `encodedHashes`
153-
/// @param header - the header information for the rollup block.
154-
/// @param blockData - full data for the block supplied directly.
155-
/// @return commit - the hash of the encoded block details.
156-
function blockCommitment(BlockHeader memory header, bytes calldata blockData)
157-
public
158-
view
159-
returns (bytes32 commit)
160-
{
161-
bytes memory encoded = abi.encodePacked(
162-
"init4.sequencer.v0",
163-
block.chainid,
164-
header.rollupChainId,
165-
header.sequence,
166-
header.gasLimit,
167-
header.confirmBy,
168-
header.rewardAddress,
169-
blockData.length,
170-
blockData
171-
);
172-
commit = keccak256(encoded);
94+
// emit event
95+
emit BlockSubmitted(sequencer, header);
17396
}
17497

17598
/// @notice Construct hash of block details that the sequencer signs.
17699
/// @param header - the header information for the rollup block.
177-
/// @param blobIndices - the indices of the 4844 blob hashes for the block data.
178100
/// @return commit - the hash of the encoded block details.
179-
function blockCommitment(BlockHeader memory header, uint32[] calldata blobIndices)
180-
public
181-
view
182-
returns (bytes32 commit)
183-
{
184-
// query the blob hashes via the indices in order to
185-
// ensure that the committed blob hashes are available in the transaction.
186-
bytes memory encodedHashes = getHashes(blobIndices);
187-
101+
function blockCommitment(BlockHeader memory header) public view returns (bytes32 commit) {
188102
bytes memory encoded = abi.encodePacked(
189103
"init4.sequencer.v0",
190104
block.chainid,
191105
header.rollupChainId,
192106
header.sequence,
193107
header.gasLimit,
194108
header.confirmBy,
195-
header.rewardAddress,
196-
encodedHashes.length,
197-
encodedHashes
109+
header.rewardAddress
198110
);
199111
commit = keccak256(encoded);
200112
}

test/Zenith.t.sol

Lines changed: 18 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@ contract ZenithTest is Test {
88
Zenith public target;
99

1010
Zenith.BlockHeader header;
11-
bytes32[] blobHashes;
12-
uint32[] blobIndices;
1311
bytes32 commit;
12+
/// @dev blockData is ignored by the contract. it's included for the purpose of DA for the node.
13+
bytes blockData = "0x1234567890abcdef";
1414

1515
uint256 sequencerKey = 123;
1616
uint256 notSequencerKey = 300;
1717

18-
event BlockSubmitted(
19-
Zenith.DataLocation indexed location, address indexed sequencer, Zenith.BlockHeader indexed header
20-
);
18+
event BlockSubmitted(address indexed sequencer, Zenith.BlockHeader indexed header);
2119

2220
function setUp() public {
2321
target = new Zenith(address(this));
@@ -30,99 +28,70 @@ contract ZenithTest is Test {
3028
header.gasLimit = 30_000_000;
3129
header.rewardAddress = address(this);
3230

33-
// set default blob info
34-
blobIndices.push(0);
35-
blobHashes.push(bytes32("JUNK BLOBHASH"));
36-
// TODO: vm.blobhashes(blobHashes);
37-
38-
// derive block commitment from sequence number and blobhashes
39-
commit = target.blockCommitment(header, packHashes(blobHashes));
40-
}
41-
42-
/// @notice Encode the array of blob hashes into a bytes string.
43-
/// @param _blobHashes - the 4844 blob hashes for the block data.
44-
/// @return encodedHashes - the encoded blob hashes.
45-
function packHashes(bytes32[] memory _blobHashes) public pure returns (bytes memory encodedHashes) {
46-
for (uint32 i = 0; i < _blobHashes.length; i++) {
47-
encodedHashes = abi.encodePacked(encodedHashes, _blobHashes[i]);
48-
}
31+
// derive block commitment from the header
32+
commit = target.blockCommitment(header);
4933
}
5034

5135
// cannot submit block with incorrect sequence number
5236
function test_badSequence() public {
5337
// change to incorrect sequence number
5438
header.sequence = 1;
39+
commit = target.blockCommitment(header);
5540

5641
// sign block commitmenet with sequencer key
5742
(uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit);
5843

5944
vm.expectRevert(abi.encodeWithSelector(Zenith.BadSequence.selector, 0));
60-
target.submitBlock(header, blobIndices, v, r, s);
45+
target.submitBlock(header, v, r, s, blockData);
6146
}
6247

6348
// cannot submit block with expired confirmBy time
6449
function test_blockExpired() public {
6550
// change to expired confirmBy time
6651
header.confirmBy = block.timestamp - 1;
52+
commit = target.blockCommitment(header);
6753

6854
// sign block commitmenet with sequencer key
6955
(uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit);
7056

7157
vm.expectRevert(abi.encodeWithSelector(Zenith.BlockExpired.selector));
72-
target.submitBlock(header, blobIndices, v, r, s);
58+
target.submitBlock(header, v, r, s, blockData);
7359
}
7460

75-
// BLOCKED by PR supporting vm.blobhashes: https://github.com/foundry-rs/foundry/pull/7001
76-
// can submit block successfully with acceptable data & correct signature provided
77-
function BLOCKED_test_submitBlock() public {
61+
// can submit block successfully with acceptable header & correct signature provided
62+
function test_submitBlock() public {
7863
// sign block commitmenet with correct sequencer key
7964
(uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit);
8065

8166
// should emit BlockSubmitted event
8267
vm.expectEmit();
83-
emit BlockSubmitted(Zenith.DataLocation.Blobs, vm.addr(sequencerKey), header);
84-
target.submitBlock(header, blobIndices, v, r, s);
68+
emit BlockSubmitted(vm.addr(sequencerKey), header);
69+
target.submitBlock(header, v, r, s, blockData);
8570

8671
// should increment sequence number
8772
assertEq(target.nextSequence(header.rollupChainId), header.sequence + 1);
8873
}
8974

9075
// cannot submit block with invalid sequencer signer from non-permissioned key
91-
function BLOCKED_test_notSequencer() public {
76+
function test_notSequencer() public {
9277
// sign block commitmenet with NOT sequencer key
9378
(uint8 v, bytes32 r, bytes32 s) = vm.sign(notSequencerKey, commit);
9479

9580
vm.expectRevert(abi.encodeWithSelector(Zenith.BadSignature.selector, vm.addr(notSequencerKey)));
96-
target.submitBlock(header, blobIndices, v, r, s);
81+
target.submitBlock(header, v, r, s, blockData);
9782
}
9883

9984
// cannot submit block with sequencer signature over different block header data
100-
function BLOCKED_test_badSignature_header() public {
85+
function test_badSignature() public {
10186
// sign original block commitmenet with sequencer key
10287
(uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit);
10388

10489
// change header data from what was signed by sequencer
10590
header.confirmBy = block.timestamp + 15 minutes;
106-
107-
bytes32 newCommit = target.blockCommitment(header, packHashes(blobHashes));
108-
address derivedSigner = ecrecover(newCommit, v, r, s);
109-
110-
vm.expectRevert(abi.encodeWithSelector(Zenith.BadSignature.selector, derivedSigner));
111-
target.submitBlock(header, blobIndices, v, r, s);
112-
}
113-
114-
// cannot submit block with sequencer signature over different blob hashes
115-
function BLOCKED_test_badSignature_blobs() public {
116-
// sign original block commitmenet with sequencer key
117-
(uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit);
118-
119-
blobHashes[0] = bytes32("DIFFERENT BLOBHASH");
120-
// TODO: vm.blobhashes(blobHashes);
121-
122-
bytes32 newCommit = target.blockCommitment(header, packHashes(blobHashes));
91+
bytes32 newCommit = target.blockCommitment(header);
12392
address derivedSigner = ecrecover(newCommit, v, r, s);
12493

12594
vm.expectRevert(abi.encodeWithSelector(Zenith.BadSignature.selector, derivedSigner));
126-
target.submitBlock(header, blobIndices, v, r, s);
95+
target.submitBlock(header, v, r, s, blockData);
12796
}
12897
}

0 commit comments

Comments
 (0)