/
BatchHeaderV0Codec.sol
212 lines (187 loc) · 9.5 KB
/
BatchHeaderV0Codec.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
// solhint-disable no-inline-assembly
/// @dev Below is the encoding for `BatchHeader` V0, total 89 + ceil(l1MessagePopped / 256) * 32 bytes.
/// ```text
/// * Field Bytes Type Index Comments
/// * version 1 uint8 0 The batch version
/// * batchIndex 8 uint64 1 The index of the batch
/// * l1MessagePopped 8 uint64 9 Number of L1 messages popped in the batch
/// * totalL1MessagePopped 8 uint64 17 Number of total L1 messages popped after the batch
/// * dataHash 32 bytes32 25 The data hash of the batch
/// * parentBatchHash 32 bytes32 57 The parent batch hash
/// * skippedL1MessageBitmap dynamic uint256[] 89 A bitmap to indicate which L1 messages are skipped in the batch
/// ```
library BatchHeaderV0Codec {
/// @dev Thrown when the length of batch header is smaller than 89
error ErrorBatchHeaderLengthTooSmall();
/// @dev Thrown when the length of skippedL1MessageBitmap is incorrect.
error ErrorIncorrectBitmapLength();
/// @dev The length of fixed parts of the batch header.
uint256 internal constant BATCH_HEADER_FIXED_LENGTH = 89;
/// @notice Load batch header in calldata to memory.
/// @param _batchHeader The encoded batch header bytes in calldata.
/// @return batchPtr The start memory offset of the batch header in memory.
/// @return length The length in bytes of the batch header.
function loadAndValidate(bytes calldata _batchHeader) internal pure returns (uint256 batchPtr, uint256 length) {
length = _batchHeader.length;
if (length < BATCH_HEADER_FIXED_LENGTH) revert ErrorBatchHeaderLengthTooSmall();
// copy batch header to memory.
assembly {
batchPtr := mload(0x40)
calldatacopy(batchPtr, _batchHeader.offset, length)
mstore(0x40, add(batchPtr, length))
}
// check batch header length
uint256 _l1MessagePopped = getL1MessagePopped(batchPtr);
unchecked {
if (length != BATCH_HEADER_FIXED_LENGTH + ((_l1MessagePopped + 255) / 256) * 32) {
revert ErrorIncorrectBitmapLength();
}
}
}
/// @notice Get the version of the batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _version The version of the batch header.
function getVersion(uint256 batchPtr) internal pure returns (uint256 _version) {
assembly {
_version := shr(248, mload(batchPtr))
}
}
/// @notice Get the batch index of the batch.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _batchIndex The batch index of the batch.
function getBatchIndex(uint256 batchPtr) internal pure returns (uint256 _batchIndex) {
assembly {
_batchIndex := shr(192, mload(add(batchPtr, 1)))
}
}
/// @notice Get the number of L1 messages of the batch.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _l1MessagePopped The number of L1 messages of the batch.
function getL1MessagePopped(uint256 batchPtr) internal pure returns (uint256 _l1MessagePopped) {
assembly {
_l1MessagePopped := shr(192, mload(add(batchPtr, 9)))
}
}
/// @notice Get the number of L1 messages popped before this batch.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _totalL1MessagePopped The the number of L1 messages popped before this batch.
function getTotalL1MessagePopped(uint256 batchPtr) internal pure returns (uint256 _totalL1MessagePopped) {
assembly {
_totalL1MessagePopped := shr(192, mload(add(batchPtr, 17)))
}
}
/// @notice Get the data hash of the batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _dataHash The data hash of the batch header.
function getDataHash(uint256 batchPtr) internal pure returns (bytes32 _dataHash) {
assembly {
_dataHash := mload(add(batchPtr, 25))
}
}
/// @notice Get the parent batch hash of the batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _parentBatchHash The parent batch hash of the batch header.
function getParentBatchHash(uint256 batchPtr) internal pure returns (bytes32 _parentBatchHash) {
assembly {
_parentBatchHash := mload(add(batchPtr, 57))
}
}
/// @notice Get the start memory offset for skipped L1 messages bitmap.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _bitmapPtr the start memory offset for skipped L1 messages bitmap.
function getSkippedBitmapPtr(uint256 batchPtr) internal pure returns (uint256 _bitmapPtr) {
assembly {
_bitmapPtr := add(batchPtr, BATCH_HEADER_FIXED_LENGTH)
}
}
/// @notice Get the skipped L1 messages bitmap.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param index The index of bitmap to load.
/// @return _bitmap The bitmap from bits `index * 256` to `index * 256 + 255`.
function getSkippedBitmap(uint256 batchPtr, uint256 index) internal pure returns (uint256 _bitmap) {
assembly {
batchPtr := add(batchPtr, BATCH_HEADER_FIXED_LENGTH)
_bitmap := mload(add(batchPtr, mul(index, 32)))
}
}
/// @notice Store the version of batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _version The version of batch header.
function storeVersion(uint256 batchPtr, uint256 _version) internal pure {
assembly {
mstore8(batchPtr, _version)
}
}
/// @notice Store the batch index of batch header.
/// @dev Because this function can overwrite the subsequent fields, it must be called before
/// `storeL1MessagePopped`, `storeTotalL1MessagePopped`, and `storeDataHash`.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _batchIndex The batch index.
function storeBatchIndex(uint256 batchPtr, uint256 _batchIndex) internal pure {
assembly {
mstore(add(batchPtr, 1), shl(192, _batchIndex))
}
}
/// @notice Store the number of L1 messages popped in current batch to batch header.
/// @dev Because this function can overwrite the subsequent fields, it must be called before
/// `storeTotalL1MessagePopped` and `storeDataHash`.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _l1MessagePopped The number of L1 messages popped in current batch.
function storeL1MessagePopped(uint256 batchPtr, uint256 _l1MessagePopped) internal pure {
assembly {
mstore(add(batchPtr, 9), shl(192, _l1MessagePopped))
}
}
/// @notice Store the total number of L1 messages popped after current batch to batch header.
/// @dev Because this function can overwrite the subsequent fields, it must be called before
/// `storeDataHash`.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _totalL1MessagePopped The total number of L1 messages popped after current batch.
function storeTotalL1MessagePopped(uint256 batchPtr, uint256 _totalL1MessagePopped) internal pure {
assembly {
mstore(add(batchPtr, 17), shl(192, _totalL1MessagePopped))
}
}
/// @notice Store the data hash of batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _dataHash The data hash.
function storeDataHash(uint256 batchPtr, bytes32 _dataHash) internal pure {
assembly {
mstore(add(batchPtr, 25), _dataHash)
}
}
/// @notice Store the parent batch hash of batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _parentBatchHash The parent batch hash.
function storeParentBatchHash(uint256 batchPtr, bytes32 _parentBatchHash) internal pure {
assembly {
mstore(add(batchPtr, 57), _parentBatchHash)
}
}
/// @notice Store the skipped L1 message bitmap of batch header.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param _skippedL1MessageBitmap The skipped L1 message bitmap.
function storeSkippedBitmap(uint256 batchPtr, bytes calldata _skippedL1MessageBitmap) internal pure {
assembly {
calldatacopy(
add(batchPtr, BATCH_HEADER_FIXED_LENGTH),
_skippedL1MessageBitmap.offset,
_skippedL1MessageBitmap.length
)
}
}
/// @notice Compute the batch hash.
/// @dev Caller should make sure that the encoded batch header is correct.
///
/// @param batchPtr The start memory offset of the batch header in memory.
/// @param length The length of the batch.
/// @return _batchHash The hash of the corresponding batch.
function computeBatchHash(uint256 batchPtr, uint256 length) internal pure returns (bytes32 _batchHash) {
// in the current version, the hash is: keccak(BatchHeader without timestamp)
assembly {
_batchHash := keccak256(batchPtr, length)
}
}
}