From e59614d727bfa5f4c318afdc58d4aaa6bea75b71 Mon Sep 17 00:00:00 2001 From: Akase Haruka Date: Tue, 4 Mar 2025 16:41:12 +0800 Subject: [PATCH] feat: portable sbv-primitives (#89) * feat: add EIP-7702 tx support (#85) * upgrade * upgrade * Update Cargo.toml * change branches * remove poseidon field * fix scroll types * trailing lf * feat: dump utils (#83) * provide utils lib * clippy * unify imports * fix * style fix * add EIP-7702 tx support * upgrade reth --------- Co-authored-by: Zhang Zhuo * feat: msg queue hash (#84) * upgrade * upgrade * Update Cargo.toml * change branches * remove poseidon field * fix scroll types * trailing lf * feat: dump utils (#83) * provide utils lib * clippy * unify imports * fix * style fix * impl msg queue hash * remove legacy test * move chunk into primitives and impl EuclidV2 * set prev_msg_queue_hash * use is_l1_message * feat: num l1 msgs in scroll block * fix: usize instead of u64 for num txs * chore: clippy fix remove unused import * apply suggestion --------- Co-authored-by: Zhang Zhuo Co-authored-by: Rohit Narurkar * fix Eip7702 signature * chore: update reth dep * fix bytecode construct * upgrade to fix * add euclid v2 test cases * fix cli * remove unused * impl is_euclid_v2 in chunk * clippy * fix ChunkInfo * fix chunk mode * refactor * refactor * refactor primitives crate * fix others * export sbv-utils * fix merge * fmt * clippy --------- Co-authored-by: Zhang Zhuo Co-authored-by: Rohit Narurkar --- Cargo.lock | 1 + crates/bin/src/commands/run_file.rs | 3 +- crates/bin/src/utils.rs | 6 +- crates/core/Cargo.toml | 4 +- crates/core/src/database.rs | 9 +- crates/core/src/executor.rs | 8 +- crates/primitives/Cargo.toml | 114 ++++- crates/primitives/src/chainspec.rs | 3 +- crates/primitives/src/ext.rs | 97 +++- crates/primitives/src/hardforks.rs | 2 +- crates/primitives/src/lib.rs | 175 +------ crates/primitives/src/types/access_list.rs | 102 +--- crates/primitives/src/types/auth_list.rs | 111 +--- crates/primitives/src/types/block_header.rs | 483 ++++++------------ crates/primitives/src/types/consensus.rs | 325 ++++++++++++ crates/primitives/src/types/eips.rs | 169 ++++++ crates/primitives/src/types/mod.rs | 131 ++--- crates/primitives/src/types/reth.rs | 389 ++++++++++++++ crates/primitives/src/types/rpc.rs | 60 +++ crates/primitives/src/types/scroll/chunk.rs | 173 ++++--- .../src/types/scroll/chunk_builder.rs | 9 +- crates/primitives/src/types/scroll/mod.rs | 17 +- crates/primitives/src/types/signature.rs | 35 +- crates/primitives/src/types/transaction.rs | 436 +++------------- crates/primitives/src/types/withdrawal.rs | 58 +-- crates/primitives/src/types/witness.rs | 115 ++--- crates/sbv/Cargo.toml | 1 + crates/sbv/src/lib.rs | 1 + crates/trie/Cargo.toml | 2 +- crates/trie/src/lib.rs | 4 +- crates/utils-cli/src/commands/witness/dump.rs | 2 +- crates/utils/Cargo.toml | 2 +- crates/utils/src/rpc.rs | 10 +- 33 files changed, 1674 insertions(+), 1383 deletions(-) create mode 100644 crates/primitives/src/types/consensus.rs create mode 100644 crates/primitives/src/types/eips.rs create mode 100644 crates/primitives/src/types/reth.rs create mode 100644 crates/primitives/src/types/rpc.rs diff --git a/Cargo.lock b/Cargo.lock index f3e61191..6d210b30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4569,6 +4569,7 @@ dependencies = [ "sbv-kv", "sbv-primitives", "sbv-trie", + "sbv-utils", ] [[package]] diff --git a/crates/bin/src/commands/run_file.rs b/crates/bin/src/commands/run_file.rs index d11583da..bc59c065 100644 --- a/crates/bin/src/commands/run_file.rs +++ b/crates/bin/src/commands/run_file.rs @@ -48,10 +48,9 @@ impl RunFileCommand { core::{EvmDatabase, EvmExecutor}, kv::{nohash::NoHashMap, null::NullProvider}, primitives::{ - BlockWitness as _, chainspec::{Chain, get_chain_spec_or_build}, ext::{BlockWitnessChunkExt, BlockWitnessExt}, - types::{BlockWitness, ChunkInfoBuilder}, + types::{BlockWitness, reth::BlockWitnessRethExt, scroll::ChunkInfoBuilder}, }, trie::BlockWitnessTrieExt, }; diff --git a/crates/bin/src/utils.rs b/crates/bin/src/utils.rs index 447d58a3..561df8ec 100644 --- a/crates/bin/src/utils.rs +++ b/crates/bin/src/utils.rs @@ -2,14 +2,14 @@ use sbv::{ core::{EvmDatabase, EvmExecutor, VerificationError}, kv::nohash::NoHashMap, primitives::{ - BlockWitness, chainspec::{Chain, get_chain_spec_or_build}, ext::BlockWitnessExt, + types::reth::BlockWitnessRethExt, }, trie::BlockWitnessTrieExt, }; -pub fn verify( +pub fn verify( witness: T, ) -> Result<(), VerificationError> { measure_duration_millis!( @@ -18,7 +18,7 @@ pub fn verify( ) } -fn verify_inner( +fn verify_inner( witness: T, ) -> Result<(), VerificationError> { dev_trace!("{witness:#?}"); diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index ca617710..3ed50676 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -21,7 +21,7 @@ reth-storage-errors.workspace = true thiserror.workspace = true -sbv-primitives.workspace = true +sbv-primitives = { workspace = true, features = ["ethereum-all", "rkyv", "serde"] } sbv-helpers.workspace = true sbv-kv.workspace = true sbv-trie.workspace = true @@ -38,7 +38,7 @@ scroll = [ "reth-evm-ethereum/scroll", "reth-execution-types/scroll", "reth-scroll-evm/scroll", - "sbv-primitives/scroll", + "sbv-primitives/scroll-all", ] debug-account = ["sbv-helpers/debug-account"] debug-storage = ["sbv-helpers/debug-storage"] diff --git a/crates/core/src/database.rs b/crates/core/src/database.rs index adb5cf74..fe1c93f4 100644 --- a/crates/core/src/database.rs +++ b/crates/core/src/database.rs @@ -1,12 +1,15 @@ use sbv_kv::{HashMap, KeyValueStoreGet}; use sbv_primitives::{ - AccountInfo, Address, B256, Bytecode, Bytes, U256, - revm::{db::BundleAccount, interpreter::analysis::to_analysed}, + Address, B256, Bytes, U256, + types::{ + AccountInfo, Bytecode, + revm::{db::BundleAccount, interpreter::analysis::to_analysed}, + }, }; use sbv_trie::{PartialStateTrie, TrieNode}; use std::{cell::RefCell, fmt}; -pub use sbv_primitives::revm::db::DatabaseRef; +pub use sbv_primitives::types::revm::db::DatabaseRef; /// A database that consists of account and storage information. pub struct EvmDatabase { diff --git a/crates/core/src/executor.rs b/crates/core/src/executor.rs index 354177f1..b12a7955 100644 --- a/crates/core/src/executor.rs +++ b/crates/core/src/executor.rs @@ -3,10 +3,12 @@ use reth_evm::execute::{BlockExecutorProvider, Executor}; use reth_execution_types::BlockExecutionOutput; use sbv_kv::KeyValueStoreGet; use sbv_primitives::{ - B256, Bytes, RecoveredBlock, + B256, Bytes, chainspec::ChainSpec, - revm::db::CacheDB, - types::reth::{Block, Receipt}, + types::{ + reth::{Block, Receipt, RecoveredBlock}, + revm::db::CacheDB, + }, }; use sbv_trie::TrieNode; use std::{fmt::Debug, sync::Arc}; diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 4148ab52..7bc8e238 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -15,23 +15,24 @@ workspace = true [dependencies] auto_impl.workspace = true itertools.workspace = true -rkyv.workspace = true -serde = { workspace = true, features = ["derive"] } tiny-keccak.workspace = true -alloy-consensus.workspace = true -alloy-eips.workspace = true -alloy-network.workspace = true -alloy-rpc-types-eth.workspace = true -alloy-serde.workspace = true +rkyv = { workspace = true, optional = true } +serde = { workspace = true, optional = true } + +alloy-consensus = { workspace = true, optional = true } +alloy-eips = { workspace = true, optional = true } +alloy-network = { workspace = true, optional = true } +alloy-rpc-types-eth = { workspace = true, optional = true } +alloy-serde = { workspace = true, optional = true } alloy-primitives.workspace = true -revm.workspace = true -reth-chainspec.workspace = true -reth-ethereum-forks.workspace = true -reth-primitives.workspace = true -reth-primitives-traits.workspace = true +revm = { workspace = true, optional = true } +reth-chainspec = { workspace = true, optional = true } +reth-ethereum-forks = { workspace = true, optional = true } +reth-primitives = { workspace = true, optional = true } +reth-primitives-traits = { workspace = true, optional = true } reth-scroll-chainspec = { workspace = true, optional = true } reth-scroll-forks = { workspace = true, optional = true } reth-scroll-primitives = { workspace = true, optional = true } @@ -46,19 +47,84 @@ sbv-kv.workspace = true [dev-dependencies] [features] -scroll = [ - "dep:reth-scroll-chainspec", - "dep:reth-scroll-forks", - "dep:reth-scroll-primitives", - "dep:scroll-alloy-consensus", - "dep:scroll-alloy-rpc-types", - "dep:scroll-alloy-network", - "reth-scroll-forks/serde", - "reth-scroll-primitives/serde", - "reth-scroll-primitives/scroll", - "revm/scroll-default-handler", - "revm/optional_no_base_fee", +# serialization +rkyv = ["dep:rkyv"] +serde = [ + "dep:alloy-serde", + "dep:serde", + "reth-scroll-primitives?/serde", +] + +# core features switch +chainspec = ["dep:reth-chainspec"] +consensus-types = ["dep:alloy-consensus"] +eips = ["dep:alloy-eips"] +network-types = ["dep:alloy-network"] +hardforks = ["dep:reth-ethereum-forks"] +reth-types = [ + "serde", + "consensus-types", + "eips", + "dep:reth-primitives", + "dep:reth-primitives-traits", +] +revm-types = ["dep:revm"] +rpc-types = ["dep:alloy-rpc-types-eth", "eips"] +ethereum-all = [ + "chainspec", + "consensus-types", + "eips", + "network-types", + "hardforks", + "reth-types", + "revm-types", + "rpc-types", +] + +scroll = [] +scroll-chainspec = ["scroll", "chainspec", "dep:reth-scroll-chainspec"] +scroll-consensus-types = [ + "scroll", + "consensus-types", + "dep:scroll-alloy-consensus", + "scroll-alloy-consensus/serde", # This is a bug + "scroll-alloy-consensus/reth-codec", # This is a bug ] +scroll-hardforks = [ + "scroll", + "hardforks", + "dep:reth-scroll-forks", + "reth-scroll-forks/serde", +] +scroll-network-types = ["scroll", "network-types", "dep:scroll-alloy-network"] +scroll-pre-deployed = ["scroll"] +scroll-reth-types = [ + "scroll", + "reth-types", + "scroll-revm", # This is a bug + "scroll-consensus-types", + "dep:reth-scroll-primitives", + "reth-scroll-primitives/scroll", +] +scroll-revm = [ + "scroll", + "revm-types", + "revm/scroll-default-handler", + "revm/optional_no_base_fee", +] +scroll-rpc-types = ["scroll", "rpc-types", "dep:scroll-alloy-rpc-types"] +scroll-all = [ + "scroll", + "scroll-chainspec", + "scroll-consensus-types", + "scroll-network-types", + "scroll-hardforks", + "scroll-pre-deployed", + "scroll-reth-types", + "scroll-revm", + "scroll-rpc-types", +] + dev = ["sbv-helpers/dev"] sp1 = [] diff --git a/crates/primitives/src/chainspec.rs b/crates/primitives/src/chainspec.rs index 02cdfe02..d088f1cc 100644 --- a/crates/primitives/src/chainspec.rs +++ b/crates/primitives/src/chainspec.rs @@ -1,7 +1,6 @@ use std::sync::Arc; -pub use reth_chainspec; -pub use reth_chainspec::*; +pub use reth_chainspec::{self, *}; #[cfg(feature = "scroll")] pub use reth_scroll_chainspec as scroll; diff --git a/crates/primitives/src/ext.rs b/crates/primitives/src/ext.rs index 4d9c5062..fb3f0bda 100644 --- a/crates/primitives/src/ext.rs +++ b/crates/primitives/src/ext.rs @@ -1,4 +1,4 @@ -use crate::{B256, BlockWitness, Bytes, keccak256, types::consensus::BlockHeader}; +use crate::{B256, BlockWitness, Bytes, keccak256}; #[cfg(feature = "scroll")] use itertools::Itertools; use sbv_helpers::cycle_track; @@ -38,7 +38,7 @@ impl BlockWitnessChunkExt for [T] { fn has_seq_block_number(&self) -> bool { self.iter() .tuple_windows() - .all(|(a, b)| a.header().number() + 1 == b.header().number()) + .all(|(a, b)| a.number() + 1 == b.number()) } } @@ -68,7 +68,7 @@ impl BlockWitnessExt for T { &self, mut block_hashes: BlockHashProvider, ) { - let block_number = self.header().number(); + let block_number = self.number(); for (i, hash) in self.block_hashes_iter().enumerate() { let block_number = block_number .checked_sub(i as u64 + 1) @@ -93,7 +93,7 @@ impl BlockWitnessExt for [T] { mut block_hashes: BlockHashProvider, ) { for witness in self.iter() { - let block_number = witness.header().number(); + let block_number = witness.number(); for (i, hash) in witness.block_hashes_iter().enumerate() { let block_number = block_number .checked_sub(i as u64 + 1) @@ -114,9 +114,9 @@ pub trait TxBytesHashExt { fn tx_bytes_hash_in(self, rlp_buffer: &mut Vec) -> (usize, B256); } -#[cfg(feature = "scroll")] -impl<'a, I: IntoIterator, Tx: alloy_eips::eip2718::Encodable2718 + 'a> TxBytesHashExt - for I +#[cfg(all(feature = "scroll", feature = "eips"))] +impl<'a, I: IntoIterator, Tx: crate::types::eips::eip2718::Encodable2718 + 'a> + TxBytesHashExt for I { fn tx_bytes_hash(self) -> (usize, B256) { let mut rlp_buffer = Vec::new(); @@ -138,3 +138,86 @@ impl<'a, I: IntoIterator, Tx: alloy_eips::eip2718::Encodable2718 (len, tx_bytes_hash) } } + +/// Chunk related extension methods for Block +#[cfg(feature = "scroll-reth-types")] +pub trait BlockChunkExt { + /// Hash the header of the block + fn legacy_hash_da_header(&self, hasher: &mut impl tiny_keccak::Hasher); + /// Hash the l1 messages of the block + fn legacy_hash_l1_msg(&self, hasher: &mut impl tiny_keccak::Hasher); + /// Hash the l1 messages of the block + fn hash_msg_queue(&self, initial_queue_hash: &B256) -> B256; + /// Number of L1 msg txs in the block + fn num_l1_msgs(&self) -> usize; +} + +#[cfg(feature = "scroll-reth-types")] +impl BlockChunkExt for crate::types::reth::RecoveredBlock { + #[inline] + fn legacy_hash_da_header(&self, hasher: &mut impl tiny_keccak::Hasher) { + use crate::U256; + + hasher.update(&self.number.to_be_bytes()); + hasher.update(&self.timestamp.to_be_bytes()); + hasher.update( + &U256::from_limbs([self.base_fee_per_gas.unwrap_or_default(), 0, 0, 0]) + .to_be_bytes::<{ U256::BYTES }>(), + ); + hasher.update(&self.gas_limit.to_be_bytes()); + // FIXME: l1 tx could be skipped, the actual tx count needs to be calculated + hasher.update(&(self.body().transactions.len() as u16).to_be_bytes()); + } + + #[inline] + fn legacy_hash_l1_msg(&self, hasher: &mut impl tiny_keccak::Hasher) { + use reth_primitives_traits::SignedTransaction; + for tx in self + .body() + .transactions + .iter() + .filter(|tx| tx.is_l1_message()) + { + hasher.update(tx.tx_hash().as_slice()) + } + } + + #[inline] + fn hash_msg_queue(&self, initial_queue_hash: &B256) -> B256 { + use reth_primitives_traits::SignedTransaction; + use tiny_keccak::Hasher; + + let mut rolling_hash = *initial_queue_hash; + for tx in self + .body() + .transactions + .iter() + .filter(|tx| tx.is_l1_message()) + { + let mut hasher = tiny_keccak::Keccak::v256(); + hasher.update(rolling_hash.as_slice()); + hasher.update(tx.tx_hash().as_slice()); + + hasher.finalize(rolling_hash.as_mut_slice()); + + // clear last 32 bits, i.e. 4 bytes. + // https://github.com/scroll-tech/da-codec/blob/26dc8d575244560611548fada6a3a2745c60fe83/encoding/da.go#L817-L825 + // see also https://github.com/scroll-tech/da-codec/pull/42 + rolling_hash.0[28] = 0; + rolling_hash.0[29] = 0; + rolling_hash.0[30] = 0; + rolling_hash.0[31] = 0; + } + + rolling_hash + } + + #[inline] + fn num_l1_msgs(&self) -> usize { + self.body() + .transactions + .iter() + .filter(|tx| tx.is_l1_message()) + .count() + } +} diff --git a/crates/primitives/src/hardforks.rs b/crates/primitives/src/hardforks.rs index 501c0d99..01580e32 100644 --- a/crates/primitives/src/hardforks.rs +++ b/crates/primitives/src/hardforks.rs @@ -1,6 +1,6 @@ pub use reth_ethereum_forks::*; -#[cfg(feature = "scroll")] +#[cfg(feature = "scroll-hardforks")] pub use reth_scroll_forks::{ DEV_HARDFORKS as SCROLL_DEV_HARDFORKS, ScrollHardfork, ScrollHardforks, }; diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 583885ca..de9eeb80 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -4,61 +4,39 @@ use auto_impl::auto_impl; use std::fmt; /// The spec of an Ethereum network +#[cfg(feature = "chainspec")] pub mod chainspec; /// Extension Traits pub mod ext; /// Ethereum fork types +#[cfg(feature = "hardforks")] pub mod hardforks; /// Predeployed contracts -#[cfg(feature = "scroll")] +#[cfg(feature = "scroll-pre-deployed")] pub mod predeployed; /// Types definition pub mod types; -pub use alloy_consensus; -pub use revm; - pub use alloy_primitives::{ - self, Address, B256, BlockHash, BlockNumber, Bytes, ChainId, PrimitiveSignature, TxHash, U256, - address, b256, keccak256, + self, Address, B64, B256, BlockHash, BlockNumber, Bloom, Bytes, ChainId, PrimitiveSignature, + TxHash, U8, U256, address, b256, keccak256, }; -pub use reth_primitives::RecoveredBlock; -pub use revm::primitives::{AccountInfo, Bytecode}; - -/// Network definition -#[cfg(not(feature = "scroll"))] -pub type Network = alloy_network::Ethereum; -/// Network definition -#[cfg(feature = "scroll")] -pub type Network = scroll_alloy_network::Scroll; - -/// Eips -pub mod eips { - pub use alloy_eips::*; -} /// BlockWitness trait #[auto_impl(&, &mut, Box, Rc, Arc)] pub trait BlockWitness: fmt::Debug { /// Chain id fn chain_id(&self) -> ChainId; - /// Header - fn header(&self) -> impl types::consensus::BlockHeader; - /// Build alloy header - #[must_use] - fn build_alloy_header(&self) -> types::consensus::Header; + /// Block number + fn number(&self) -> BlockNumber; /// Pre-state root - #[must_use] fn pre_state_root(&self) -> B256; + /// Pre-state root + fn post_state_root(&self) -> B256; + /// Withdrawal root + fn withdrawals_root(&self) -> Option; /// Number of transactions fn num_transactions(&self) -> usize; - /// Transactions - #[must_use] - fn build_typed_transactions( - &self, - ) -> impl ExactSizeIterator< - Item = Result, - >; /// Block hashes #[must_use] #[cfg(not(feature = "scroll"))] @@ -75,18 +53,6 @@ pub trait BlockWitness: fmt::Debug { // provided methods - /// Pre-state root - #[must_use] - fn post_state_root(&self) -> B256 { - use types::consensus::BlockHeader; - self.header().state_root() - } - /// Withdrawal root - #[must_use] - fn withdrawals_root(&self) -> Option { - use types::consensus::BlockHeader; - self.header().withdrawals_root() - } /// Number of states fn num_states(&self) -> usize { self.states_iter().len() @@ -95,44 +61,6 @@ pub trait BlockWitness: fmt::Debug { fn num_codes(&self) -> usize { self.codes_iter().len() } - - /// Build a reth block - fn build_reth_block( - &self, - ) -> Result, alloy_primitives::SignatureError> { - use reth_primitives_traits::transaction::signed::SignedTransaction; - - let header = self.build_alloy_header(); - let transactions = self - .build_typed_transactions() - .collect::, _>>()?; - let senders = transactions - .iter() - .map(|tx| tx.recover_signer()) - .collect::, _>>() - .expect("Failed to recover signer"); - - let body = types::reth::BlockBody { - transactions, - ommers: vec![], - withdrawals: self.withdrawals_iter().map(|iter| { - alloy_eips::eip4895::Withdrawals( - iter.map(|w| alloy_eips::eip4895::Withdrawal { - index: w.index(), - validator_index: w.validator_index(), - address: w.address(), - amount: w.amount(), - }) - .collect(), - ) - }), - }; - - Ok(RecoveredBlock::new_unhashed( - types::reth::Block { header, body }, - senders, - )) - } } /// Withdrawal trait @@ -147,84 +75,3 @@ pub trait Withdrawal: fmt::Debug { /// Value of the withdrawal in gwei. fn amount(&self) -> u64; } - -/// Chunk related extension methods for Block -#[cfg(feature = "scroll")] -pub trait BlockChunkExt { - /// Hash the header of the block - fn legacy_hash_da_header(&self, hasher: &mut impl tiny_keccak::Hasher); - /// Hash the l1 messages of the block - fn legacy_hash_l1_msg(&self, hasher: &mut impl tiny_keccak::Hasher); - /// Hash the l1 messages of the block - fn hash_msg_queue(&self, initial_queue_hash: &B256) -> B256; - /// Number of L1 msg txs in the block - fn num_l1_msgs(&self) -> usize; -} - -#[cfg(feature = "scroll")] -impl BlockChunkExt for RecoveredBlock { - #[inline] - fn legacy_hash_da_header(&self, hasher: &mut impl tiny_keccak::Hasher) { - hasher.update(&self.number.to_be_bytes()); - hasher.update(&self.timestamp.to_be_bytes()); - hasher.update( - &U256::from_limbs([self.base_fee_per_gas.unwrap_or_default(), 0, 0, 0]) - .to_be_bytes::<{ U256::BYTES }>(), - ); - hasher.update(&self.gas_limit.to_be_bytes()); - // FIXME: l1 tx could be skipped, the actual tx count needs to be calculated - hasher.update(&(self.body().transactions.len() as u16).to_be_bytes()); - } - - #[inline] - fn legacy_hash_l1_msg(&self, hasher: &mut impl tiny_keccak::Hasher) { - use reth_primitives_traits::SignedTransaction; - for tx in self - .body() - .transactions - .iter() - .filter(|tx| tx.is_l1_message()) - { - hasher.update(tx.tx_hash().as_slice()) - } - } - - #[inline] - fn hash_msg_queue(&self, initial_queue_hash: &B256) -> B256 { - use reth_primitives_traits::SignedTransaction; - use tiny_keccak::Hasher; - - let mut rolling_hash = *initial_queue_hash; - for tx in self - .body() - .transactions - .iter() - .filter(|tx| tx.is_l1_message()) - { - let mut hasher = tiny_keccak::Keccak::v256(); - hasher.update(rolling_hash.as_slice()); - hasher.update(tx.tx_hash().as_slice()); - - hasher.finalize(rolling_hash.as_mut_slice()); - - // clear last 32 bits, i.e. 4 bytes. - // https://github.com/scroll-tech/da-codec/blob/26dc8d575244560611548fada6a3a2745c60fe83/encoding/da.go#L817-L825 - // see also https://github.com/scroll-tech/da-codec/pull/42 - rolling_hash.0[28] = 0; - rolling_hash.0[29] = 0; - rolling_hash.0[30] = 0; - rolling_hash.0[31] = 0; - } - - rolling_hash - } - - #[inline] - fn num_l1_msgs(&self) -> usize { - self.body() - .transactions - .iter() - .filter(|tx| tx.is_l1_message()) - .count() - } -} diff --git a/crates/primitives/src/types/access_list.rs b/crates/primitives/src/types/access_list.rs index ea3f4d0a..e93d0232 100644 --- a/crates/primitives/src/types/access_list.rs +++ b/crates/primitives/src/types/access_list.rs @@ -2,96 +2,34 @@ use crate::{Address, B256}; /// A list of addresses and storage keys that the transaction plans to access. /// Accesses outside the list are possible, but become more expensive. -#[derive( - Clone, - Debug, - Default, - PartialEq, - Eq, - Hash, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, - serde::Serialize, - serde::Deserialize, +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, Hash, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AccessListItem { /// Account addresses that would be loaded at the start of execution - #[rkyv(attr(doc = "Account addresses that would be loaded at the start of execution"))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Account addresses that would be loaded at the start of execution")) + )] pub address: Address, /// Keys of storage that would be loaded at the start of execution - #[rkyv(attr(doc = "Keys of storage that would be loaded at the start of execution"))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Keys of storage that would be loaded at the start of execution")) + )] pub storage_keys: Vec, } /// AccessList as defined in EIP-2930 -#[derive( - Clone, - Debug, - Default, - PartialEq, - Eq, - Hash, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, - serde::Serialize, - serde::Deserialize, +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, Hash, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AccessList(pub Vec); - -impl From<&alloy_eips::eip2930::AccessListItem> for AccessListItem { - fn from(item: &alloy_eips::eip2930::AccessListItem) -> Self { - Self { - address: item.address, - storage_keys: item.storage_keys.clone(), - } - } -} - -impl From for alloy_eips::eip2930::AccessListItem { - fn from(item: AccessListItem) -> Self { - Self { - address: item.address, - storage_keys: item.storage_keys, - } - } -} - -impl From<&alloy_eips::eip2930::AccessList> for AccessList { - fn from(list: &alloy_eips::eip2930::AccessList) -> Self { - Self(list.0.iter().map(Into::into).collect()) - } -} - -impl From for alloy_eips::eip2930::AccessList { - fn from(list: AccessList) -> Self { - Self(list.0.into_iter().map(Into::into).collect()) - } -} - -impl From<&ArchivedAccessListItem> for alloy_eips::eip2930::AccessListItem { - fn from(item: &ArchivedAccessListItem) -> Self { - Self { - address: Address::from(item.address), - storage_keys: item - .storage_keys - .iter() - .map(|key| B256::from(*key)) - .collect(), - } - } -} - -impl From<&ArchivedAccessList> for alloy_eips::eip2930::AccessList { - fn from(list: &ArchivedAccessList) -> Self { - Self( - list.0 - .iter() - .map(alloy_eips::eip2930::AccessListItem::from) - .collect(), - ) - } -} diff --git a/crates/primitives/src/types/auth_list.rs b/crates/primitives/src/types/auth_list.rs index 368f1019..2ece88da 100644 --- a/crates/primitives/src/types/auth_list.rs +++ b/crates/primitives/src/types/auth_list.rs @@ -1,112 +1,39 @@ -use alloy_primitives::{Address, U8, U256}; +use crate::{Address, U8, U256}; -#[derive( - Debug, - Clone, - Hash, - Eq, - PartialEq, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, - serde::Serialize, - serde::Deserialize, +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, Hash, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Authorization { /// The chain ID of the authorization. pub chain_id: U256, /// The address of the authorization. pub address: Address, /// The nonce for the authorization. - #[serde(with = "alloy_serde::quantity")] + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] pub nonce: u64, } /// A signed EIP-7702 authorization. -#[derive( - Debug, - Clone, - Eq, - PartialEq, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, - serde::Serialize, - serde::Deserialize, +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, Hash, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SignedAuthorization { /// Inner authorization. - inner: Authorization, + pub inner: Authorization, /// Signature parity value. We allow any [`U8`] here, however, the only valid values are `0` /// and `1` and anything else will result in error during recovery. - #[serde(rename = "yParity", alias = "v")] - y_parity: U8, + #[cfg_attr(feature = "serde", serde(rename = "yParity", alias = "v"))] + pub y_parity: U8, /// Signature `r` value. - r: U256, + pub r: U256, /// Signature `s` value. - s: U256, -} - -impl From<&alloy_eips::eip7702::Authorization> for Authorization { - fn from(auth: &alloy_eips::eip7702::Authorization) -> Self { - Self { - chain_id: auth.chain_id, - address: auth.address, - nonce: auth.nonce, - } - } -} - -impl From for alloy_eips::eip7702::Authorization { - fn from(auth: Authorization) -> Self { - Self { - chain_id: auth.chain_id, - address: auth.address, - nonce: auth.nonce, - } - } -} - -impl From<&alloy_eips::eip7702::SignedAuthorization> for SignedAuthorization { - fn from(auth: &alloy_eips::eip7702::SignedAuthorization) -> Self { - Self { - inner: Authorization { - chain_id: auth.chain_id, - address: auth.address, - nonce: auth.nonce, - }, - y_parity: U8::from(auth.y_parity()), - r: auth.r(), - s: auth.s(), - } - } -} - -impl From for alloy_eips::eip7702::SignedAuthorization { - fn from(auth: SignedAuthorization) -> Self { - alloy_eips::eip7702::SignedAuthorization::new_unchecked( - auth.inner.into(), - auth.y_parity.to(), - auth.r, - auth.s, - ) - } -} - -impl From<&ArchivedSignedAuthorization> for alloy_eips::eip7702::SignedAuthorization { - fn from(auth: &ArchivedSignedAuthorization) -> Self { - let y_parity: U8 = From::from(&auth.y_parity); - alloy_eips::eip7702::SignedAuthorization::new_unchecked( - alloy_eips::eip7702::Authorization { - chain_id: auth.inner.chain_id.into(), - address: Address::from(auth.inner.address), - nonce: auth.inner.nonce.to_native(), - }, - y_parity.to(), - auth.r.into(), - auth.s.into(), - ) - } + pub s: U256, } diff --git a/crates/primitives/src/types/block_header.rs b/crates/primitives/src/types/block_header.rs index 82bd5bb2..28d9efb0 100644 --- a/crates/primitives/src/types/block_header.rs +++ b/crates/primitives/src/types/block_header.rs @@ -2,119 +2,155 @@ use crate::{ Address, B256, BlockNumber, Bytes, U256, alloy_primitives::{B64, Bloom}, }; -use auto_impl::auto_impl; -use std::sync::OnceLock; /// Block header representation. -#[derive( - Clone, - Debug, - Default, - Hash, - PartialEq, - Eq, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, - serde::Serialize, - serde::Deserialize, +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, Hash, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BlockHeader { /// The Keccak 256-bit hash of the parent /// block’s header, in its entirety; formally Hp. - #[rkyv(attr( - doc = "The Keccak 256-bit hash of the parent block’s header, in its entirety; formally Hp." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The Keccak 256-bit hash of the parent block’s header, in its entirety; formally Hp." + )) + )] pub parent_hash: B256, /// The Keccak 256-bit hash of the ommers list portion of this block; formally Ho. - #[serde(rename = "sha3Uncles", alias = "ommersHash")] - #[rkyv(attr( - doc = "The Keccak 256-bit hash of the ommers list portion of this block; formally Ho." - ))] + #[cfg_attr(feature = "serde", serde(rename = "sha3Uncles", alias = "ommersHash"))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The Keccak 256-bit hash of the ommers list portion of this block; formally Ho." + )) + )] pub ommers_hash: B256, /// The 160-bit address to which all fees collected from the successful mining of this block /// be transferred; formally Hc. - #[serde(rename = "miner", alias = "beneficiary")] - #[rkyv(attr( - doc = "The 160-bit address to which all fees collected from the successful mining of this block be transferred; formally Hc." - ))] + #[cfg_attr(feature = "serde", serde(rename = "miner", alias = "beneficiary"))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The 160-bit address to which all fees collected from the successful mining of this block be transferred; formally Hc." + )) + )] pub beneficiary: Address, /// The Keccak 256-bit hash of the root node of the state trie, after all transactions are /// executed and finalisations applied; formally Hr. - #[rkyv(attr( - doc = "The Keccak 256-bit hash of the root node of the state trie, after all transactions are executed and finalisations applied; formally Hr." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The Keccak 256-bit hash of the root node of the state trie, after all transactions are executed and finalisations applied; formally Hr." + )) + )] pub state_root: B256, /// The Keccak 256-bit hash of the root node of the trie structure populated with each /// transaction in the transactions list portion of the block; formally Ht. - #[rkyv(attr( - doc = "The Keccak 256-bit hash of the root node of the trie structure populated with each transaction in the transactions list portion of the block; formally Ht." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The Keccak 256-bit hash of the root node of the trie structure populated with each transaction in the transactions list portion of the block; formally Ht." + )) + )] pub transactions_root: B256, /// The Keccak 256-bit hash of the root node of the trie structure populated with the receipts /// of each transaction in the transactions list portion of the block; formally He. - #[rkyv(attr( - doc = "The Keccak 256-bit hash of the root node of the trie structure populated with the receipts of each transaction in the transactions list portion of the block; formally He." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The Keccak 256-bit hash of the root node of the trie structure populated with the receipts of each transaction in the transactions list portion of the block; formally He." + )) + )] pub receipts_root: B256, /// The Bloom filter composed from indexable information (logger address and log topics) /// contained in each log entry from the receipt of each transaction in the transactions list; /// formally Hb. - #[rkyv(attr( - doc = "The Bloom filter composed from indexable information (logger address and log topics) contained in each log entry from the receipt of each transaction in the transactions list; formally Hb." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The Bloom filter composed from indexable information (logger address and log topics) contained in each log entry from the receipt of each transaction in the transactions list; formally Hb." + )) + )] pub logs_bloom: Bloom, /// A scalar value corresponding to the difficulty level of this block. This can be calculated /// from the previous block’s difficulty level and the timestamp; formally Hd. - #[rkyv(attr( - doc = "A scalar value corresponding to the difficulty level of this block. This can be calculated from the previous block’s difficulty level and the timestamp; formally Hd." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "A scalar value corresponding to the difficulty level of this block. This can be calculated from the previous block’s difficulty level and the timestamp; formally Hd." + )) + )] pub difficulty: U256, /// A scalar value equal to the number of ancestor blocks. The genesis block has a number of /// zero; formally Hi. - #[serde(with = "alloy_serde::quantity")] - #[rkyv(attr( - doc = "A scalar value equal to the number of ancestor blocks. The genesis block has a number of zero; formally Hi." - ))] + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "A scalar value equal to the number of ancestor blocks. The genesis block has a number of zero; formally Hi." + )) + )] pub number: BlockNumber, /// A scalar value equal to the current limit of gas expenditure per block; formally Hl. - #[serde(with = "alloy_serde::quantity")] - #[rkyv(attr( - doc = "A scalar value equal to the current limit of gas expenditure per block; formally Hl." - ))] + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "A scalar value equal to the current limit of gas expenditure per block; formally Hl." + )) + )] pub gas_limit: u64, /// A scalar value equal to the total gas used in transactions in this block; formally Hg. - #[serde(with = "alloy_serde::quantity")] - #[rkyv(attr( - doc = "A scalar value equal to the total gas used in transactions in this block; formally Hg." - ))] + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "A scalar value equal to the total gas used in transactions in this block; formally Hg." + )) + )] pub gas_used: u64, /// A scalar value equal to the reasonable output of Unix’s time() at this block’s inception; /// formally Hs. - #[serde(with = "alloy_serde::quantity")] - #[rkyv(attr( - doc = "A scalar value equal to the reasonable output of Unix’s time() at this block’s inception; formally Hs." - ))] + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "A scalar value equal to the reasonable output of Unix’s time() at this block’s inception; formally Hs." + )) + )] pub timestamp: u64, /// An arbitrary byte array containing data relevant to this block. This must be 32 bytes or /// fewer; formally Hx. - #[rkyv(attr( - doc = "An arbitrary byte array containing data relevant to this block. This must be 32 bytes or fewer; formally Hx." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "An arbitrary byte array containing data relevant to this block. This must be 32 bytes or fewer; formally Hx." + )) + )] pub extra_data: Bytes, /// A 256-bit hash which, combined with the /// nonce, proves that a sufficient amount of computation has been carried out on this block; /// formally Hm. - #[rkyv(attr( - doc = "A 256-bit hash which, combined with the nonce, proves that a sufficient amount of computation has been carried out on this block; formally Hm." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "A 256-bit hash which, combined with the nonce, proves that a sufficient amount of computation has been carried out on this block; formally Hm." + )) + )] pub mix_hash: B256, /// A 64-bit value which, combined with the mixhash, proves that a sufficient amount of /// computation has been carried out on this block; formally Hn. - #[rkyv(attr( - doc = "A 64-bit value which, combined with the mixhash, proves that a sufficient amount of computation has been carried out on this block; formally Hn." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "A 64-bit value which, combined with the mixhash, proves that a sufficient amount of computation has been carried out on this block; formally Hn." + )) + )] pub nonce: B64, /// A scalar representing EIP1559 base fee which can move up or down each block according /// to a formula which is a function of gas used in parent block and gas target @@ -122,39 +158,53 @@ pub struct BlockHeader { /// The algorithm results in the base fee per gas increasing when blocks are /// above the gas target, and decreasing when blocks are below the gas target. The base fee per /// gas is burned. - #[serde( - default, - with = "alloy_serde::quantity::opt", + #[cfg_attr( + feature = "serde", + serde(default, with = "alloy_serde::quantity::opt",) + )] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "A scalar representing EIP1559 base fee which can move up or down each block according to a formula which is a function of gas used in parent block and gas target (block gas limit divided by elasticity multiplier) of parent block. The algorithm results in the base fee per gas increasing when blocks are above the gas target, and decreasing when blocks are below the gas target. The base fee per gas is burned." + )) )] - #[rkyv(attr( - doc = "A scalar representing EIP1559 base fee which can move up or down each block according to a formula which is a function of gas used in parent block and gas target (block gas limit divided by elasticity multiplier) of parent block. The algorithm results in the base fee per gas increasing when blocks are above the gas target, and decreasing when blocks are below the gas target. The base fee per gas is burned." - ))] pub base_fee_per_gas: Option, /// The Keccak 256-bit hash of the withdrawals list portion of this block. /// - #[serde(default)] - #[rkyv(attr(doc = "The Keccak 256-bit hash of the withdrawals list portion of this block."))] + #[cfg_attr(feature = "serde", serde(default))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The Keccak 256-bit hash of the withdrawals list portion of this block." + )) + )] pub withdrawals_root: Option, /// The total amount of blob gas consumed by the transactions within the block, added in /// EIP-4844. - #[serde( - default, - with = "alloy_serde::quantity::opt", + #[cfg_attr( + feature = "serde", + serde(default, with = "alloy_serde::quantity::opt",) + )] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The total amount of blob gas consumed by the transactions within the block, added in EIP-4844." + )) )] - #[rkyv(attr( - doc = "The total amount of blob gas consumed by the transactions within the block, added in EIP-4844." - ))] pub blob_gas_used: Option, /// A running total of blob gas consumed in excess of the target, prior to the block. Blocks /// with above-target blob gas consumption increase this value, blocks with below-target blob /// gas consumption decrease it (bounded at 0). This was added in EIP-4844. - #[serde( - default, - with = "alloy_serde::quantity::opt", + #[cfg_attr( + feature = "serde", + serde(default, with = "alloy_serde::quantity::opt",) + )] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "A running total of blob gas consumed in excess of the target, prior to the block. Blocks with above-target blob gas consumption increase this value, blocks with below-target blob gas consumption decrease it (bounded at 0). This was added in EIP-4844." + )) )] - #[rkyv(attr( - doc = "A running total of blob gas consumed in excess of the target, prior to the block. Blocks with above-target blob gas consumption increase this value, blocks with below-target blob gas consumption decrease it (bounded at 0). This was added in EIP-4844." - ))] pub excess_blob_gas: Option, /// The hash of the parent beacon block's root is included in execution blocks, as proposed by /// EIP-4788. @@ -163,257 +213,24 @@ pub struct BlockHeader { /// and more. /// /// The beacon roots contract handles root storage, enhancing Ethereum's functionalities. - #[serde(default)] - #[rkyv(attr( - doc = "The hash of the parent beacon block's root is included in execution blocks, as proposed by EIP-4788. This enables trust-minimized access to consensus state, supporting staking pools, bridges, and more. The beacon roots contract handles root storage, enhancing Ethereum's functionalities." - ))] + #[cfg_attr(feature = "serde", serde(default))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The hash of the parent beacon block's root is included in execution blocks, as proposed by EIP-4788. This enables trust-minimized access to consensus state, supporting staking pools, bridges, and more. The beacon roots contract handles root storage, enhancing Ethereum's functionalities." + )) + )] pub parent_beacon_block_root: Option, /// The Keccak 256-bit hash of the an RLP encoded list with each /// [EIP-7685] request in the block body. /// /// [EIP-7685]: https://eips.ethereum.org/EIPS/eip-7685 - #[serde(default)] - #[rkyv(attr( - doc = "The Keccak 256-bit hash of the an RLP encoded list with each [EIP-7685] request in the block body." - ))] + #[cfg_attr(feature = "serde", serde(default))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The Keccak 256-bit hash of the an RLP encoded list with each [EIP-7685] request in the block body." + )) + )] pub requests_hash: Option, } - -#[auto_impl(&, &mut, Box, Rc, Arc)] -trait FromHelper: alloy_consensus::BlockHeader {} - -impl FromHelper for alloy_rpc_types_eth::Header {} -impl FromHelper for alloy_consensus::Header {} - -#[auto_impl(&, &mut, Box, Rc, Arc)] -pub(crate) trait ToHelper: alloy_consensus::BlockHeader { - fn to_alloy(&self) -> alloy_consensus::Header { - alloy_consensus::Header { - parent_hash: self.parent_hash(), - ommers_hash: self.ommers_hash(), - beneficiary: self.beneficiary(), - state_root: self.state_root(), - transactions_root: self.transactions_root(), - receipts_root: self.receipts_root(), - logs_bloom: self.logs_bloom(), - difficulty: self.difficulty(), - number: self.number(), - gas_limit: self.gas_limit(), - gas_used: self.gas_used(), - timestamp: self.timestamp(), - extra_data: self.extra_data().clone(), - mix_hash: self.mix_hash().unwrap(), - nonce: self.nonce().unwrap(), - base_fee_per_gas: self.base_fee_per_gas(), - withdrawals_root: self.withdrawals_root(), - blob_gas_used: self.blob_gas_used(), - excess_blob_gas: self.excess_blob_gas(), - parent_beacon_block_root: self.parent_beacon_block_root(), - requests_hash: self.requests_hash(), - } - } -} - -impl ToHelper for BlockHeader {} -impl ToHelper for ArchivedBlockHeader {} - -impl From for BlockHeader { - fn from(header: T) -> Self { - Self { - parent_hash: header.parent_hash(), - ommers_hash: header.ommers_hash(), - beneficiary: header.beneficiary(), - state_root: header.state_root(), - transactions_root: header.transactions_root(), - receipts_root: header.receipts_root(), - logs_bloom: header.logs_bloom(), - difficulty: header.difficulty(), - number: header.number(), - gas_limit: header.gas_limit(), - gas_used: header.gas_used(), - timestamp: header.timestamp(), - extra_data: header.extra_data().clone(), - mix_hash: header.mix_hash().expect("mix hash"), - nonce: header.nonce().unwrap(), - base_fee_per_gas: header.base_fee_per_gas(), - withdrawals_root: header.withdrawals_root(), - blob_gas_used: header.blob_gas_used(), - excess_blob_gas: header.excess_blob_gas(), - parent_beacon_block_root: header.parent_beacon_block_root(), - requests_hash: header.requests_hash(), - } - } -} - -impl alloy_consensus::BlockHeader for BlockHeader { - fn parent_hash(&self) -> B256 { - self.parent_hash - } - - fn ommers_hash(&self) -> B256 { - self.ommers_hash - } - - fn beneficiary(&self) -> Address { - self.beneficiary - } - - fn state_root(&self) -> B256 { - self.state_root - } - - fn transactions_root(&self) -> B256 { - self.transactions_root - } - - fn receipts_root(&self) -> B256 { - self.receipts_root - } - - fn withdrawals_root(&self) -> Option { - self.withdrawals_root - } - - fn logs_bloom(&self) -> Bloom { - self.logs_bloom - } - - fn difficulty(&self) -> U256 { - self.difficulty - } - - fn number(&self) -> BlockNumber { - self.number - } - - fn gas_limit(&self) -> u64 { - self.gas_limit - } - - fn gas_used(&self) -> u64 { - self.gas_used - } - - fn timestamp(&self) -> u64 { - self.timestamp - } - - fn mix_hash(&self) -> Option { - Some(self.mix_hash) - } - - fn nonce(&self) -> Option { - Some(self.nonce) - } - - fn base_fee_per_gas(&self) -> Option { - self.base_fee_per_gas - } - - fn blob_gas_used(&self) -> Option { - self.blob_gas_used - } - - fn excess_blob_gas(&self) -> Option { - self.excess_blob_gas - } - - fn parent_beacon_block_root(&self) -> Option { - self.parent_beacon_block_root - } - - fn requests_hash(&self) -> Option { - self.requests_hash - } - - fn extra_data(&self) -> &Bytes { - &self.extra_data - } -} - -impl alloy_consensus::BlockHeader for ArchivedBlockHeader { - fn parent_hash(&self) -> B256 { - self.parent_hash.into() - } - - fn ommers_hash(&self) -> B256 { - self.ommers_hash.into() - } - - fn beneficiary(&self) -> Address { - self.beneficiary.into() - } - - fn state_root(&self) -> B256 { - self.state_root.into() - } - - fn transactions_root(&self) -> B256 { - self.transactions_root.into() - } - - fn receipts_root(&self) -> B256 { - self.receipts_root.into() - } - - fn withdrawals_root(&self) -> Option { - self.withdrawals_root.as_ref().map(|x| x.0.into()) - } - - fn logs_bloom(&self) -> Bloom { - self.logs_bloom.into() - } - - fn difficulty(&self) -> U256 { - self.difficulty.into() - } - - fn number(&self) -> BlockNumber { - self.number.into() - } - - fn gas_limit(&self) -> u64 { - self.gas_limit.to_native() - } - - fn gas_used(&self) -> u64 { - self.gas_used.to_native() - } - - fn timestamp(&self) -> u64 { - self.timestamp.to_native() - } - - fn mix_hash(&self) -> Option { - Some(self.mix_hash.into()) - } - - fn nonce(&self) -> Option { - Some(self.nonce.into()) - } - - fn base_fee_per_gas(&self) -> Option { - self.base_fee_per_gas.as_ref().map(|x| x.to_native()) - } - - fn blob_gas_used(&self) -> Option { - self.blob_gas_used.as_ref().map(|x| x.to_native()) - } - - fn excess_blob_gas(&self) -> Option { - self.excess_blob_gas.as_ref().map(|x| x.to_native()) - } - - fn parent_beacon_block_root(&self) -> Option { - self.parent_beacon_block_root.as_ref().map(|x| x.0.into()) - } - - fn requests_hash(&self) -> Option { - self.requests_hash.as_ref().map(|x| x.0.into()) - } - - fn extra_data(&self) -> &Bytes { - static BYTES: OnceLock = OnceLock::new(); - BYTES.get_or_init(|| Bytes::copy_from_slice(self.extra_data.as_slice())) - } -} diff --git a/crates/primitives/src/types/consensus.rs b/crates/primitives/src/types/consensus.rs new file mode 100644 index 00000000..d535f768 --- /dev/null +++ b/crates/primitives/src/types/consensus.rs @@ -0,0 +1,325 @@ +use crate::{Address, B64, B256, BlockNumber, Bloom, Bytes, PrimitiveSignature, U256}; +use auto_impl::auto_impl; + +pub use alloy_consensus::{ + BlockHeader, Header, SignableTransaction, Transaction, TxEip1559, TxEip2930, TxEip4844, + TxEip4844Variant, TxEip4844WithSidecar, TxEip7702, TxLegacy, Typed2718, +}; + +#[cfg(not(feature = "scroll"))] +pub use alloy_consensus::{TxEnvelope, TxType, TypedTransaction}; +#[cfg(feature = "scroll")] +pub use scroll_alloy_consensus::{ + ScrollReceiptEnvelope as ReceiptEnvelope, ScrollTxEnvelope as TxEnvelope, + ScrollTxType as TxType, ScrollTypedTransaction as TypedTransaction, TxL1Message, +}; + +/// Extension trait for `TxEnvelope` +pub trait TxEnvelopeExt { + /// get the signature of the transaction + fn signature(&self) -> Option<&PrimitiveSignature>; + + /// get the index of the transaction in the queue + fn queue_index(&self) -> Option { + None + } +} + +/// BlockWitnessConsensusExt trait +#[auto_impl(&, &mut, Box, Rc, Arc)] +pub trait BlockWitnessConsensusExt: crate::BlockWitness { + /// Header + fn header(&self) -> impl BlockHeader; + /// Build alloy header + #[must_use] + fn build_alloy_header(&self) -> Header; +} + +#[auto_impl(&, &mut, Box, Rc, Arc)] +pub(crate) trait FromHelper: BlockHeader {} + +#[auto_impl(&, &mut, Box, Rc, Arc)] +pub(crate) trait ToHelper: BlockHeader { + fn to_alloy(&self) -> Header { + Header { + parent_hash: self.parent_hash(), + ommers_hash: self.ommers_hash(), + beneficiary: self.beneficiary(), + state_root: self.state_root(), + transactions_root: self.transactions_root(), + receipts_root: self.receipts_root(), + logs_bloom: self.logs_bloom(), + difficulty: self.difficulty(), + number: self.number(), + gas_limit: self.gas_limit(), + gas_used: self.gas_used(), + timestamp: self.timestamp(), + extra_data: self.extra_data().clone(), + mix_hash: self.mix_hash().unwrap(), + nonce: self.nonce().unwrap(), + base_fee_per_gas: self.base_fee_per_gas(), + withdrawals_root: self.withdrawals_root(), + blob_gas_used: self.blob_gas_used(), + excess_blob_gas: self.excess_blob_gas(), + parent_beacon_block_root: self.parent_beacon_block_root(), + requests_hash: self.requests_hash(), + } + } +} + +#[cfg(not(feature = "scroll"))] +impl TxEnvelopeExt for TxEnvelope { + fn signature(&self) -> Option<&PrimitiveSignature> { + Some(TxEnvelope::signature(self)) + } +} + +#[cfg(feature = "scroll")] +impl TxEnvelopeExt for TxEnvelope { + fn signature(&self) -> Option<&PrimitiveSignature> { + match self { + TxEnvelope::Legacy(tx) => Some(tx.signature()), + TxEnvelope::Eip2930(tx) => Some(tx.signature()), + TxEnvelope::Eip1559(tx) => Some(tx.signature()), + TxEnvelope::Eip7702(tx) => Some(tx.signature()), + _ => None, + } + } + + fn queue_index(&self) -> Option { + match self { + TxEnvelope::L1Message(tx) => Some(tx.queue_index), + _ => None, + } + } +} + +impl BlockWitnessConsensusExt for super::BlockWitness { + fn header(&self) -> impl BlockHeader { + &self.header + } + fn build_alloy_header(&self) -> Header { + self.header.to_alloy() + } +} + +#[cfg(feature = "rkyv")] +impl BlockWitnessConsensusExt for super::ArchivedBlockWitness { + fn header(&self) -> impl BlockHeader { + &self.header + } + fn build_alloy_header(&self) -> Header { + self.header.to_alloy() + } +} + +#[cfg(feature = "rpc-types")] +impl FromHelper for alloy_rpc_types_eth::Header {} +impl FromHelper for Header {} + +impl From for super::BlockHeader { + fn from(header: T) -> Self { + Self { + parent_hash: header.parent_hash(), + ommers_hash: header.ommers_hash(), + beneficiary: header.beneficiary(), + state_root: header.state_root(), + transactions_root: header.transactions_root(), + receipts_root: header.receipts_root(), + logs_bloom: header.logs_bloom(), + difficulty: header.difficulty(), + number: header.number(), + gas_limit: header.gas_limit(), + gas_used: header.gas_used(), + timestamp: header.timestamp(), + extra_data: header.extra_data().clone(), + mix_hash: header.mix_hash().expect("mix hash"), + nonce: header.nonce().unwrap(), + base_fee_per_gas: header.base_fee_per_gas(), + withdrawals_root: header.withdrawals_root(), + blob_gas_used: header.blob_gas_used(), + excess_blob_gas: header.excess_blob_gas(), + parent_beacon_block_root: header.parent_beacon_block_root(), + requests_hash: header.requests_hash(), + } + } +} + +impl ToHelper for super::BlockHeader {} +#[cfg(feature = "rkyv")] +impl ToHelper for super::ArchivedBlockHeader {} + +impl BlockHeader for super::BlockHeader { + fn parent_hash(&self) -> B256 { + self.parent_hash + } + + fn ommers_hash(&self) -> B256 { + self.ommers_hash + } + + fn beneficiary(&self) -> Address { + self.beneficiary + } + + fn state_root(&self) -> B256 { + self.state_root + } + + fn transactions_root(&self) -> B256 { + self.transactions_root + } + + fn receipts_root(&self) -> B256 { + self.receipts_root + } + + fn withdrawals_root(&self) -> Option { + self.withdrawals_root + } + + fn logs_bloom(&self) -> Bloom { + self.logs_bloom + } + + fn difficulty(&self) -> U256 { + self.difficulty + } + + fn number(&self) -> BlockNumber { + self.number + } + + fn gas_limit(&self) -> u64 { + self.gas_limit + } + + fn gas_used(&self) -> u64 { + self.gas_used + } + + fn timestamp(&self) -> u64 { + self.timestamp + } + + fn mix_hash(&self) -> Option { + Some(self.mix_hash) + } + + fn nonce(&self) -> Option { + Some(self.nonce) + } + + fn base_fee_per_gas(&self) -> Option { + self.base_fee_per_gas + } + + fn blob_gas_used(&self) -> Option { + self.blob_gas_used + } + + fn excess_blob_gas(&self) -> Option { + self.excess_blob_gas + } + + fn parent_beacon_block_root(&self) -> Option { + self.parent_beacon_block_root + } + + fn requests_hash(&self) -> Option { + self.requests_hash + } + + fn extra_data(&self) -> &Bytes { + &self.extra_data + } +} + +#[cfg(feature = "rkyv")] +impl BlockHeader for super::ArchivedBlockHeader { + fn parent_hash(&self) -> B256 { + self.parent_hash.into() + } + + fn ommers_hash(&self) -> B256 { + self.ommers_hash.into() + } + + fn beneficiary(&self) -> Address { + self.beneficiary.into() + } + + fn state_root(&self) -> B256 { + self.state_root.into() + } + + fn transactions_root(&self) -> B256 { + self.transactions_root.into() + } + + fn receipts_root(&self) -> B256 { + self.receipts_root.into() + } + + fn withdrawals_root(&self) -> Option { + self.withdrawals_root.as_ref().map(|x| x.0.into()) + } + + fn logs_bloom(&self) -> Bloom { + self.logs_bloom.into() + } + + fn difficulty(&self) -> U256 { + self.difficulty.into() + } + + fn number(&self) -> BlockNumber { + self.number.into() + } + + fn gas_limit(&self) -> u64 { + self.gas_limit.to_native() + } + + fn gas_used(&self) -> u64 { + self.gas_used.to_native() + } + + fn timestamp(&self) -> u64 { + self.timestamp.to_native() + } + + fn mix_hash(&self) -> Option { + Some(self.mix_hash.into()) + } + + fn nonce(&self) -> Option { + Some(self.nonce.into()) + } + + fn base_fee_per_gas(&self) -> Option { + self.base_fee_per_gas.as_ref().map(|x| x.to_native()) + } + + fn blob_gas_used(&self) -> Option { + self.blob_gas_used.as_ref().map(|x| x.to_native()) + } + + fn excess_blob_gas(&self) -> Option { + self.excess_blob_gas.as_ref().map(|x| x.to_native()) + } + + fn parent_beacon_block_root(&self) -> Option { + self.parent_beacon_block_root.as_ref().map(|x| x.0.into()) + } + + fn requests_hash(&self) -> Option { + self.requests_hash.as_ref().map(|x| x.0.into()) + } + + fn extra_data(&self) -> &Bytes { + use std::sync::OnceLock; + static BYTES: OnceLock = OnceLock::new(); + BYTES.get_or_init(|| Bytes::copy_from_slice(self.extra_data.as_slice())) + } +} diff --git a/crates/primitives/src/types/eips.rs b/crates/primitives/src/types/eips.rs new file mode 100644 index 00000000..77f0d76e --- /dev/null +++ b/crates/primitives/src/types/eips.rs @@ -0,0 +1,169 @@ +#[cfg(feature = "rkyv")] +use crate::types::{ + access_list::{ArchivedAccessList, ArchivedAccessListItem}, + auth_list::ArchivedSignedAuthorization, + withdrawal::ArchivedWithdrawal, +}; +use crate::{ + U8, + types::{ + access_list::{AccessList, AccessListItem}, + auth_list::{Authorization, SignedAuthorization}, + withdrawal::Withdrawal, + }, +}; + +pub use alloy_eips::*; + +impl From<&eip2930::AccessListItem> for AccessListItem { + fn from(item: &eip2930::AccessListItem) -> Self { + Self { + address: item.address, + storage_keys: item.storage_keys.clone(), + } + } +} + +impl From for eip2930::AccessListItem { + fn from(item: AccessListItem) -> Self { + Self { + address: item.address, + storage_keys: item.storage_keys, + } + } +} + +impl From<&eip2930::AccessList> for AccessList { + fn from(list: &eip2930::AccessList) -> Self { + Self(list.0.iter().map(Into::into).collect()) + } +} + +impl From for eip2930::AccessList { + fn from(list: AccessList) -> Self { + Self(list.0.into_iter().map(Into::into).collect()) + } +} + +#[cfg(feature = "rkyv")] +impl From<&ArchivedAccessListItem> for eip2930::AccessListItem { + fn from(item: &ArchivedAccessListItem) -> Self { + Self { + address: crate::Address::from(item.address), + storage_keys: item + .storage_keys + .iter() + .map(|key| crate::B256::from(*key)) + .collect(), + } + } +} + +#[cfg(feature = "rkyv")] +impl From<&ArchivedAccessList> for eip2930::AccessList { + fn from(list: &ArchivedAccessList) -> Self { + Self( + list.0 + .iter() + .map(alloy_eips::eip2930::AccessListItem::from) + .collect(), + ) + } +} + +impl From<&eip7702::Authorization> for Authorization { + fn from(auth: &eip7702::Authorization) -> Self { + Self { + chain_id: auth.chain_id, + address: auth.address, + nonce: auth.nonce, + } + } +} + +impl From for eip7702::Authorization { + fn from(auth: Authorization) -> Self { + Self { + chain_id: auth.chain_id, + address: auth.address, + nonce: auth.nonce, + } + } +} + +impl From<&eip7702::SignedAuthorization> for SignedAuthorization { + fn from(auth: &eip7702::SignedAuthorization) -> Self { + Self { + inner: Authorization { + chain_id: auth.chain_id, + address: auth.address, + nonce: auth.nonce, + }, + y_parity: U8::from(auth.y_parity()), + r: auth.r(), + s: auth.s(), + } + } +} + +impl From for eip7702::SignedAuthorization { + fn from(auth: SignedAuthorization) -> Self { + eip7702::SignedAuthorization::new_unchecked( + auth.inner.into(), + auth.y_parity.to(), + auth.r, + auth.s, + ) + } +} + +#[cfg(feature = "rkyv")] +impl From<&ArchivedSignedAuthorization> for eip7702::SignedAuthorization { + fn from(auth: &ArchivedSignedAuthorization) -> Self { + let y_parity: U8 = From::from(&auth.y_parity); + eip7702::SignedAuthorization::new_unchecked( + eip7702::Authorization { + chain_id: auth.inner.chain_id.into(), + address: crate::Address::from(auth.inner.address), + nonce: auth.inner.nonce.to_native(), + }, + y_parity.to(), + auth.r.into(), + auth.s.into(), + ) + } +} + +impl From<&eip4895::Withdrawal> for Withdrawal { + fn from(withdrawal: &eip4895::Withdrawal) -> Self { + Self { + index: withdrawal.index, + validator_index: withdrawal.validator_index, + address: withdrawal.address, + amount: withdrawal.amount, + } + } +} + +impl From<&Withdrawal> for eip4895::Withdrawal { + fn from(withdrawal: &Withdrawal) -> Self { + Self { + index: withdrawal.index, + validator_index: withdrawal.validator_index, + address: withdrawal.address, + amount: withdrawal.amount, + } + } +} + +#[cfg(feature = "rkyv")] +impl From<&ArchivedWithdrawal> for eip4895::Withdrawal { + fn from(withdrawal: &ArchivedWithdrawal) -> Self { + Self { + index: withdrawal.index.to_native(), + validator_index: withdrawal.validator_index.to_native(), + address: withdrawal.address.into(), + amount: withdrawal.amount.to_native(), + } + } +} diff --git a/crates/primitives/src/types/mod.rs b/crates/primitives/src/types/mod.rs index cd6d8411..51751944 100644 --- a/crates/primitives/src/types/mod.rs +++ b/crates/primitives/src/types/mod.rs @@ -1,103 +1,72 @@ mod access_list; mod auth_list; mod block_header; -#[cfg(feature = "scroll")] -mod scroll; mod signature; mod transaction; mod withdrawal; mod witness; -pub use access_list::{AccessList, AccessListItem, ArchivedAccessList, ArchivedAccessListItem}; -pub use alloy_consensus::{Header as AlloyHeader, TypedTransaction as AlloyTypedTransaction}; -pub use alloy_eips::eip4895::{Withdrawal as AlloyWithdrawal, Withdrawals as AlloyWithdrawals}; -pub use block_header::{ArchivedBlockHeader, BlockHeader}; -#[cfg(feature = "scroll")] -pub use scroll::*; -pub use signature::{ArchivedSignature, Signature}; -pub use transaction::{ArchivedTransaction, Transaction}; -pub use withdrawal::{ArchivedWithdrawal, Withdrawal}; -pub use witness::{ArchivedBlockWitness, BlockWitness, ExecutionWitness}; +pub use access_list::AccessList; +pub use block_header::BlockHeader; +pub use signature::Signature; +pub use transaction::Transaction; +pub use withdrawal::Withdrawal; +pub use witness::{BlockWitness, ExecutionWitness}; -/// re-export types from alloy_consensus -pub mod consensus { - pub use alloy_consensus::{ - BlockHeader, Header, SignableTransaction, Transaction, TxEip1559, TxEip2930, TxEip4844, - TxEip4844Variant, TxEip4844WithSidecar, TxEip7702, TxLegacy, Typed2718, +#[cfg(feature = "rkyv")] +mod rkyv_types { + pub use super::{ + access_list::{ArchivedAccessList, ArchivedAccessListItem}, + block_header::ArchivedBlockHeader, + signature::ArchivedSignature, + transaction::ArchivedTransaction, + withdrawal::ArchivedWithdrawal, + witness::ArchivedBlockWitness, }; +} +#[cfg(feature = "rkyv")] +pub use rkyv_types::*; - #[cfg(not(feature = "scroll"))] - pub use alloy_consensus::{TxEnvelope, TxType, TypedTransaction}; - use reth_primitives_traits::transaction::signature::Signature; - #[cfg(feature = "scroll")] - pub use scroll_alloy_consensus::{ - ScrollReceiptEnvelope as ReceiptEnvelope, ScrollTxEnvelope as TxEnvelope, - ScrollTxType as TxType, ScrollTypedTransaction as TypedTransaction, TxL1Message, - }; +/// re-export types from alloy_consensus +#[cfg(feature = "consensus-types")] +pub mod consensus; +#[cfg(feature = "consensus-types")] +pub use consensus::{Header as AlloyHeader, TypedTransaction as AlloyTypedTransaction}; - /// Extension trait for `TxEnvelope` - pub trait TxEnvelopeExt { - /// get the signature of the transaction - fn signature(&self) -> Option<&Signature>; +/// re-export types from alloy_eips +#[cfg(feature = "eips")] +pub mod eips; - /// get the index of the transaction in the queue - fn queue_index(&self) -> Option { - None - } - } +#[cfg(feature = "eips")] +pub use eips::eip4895::{Withdrawal as AlloyWithdrawal, Withdrawals as AlloyWithdrawals}; +/// re-export types from alloy_network +#[cfg(feature = "network-types")] +pub mod network { + /// Network definition #[cfg(not(feature = "scroll"))] - impl TxEnvelopeExt for TxEnvelope { - fn signature(&self) -> Option<&Signature> { - Some(TxEnvelope::signature(self)) - } - } - + pub type Network = alloy_network::Ethereum; + /// Network definition #[cfg(feature = "scroll")] - impl TxEnvelopeExt for TxEnvelope { - fn signature(&self) -> Option<&Signature> { - match self { - TxEnvelope::Legacy(tx) => Some(tx.signature()), - TxEnvelope::Eip2930(tx) => Some(tx.signature()), - TxEnvelope::Eip1559(tx) => Some(tx.signature()), - TxEnvelope::Eip7702(tx) => Some(tx.signature()), - _ => None, - } - } - - fn queue_index(&self) -> Option { - match self { - TxEnvelope::L1Message(tx) => Some(tx.queue_index), - _ => None, - } - } - } + pub type Network = scroll_alloy_network::Scroll; } +#[cfg(feature = "network-types")] +pub use network::*; + +/// re-export types from revm +#[cfg(feature = "revm-types")] +pub use revm; +#[cfg(feature = "revm-types")] +pub use revm::primitives::{AccountInfo, Bytecode}; /// re-export types from reth_primitives -pub mod reth { - #[cfg(not(feature = "scroll"))] - pub use reth_primitives::{Block, BlockBody, Receipt, TransactionSigned}; - #[cfg(feature = "scroll")] - pub use reth_scroll_primitives::{ - ScrollBlock as Block, ScrollBlockBody as BlockBody, ScrollReceipt as Receipt, - ScrollTransactionSigned as TransactionSigned, - }; -} +#[cfg(feature = "reth-types")] +pub mod reth; /// re-export types from alloy_rpc_types_eth -pub mod rpc { - pub use alloy_rpc_types_eth::{Header, Transaction as AlloyRpcTransaction}; - - #[cfg(not(feature = "scroll"))] - pub use alloy_rpc_types_eth::{Transaction, TransactionReceipt, TransactionRequest}; +#[cfg(feature = "rpc-types")] +pub mod rpc; - #[cfg(feature = "scroll")] - pub use scroll_alloy_rpc_types::{ - ScrollTransactionReceipt as TransactionReceipt, - ScrollTransactionRequest as TransactionRequest, Transaction, - }; - - /// Block representation for RPC. - pub type Block = alloy_rpc_types_eth::Block; -} +/// Scroll types +#[cfg(feature = "scroll")] +pub mod scroll; diff --git a/crates/primitives/src/types/reth.rs b/crates/primitives/src/types/reth.rs new file mode 100644 index 00000000..e1661114 --- /dev/null +++ b/crates/primitives/src/types/reth.rs @@ -0,0 +1,389 @@ +use crate::{ + Withdrawal, + alloy_primitives::SignatureError, + types::{ + Transaction, + consensus::{ + BlockWitnessConsensusExt, SignableTransaction, TxEip1559, TxEip2930, TxLegacy, + }, + }, +}; +use auto_impl::auto_impl; + +pub use reth_primitives::RecoveredBlock; + +#[cfg(not(feature = "scroll"))] +pub use reth_primitives::{Block, BlockBody, Receipt, TransactionSigned}; +#[cfg(feature = "scroll")] +pub use reth_scroll_primitives::{ + ScrollBlock as Block, ScrollBlockBody as BlockBody, ScrollReceipt as Receipt, + ScrollTransactionSigned as TransactionSigned, +}; + +/// BlockWitnessRethExt trait +#[auto_impl(&, &mut, Box, Rc, Arc)] +pub trait BlockWitnessRethExt: BlockWitnessConsensusExt { + /// Transactions + #[must_use] + fn build_typed_transactions( + &self, + ) -> impl ExactSizeIterator>; + + /// Build a reth block + fn build_reth_block(&self) -> Result, SignatureError> { + use reth_primitives_traits::transaction::signed::SignedTransaction; + + let header = self.build_alloy_header(); + let transactions = self + .build_typed_transactions() + .collect::, _>>()?; + let senders = transactions + .iter() + .map(|tx| tx.recover_signer()) + .collect::, _>>() + .expect("Failed to recover signer"); + + let body = BlockBody { + transactions, + ommers: vec![], + withdrawals: self.withdrawals_iter().map(|iter| { + super::eips::eip4895::Withdrawals( + iter.map(|w| super::eips::eip4895::Withdrawal { + index: w.index(), + validator_index: w.validator_index(), + address: w.address(), + amount: w.amount(), + }) + .collect(), + ) + }), + }; + + Ok(RecoveredBlock::new_unhashed( + Block { header, body }, + senders, + )) + } +} + +impl TryFrom<&Transaction> for TransactionSigned { + type Error = SignatureError; + + fn try_from(tx: &Transaction) -> Result { + let tx_type = tx.transaction_type; + + let tx = match tx_type { + 0x00 => { + let sig = tx.signature.expect("missing signature").into(); + let tx = TxLegacy { + chain_id: tx.chain_id, + nonce: tx.nonce, + gas_price: tx.gas_price.unwrap(), + gas_limit: tx.gas, + to: tx.to.into(), + value: tx.value, + input: tx.input.clone(), + }; + + tx.into_signed(sig).into() + } + 0x01 => { + let sig = tx.signature.expect("missing signature").into(); + let tx = TxEip2930 { + chain_id: tx.chain_id.expect("missing chain_id"), + nonce: tx.nonce, + gas_price: tx.gas_price.unwrap(), + gas_limit: tx.gas, + to: tx.to.into(), + value: tx.value, + access_list: tx.access_list.clone().expect("missing access_list").into(), + input: tx.input.clone(), + }; + + tx.into_signed(sig).into() + } + 0x02 => { + let sig = tx.signature.expect("missing signature").into(); + let tx = TxEip1559 { + chain_id: tx.chain_id.expect("missing chain_id"), + nonce: tx.nonce, + max_fee_per_gas: tx.max_fee_per_gas, + max_priority_fee_per_gas: tx + .max_priority_fee_per_gas + .expect("missing max_priority_fee_per_gas"), + gas_limit: tx.gas, + to: tx.to.into(), + value: tx.value, + access_list: tx.access_list.clone().expect("missing access_list").into(), + input: tx.input.clone(), + }; + + tx.into_signed(sig).into() + } + #[cfg(not(feature = "scroll"))] + 0x03 => { + let sig = tx.signature.expect("missing signature").into(); + let tx = super::consensus::TxEip4844 { + chain_id: tx.chain_id.expect("missing chain_id"), + nonce: tx.nonce, + max_fee_per_gas: tx.max_fee_per_gas, + max_priority_fee_per_gas: tx + .max_priority_fee_per_gas + .expect("missing max_priority_fee_per_gas"), + gas_limit: tx.gas, + to: tx.to.expect("missing to"), + value: tx.value, + input: tx.input.clone(), + access_list: tx.access_list.clone().expect("missing access_list").into(), + blob_versioned_hashes: tx + .blob_versioned_hashes + .clone() + .expect("missing blob_versioned_hashes"), + max_fee_per_blob_gas: tx + .max_fee_per_blob_gas + .expect("missing max_fee_per_blob_gas"), + }; + tx.into_signed(sig).into() + } + 0x04 => { + let sig = tx.signature.expect("missing signature").into(); + let tx = super::consensus::TxEip7702 { + chain_id: tx.chain_id.expect("missing chain_id"), + nonce: tx.nonce, + gas_limit: tx.gas, + max_fee_per_gas: tx.max_fee_per_gas, + max_priority_fee_per_gas: tx + .max_priority_fee_per_gas + .expect("missing max_priority_fee_per_gas"), + to: tx.to.expect("missing to"), + value: tx.value, + access_list: tx.access_list.clone().expect("missing access_list").into(), + authorization_list: tx + .authorization_list + .as_ref() + .expect("missing authorization_list") + .iter() + .cloned() + .map(|x| x.into()) + .collect(), + input: tx.input.clone(), + }; + tx.into_signed(sig).into() + } + #[cfg(feature = "scroll")] + 0x7e => { + use super::consensus::TxL1Message; + let tx = TxL1Message { + queue_index: tx.queue_index.expect("missing queue_index"), + gas_limit: tx.gas, + to: tx.to.expect("missing to"), + value: tx.value, + sender: tx.from, + input: tx.input.clone(), + }; + + TransactionSigned::new_unhashed(tx.into(), TxL1Message::signature()) + } + _ => unimplemented!("unsupported tx type: {}", tx_type), + }; + + Ok(tx) + } +} + +#[cfg(feature = "rkyv")] +impl TryFrom<&super::ArchivedTransaction> for TransactionSigned { + type Error = SignatureError; + + fn try_from(tx: &super::ArchivedTransaction) -> Result { + let tx_type = tx.transaction_type; + let input = crate::Bytes::copy_from_slice(tx.input.as_slice()); + let to = tx.to.as_ref().map(|to| crate::Address::from(*to)); + + let tx = match tx_type { + 0x00 => { + let sig = tx.signature.as_ref().expect("missing signature").into(); + let tx = TxLegacy { + chain_id: tx.chain_id.as_ref().map(|x| x.to_native()), + nonce: tx.nonce.to_native(), + gas_price: tx.gas_price.unwrap().to_native(), + gas_limit: tx.gas.to_native(), + to: to.into(), + value: tx.value.into(), + input, + }; + + tx.into_signed(sig).into() + } + 0x01 => { + let sig = tx.signature.as_ref().expect("missing signature").into(); + let tx = TxEip2930 { + chain_id: tx.chain_id.as_ref().expect("missing chain_id").to_native(), + nonce: tx.nonce.to_native(), + gas_price: tx.gas_price.unwrap().to_native(), + gas_limit: tx.gas.to_native(), + to: to.into(), + value: tx.value.into(), + access_list: tx.access_list.as_ref().expect("missing access_list").into(), + input, + }; + + tx.into_signed(sig).into() + } + 0x02 => { + let sig = tx.signature.as_ref().expect("missing signature").into(); + let tx = TxEip1559 { + chain_id: tx.chain_id.as_ref().expect("missing chain_id").to_native(), + nonce: tx.nonce.to_native(), + max_fee_per_gas: tx.max_fee_per_gas.to_native(), + max_priority_fee_per_gas: tx + .max_priority_fee_per_gas + .as_ref() + .expect("missing max_priority_fee_per_gas") + .to_native(), + gas_limit: tx.gas.to_native(), + to: to.into(), + value: tx.value.into(), + access_list: tx.access_list.as_ref().expect("missing access_list").into(), + input, + }; + + tx.into_signed(sig).into() + } + #[cfg(not(feature = "scroll"))] + 0x03 => { + let sig = tx.signature.as_ref().expect("missing signature").into(); + let tx = super::consensus::TxEip4844 { + chain_id: tx.chain_id.as_ref().expect("missing chain_id").to_native(), + nonce: tx.nonce.to_native(), + max_fee_per_gas: tx.max_fee_per_gas.to_native(), + max_priority_fee_per_gas: tx + .max_priority_fee_per_gas + .as_ref() + .expect("missing max_priority_fee_per_gas") + .to_native(), + gas_limit: tx.gas.to_native(), + to: to.expect("missing to"), + value: tx.value.into(), + input, + access_list: tx.access_list.as_ref().expect("missing access_list").into(), + blob_versioned_hashes: tx + .blob_versioned_hashes + .as_ref() + .expect("missing blob_versioned_hashes") + .iter() + .map(|x| crate::B256::from(*x)) + .collect(), + max_fee_per_blob_gas: tx + .max_fee_per_blob_gas + .as_ref() + .expect("missing max_fee_per_blob_gas") + .to_native(), + }; + tx.into_signed(sig).into() + } + 0x04 => { + let sig = tx.signature.as_ref().expect("missing signature").into(); + let tx = super::consensus::TxEip7702 { + chain_id: tx.chain_id.as_ref().expect("missing chain_id").to_native(), + nonce: tx.nonce.to_native(), + gas_limit: tx.gas.to_native(), + max_fee_per_gas: tx.max_fee_per_gas.to_native(), + max_priority_fee_per_gas: tx + .max_priority_fee_per_gas + .as_ref() + .expect("missing max_priority_fee_per_gas") + .to_native(), + to: to.expect("missing to"), + value: tx.value.into(), + access_list: tx.access_list.as_ref().expect("missing access_list").into(), + authorization_list: tx + .authorization_list + .as_ref() + .expect("missing authorization_list") + .iter() + .map(|x| x.into()) + .collect(), + input, + }; + tx.into_signed(sig).into() + } + #[cfg(feature = "scroll")] + 0x7e => { + let tx = super::consensus::TxL1Message { + queue_index: tx + .queue_index + .as_ref() + .expect("missing queue_index") + .to_native(), + gas_limit: tx.gas.to_native(), + to: to.expect("missing to"), + value: tx.value.into(), + sender: crate::Address::from(tx.from), + input, + }; + + TransactionSigned::new_unhashed( + tx.into(), + super::consensus::TxL1Message::signature(), + ) + } + _ => unimplemented!("unsupported tx type: {}", tx_type), + }; + + Ok(tx) + } +} + +impl BlockWitnessRethExt for super::BlockWitness { + fn build_typed_transactions( + &self, + ) -> impl ExactSizeIterator> { + self.transaction.iter().map(|tx| tx.try_into()) + } +} + +#[cfg(feature = "rkyv")] +impl BlockWitnessRethExt for super::ArchivedBlockWitness { + fn build_typed_transactions( + &self, + ) -> impl ExactSizeIterator> { + self.transaction.iter().map(|tx| tx.try_into()) + } +} + +#[cfg(feature = "rpc-types")] +impl super::BlockWitness { + /// Creates a new block witness from a block, pre-state root, execution witness. + pub fn new_from_block( + chain_id: crate::ChainId, + block: super::rpc::Block, + pre_state_root: crate::B256, + #[cfg(not(feature = "scroll"))] block_hashes: Vec, + witness: super::ExecutionWitness, + ) -> Self { + let header = super::BlockHeader::from(block.header); + + let transaction = block + .transactions + .into_transactions() + .map(Transaction::from_rpc) + .collect(); + let withdrawals = block + .withdrawals + .map(|w| w.iter().map(super::Withdrawal::from).collect()); + let states = witness.state.into_values().collect(); + let codes = witness.codes.into_values().collect(); + Self { + chain_id, + header, + transaction, + #[cfg(not(feature = "scroll"))] + block_hashes, + withdrawals, + pre_state_root, + states, + codes, + } + } +} diff --git a/crates/primitives/src/types/rpc.rs b/crates/primitives/src/types/rpc.rs new file mode 100644 index 00000000..476e3bf0 --- /dev/null +++ b/crates/primitives/src/types/rpc.rs @@ -0,0 +1,60 @@ +pub use alloy_rpc_types_eth::{Header, Transaction as AlloyRpcTransaction}; + +#[cfg(not(feature = "scroll"))] +pub use alloy_rpc_types_eth::{Transaction, TransactionReceipt, TransactionRequest}; +#[cfg(feature = "scroll")] +pub use scroll_alloy_rpc_types::{ + ScrollTransactionReceipt as TransactionReceipt, ScrollTransactionRequest as TransactionRequest, + Transaction, +}; + +/// Block representation for RPC. +pub type Block = alloy_rpc_types_eth::Block; + +#[cfg(feature = "consensus-types")] +use crate::types::{ + auth_list::SignedAuthorization, + consensus::{Transaction as _, TxEnvelope, TxEnvelopeExt}, + eips::{Encodable2718, Typed2718}, +}; + +#[cfg(feature = "consensus-types")] +impl crate::types::Transaction { + /// Create a transaction from a rpc transaction + #[cfg(feature = "scroll")] + pub fn from_rpc(tx: Transaction) -> Self { + crate::types::Transaction::from_rpc_inner(tx.inner) + } + + /// Create a transaction from a rpc transaction + #[cfg(not(feature = "scroll"))] + pub fn from_rpc(tx: Transaction) -> Self { + crate::types::Transaction::from_rpc_inner(tx) + } + + fn from_rpc_inner(tx: AlloyRpcTransaction) -> Self { + Self { + hash: tx.inner.trie_hash(), + nonce: tx.nonce(), + from: tx.from, + to: tx.to(), + value: tx.value(), + gas_price: tx.gas_price(), + gas: tx.gas_limit(), + max_fee_per_gas: tx.max_fee_per_gas(), + max_priority_fee_per_gas: tx.max_priority_fee_per_gas(), + max_fee_per_blob_gas: tx.max_fee_per_blob_gas(), + input: tx.input().clone(), + signature: TxEnvelopeExt::signature(&tx.inner).map(Into::into), + chain_id: tx.chain_id(), + blob_versioned_hashes: tx.blob_versioned_hashes().map(Vec::from), + access_list: tx.access_list().map(Into::into), + transaction_type: tx.ty(), + authorization_list: tx + .authorization_list() + .map(|list| list.iter().map(Into::::into).collect()), + #[cfg(feature = "scroll")] + queue_index: tx.inner.queue_index(), + } + } +} diff --git a/crates/primitives/src/types/scroll/chunk.rs b/crates/primitives/src/types/scroll/chunk.rs index 519400df..e7ab7450 100644 --- a/crates/primitives/src/types/scroll/chunk.rs +++ b/crates/primitives/src/types/scroll/chunk.rs @@ -3,18 +3,13 @@ use crate::{B256, U256}; use tiny_keccak::{Hasher, Keccak}; /// ChunkInfo is metadata of chunk. -#[derive( - Clone, - Debug, - PartialEq, - Eq, - serde::Serialize, - serde::Deserialize, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ChunkInfo { /// ChunkInfo before EuclidV2 hardfork Legacy(LegacyChunkInfo), @@ -23,117 +18,156 @@ pub enum ChunkInfo { } /// ChunkInfo before EuclidV2 hardfork -#[derive( - Clone, - Debug, - PartialEq, - Eq, - serde::Serialize, - serde::Deserialize, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct LegacyChunkInfo { /// The EIP-155 chain ID for all txs in the chunk. - #[rkyv(attr(doc = "The EIP-155 chain ID for all txs in the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The EIP-155 chain ID for all txs in the chunk.")) + )] pub chain_id: u64, /// The state root before applying the chunk. - #[rkyv(attr(doc = "The state root before applying the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The state root before applying the chunk.")) + )] pub prev_state_root: B256, /// The state root after applying the chunk. - #[rkyv(attr(doc = "The state root after applying the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The state root after applying the chunk.")) + )] pub post_state_root: B256, /// The withdrawals root after applying the chunk. - #[rkyv(attr(doc = "The withdrawals root after applying the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The withdrawals root after applying the chunk.")) + )] pub withdraw_root: B256, /// Digest of L1 message txs force included in the chunk. - #[rkyv(attr(doc = "Digest of L1 message txs force included in the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Digest of L1 message txs force included in the chunk.")) + )] pub data_hash: B256, /// Digest of L2 tx data flattened over all L2 txs in the chunk. - #[rkyv(attr(doc = "Digest of L2 tx data flattened over all L2 txs in the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Digest of L2 tx data flattened over all L2 txs in the chunk.")) + )] pub tx_data_digest: B256, } /// ChunkInfo after EuclidV2 hardfork -#[derive( - Clone, - Debug, - PartialEq, - Eq, - serde::Serialize, - serde::Deserialize, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct EuclidV2ChunkInfo { /// The EIP-155 chain ID for all txs in the chunk. - #[rkyv(attr(doc = "The EIP-155 chain ID for all txs in the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The EIP-155 chain ID for all txs in the chunk.")) + )] pub chain_id: u64, /// The state root before applying the chunk. - #[rkyv(attr(doc = "The state root before applying the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The state root before applying the chunk.")) + )] pub prev_state_root: B256, /// The state root after applying the chunk. - #[rkyv(attr(doc = "The state root after applying the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The state root after applying the chunk.")) + )] pub post_state_root: B256, /// The withdrawals root after applying the chunk. - #[rkyv(attr(doc = "The withdrawals root after applying the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The withdrawals root after applying the chunk.")) + )] pub withdraw_root: B256, /// length of L2 tx data (rlp encoded) flattened over all L2 txs in the chunk. - #[rkyv(attr(doc = "Digest of L2 tx data flattened over all L2 txs in the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Digest of L2 tx data flattened over all L2 txs in the chunk.")) + )] pub tx_data_length: usize, /// Digest of L2 tx data flattened over all L2 txs in the chunk. - #[rkyv(attr(doc = "Digest of L2 tx data flattened over all L2 txs in the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Digest of L2 tx data flattened over all L2 txs in the chunk.")) + )] pub tx_data_digest: B256, /// Rolling hash of message queue before applying the chunk. - #[rkyv(attr(doc = "Rolling hash of message queue before applying the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Rolling hash of message queue before applying the chunk.")) + )] pub prev_msg_queue_hash: B256, /// Rolling hash of message queue after applying the chunk. - #[rkyv(attr(doc = "Rolling hash of message queue after applying the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Rolling hash of message queue after applying the chunk.")) + )] pub post_msg_queue_hash: B256, /// The block number of the first block in the chunk. - #[rkyv(attr(doc = "The block number of the first block in the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The block number of the first block in the chunk.")) + )] pub initial_block_number: u64, /// The block contexts of the blocks in the chunk. - #[rkyv(attr(doc = "The block contexts of the blocks in the chunk."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The block contexts of the blocks in the chunk.")) + )] pub block_ctxs: Vec, } /// Represents the version 2 of block context. /// /// The difference between v2 and v1 is that the block number field has been removed since v2. -#[derive( - Clone, - Debug, - PartialEq, - Eq, - serde::Serialize, - serde::Deserialize, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BlockContextV2 { /// The timestamp of the block. - #[rkyv(attr(doc = "The timestamp of the block."))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "The timestamp of the block.")))] pub timestamp: u64, /// The base fee of the block. - #[rkyv(attr(doc = "The base fee of the block."))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "The base fee of the block.")))] pub base_fee: U256, /// The gas limit of the block. - #[rkyv(attr(doc = "The gas limit of the block."))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "The gas limit of the block.")))] pub gas_limit: u64, /// The number of transactions in the block, including both L1 msg txs and L2 txs. - #[rkyv(attr( - doc = "The number of transactions in the block, including both L1 msg txs and L2 txs." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "The number of transactions in the block, including both L1 msg txs and L2 txs." + )) + )] pub num_txs: u16, /// The number of L1 msg txs in the block. - #[rkyv(attr(doc = "The number of L1 msg txs in the block."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The number of L1 msg txs in the block.")) + )] pub num_l1_msgs: u16, } @@ -244,6 +278,7 @@ impl ChunkInfo { } } +#[cfg(feature = "rkyv")] impl ArchivedChunkInfo { /// Public input hash for a given chunk is defined as /// @@ -343,6 +378,7 @@ impl EuclidV2ChunkInfo { } } +#[cfg(feature = "rkyv")] impl ArchivedLegacyChunkInfo { /// Public input hash for a given chunk is defined as /// ```text @@ -371,6 +407,7 @@ impl ArchivedLegacyChunkInfo { } } +#[cfg(feature = "rkyv")] impl ArchivedEuclidV2ChunkInfo { /// Public input hash for a given chunk is defined as /// ```text @@ -454,6 +491,7 @@ impl> From for BlockContextV2 { } } +#[cfg(feature = "rkyv")] impl ArchivedBlockContextV2 { /// Number of bytes used to serialise [`BlockContextV2`] into bytes. pub const BYTES_SIZE: usize = BlockContextV2::BYTES_SIZE; @@ -482,6 +520,7 @@ impl ArchivedBlockContextV2 { } #[cfg(test)] +#[cfg(feature = "rkyv")] mod tests { use super::*; use rkyv::rancor; diff --git a/crates/primitives/src/types/scroll/chunk_builder.rs b/crates/primitives/src/types/scroll/chunk_builder.rs index b06e2ca9..9f4cfd1f 100644 --- a/crates/primitives/src/types/scroll/chunk_builder.rs +++ b/crates/primitives/src/types/scroll/chunk_builder.rs @@ -1,9 +1,12 @@ use crate::{ - B256, BlockChunkExt, RecoveredBlock, + B256, chainspec::ChainSpec, - ext::TxBytesHashExt, + ext::{BlockChunkExt, TxBytesHashExt}, hardforks::ScrollHardforks, - types::{BlockContextV2, ChunkInfo, EuclidV2ChunkInfo, LegacyChunkInfo, reth::Block}, + types::{ + reth::{Block, RecoveredBlock}, + scroll::{BlockContextV2, ChunkInfo, EuclidV2ChunkInfo, LegacyChunkInfo}, + }, }; use alloy_primitives::U256; use itertools::Itertools; diff --git a/crates/primitives/src/types/scroll/mod.rs b/crates/primitives/src/types/scroll/mod.rs index 4c4041f5..a436458d 100644 --- a/crates/primitives/src/types/scroll/mod.rs +++ b/crates/primitives/src/types/scroll/mod.rs @@ -1,18 +1,27 @@ use crate::B256; -use serde::{Deserialize, Serialize}; mod chunk; pub use chunk::*; +#[cfg(all(feature = "scroll-reth-types", feature = "scroll-hardforks"))] mod chunk_builder; +#[cfg(all(feature = "scroll-reth-types", feature = "scroll-hardforks"))] pub use chunk_builder::*; /// RPC response of the `scroll_diskRoot` method. -#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct DiskRoot { /// MPT state root - #[serde(rename = "diskRoot")] + #[cfg_attr(feature = "serde", serde(rename = "diskRoot"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "MPT state root")))] pub disk_root: B256, /// B-MPT state root - #[serde(rename = "headerRoot")] + #[cfg_attr(feature = "serde", serde(rename = "headerRoot"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "B-MPT state root")))] pub header_root: B256, } diff --git a/crates/primitives/src/types/signature.rs b/crates/primitives/src/types/signature.rs index 014a385c..dfb40924 100644 --- a/crates/primitives/src/types/signature.rs +++ b/crates/primitives/src/types/signature.rs @@ -1,29 +1,31 @@ use crate::{PrimitiveSignature, U256}; /// An Ethereum ECDSA signature. -#[derive( - Copy, - Clone, - Debug, - Default, - PartialEq, - Eq, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, - serde::Serialize, - serde::Deserialize, +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, Hash, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Signature { /// The R field of the signature; the point on the curve. - #[rkyv(attr(doc = "The R field of the signature; the point on the curve."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The R field of the signature; the point on the curve.")) + )] pub r: U256, /// The S field of the signature; the point on the curve. - #[rkyv(attr(doc = "The S field of the signature; the point on the curve."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The S field of the signature; the point on the curve.")) + )] pub s: U256, /// The parity of the Y coordinate of the public key. - #[rkyv(attr(doc = "The parity of the Y coordinate of the public key."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The parity of the Y coordinate of the public key.")) + )] pub y_parity: bool, } @@ -43,6 +45,7 @@ impl From for PrimitiveSignature { } } +#[cfg(feature = "rkyv")] impl From<&ArchivedSignature> for PrimitiveSignature { fn from(sig: &ArchivedSignature) -> Self { Self::new(sig.r.into(), sig.s.into(), sig.y_parity) diff --git a/crates/primitives/src/types/transaction.rs b/crates/primitives/src/types/transaction.rs index 3ac49def..e1e1510e 100644 --- a/crates/primitives/src/types/transaction.rs +++ b/crates/primitives/src/types/transaction.rs @@ -1,434 +1,128 @@ use crate::{ Address, B256, Bytes, ChainId, TxHash, U256, - alloy_primitives::SignatureError, - eips::Encodable2718, - types::{ - access_list::AccessList, - auth_list::SignedAuthorization, - consensus::{ - SignableTransaction, Transaction as _, TxEip1559, TxEip2930, TxEnvelope, TxEnvelopeExt, - TxLegacy, Typed2718, - }, - reth::TransactionSigned, - rpc::AlloyRpcTransaction, - signature::Signature, - }, + types::{access_list::AccessList, auth_list::SignedAuthorization, signature::Signature}, }; /// Transaction object used in RPC -#[derive( - Clone, - Debug, - Default, - PartialEq, - Eq, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, - serde::Serialize, - serde::Deserialize, +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, Hash, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Transaction { /// Hash - #[rkyv(attr(doc = "Hash"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Hash")))] pub hash: TxHash, /// Nonce - #[rkyv(attr(doc = "Nonce"))] - #[serde(with = "alloy_serde::quantity")] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Nonce")))] + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] pub nonce: u64, /// Sender - #[rkyv(attr(doc = "Sender"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Sender")))] pub from: Address, /// Recipient - #[rkyv(attr(doc = "Recipient"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Recipient")))] pub to: Option
, /// Transferred value - #[rkyv(attr(doc = "Transferred value"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Transferred value")))] pub value: U256, /// Gas Price - #[rkyv(attr(doc = "Gas Price"))] - #[serde( - default, - with = "alloy_serde::quantity::opt", + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Gas Price")))] + #[cfg_attr( + feature = "serde", + serde(default, with = "alloy_serde::quantity::opt",) )] pub gas_price: Option, /// Gas amount - #[rkyv(attr(doc = "Gas amount"))] - #[serde(with = "alloy_serde::quantity")] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Gas amount")))] + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] pub gas: u64, /// Max BaseFeePerGas the user is willing to pay. - #[rkyv(attr(doc = "Max BaseFeePerGas the user is willing to pay."))] - #[serde(with = "alloy_serde::quantity")] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Max BaseFeePerGas the user is willing to pay.")) + )] + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] pub max_fee_per_gas: u128, /// The miner's tip. - #[rkyv(attr(doc = "The miner's tip."))] - #[serde( - default, - with = "alloy_serde::quantity::opt", + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "The miner's tip.")))] + #[cfg_attr( + feature = "serde", + serde(default, with = "alloy_serde::quantity::opt",) )] pub max_priority_fee_per_gas: Option, /// Configured max fee per blob gas for eip-4844 transactions - #[rkyv(attr(doc = "Configured max fee per blob gas for eip-4844 transactions"))] - #[serde( - default, - with = "alloy_serde::quantity::opt", + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Configured max fee per blob gas for eip-4844 transactions")) + )] + #[cfg_attr( + feature = "serde", + serde(default, with = "alloy_serde::quantity::opt",) )] pub max_fee_per_blob_gas: Option, /// Data - #[rkyv(attr(doc = "Data"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Data")))] pub input: Bytes, /// All _flattened_ fields of the transaction signature. /// /// Note: this is an option so special transaction types without a signature (e.g. ) can be supported. - #[rkyv(attr( - doc = "All _flattened_ fields of the transaction signature. Note: this is an option so special transaction types without a signature (e.g. ) can be supported." - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "All _flattened_ fields of the transaction signature. Note: this is an option so special transaction types without a signature (e.g. ) can be supported." + )) + )] pub signature: Option, /// The chain id of the transaction, if any. - #[rkyv(attr(doc = "The chain id of the transaction, if any."))] - #[serde( - default, - with = "alloy_serde::quantity::opt" + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "The chain id of the transaction, if any.")) )] + #[cfg_attr(feature = "serde", serde(default, with = "alloy_serde::quantity::opt"))] pub chain_id: Option, /// Contains the blob hashes for eip-4844 transactions. - #[rkyv(attr(doc = "Contains the blob hashes for eip-4844 transactions."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Contains the blob hashes for eip-4844 transactions.")) + )] pub blob_versioned_hashes: Option>, /// EIP2930 /// /// Pre-pay to warm storage access. - #[rkyv(attr(doc = "EIP2930 Pre-pay to warm storage access."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "EIP2930 Pre-pay to warm storage access.")) + )] pub access_list: Option, /// EIP7702 /// /// Authorizations are used to temporarily set the code of its signer to /// the code referenced by `address`. These also include a `chain_id` (which /// can be set to zero and not evaluated) as well as an optional `nonce`. - #[rkyv(attr(doc = "EIP7702 Authorizations"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "EIP7702 Authorizations")))] pub authorization_list: Option>, /// EIP2718 /// /// Transaction type, /// Some(4) for EIP-7702 transaction, Some(3) for EIP-4844 transaction, Some(2) for EIP-1559 /// transaction, Some(1) for AccessList transaction, None or Some(0) for Legacy - #[rkyv(attr( - doc = "EIP2718 Transaction type, Some(4) for EIP-7702 transaction, Some(3) for EIP-4844 transaction, Some(2) for EIP-1559 transaction, Some(1) for AccessList transaction, None or Some(0) for Legacy" - ))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr( + doc = "EIP2718 Transaction type, Some(4) for EIP-7702 transaction, Some(3) for EIP-4844 transaction, Some(2) for EIP-1559 transaction, Some(1) for AccessList transaction, None or Some(0) for Legacy" + )) + )] #[doc(alias = "tx_type")] pub transaction_type: u8, /// L1Msg queueIndex #[cfg(feature = "scroll")] - #[rkyv(attr(doc = "L1Msg queueIndex"))] - #[serde( - default, - with = "alloy_serde::quantity::opt", + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "L1Msg queueIndex")))] + #[cfg_attr( + feature = "serde", + serde(default, with = "alloy_serde::quantity::opt",) )] pub queue_index: Option, } - -impl Transaction { - /// Create a transaction from a rpc transaction - #[cfg(feature = "scroll")] - pub fn from_rpc(tx: crate::types::rpc::Transaction) -> Self { - Transaction::from_rpc_inner(tx.inner) - } - - /// Create a transaction from a rpc transaction - #[cfg(not(feature = "scroll"))] - pub fn from_rpc(tx: crate::types::rpc::Transaction) -> Self { - Transaction::from_rpc_inner(tx) - } - - fn from_rpc_inner(tx: AlloyRpcTransaction) -> Self { - Self { - hash: tx.inner.trie_hash(), - nonce: tx.nonce(), - from: tx.from, - to: tx.to(), - value: tx.value(), - gas_price: tx.gas_price(), - gas: tx.gas_limit(), - max_fee_per_gas: tx.max_fee_per_gas(), - max_priority_fee_per_gas: tx.max_priority_fee_per_gas(), - max_fee_per_blob_gas: tx.max_fee_per_blob_gas(), - input: tx.input().clone(), - signature: TxEnvelopeExt::signature(&tx.inner).map(Into::into), - chain_id: tx.chain_id(), - blob_versioned_hashes: tx.blob_versioned_hashes().map(Vec::from), - access_list: tx.access_list().map(Into::into), - transaction_type: tx.ty(), - authorization_list: tx - .authorization_list() - .map(|list| list.iter().map(Into::::into).collect()), - #[cfg(feature = "scroll")] - queue_index: tx.inner.queue_index(), // FIXME: scroll mode - } - } -} - -impl TryFrom<&Transaction> for TransactionSigned { - type Error = SignatureError; - - fn try_from(tx: &Transaction) -> Result { - let tx_type = tx.transaction_type; - - let tx = match tx_type { - 0x00 => { - let sig = tx.signature.expect("missing signature").into(); - let tx = TxLegacy { - chain_id: tx.chain_id, - nonce: tx.nonce, - gas_price: tx.gas_price.unwrap(), - gas_limit: tx.gas, - to: tx.to.into(), - value: tx.value, - input: tx.input.clone(), - }; - - tx.into_signed(sig).into() - } - 0x01 => { - let sig = tx.signature.expect("missing signature").into(); - let tx = TxEip2930 { - chain_id: tx.chain_id.expect("missing chain_id"), - nonce: tx.nonce, - gas_price: tx.gas_price.unwrap(), - gas_limit: tx.gas, - to: tx.to.into(), - value: tx.value, - access_list: tx.access_list.clone().expect("missing access_list").into(), - input: tx.input.clone(), - }; - - tx.into_signed(sig).into() - } - 0x02 => { - let sig = tx.signature.expect("missing signature").into(); - let tx = TxEip1559 { - chain_id: tx.chain_id.expect("missing chain_id"), - nonce: tx.nonce, - max_fee_per_gas: tx.max_fee_per_gas, - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .expect("missing max_priority_fee_per_gas"), - gas_limit: tx.gas, - to: tx.to.into(), - value: tx.value, - access_list: tx.access_list.clone().expect("missing access_list").into(), - input: tx.input.clone(), - }; - - tx.into_signed(sig).into() - } - #[cfg(not(feature = "scroll"))] - 0x03 => { - let sig = tx.signature.expect("missing signature").into(); - let tx = alloy_consensus::TxEip4844 { - chain_id: tx.chain_id.expect("missing chain_id"), - nonce: tx.nonce, - max_fee_per_gas: tx.max_fee_per_gas, - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .expect("missing max_priority_fee_per_gas"), - gas_limit: tx.gas, - to: tx.to.expect("missing to"), - value: tx.value, - input: tx.input.clone(), - access_list: tx.access_list.clone().expect("missing access_list").into(), - blob_versioned_hashes: tx - .blob_versioned_hashes - .clone() - .expect("missing blob_versioned_hashes"), - max_fee_per_blob_gas: tx - .max_fee_per_blob_gas - .expect("missing max_fee_per_blob_gas"), - }; - tx.into_signed(sig).into() - } - 0x04 => { - let sig = tx.signature.expect("missing signature").into(); - let tx = alloy_consensus::TxEip7702 { - chain_id: tx.chain_id.expect("missing chain_id"), - nonce: tx.nonce, - gas_limit: tx.gas, - max_fee_per_gas: tx.max_fee_per_gas, - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .expect("missing max_priority_fee_per_gas"), - to: tx.to.expect("missing to"), - value: tx.value, - access_list: tx.access_list.clone().expect("missing access_list").into(), - authorization_list: tx - .authorization_list - .as_ref() - .expect("missing authorization_list") - .iter() - .cloned() - .map(|x| x.into()) - .collect(), - input: tx.input.clone(), - }; - tx.into_signed(sig).into() - } - #[cfg(feature = "scroll")] - 0x7e => { - use scroll_alloy_consensus::TxL1Message; - let tx = TxL1Message { - queue_index: tx.queue_index.expect("missing queue_index"), - gas_limit: tx.gas, - to: tx.to.expect("missing to"), - value: tx.value, - sender: tx.from, - input: tx.input.clone(), - }; - - TransactionSigned::new_unhashed(tx.into(), TxL1Message::signature()) - } - _ => unimplemented!("unsupported tx type: {}", tx_type), - }; - - Ok(tx) - } -} - -impl TryFrom<&ArchivedTransaction> for TransactionSigned { - type Error = SignatureError; - - fn try_from(tx: &ArchivedTransaction) -> Result { - let tx_type = tx.transaction_type; - let input = Bytes::copy_from_slice(tx.input.as_slice()); - let to = tx.to.as_ref().map(|to| Address::from(*to)); - - let tx = match tx_type { - 0x00 => { - let sig = tx.signature.as_ref().expect("missing signature").into(); - let tx = TxLegacy { - chain_id: tx.chain_id.as_ref().map(|x| x.to_native()), - nonce: tx.nonce.to_native(), - gas_price: tx.gas_price.unwrap().to_native(), - gas_limit: tx.gas.to_native(), - to: to.into(), - value: tx.value.into(), - input, - }; - - tx.into_signed(sig).into() - } - 0x01 => { - let sig = tx.signature.as_ref().expect("missing signature").into(); - let tx = TxEip2930 { - chain_id: tx.chain_id.as_ref().expect("missing chain_id").to_native(), - nonce: tx.nonce.to_native(), - gas_price: tx.gas_price.unwrap().to_native(), - gas_limit: tx.gas.to_native(), - to: to.into(), - value: tx.value.into(), - access_list: tx.access_list.as_ref().expect("missing access_list").into(), - input, - }; - - tx.into_signed(sig).into() - } - 0x02 => { - let sig = tx.signature.as_ref().expect("missing signature").into(); - let tx = TxEip1559 { - chain_id: tx.chain_id.as_ref().expect("missing chain_id").to_native(), - nonce: tx.nonce.to_native(), - max_fee_per_gas: tx.max_fee_per_gas.to_native(), - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .as_ref() - .expect("missing max_priority_fee_per_gas") - .to_native(), - gas_limit: tx.gas.to_native(), - to: to.into(), - value: tx.value.into(), - access_list: tx.access_list.as_ref().expect("missing access_list").into(), - input, - }; - - tx.into_signed(sig).into() - } - #[cfg(not(feature = "scroll"))] - 0x03 => { - let sig = tx.signature.as_ref().expect("missing signature").into(); - let tx = alloy_consensus::TxEip4844 { - chain_id: tx.chain_id.as_ref().expect("missing chain_id").to_native(), - nonce: tx.nonce.to_native(), - max_fee_per_gas: tx.max_fee_per_gas.to_native(), - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .as_ref() - .expect("missing max_priority_fee_per_gas") - .to_native(), - gas_limit: tx.gas.to_native(), - to: to.expect("missing to"), - value: tx.value.into(), - input, - access_list: tx.access_list.as_ref().expect("missing access_list").into(), - blob_versioned_hashes: tx - .blob_versioned_hashes - .as_ref() - .expect("missing blob_versioned_hashes") - .iter() - .map(|x| B256::from(*x)) - .collect(), - max_fee_per_blob_gas: tx - .max_fee_per_blob_gas - .as_ref() - .expect("missing max_fee_per_blob_gas") - .to_native(), - }; - tx.into_signed(sig).into() - } - 0x04 => { - let sig = tx.signature.as_ref().expect("missing signature").into(); - let tx = alloy_consensus::TxEip7702 { - chain_id: tx.chain_id.as_ref().expect("missing chain_id").to_native(), - nonce: tx.nonce.to_native(), - gas_limit: tx.gas.to_native(), - max_fee_per_gas: tx.max_fee_per_gas.to_native(), - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .as_ref() - .expect("missing max_priority_fee_per_gas") - .to_native(), - to: to.expect("missing to"), - value: tx.value.into(), - access_list: tx.access_list.as_ref().expect("missing access_list").into(), - authorization_list: tx - .authorization_list - .as_ref() - .expect("missing authorization_list") - .iter() - .map(|x| x.into()) - .collect(), - input, - }; - tx.into_signed(sig).into() - } - #[cfg(feature = "scroll")] - 0x7e => { - use scroll_alloy_consensus::TxL1Message; - let tx = TxL1Message { - queue_index: tx - .queue_index - .as_ref() - .expect("missing queue_index") - .to_native(), - gas_limit: tx.gas.to_native(), - to: to.expect("missing to"), - value: tx.value.into(), - sender: Address::from(tx.from), - input, - }; - - TransactionSigned::new_unhashed(tx.into(), TxL1Message::signature()) - } - _ => unimplemented!("unsupported tx type: {}", tx_type), - }; - - Ok(tx) - } -} diff --git a/crates/primitives/src/types/withdrawal.rs b/crates/primitives/src/types/withdrawal.rs index dfef6757..39f3b290 100644 --- a/crates/primitives/src/types/withdrawal.rs +++ b/crates/primitives/src/types/withdrawal.rs @@ -1,50 +1,43 @@ use crate::Address; /// Withdrawal represents a validator withdrawal from the consensus layer. -#[derive( - Clone, - Copy, - Debug, - Default, - PartialEq, - Eq, - Hash, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, - serde::Serialize, - serde::Deserialize, +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Withdrawal { /// Monotonically increasing identifier issued by consensus layer. - #[rkyv(attr(doc = "Monotonically increasing identifier issued by consensus layer."))] - #[serde(with = "alloy_serde::quantity")] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Monotonically increasing identifier issued by consensus layer.")) + )] + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] pub index: u64, /// Index of validator associated with withdrawal. - #[rkyv(attr(doc = "Index of validator associated with withdrawal."))] - #[serde(with = "alloy_serde::quantity", rename = "validatorIndex")] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Index of validator associated with withdrawal.")) + )] + #[cfg_attr( + feature = "serde", + serde(with = "alloy_serde::quantity", rename = "validatorIndex") + )] pub validator_index: u64, /// Target address for withdrawn ether. - #[rkyv(attr(doc = "Target address for withdrawn ether."))] + #[cfg_attr( + feature = "rkyv", + rkyv(attr(doc = "Target address for withdrawn ether.")) + )] pub address: Address, /// Value of the withdrawal in gwei. - #[rkyv(attr(doc = "Value of the withdrawal in gwei."))] - #[serde(with = "alloy_serde::quantity")] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Value of the withdrawal in gwei.")))] + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] pub amount: u64, } -impl From<&alloy_eips::eip4895::Withdrawal> for Withdrawal { - fn from(withdrawal: &alloy_eips::eip4895::Withdrawal) -> Self { - Self { - index: withdrawal.index, - validator_index: withdrawal.validator_index, - address: withdrawal.address, - amount: withdrawal.amount, - } - } -} - impl crate::Withdrawal for Withdrawal { fn index(&self) -> u64 { self.index @@ -61,6 +54,7 @@ impl crate::Withdrawal for Withdrawal { } } +#[cfg(feature = "rkyv")] impl crate::Withdrawal for ArchivedWithdrawal { fn index(&self) -> u64 { self.index.to_native() diff --git a/crates/primitives/src/types/witness.rs b/crates/primitives/src/types/witness.rs index ff1a5bb2..f818ebb4 100644 --- a/crates/primitives/src/types/witness.rs +++ b/crates/primitives/src/types/witness.rs @@ -1,14 +1,13 @@ use crate::{ B256, Bytes, ChainId, alloy_primitives::map::B256HashMap, - types::{ - BlockHeader, Transaction, Withdrawal, block_header::ToHelper as _, reth::TransactionSigned, - rpc::Block, - }, + types::{BlockHeader, Transaction, Withdrawal}, }; +use alloy_primitives::BlockNumber; /// Represents the execution witness of a block. Contains an optional map of state preimages. -#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ExecutionWitness { /// Map of all hashed trie nodes to their preimages that were required during the execution of /// the block, including during state root recomputation. @@ -23,102 +22,60 @@ pub struct ExecutionWitness { } /// Witness for a block. -#[derive( - Clone, - Debug, - PartialEq, - Eq, - rkyv::Archive, - rkyv::Serialize, - rkyv::Deserialize, - serde::Serialize, - serde::Deserialize, +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), + rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[rkyv(derive(Debug, PartialEq, Eq))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BlockWitness { /// Chain id - #[rkyv(attr(doc = "Chain id"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Chain id")))] pub chain_id: ChainId, /// Block header representation. - #[rkyv(attr(doc = "Block header representation"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Block header representation")))] pub header: BlockHeader, /// State trie root before the block. - #[rkyv(attr(doc = "State trie root before the block"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "State trie root before the block")))] pub pre_state_root: B256, /// Transactions in the block. - #[rkyv(attr(doc = "Transactions in the block"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Transactions in the block")))] pub transaction: Vec, /// Withdrawals in the block. - #[rkyv(attr(doc = "Withdrawals in the block"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Withdrawals in the block")))] pub withdrawals: Option>, /// Last 256 Ancestor block hashes. - #[rkyv(attr(doc = "Ancestor block hashes"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Ancestor block hashes")))] #[cfg(not(feature = "scroll"))] pub block_hashes: Vec, /// Rlp encoded state trie nodes. - #[rkyv(attr(doc = "Rlp encoded state trie nodes"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Rlp encoded state trie nodes")))] pub states: Vec, /// Code bytecodes - #[rkyv(attr(doc = "Code bytecodes"))] + #[cfg_attr(feature = "rkyv", rkyv(attr(doc = "Code bytecodes")))] pub codes: Vec, } -impl BlockWitness { - /// Creates a new block witness from a block, pre-state root, execution witness. - pub fn new_from_block( - chain_id: ChainId, - block: Block, - pre_state_root: B256, - #[cfg(not(feature = "scroll"))] block_hashes: Vec, - witness: ExecutionWitness, - ) -> Self { - let header = BlockHeader::from(block.header); - let transaction = block - .transactions - .into_transactions() - .map(Transaction::from_rpc) - .collect(); - let withdrawals = block - .withdrawals - .map(|w| w.iter().map(Withdrawal::from).collect()); - let states = witness.state.into_values().collect(); - let codes = witness.codes.into_values().collect(); - Self { - chain_id, - header, - transaction, - #[cfg(not(feature = "scroll"))] - block_hashes, - withdrawals, - pre_state_root, - states, - codes, - } - } -} - impl crate::BlockWitness for BlockWitness { fn chain_id(&self) -> ChainId { self.chain_id } - fn header(&self) -> impl alloy_consensus::BlockHeader { - &self.header - } - fn build_alloy_header(&self) -> alloy_consensus::Header { - self.header.to_alloy() + fn number(&self) -> BlockNumber { + self.header.number } fn pre_state_root(&self) -> B256 { self.pre_state_root } + fn post_state_root(&self) -> B256 { + self.header.state_root + } + fn withdrawals_root(&self) -> Option { + self.header.withdrawals_root + } fn num_transactions(&self) -> usize { self.transaction.len() } - fn build_typed_transactions( - &self, - ) -> impl ExactSizeIterator> - { - self.transaction.iter().map(|tx| tx.try_into()) - } #[cfg(not(feature = "scroll"))] fn block_hashes_iter(&self) -> impl ExactSizeIterator { self.block_hashes.iter().copied() @@ -134,28 +91,26 @@ impl crate::BlockWitness for BlockWitness { } } +#[cfg(feature = "rkyv")] impl crate::BlockWitness for ArchivedBlockWitness { fn chain_id(&self) -> ChainId { self.chain_id.to_native() } - fn header(&self) -> impl alloy_consensus::BlockHeader { - &self.header - } - fn build_alloy_header(&self) -> alloy_consensus::Header { - self.header.to_alloy() + fn number(&self) -> BlockNumber { + self.header.number.to_native() } fn pre_state_root(&self) -> B256 { self.pre_state_root.into() } + fn post_state_root(&self) -> B256 { + self.header.state_root.into() + } + fn withdrawals_root(&self) -> Option { + self.header.withdrawals_root.as_ref().map(|x| x.0.into()) + } fn num_transactions(&self) -> usize { self.transaction.len() } - fn build_typed_transactions( - &self, - ) -> impl ExactSizeIterator> - { - self.transaction.iter().map(|tx| tx.try_into()) - } #[cfg(not(feature = "scroll"))] fn block_hashes_iter(&self) -> impl ExactSizeIterator { self.block_hashes.iter().map(|h| B256::from(h.0)) diff --git a/crates/sbv/Cargo.toml b/crates/sbv/Cargo.toml index bd213bfa..f5ae49db 100644 --- a/crates/sbv/Cargo.toml +++ b/crates/sbv/Cargo.toml @@ -15,6 +15,7 @@ sbv-kv.workspace = true sbv-primitives.workspace = true sbv-trie.workspace = true sbv-helpers.workspace = true +sbv-utils.workspace = true [features] scroll = ["sbv-core/scroll", "sbv-primitives/scroll", "sbv-core/scroll"] diff --git a/crates/sbv/src/lib.rs b/crates/sbv/src/lib.rs index 6c0bf251..123ac08a 100644 --- a/crates/sbv/src/lib.rs +++ b/crates/sbv/src/lib.rs @@ -5,6 +5,7 @@ pub use sbv_helpers as helpers; pub use sbv_kv as kv; pub use sbv_primitives as primitives; pub use sbv_trie as trie; +pub use sbv_utils as utils; pub use sbv_helpers::{ cycle_track, cycle_tracker_end, cycle_tracker_start, dev_debug, dev_error, dev_info, dev_trace, diff --git a/crates/trie/Cargo.toml b/crates/trie/Cargo.toml index a1110066..d69af073 100644 --- a/crates/trie/Cargo.toml +++ b/crates/trie/Cargo.toml @@ -29,7 +29,7 @@ serde_json.workspace = true [features] scroll = [ "reth-trie/scroll", - "sbv-primitives/scroll", + "sbv-primitives/scroll-all", ] dev = [ "sbv-primitives/dev", diff --git a/crates/trie/src/lib.rs b/crates/trie/src/lib.rs index deb4f76e..757b930d 100644 --- a/crates/trie/src/lib.rs +++ b/crates/trie/src/lib.rs @@ -9,7 +9,9 @@ use alloy_trie::{ }; use reth_trie_sparse::RevealedSparseTrie; use sbv_kv::{HashMap, nohash::NoHashMap}; -use sbv_primitives::{Address, B256, BlockWitness, U256, keccak256, revm::db::BundleAccount}; +use sbv_primitives::{ + Address, B256, BlockWitness, U256, keccak256, types::revm::db::BundleAccount, +}; use std::cell::RefCell; pub use alloy_trie::{TrieAccount, nodes::TrieNode}; diff --git a/crates/utils-cli/src/commands/witness/dump.rs b/crates/utils-cli/src/commands/witness/dump.rs index 2355acd6..f435a57b 100644 --- a/crates/utils-cli/src/commands/witness/dump.rs +++ b/crates/utils-cli/src/commands/witness/dump.rs @@ -6,7 +6,7 @@ use clap::Args; use console::{Emoji, style}; use indicatif::{HumanBytes, HumanDuration, ProgressBar, ProgressStyle}; use rkyv::rancor; -use sbv_primitives::Network; +use sbv_primitives::types::Network; use sbv_utils::rpc::ProviderExt; use std::{ path::PathBuf, diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index 63eb5c1d..6374316b 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -23,4 +23,4 @@ thiserror.workspace = true sbv-primitives.workspace = true [features] -scroll = ["sbv-primitives/scroll"] +scroll = ["sbv-primitives/scroll-all"] diff --git a/crates/utils/src/rpc.rs b/crates/utils/src/rpc.rs index 1e609b68..aacbe043 100644 --- a/crates/utils/src/rpc.rs +++ b/crates/utils/src/rpc.rs @@ -1,11 +1,7 @@ //! Rpc Extension use alloy_provider::{Provider, network::primitives::BlockTransactionsKind}; use alloy_transport::TransportResult; -use sbv_primitives::{ - Network, - eips::BlockNumberOrTag, - types::{BlockWitness, ExecutionWitness}, -}; +use sbv_primitives::types::{BlockWitness, ExecutionWitness, Network, eips::BlockNumberOrTag}; /// Extension trait for [`Provider`](Provider). #[async_trait::async_trait] @@ -25,9 +21,9 @@ pub trait ProviderExt: Provider { async fn scroll_disk_root( &self, number: BlockNumberOrTag, - ) -> TransportResult { + ) -> TransportResult { self.client() - .request::<_, sbv_primitives::types::DiskRoot>("scroll_diskRoot", (number,)) + .request::<_, sbv_primitives::types::scroll::DiskRoot>("scroll_diskRoot", (number,)) .await }