Skip to content

Commit dbb9cb0

Browse files
authored
feat: integrate batch changes (#41)
* feat: wip * feat: changes to the data model * fix: codec issue * feat: modify derivation pipeline to fetch blob * test: move test data to file * fix: lints * fix: answer comments * test: fix migration * feat: derivation pipeline (#40) * test: move calldata to files * feat: batch header decoding * feat: improve codec interface * chore: manifests fixes * feat: revert some codec changes * feat: wip derivation pipeline * feat: batch header v7 * feat: add batch abstraction * feat: basic derivation pipeline * feat: implement batch data hash * feat: move PayloadData * feat: improve batch data hash computation * test: derivation * chore: cleaning * fix: lints * fix: lints * fix: skip wasm for derivation pipeline * fix: data hash computation for batch * fix: lint * fix: lint * fix: lints * fix: answer comments * fix: lints * fix: comments
1 parent b1b223e commit dbb9cb0

File tree

23 files changed

+417
-553
lines changed

23 files changed

+417
-553
lines changed

Cargo.lock

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/codec/src/decoding/batch.rs

+5-29
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ impl Batch {
5454
let num_l1_messages = b.context.num_l1_messages as usize;
5555
let block_messages = l1_messages_buf.get(..num_l1_messages).unwrap_or(&[]);
5656
*l1_messages_buf = l1_messages_buf.get(num_l1_messages..).unwrap_or(&[]);
57+
5758
block_messages
5859
})
5960
.collect::<Vec<_>>();
@@ -113,7 +114,7 @@ fn hash_chunk(
113114
mod tests {
114115
use crate::decoding::{test_utils::read_to_bytes, v0::decode_v0, v1::decode_v1};
115116

116-
use alloy_primitives::{address, b256, bytes, U256};
117+
use alloy_primitives::b256;
117118
use scroll_alloy_consensus::TxL1Message;
118119

119120
#[test]
@@ -134,35 +135,10 @@ mod tests {
134135
// <https://etherscan.io/tx/0xdc0a315b25b46f4c1085e3884c63f8ede61e984e47655f7667e5f14e3df55f82>
135136
let raw_calldata = read_to_bytes("./testdata/calldata_v0_with_l1_messages.bin")?;
136137
let batch = decode_v0(&raw_calldata)?;
138+
let l1_messages: Vec<TxL1Message> =
139+
serde_json::from_str(&std::fs::read_to_string("./testdata/l1_messages_v0.json")?)?;
137140

138-
let hash = batch
139-
.try_compute_data_hash(&[
140-
TxL1Message {
141-
queue_index: 39,
142-
gas_limit: 180000,
143-
to: address!("781e90f1c8Fc4611c9b7497C3B47F99Ef6969CbC"),
144-
value: U256::ZERO,
145-
sender: address!("7885BcBd5CeCEf1336b5300fb5186A12DDD8c478"),
146-
input: bytes!("8ef1332e000000000000000000000000f1af3b23de0a5ca3cab7261cb0061c0d779a5c7b00000000000000000000000033b60d5dd260d453cac3782b0bdc01ce846721420000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e48431f5c1000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a4000000000000000000000000c451b0191351ce308fdfd779d73814c910fc5ecb000000000000000000000000c451b0191351ce308fdfd779d73814c910fc5ecb00000000000000000000000000000000000000000000000000000005d21dba0000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
147-
},
148-
TxL1Message {
149-
queue_index: 40,
150-
gas_limit: 168000,
151-
to: address!("781e90f1c8Fc4611c9b7497C3B47F99Ef6969CbC"),
152-
value: U256::ZERO,
153-
sender: address!("7885BcBd5CeCEf1336b5300fb5186A12DDD8c478"),
154-
input: bytes!("8ef1332e0000000000000000000000007f2b8c31f88b6006c382775eea88297ec1e3e9050000000000000000000000006ea73e05adc79974b931123675ea8f78ffdacdf00000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a4232e8748000000000000000000000000b89db2813541287a4dd1fc6801eec30595ecdc6c000000000000000000000000b89db2813541287a4dd1fc6801eec30595ecdc6c0000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
155-
},
156-
TxL1Message {
157-
queue_index: 41,
158-
gas_limit: 168000,
159-
to: address!("781e90f1c8Fc4611c9b7497C3B47F99Ef6969CbC"),
160-
value: U256::ZERO,
161-
sender: address!("7885BcBd5CeCEf1336b5300fb5186A12DDD8c478"),
162-
input: bytes!("8ef1332e0000000000000000000000007f2b8c31f88b6006c382775eea88297ec1e3e9050000000000000000000000006ea73e05adc79974b931123675ea8f78ffdacdf0000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a4232e87480000000000000000000000003219c394111d45757ccb68a4fd353b4f7f9660960000000000000000000000003219c394111d45757ccb68a4fd353b4f7f966096000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
163-
},
164-
])
165-
.unwrap();
141+
let hash = batch.try_compute_data_hash(&l1_messages).unwrap();
166142

167143
assert_eq!(hash, b256!("55fd647c58461d910b5bfb4539f2177ba575c9c8d578a344558976a4375cc287"));
168144

crates/codec/src/error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use alloy_primitives::U256;
2+
13
/// An error occurring during the codec process.
24
#[derive(Debug, thiserror::Error)]
35
pub enum CodecError {
@@ -13,6 +15,8 @@ pub enum DecodingError {
1315
MissingCodecVersion,
1416
#[error("unsupported codec version {0}")]
1517
UnsupportedCodecVersion(u8),
18+
#[error("malformed codec version: {0}")]
19+
MalformedCodecVersion(U256),
1620
#[error("missing blob from data source")]
1721
MissingBlob,
1822
#[error("missing chunk data")]

crates/codec/src/lib.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::decoding::{
1313
};
1414

1515
use alloy_eips::eip4844::Blob;
16-
use alloy_primitives::Bytes;
16+
use alloy_primitives::{ruint::UintTryTo, Bytes, U256};
1717

1818
/// The Codec.
1919
#[derive(Debug)]
@@ -43,7 +43,7 @@ impl Codec {
4343
/// Decodes the input data and returns the decoded [`Batch`].
4444
pub fn decode<T: CommitDataSource>(input: &T) -> Result<Batch, CodecError> {
4545
let calldata = input.calldata();
46-
let version = calldata.first().ok_or(DecodingError::MissingCodecVersion)?;
46+
let version = get_codec_version(calldata)?;
4747

4848
let payload = match version {
4949
0 => decode_v0(calldata)?,
@@ -63,7 +63,7 @@ impl Codec {
6363
let blob = input.blob().ok_or(DecodingError::MissingBlob)?;
6464
decode_v7(blob.as_ref())?
6565
}
66-
v => return Err(DecodingError::UnsupportedCodecVersion(*v).into()),
66+
v => return Err(DecodingError::UnsupportedCodecVersion(v).into()),
6767
};
6868

6969
Ok(payload)
@@ -77,3 +77,23 @@ pub trait CommitDataSource {
7777
/// Returns the blob for decoding.
7878
fn blob(&self) -> Option<&Blob>;
7979
}
80+
81+
/// Returns the codec version from the calldata.
82+
fn get_codec_version(calldata: &[u8]) -> Result<u8, DecodingError> {
83+
const CODEC_VERSION_OFFSET_START: usize = 4;
84+
const CODEC_VERSION_LEN: usize = 32;
85+
const CODEC_VERSION_OFFSET_END: usize = CODEC_VERSION_OFFSET_START + CODEC_VERSION_LEN;
86+
const HIGH_BYTES_MASK: U256 =
87+
U256::from_limbs([u64::MAX, u64::MAX, u64::MAX, 0xffffffffffffff00]);
88+
89+
let version = calldata
90+
.get(CODEC_VERSION_OFFSET_START..CODEC_VERSION_OFFSET_END)
91+
.ok_or(DecodingError::Eof)?;
92+
let version = U256::from_be_slice(version);
93+
94+
if (version & HIGH_BYTES_MASK) != U256::ZERO {
95+
return Err(DecodingError::MalformedCodecVersion(version))
96+
}
97+
98+
Ok(version.uint_try_to().expect("fits in single byte"))
99+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[
2+
{
3+
"queueIndex": "39",
4+
"gas": "180000",
5+
"to": "0x781e90f1c8fc4611c9b7497c3b47f99ef6969cbc",
6+
"value": "0x0",
7+
"sender": "0x7885bcbd5cecef1336b5300fb5186a12ddd8c478",
8+
"input": "8ef1332e000000000000000000000000f1af3b23de0a5ca3cab7261cb0061c0d779a5c7b00000000000000000000000033b60d5dd260d453cac3782b0bdc01ce846721420000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e48431f5c1000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a4000000000000000000000000c451b0191351ce308fdfd779d73814c910fc5ecb000000000000000000000000c451b0191351ce308fdfd779d73814c910fc5ecb00000000000000000000000000000000000000000000000000000005d21dba0000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
9+
},
10+
{
11+
"queueIndex": "40",
12+
"gas": "168000",
13+
"to": "0x781e90f1c8fc4611c9b7497c3b47f99ef6969cbc",
14+
"value": "0x0",
15+
"sender": "0x7885bcbd5cecef1336b5300fb5186a12ddd8c478",
16+
"input": "8ef1332e0000000000000000000000007f2b8c31f88b6006c382775eea88297ec1e3e9050000000000000000000000006ea73e05adc79974b931123675ea8f78ffdacdf00000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a4232e8748000000000000000000000000b89db2813541287a4dd1fc6801eec30595ecdc6c000000000000000000000000b89db2813541287a4dd1fc6801eec30595ecdc6c0000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
17+
},
18+
{
19+
"queueIndex": "41",
20+
"gas": "168000",
21+
"to": "0x781e90f1c8fc4611c9b7497c3b47f99ef6969cbc",
22+
"value": "0x0",
23+
"sender": "0x7885bcbd5cecef1336b5300fb5186a12ddd8c478",
24+
"input": "8ef1332e0000000000000000000000007f2b8c31f88b6006c382775eea88297ec1e3e9050000000000000000000000006ea73e05adc79974b931123675ea8f78ffdacdf0000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a4232e87480000000000000000000000003219c394111d45757ccb68a4fd353b4f7f9660960000000000000000000000003219c394111d45757ccb68a4fd353b4f7f966096000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
25+
}
26+
]

crates/database/db/src/db.rs

+8-20
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,14 @@ impl From<DatabaseConnection> for Database {
4646
#[cfg(test)]
4747
mod test {
4848
use crate::{operations::DatabaseOperations, test_utils::setup_test_db};
49+
4950
use arbitrary::{Arbitrary, Unstructured};
5051
use futures::StreamExt;
5152
use rand::Rng;
52-
use rollup_node_primitives::{
53-
BatchInput, BatchInputV1, BatchInputV2, L1MessageWithBlockNumber,
54-
};
53+
use rollup_node_primitives::{BatchCommitData, L1MessageWithBlockNumber};
5554

5655
#[tokio::test]
57-
async fn test_database_round_trip_batch_input() {
56+
async fn test_database_round_trip_batch_commit() {
5857
// Set up the test database.
5958
let db = setup_test_db().await;
6059

@@ -64,24 +63,13 @@ mod test {
6463
let mut u = Unstructured::new(&bytes);
6564

6665
// Generate a random BatchInputV1.
67-
let batch_input_v1 = BatchInputV1::arbitrary(&mut u).unwrap();
68-
let batch_input = BatchInput::BatchInputDataV1(batch_input_v1);
69-
70-
// Round trip the BatchInput through the database.
71-
db.insert_batch_input(batch_input.clone()).await.unwrap();
72-
let batch_input_from_db =
73-
db.get_batch_input_by_batch_index(batch_input.batch_index()).await.unwrap().unwrap();
74-
assert_eq!(batch_input, batch_input_from_db);
75-
76-
// Generate a random BatchInputV2.
77-
let batch_input_v2 = BatchInputV2::arbitrary(&mut u).unwrap();
78-
let batch_input = BatchInput::BatchInputDataV2(batch_input_v2);
66+
let batch_commit = BatchCommitData::arbitrary(&mut u).unwrap();
7967

8068
// Round trip the BatchInput through the database.
81-
db.insert_batch_input(batch_input.clone()).await.unwrap();
82-
let batch_input_from_db =
83-
db.get_batch_input_by_batch_index(batch_input.batch_index()).await.unwrap().unwrap();
84-
assert_eq!(batch_input, batch_input_from_db);
69+
db.insert_batch(batch_commit.clone()).await.unwrap();
70+
let batch_commit_from_db =
71+
db.get_batch_by_index(batch_commit.index).await.unwrap().unwrap();
72+
assert_eq!(batch_commit, batch_commit_from_db);
8573
}
8674

8775
#[tokio::test]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use std::sync::Arc;
2+
3+
use rollup_node_primitives::BatchCommitData;
4+
use sea_orm::{entity::prelude::*, ActiveValue};
5+
6+
/// A database model that represents a batch input.
7+
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
8+
#[sea_orm(table_name = "batch_commit")]
9+
pub struct Model {
10+
#[sea_orm(primary_key)]
11+
index: i64,
12+
hash: Vec<u8>,
13+
block_number: i64,
14+
calldata: Vec<u8>,
15+
blob_hash: Option<Vec<u8>>,
16+
finalized_block_number: Option<i64>,
17+
}
18+
19+
/// The relation for the batch input model.
20+
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
21+
pub enum Relation {}
22+
23+
/// The active model behavior for the batch input model.
24+
impl ActiveModelBehavior for ActiveModel {}
25+
26+
impl From<BatchCommitData> for ActiveModel {
27+
fn from(batch_commit: BatchCommitData) -> Self {
28+
Self {
29+
index: ActiveValue::Set(
30+
batch_commit.index.try_into().expect("index should fit in i64"),
31+
),
32+
hash: ActiveValue::Set(batch_commit.hash.to_vec()),
33+
block_number: ActiveValue::Set(
34+
batch_commit.block_number.try_into().expect("block number should fit in i64"),
35+
),
36+
calldata: ActiveValue::Set(batch_commit.calldata.0.to_vec()),
37+
blob_hash: ActiveValue::Set(batch_commit.blob_versioned_hash.map(|b| b.to_vec())),
38+
finalized_block_number: ActiveValue::Unchanged(None),
39+
}
40+
}
41+
}
42+
43+
impl From<Model> for BatchCommitData {
44+
fn from(value: Model) -> Self {
45+
Self {
46+
hash: value.hash.as_slice().try_into().expect("data persisted in database is valid"),
47+
index: value.index as u64,
48+
block_number: value.block_number as u64,
49+
calldata: Arc::new(value.calldata.into()),
50+
blob_versioned_hash: value
51+
.blob_hash
52+
.map(|b| b.as_slice().try_into().expect("data persisted in database is valid")),
53+
}
54+
}
55+
}

crates/database/db/src/models/batch_input.rs

-105
This file was deleted.

crates/database/db/src/models/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
/// This module contains the batch input database model.
2-
pub mod batch_input;
1+
/// This module contains the batch commit database model.
2+
pub mod batch_commit;
33

44
/// This module contains the L1 message database model.
55
pub mod l1_message;

0 commit comments

Comments
 (0)