Skip to content

Commit 84ba25d

Browse files
authored
feat: skipped l1 messages bitmap (#186)
1 parent ae209ae commit 84ba25d

File tree

12 files changed

+179
-39
lines changed

12 files changed

+179
-39
lines changed

crates/codec/src/decoding/payload.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub struct PayloadData {
1111
pub blocks: Vec<L2Block>,
1212
/// Contains information about the current state of the L1 message queue.
1313
pub l1_message_queue_info: L1MessageQueueInfo,
14+
/// Contains the skipped L1 message bitmap if present.
15+
pub skipped_l1_message_bitmap: Option<Vec<u8>>,
1416
}
1517

1618
/// Information about the state of the L1 message queue.

crates/codec/src/decoding/v0/batch_header.rs

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55

66
use alloy_primitives::{
77
bytes::{Buf, BufMut},
8-
keccak256, B256, U256,
8+
keccak256, B256,
99
};
1010

1111
/// The batch header for V0.
@@ -24,7 +24,7 @@ pub struct BatchHeaderV0 {
2424
/// The parent batch hash.
2525
pub parent_batch_hash: B256,
2626
/// A bitmap to indicate which L1 messages are skipped in the batch.
27-
pub skipped_l1_message_bitmap: Vec<U256>,
27+
pub skipped_l1_message_bitmap: Vec<u8>,
2828
}
2929

3030
impl BatchHeaderV0 {
@@ -38,7 +38,7 @@ impl BatchHeaderV0 {
3838
total_l1_message_popped: u64,
3939
data_hash: B256,
4040
parent_batch_hash: B256,
41-
skipped_l1_message_bitmap: Vec<U256>,
41+
skipped_l1_message_bitmap: Vec<u8>,
4242
) -> Self {
4343
Self {
4444
version,
@@ -69,7 +69,9 @@ impl BatchHeaderV0 {
6969

7070
let skipped_l1_message_bitmap: Vec<_> = buf
7171
.chunks(SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE)
72-
.map(|chunk| U256::from_be_slice(chunk))
72+
.flatten()
73+
.rev()
74+
.copied()
7375
.collect();
7476

7577
// check leftover bytes are correct.
@@ -78,7 +80,7 @@ impl BatchHeaderV0 {
7880
{
7981
return Err(DecodingError::Eof)
8082
}
81-
buf.advance(skipped_l1_message_bitmap.len() * SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE);
83+
buf.advance(skipped_l1_message_bitmap.len());
8284

8385
Ok(Self {
8486
version,
@@ -104,12 +106,7 @@ impl BatchHeaderV0 {
104106
bytes.put_slice(&self.data_hash.0);
105107
bytes.put_slice(&self.parent_batch_hash.0);
106108

107-
let skipped_l1_message_flat_bitmap = self
108-
.skipped_l1_message_bitmap
109-
.iter()
110-
.flat_map(|u| u.to_be_bytes::<32>())
111-
.collect::<Vec<_>>();
112-
bytes.put_slice(&skipped_l1_message_flat_bitmap);
109+
bytes.put_slice(&self.skipped_l1_message_bitmap);
113110

114111
keccak256(bytes)
115112
}
@@ -119,7 +116,7 @@ impl BatchHeaderV0 {
119116
mod tests {
120117
use crate::decoding::{test_utils::read_to_bytes, v0::BatchHeaderV0};
121118

122-
use alloy_primitives::{b256, U256};
119+
use alloy_primitives::b256;
123120
use alloy_sol_types::SolCall;
124121
use scroll_l1::abi::calls::commitBatchCall;
125122

@@ -139,7 +136,34 @@ mod tests {
139136
33,
140137
b256!("2aa3eeb5adebb96a49736583c744b89b0b3be45056e8e178106a42ab2cd1a063"),
141138
b256!("c0173d7e3561501cf57913763c7c34716216092a222a99fe8b85dcb466730f56"),
142-
vec![U256::ZERO],
139+
vec![0; 32],
140+
);
141+
assert_eq!(header, expected);
142+
143+
Ok(())
144+
}
145+
146+
#[test]
147+
fn test_should_decode_header_with_skipped_l1_messages() -> eyre::Result<()> {
148+
// <https://sepolia.etherscan.io/tx/0xacacfe48bed1944d6586ca8f0bec3ecd10ea0a99e104517f75845b8602dcab31>
149+
let raw_commit_calldata =
150+
read_to_bytes("./testdata/calldata_v0_with_skipped_l1_messages.bin")?;
151+
let commit_calldata = commitBatchCall::abi_decode(&raw_commit_calldata)?;
152+
153+
let mut raw_batch_header = &*commit_calldata.parent_batch_header.to_vec();
154+
let header = BatchHeaderV0::try_from_buf(&mut raw_batch_header)?;
155+
156+
let expected = BatchHeaderV0::new(
157+
0,
158+
100,
159+
3,
160+
22,
161+
b256!("4867e8b3c751abf5f0f8cd8e3e91f78ff15011b48b981ad742cb42dfd746844c"),
162+
b256!("b4d0a673c704d567eebcd758802ce87cf103b16acbae7c52b2807928fd8dc76e"),
163+
vec![
164+
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
165+
0, 0, 0, 0,
166+
],
143167
);
144168
assert_eq!(header, expected);
145169

@@ -156,7 +180,7 @@ mod tests {
156180
33,
157181
b256!("2aa3eeb5adebb96a49736583c744b89b0b3be45056e8e178106a42ab2cd1a063"),
158182
b256!("c0173d7e3561501cf57913763c7c34716216092a222a99fe8b85dcb466730f56"),
159-
vec![U256::ZERO],
183+
vec![0; 32],
160184
);
161185

162186
let expected = b256!("A7F7C528E1827D3E64E406C76DE6C750D5FC3DE3DE4386E6C69958A89461D064");

crates/codec/src/decoding/v0/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ pub fn decode_v0(calldata: &[u8]) -> Result<Batch, DecodingError> {
6161
let parent_header = BatchHeaderV0::try_from_buf(&mut (&*raw_parent_header))?;
6262
let l1_message_start_index = parent_header.total_l1_message_popped;
6363

64-
let payload =
65-
PayloadData { blocks: l2_blocks, l1_message_queue_info: l1_message_start_index.into() };
64+
let payload = PayloadData {
65+
blocks: l2_blocks,
66+
l1_message_queue_info: l1_message_start_index.into(),
67+
skipped_l1_message_bitmap: call.skipped_l1_message_bitmap(),
68+
};
6669

6770
Ok(Batch::new(call.version(), Some(chunks_block_count), payload))
6871
}

crates/codec/src/decoding/v1/batch_header.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55

66
use alloy_primitives::{
77
bytes::{Buf, BufMut},
8-
keccak256, B256, U256,
8+
keccak256, B256,
99
};
1010

1111
/// The batch header for V1.
@@ -26,7 +26,7 @@ pub struct BatchHeaderV1 {
2626
/// The parent batch hash.
2727
pub parent_batch_hash: B256,
2828
/// A bitmap to indicate which L1 messages are skipped in the batch.
29-
pub skipped_l1_message_bitmap: Vec<U256>,
29+
pub skipped_l1_message_bitmap: Vec<u8>,
3030
}
3131

3232
impl BatchHeaderV1 {
@@ -42,7 +42,7 @@ impl BatchHeaderV1 {
4242
data_hash: B256,
4343
blob_versioned_hash: B256,
4444
parent_batch_hash: B256,
45-
skipped_l1_message_bitmap: Vec<U256>,
45+
skipped_l1_message_bitmap: Vec<u8>,
4646
) -> Self {
4747
Self {
4848
version,
@@ -75,7 +75,9 @@ impl BatchHeaderV1 {
7575

7676
let skipped_l1_message_bitmap: Vec<_> = buf
7777
.chunks(SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE)
78-
.map(|chunk| U256::from_be_slice(chunk))
78+
.flatten()
79+
.rev()
80+
.copied()
7981
.collect();
8082

8183
// check leftover bytes are correct.
@@ -84,7 +86,7 @@ impl BatchHeaderV1 {
8486
{
8587
return Err(DecodingError::Eof)
8688
}
87-
buf.advance(skipped_l1_message_bitmap.len() * SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE);
89+
buf.advance(skipped_l1_message_bitmap.len());
8890

8991
Ok(Self {
9092
version,
@@ -112,12 +114,7 @@ impl BatchHeaderV1 {
112114
bytes.put_slice(&self.blob_versioned_hash.0);
113115
bytes.put_slice(&self.parent_batch_hash.0);
114116

115-
let skipped_l1_message_flat_bitmap = self
116-
.skipped_l1_message_bitmap
117-
.iter()
118-
.flat_map(|u| u.to_be_bytes::<32>())
119-
.collect::<Vec<_>>();
120-
bytes.put_slice(&skipped_l1_message_flat_bitmap);
117+
bytes.put_slice(&self.skipped_l1_message_bitmap);
121118

122119
keccak256(bytes)
123120
}

crates/codec/src/decoding/v1/mod.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,19 @@ pub fn decode_v1(calldata: &[u8], blob: &[u8]) -> Result<Batch, DecodingError> {
5252
// move pass chunk information.
5353
buf.advance(TRANSACTION_DATA_BLOB_INDEX_OFFSET);
5454

55-
decode_v1_chunk(call.version(), l1_message_start_index, chunks, buf)
55+
decode_v1_chunk(
56+
call.version(),
57+
call.skipped_l1_message_bitmap(),
58+
l1_message_start_index,
59+
chunks,
60+
buf,
61+
)
5662
}
5763

5864
/// Decode the provided chunks and blob data into [`L2Block`].
5965
pub(crate) fn decode_v1_chunk(
6066
version: u8,
67+
skipped_l1_message_bitmap: Option<Vec<u8>>,
6168
l1_message_start_index: u64,
6269
chunks: Vec<&[u8]>,
6370
blob: &[u8],
@@ -98,8 +105,11 @@ pub(crate) fn decode_v1_chunk(
98105
}
99106
}
100107

101-
let payload =
102-
PayloadData { blocks: l2_blocks, l1_message_queue_info: l1_message_start_index.into() };
108+
let payload = PayloadData {
109+
blocks: l2_blocks,
110+
l1_message_queue_info: l1_message_start_index.into(),
111+
skipped_l1_message_bitmap,
112+
};
103113

104114
Ok(Batch::new(version, Some(chunks_block_count), payload))
105115
}

crates/codec/src/decoding/v2/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ pub fn decode_v2(calldata: &[u8], blob: &[u8]) -> Result<Batch, DecodingError> {
5050
// clone buf and move pass chunk information.
5151
buf.advance(TRANSACTION_DATA_BLOB_INDEX_OFFSET);
5252

53-
decode_v1_chunk(call.version(), l1_message_start_index, chunks, buf)
53+
decode_v1_chunk(
54+
call.version(),
55+
call.skipped_l1_message_bitmap(),
56+
l1_message_start_index,
57+
chunks,
58+
buf,
59+
)
5460
}
5561

5662
#[cfg(test)]

crates/codec/src/decoding/v4/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ pub fn decode_v4(calldata: &[u8], blob: &[u8]) -> Result<Batch, DecodingError> {
4646
// clone buf and move pass chunk information.
4747
buf.advance(super::v2::TRANSACTION_DATA_BLOB_INDEX_OFFSET);
4848

49-
decode_v1_chunk(call.version(), l1_message_start_index, chunks, buf)
49+
decode_v1_chunk(
50+
call.version(),
51+
call.skipped_l1_message_bitmap(),
52+
l1_message_start_index,
53+
chunks,
54+
buf,
55+
)
5056
}
5157

5258
#[cfg(test)]

crates/codec/src/decoding/v7/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ pub(crate) fn decode_v7_payload(blob: &[u8]) -> Result<Batch, DecodingError> {
9797
let payload = PayloadData {
9898
blocks: l2_blocks,
9999
l1_message_queue_info: (prev_message_queue_hash, post_message_queue_hash).into(),
100+
skipped_l1_message_bitmap: None,
100101
};
101102

102103
Ok(Batch::new(7, None, payload))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0x1325aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000079000000000000000064000000000000000300000000000000164867e8b3c751abf5f0f8cd8e3e91f78ff15011b48b981ad742cb42dfd746844cb4d0a673c704d567eebcd758802ce87cf103b16acbae7c52b2807928fd8dc76e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000ce0100000000000003110000000064d18d75000000000000000000000000000000000000000000000000000000000000000000000000007a1200000100000000008df88b82021c830f424082ce1d94530000000000000000000000000000000000000280a4bede39b5000000000000000000000000000000000000000000000000000000000b0528c183104ec1a0efedcf8b129a97dcf5142d6b3d0da93033c0cc8815057534bbd009ea93ffa64ca00b9381c46f1869b7eb722dc505fb3c1f4d6883aacb4a046003dedebf6e0ffba200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce0100000000000003120000000064d18d87000000000000000000000000000000000000000000000000000000000000000000000000007a1200000100000000008df88b82021d830f424082ce1d94530000000000000000000000000000000000000280a4bede39b5000000000000000000000000000000000000000000000000000000000bbd974583104ec2a00b4b682ac0013ace0bf6ce2ff006908e83dfbd08e511ab1c631e0335b76dbd94a03d49506aed45459656e9176188dbb7524278a273c156619785c3867d5c6ae07d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce0100000000000003130000000064d18efb000000000000000000000000000000000000000000000000000000000000000000000000007a1200000100000000008df88b82021e830f424082ce1d94530000000000000000000000000000000000000280a4bede39b5000000000000000000000000000000000000000000000000000000000aff8de183104ec1a082410e24156d5837934e3e9628dac3f995de69eda6789e2bbe1a082d2b063b80a01bdbcb384b9ff032cbb1f806864b6cc359e1f4b5e7eed58b966241e7819e1ac900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce0100000000000003140000000064d18f04000000000000000000000000000000000000000000000000000000000000000000000000007a1200000100000000008df88b82021f830f424082ce1d94530000000000000000000000000000000000000280a4bede39b500000000000000000000000000000000000000000000000000000000099bd5e283104ec1a0317f5c505edf2e836cc92e33f62e8629ca355788bdc35e618fb46dbe8c06ff3ba00bd9d475ebb7a4be4423d7d6576280757f5e9e1fe8622fce33e0f04fce445f52000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003d0100000000000003150000000064d19066000000000000000000000000000000000000000000000000000000000000000000000000007a12000001000100000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000

0 commit comments

Comments
 (0)