Skip to content

feat: update block data hint database models #180

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,054 changes: 636 additions & 418 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions crates/codec/src/decoding/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub struct PayloadData {
pub blocks: Vec<L2Block>,
/// Contains information about the current state of the L1 message queue.
pub l1_message_queue_info: L1MessageQueueInfo,
/// Contains the skipped L1 message bitmap if present.
pub skipped_l1_message_bitmap: Option<Vec<u8>>,
}

/// Information about the state of the L1 message queue.
Expand Down
27 changes: 10 additions & 17 deletions crates/codec/src/decoding/v0/batch_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{

use alloy_primitives::{
bytes::{Buf, BufMut},
keccak256, B256, U256,
keccak256, B256,
};

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

impl BatchHeaderV0 {
Expand All @@ -38,7 +38,7 @@ impl BatchHeaderV0 {
total_l1_message_popped: u64,
data_hash: B256,
parent_batch_hash: B256,
skipped_l1_message_bitmap: Vec<U256>,
skipped_l1_message_bitmap: Vec<u8>,
) -> Self {
Self {
version,
Expand Down Expand Up @@ -67,18 +67,16 @@ impl BatchHeaderV0 {
let data_hash = from_slice_and_advance_buf!(B256, buf);
let parent_batch_hash = from_slice_and_advance_buf!(B256, buf);

let skipped_l1_message_bitmap: Vec<_> = buf
.chunks(SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE)
.map(|chunk| U256::from_be_slice(chunk))
.collect();
let skipped_l1_message_bitmap: Vec<_> =
buf.chunks(SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE).flatten().copied().collect();

// check leftover bytes are correct.
if buf.len() as u64 !=
l1_message_popped.div_ceil(256) * SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE as u64
{
return Err(DecodingError::Eof)
}
buf.advance(skipped_l1_message_bitmap.len() * SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE);
buf.advance(skipped_l1_message_bitmap.len());

Ok(Self {
version,
Expand All @@ -104,12 +102,7 @@ impl BatchHeaderV0 {
bytes.put_slice(&self.data_hash.0);
bytes.put_slice(&self.parent_batch_hash.0);

let skipped_l1_message_flat_bitmap = self
.skipped_l1_message_bitmap
.iter()
.flat_map(|u| u.to_be_bytes::<32>())
.collect::<Vec<_>>();
bytes.put_slice(&skipped_l1_message_flat_bitmap);
bytes.put_slice(&self.skipped_l1_message_bitmap);

keccak256(bytes)
}
Expand All @@ -119,7 +112,7 @@ impl BatchHeaderV0 {
mod tests {
use crate::decoding::{test_utils::read_to_bytes, v0::BatchHeaderV0};

use alloy_primitives::{b256, U256};
use alloy_primitives::b256;
use alloy_sol_types::SolCall;
use scroll_l1::abi::calls::commitBatchCall;

Expand All @@ -139,7 +132,7 @@ mod tests {
33,
b256!("2aa3eeb5adebb96a49736583c744b89b0b3be45056e8e178106a42ab2cd1a063"),
b256!("c0173d7e3561501cf57913763c7c34716216092a222a99fe8b85dcb466730f56"),
vec![U256::ZERO],
vec![0; 32],
);
assert_eq!(header, expected);

Expand All @@ -156,7 +149,7 @@ mod tests {
33,
b256!("2aa3eeb5adebb96a49736583c744b89b0b3be45056e8e178106a42ab2cd1a063"),
b256!("c0173d7e3561501cf57913763c7c34716216092a222a99fe8b85dcb466730f56"),
vec![U256::ZERO],
vec![0; 32],
);

let expected = b256!("A7F7C528E1827D3E64E406C76DE6C750D5FC3DE3DE4386E6C69958A89461D064");
Expand Down
7 changes: 5 additions & 2 deletions crates/codec/src/decoding/v0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ pub fn decode_v0(calldata: &[u8]) -> Result<Batch, DecodingError> {
let parent_header = BatchHeaderV0::try_from_buf(&mut (&*raw_parent_header))?;
let l1_message_start_index = parent_header.total_l1_message_popped;

let payload =
PayloadData { blocks: l2_blocks, l1_message_queue_info: l1_message_start_index.into() };
let payload = PayloadData {
blocks: l2_blocks,
l1_message_queue_info: l1_message_start_index.into(),
skipped_l1_message_bitmap: call.skipped_l1_message_bitmap(),
};

Ok(Batch::new(call.version(), Some(chunks_block_count), payload))
}
Expand Down
21 changes: 7 additions & 14 deletions crates/codec/src/decoding/v1/batch_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{

use alloy_primitives::{
bytes::{Buf, BufMut},
keccak256, B256, U256,
keccak256, B256,
};

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

impl BatchHeaderV1 {
Expand All @@ -42,7 +42,7 @@ impl BatchHeaderV1 {
data_hash: B256,
blob_versioned_hash: B256,
parent_batch_hash: B256,
skipped_l1_message_bitmap: Vec<U256>,
skipped_l1_message_bitmap: Vec<u8>,
) -> Self {
Self {
version,
Expand Down Expand Up @@ -73,18 +73,16 @@ impl BatchHeaderV1 {
let blob_versioned_hash = from_slice_and_advance_buf!(B256, buf);
let parent_batch_hash = from_slice_and_advance_buf!(B256, buf);

let skipped_l1_message_bitmap: Vec<_> = buf
.chunks(SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE)
.map(|chunk| U256::from_be_slice(chunk))
.collect();
let skipped_l1_message_bitmap: Vec<_> =
buf.chunks(SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE).flatten().copied().collect();

// check leftover bytes are correct.
if buf.len() as u64 !=
l1_message_popped.div_ceil(256) * SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE as u64
{
return Err(DecodingError::Eof)
}
buf.advance(skipped_l1_message_bitmap.len() * SKIPPED_L1_MESSAGE_BITMAP_ITEM_BYTES_SIZE);
buf.advance(skipped_l1_message_bitmap.len());

Ok(Self {
version,
Expand Down Expand Up @@ -112,12 +110,7 @@ impl BatchHeaderV1 {
bytes.put_slice(&self.blob_versioned_hash.0);
bytes.put_slice(&self.parent_batch_hash.0);

let skipped_l1_message_flat_bitmap = self
.skipped_l1_message_bitmap
.iter()
.flat_map(|u| u.to_be_bytes::<32>())
.collect::<Vec<_>>();
bytes.put_slice(&skipped_l1_message_flat_bitmap);
bytes.put_slice(&self.skipped_l1_message_bitmap);

keccak256(bytes)
}
Expand Down
16 changes: 13 additions & 3 deletions crates/codec/src/decoding/v1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,19 @@ pub fn decode_v1(calldata: &[u8], blob: &[u8]) -> Result<Batch, DecodingError> {
// move pass chunk information.
buf.advance(TRANSACTION_DATA_BLOB_INDEX_OFFSET);

decode_v1_chunk(call.version(), l1_message_start_index, chunks, buf)
decode_v1_chunk(
call.version(),
call.skipped_l1_message_bitmap(),
l1_message_start_index,
chunks,
buf,
)
}

/// Decode the provided chunks and blob data into [`L2Block`].
pub(crate) fn decode_v1_chunk(
version: u8,
skipped_l1_message_bitmap: Option<Vec<u8>>,
l1_message_start_index: u64,
chunks: Vec<&[u8]>,
blob: &[u8],
Expand Down Expand Up @@ -98,8 +105,11 @@ pub(crate) fn decode_v1_chunk(
}
}

let payload =
PayloadData { blocks: l2_blocks, l1_message_queue_info: l1_message_start_index.into() };
let payload = PayloadData {
blocks: l2_blocks,
l1_message_queue_info: l1_message_start_index.into(),
skipped_l1_message_bitmap,
};

Ok(Batch::new(version, Some(chunks_block_count), payload))
}
Expand Down
8 changes: 7 additions & 1 deletion crates/codec/src/decoding/v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,13 @@ pub fn decode_v2(calldata: &[u8], blob: &[u8]) -> Result<Batch, DecodingError> {
// clone buf and move pass chunk information.
buf.advance(TRANSACTION_DATA_BLOB_INDEX_OFFSET);

decode_v1_chunk(call.version(), l1_message_start_index, chunks, buf)
decode_v1_chunk(
call.version(),
call.skipped_l1_message_bitmap(),
l1_message_start_index,
chunks,
buf,
)
}

#[cfg(test)]
Expand Down
8 changes: 7 additions & 1 deletion crates/codec/src/decoding/v4/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ pub fn decode_v4(calldata: &[u8], blob: &[u8]) -> Result<Batch, DecodingError> {
// clone buf and move pass chunk information.
buf.advance(super::v2::TRANSACTION_DATA_BLOB_INDEX_OFFSET);

decode_v1_chunk(call.version(), l1_message_start_index, chunks, buf)
decode_v1_chunk(
call.version(),
call.skipped_l1_message_bitmap(),
l1_message_start_index,
chunks,
buf,
)
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions crates/codec/src/decoding/v7/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub(crate) fn decode_v7_payload(blob: &[u8]) -> Result<Batch, DecodingError> {
let payload = PayloadData {
blocks: l2_blocks,
l1_message_queue_info: (prev_message_queue_hash, post_message_queue_hash).into(),
skipped_l1_message_bitmap: None,
};

Ok(Batch::new(7, None, payload))
Expand Down
19 changes: 13 additions & 6 deletions crates/database/db/src/models/block_data.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use alloy_primitives::U256;
use alloy_primitives::{Address, B256, U256};
use scroll_alloy_rpc_types_engine::BlockDataHint;
use sea_orm::entity::prelude::*;

Expand All @@ -8,9 +8,11 @@ use sea_orm::entity::prelude::*;
pub struct Model {
#[sea_orm(primary_key)]
number: i64,
extra_data: Vec<u8>,
state_root: Vec<u8>,
difficulty: Vec<u8>,
extra_data: Option<Vec<u8>>,
state_root: Option<Vec<u8>>,
coinbase: Option<Vec<u8>>,
nonce: Option<String>,
difficulty: Option<i8>,
}

/// The relation for the extra data model.
Expand All @@ -23,8 +25,13 @@ impl ActiveModelBehavior for ActiveModel {}
impl From<Model> for BlockDataHint {
fn from(value: Model) -> Self {
Self {
extra_data: value.extra_data.into(),
difficulty: U256::from_be_slice(value.difficulty.as_ref()),
extra_data: value.extra_data.map(Into::into),
state_root: value.state_root.map(|s| B256::from_slice(&s)),
coinbase: value.coinbase.as_deref().map(Address::from_slice),
nonce: value.nonce.map(|n| {
u64::from_str_radix(&n, 16).expect("nonce stored as hex string in database")
}),
difficulty: value.difficulty.map(U256::from),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ impl MigrationTrait for Migration {
.table(BlockData::Table)
.if_not_exists()
.col(big_unsigned(BlockData::Number).primary_key())
.col(binary(BlockData::ExtraData))
.col(binary_len(BlockData::StateRoot, 32))
.col(binary_len(BlockData::Difficulty, 32))
.col(binary_null(BlockData::ExtraData))
.col(binary_len_null(BlockData::StateRoot, 32))
.col(binary_len_null(BlockData::Coinbase, 20))
.col(text_null(BlockData::Nonce))
.col(tiny_integer_null(BlockData::Difficulty))
.to_owned(),
)
.await
Expand All @@ -32,5 +34,7 @@ enum BlockData {
Number,
ExtraData,
StateRoot,
Coinbase,
Nonce,
Difficulty,
}
Loading
Loading