From 006e813dda3fa223757ab07eab7b2ea18b52e5f3 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Fri, 18 Oct 2024 02:02:57 +0000 Subject: [PATCH 1/4] enable blob slice to support multi-blocks in single blob --- lib/src/builder.rs | 2 +- lib/src/input.rs | 16 +++++++++++++++- lib/src/utils.rs | 41 +++++++++++++++++++++++++++++------------ 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/lib/src/builder.rs b/lib/src/builder.rs index b60be8f00..7e3a221a8 100644 --- a/lib/src/builder.rs +++ b/lib/src/builder.rs @@ -131,7 +131,7 @@ impl + DatabaseCommit + OptimisticDatabase> let mut block = self.input.block.clone(); block.body = generate_transactions( &self.input.chain_spec, - self.input.taiko.block_proposed.blob_used(), + &self.input.taiko.block_proposed, &self.input.taiko.tx_data, &self.input.taiko.anchor_tx, ); diff --git a/lib/src/input.rs b/lib/src/input.rs index bb9c9ed9b..8257955fb 100644 --- a/lib/src/input.rs +++ b/lib/src/input.rs @@ -13,7 +13,10 @@ use serde_with::serde_as; #[cfg(not(feature = "std"))] use crate::no_std::*; use crate::{ - consts::ChainSpec, primitives::mpt::MptNode, prover::Proof, utils::zlib_compress_data, + consts::ChainSpec, + primitives::mpt::MptNode, + prover::Proof, + utils::{self, zlib_compress_data}, }; /// Represents the state of an account's storage. @@ -139,6 +142,17 @@ impl BlockProposedFork { _ => ProtocolBaseFeeConfig::default(), } } + + pub fn blob_tx_slice_param(&self) -> (usize, usize) { + match self { + BlockProposedFork::Hekla(_) => (0, utils::BLOB_DATA_CAPACITY), + BlockProposedFork::Ontake(block) => ( + block.meta.blobTxListOffset as usize, + block.meta.blobTxListLength as usize, + ), + _ => (0, utils::BLOB_DATA_CAPACITY), + } + } } #[serde_as] diff --git a/lib/src/utils.rs b/lib/src/utils.rs index 1fd370103..2ab73817c 100644 --- a/lib/src/utils.rs +++ b/lib/src/utils.rs @@ -4,9 +4,10 @@ use alloy_rlp::Decodable; use anyhow::Result; use libflate::zlib::{Decoder as zlibDecoder, Encoder as zlibEncoder}; use reth_primitives::TransactionSigned; -use tracing::warn; +use tracing::{error, warn}; use crate::consts::{ChainSpec, Network}; +use crate::input::BlockProposedFork; #[cfg(not(feature = "std"))] use crate::no_std::*; @@ -24,16 +25,22 @@ fn validate_calldata_tx_list(tx_list: &[u8]) -> bool { tx_list.len() <= CALL_DATA_CAPACITY } -fn get_tx_list(chain_spec: &ChainSpec, is_blob_data: bool, tx_list: &[u8]) -> Vec { +fn unzip_tx_list_from_data_buf( + chain_spec: &ChainSpec, + is_blob_data: bool, + offset: usize, + length: usize, + tx_list_data_buf: &[u8], +) -> Vec { #[allow(clippy::collapsible_else_if)] if chain_spec.is_taiko() { // taiko has some limitations to be aligned with taiko-client if is_blob_data { - let compressed_tx_list = decode_blob_data(tx_list); - zlib_decompress_data(&compressed_tx_list).unwrap_or_default() + let compressed_tx_list = decode_blob_data(tx_list_data_buf); + zlib_decompress_data(&compressed_tx_list[offset..offset + length]).unwrap_or_default() } else { if Network::TaikoA7.to_string() == chain_spec.network() { - let tx_list = zlib_decompress_data(tx_list).unwrap_or_default(); + let tx_list = zlib_decompress_data(tx_list_data_buf).unwrap_or_default(); if validate_calldata_tx_list(&tx_list) { tx_list } else { @@ -41,8 +48,8 @@ fn get_tx_list(chain_spec: &ChainSpec, is_blob_data: bool, tx_list: &[u8]) -> Ve vec![] } } else { - if validate_calldata_tx_list(tx_list) { - zlib_decompress_data(tx_list).unwrap_or_default() + if validate_calldata_tx_list(tx_list_data_buf) { + zlib_decompress_data(tx_list_data_buf).unwrap_or_default() } else { warn!("validate_calldata_tx_list failed, use empty tx_list"); vec![] @@ -51,20 +58,30 @@ fn get_tx_list(chain_spec: &ChainSpec, is_blob_data: bool, tx_list: &[u8]) -> Ve } } else { // no limitation on non-taiko chains - zlib_decompress_data(tx_list).unwrap_or_default() + zlib_decompress_data(tx_list_data_buf).unwrap_or_default() } } pub fn generate_transactions( chain_spec: &ChainSpec, - is_blob_data: bool, - tx_list: &[u8], + // is_blob_data: bool, + block_proposal: &BlockProposedFork, + tx_list_data_buf: &[u8], anchor_tx: &Option, ) -> Vec { + let is_blob_data = block_proposal.blob_used(); + let (offset, length) = block_proposal.blob_tx_slice_param(); + if (offset + length) as u32 > BLOB_DATA_CAPACITY as u32 { + error!( + "BlobTxListOffset: {offset} + BlobTxListLength: {length} exceeds capacity: {BLOB_DATA_CAPACITY}" + ); + return vec![]; + } // Decode the tx list from the raw data posted onchain - let tx_list = get_tx_list(chain_spec, is_blob_data, tx_list); + let unzip_tx_list_buf = + unzip_tx_list_from_data_buf(chain_spec, is_blob_data, offset, length, tx_list_data_buf); // Decode the transactions from the tx list - let mut transactions = decode_transactions(&tx_list); + let mut transactions = decode_transactions(&unzip_tx_list_buf); // Add the anchor tx at the start of the list if let Some(anchor_tx) = anchor_tx { transactions.insert(0, anchor_tx.clone()); From cb456713f105cf9fc4cc84d5fe6e2ecf46acd23e Mon Sep 17 00:00:00 2001 From: smtmfft Date: Fri, 18 Oct 2024 07:58:08 +0000 Subject: [PATCH 2/4] fix compile --- lib/src/input.rs | 6 +++--- lib/src/utils.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/input.rs b/lib/src/input.rs index 8257955fb..9ccc7665a 100644 --- a/lib/src/input.rs +++ b/lib/src/input.rs @@ -16,7 +16,7 @@ use crate::{ consts::ChainSpec, primitives::mpt::MptNode, prover::Proof, - utils::{self, zlib_compress_data}, + utils::{zlib_compress_data, BLOB_DATA_CAPACITY}, }; /// Represents the state of an account's storage. @@ -145,12 +145,12 @@ impl BlockProposedFork { pub fn blob_tx_slice_param(&self) -> (usize, usize) { match self { - BlockProposedFork::Hekla(_) => (0, utils::BLOB_DATA_CAPACITY), + BlockProposedFork::Hekla(_) => (0, BLOB_DATA_CAPACITY), BlockProposedFork::Ontake(block) => ( block.meta.blobTxListOffset as usize, block.meta.blobTxListLength as usize, ), - _ => (0, utils::BLOB_DATA_CAPACITY), + _ => (0, BLOB_DATA_CAPACITY), } } } diff --git a/lib/src/utils.rs b/lib/src/utils.rs index 2ab73817c..c3a14ae71 100644 --- a/lib/src/utils.rs +++ b/lib/src/utils.rs @@ -91,7 +91,7 @@ pub fn generate_transactions( const BLOB_FIELD_ELEMENT_NUM: usize = 4096; const BLOB_FIELD_ELEMENT_BYTES: usize = 32; -const BLOB_DATA_CAPACITY: usize = BLOB_FIELD_ELEMENT_NUM * BLOB_FIELD_ELEMENT_BYTES; +pub(crate) const BLOB_DATA_CAPACITY: usize = BLOB_FIELD_ELEMENT_NUM * BLOB_FIELD_ELEMENT_BYTES; // max call data bytes const CALL_DATA_CAPACITY: usize = BLOB_FIELD_ELEMENT_NUM * (BLOB_FIELD_ELEMENT_BYTES - 1); const BLOB_VERSION_OFFSET: usize = 1; From f0eaeaa9d784fb1358154d77b501205e305c1a53 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Fri, 18 Oct 2024 09:44:41 +0000 Subject: [PATCH 3/4] refine tx_list slice --- lib/src/input.rs | 14 +++++--------- lib/src/utils.rs | 28 ++++++++++++++++------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/src/input.rs b/lib/src/input.rs index 9ccc7665a..d6f4b3438 100644 --- a/lib/src/input.rs +++ b/lib/src/input.rs @@ -13,10 +13,7 @@ use serde_with::serde_as; #[cfg(not(feature = "std"))] use crate::no_std::*; use crate::{ - consts::ChainSpec, - primitives::mpt::MptNode, - prover::Proof, - utils::{zlib_compress_data, BLOB_DATA_CAPACITY}, + consts::ChainSpec, primitives::mpt::MptNode, prover::Proof, utils::zlib_compress_data, }; /// Represents the state of an account's storage. @@ -143,14 +140,13 @@ impl BlockProposedFork { } } - pub fn blob_tx_slice_param(&self) -> (usize, usize) { + pub fn blob_tx_slice_param(&self) -> Option<(usize, usize)> { match self { - BlockProposedFork::Hekla(_) => (0, BLOB_DATA_CAPACITY), - BlockProposedFork::Ontake(block) => ( + BlockProposedFork::Ontake(block) => Some(( block.meta.blobTxListOffset as usize, block.meta.blobTxListLength as usize, - ), - _ => (0, BLOB_DATA_CAPACITY), + )), + _ => None, } } } diff --git a/lib/src/utils.rs b/lib/src/utils.rs index c3a14ae71..92f8171a2 100644 --- a/lib/src/utils.rs +++ b/lib/src/utils.rs @@ -28,8 +28,7 @@ fn validate_calldata_tx_list(tx_list: &[u8]) -> bool { fn unzip_tx_list_from_data_buf( chain_spec: &ChainSpec, is_blob_data: bool, - offset: usize, - length: usize, + blob_slice_param: Option<(usize, usize)>, tx_list_data_buf: &[u8], ) -> Vec { #[allow(clippy::collapsible_else_if)] @@ -37,7 +36,18 @@ fn unzip_tx_list_from_data_buf( // taiko has some limitations to be aligned with taiko-client if is_blob_data { let compressed_tx_list = decode_blob_data(tx_list_data_buf); - zlib_decompress_data(&compressed_tx_list[offset..offset + length]).unwrap_or_default() + assert!(compressed_tx_list.len() <= MAX_BLOB_DATA_SIZE); + let slice_compressed_tx_list = if let Some((offset, length)) = blob_slice_param { + if offset + length > compressed_tx_list.len() { + error!("blob_slice_param ({offset},{length}) out of range, use empty tx_list"); + vec![] + } else { + compressed_tx_list[offset..offset + length].to_vec() + } + } else { + compressed_tx_list.to_vec() + }; + zlib_decompress_data(&slice_compressed_tx_list).unwrap_or_default() } else { if Network::TaikoA7.to_string() == chain_spec.network() { let tx_list = zlib_decompress_data(tx_list_data_buf).unwrap_or_default(); @@ -70,16 +80,10 @@ pub fn generate_transactions( anchor_tx: &Option, ) -> Vec { let is_blob_data = block_proposal.blob_used(); - let (offset, length) = block_proposal.blob_tx_slice_param(); - if (offset + length) as u32 > BLOB_DATA_CAPACITY as u32 { - error!( - "BlobTxListOffset: {offset} + BlobTxListLength: {length} exceeds capacity: {BLOB_DATA_CAPACITY}" - ); - return vec![]; - } + let blob_slice_param = block_proposal.blob_tx_slice_param(); // Decode the tx list from the raw data posted onchain let unzip_tx_list_buf = - unzip_tx_list_from_data_buf(chain_spec, is_blob_data, offset, length, tx_list_data_buf); + unzip_tx_list_from_data_buf(chain_spec, is_blob_data, blob_slice_param, tx_list_data_buf); // Decode the transactions from the tx list let mut transactions = decode_transactions(&unzip_tx_list_buf); // Add the anchor tx at the start of the list @@ -91,7 +95,7 @@ pub fn generate_transactions( const BLOB_FIELD_ELEMENT_NUM: usize = 4096; const BLOB_FIELD_ELEMENT_BYTES: usize = 32; -pub(crate) const BLOB_DATA_CAPACITY: usize = BLOB_FIELD_ELEMENT_NUM * BLOB_FIELD_ELEMENT_BYTES; +const BLOB_DATA_CAPACITY: usize = BLOB_FIELD_ELEMENT_NUM * BLOB_FIELD_ELEMENT_BYTES; // max call data bytes const CALL_DATA_CAPACITY: usize = BLOB_FIELD_ELEMENT_NUM * (BLOB_FIELD_ELEMENT_BYTES - 1); const BLOB_VERSION_OFFSET: usize = 1; From 7877624cc0a35bc2e4ee5a9b0a7705c9b7d888f6 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Fri, 18 Oct 2024 09:48:36 +0000 Subject: [PATCH 4/4] code clean --- lib/src/utils.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/utils.rs b/lib/src/utils.rs index 92f8171a2..5a9ec9fc8 100644 --- a/lib/src/utils.rs +++ b/lib/src/utils.rs @@ -74,7 +74,6 @@ fn unzip_tx_list_from_data_buf( pub fn generate_transactions( chain_spec: &ChainSpec, - // is_blob_data: bool, block_proposal: &BlockProposedFork, tx_list_data_buf: &[u8], anchor_tx: &Option,