diff --git a/Cargo.lock b/Cargo.lock index 65fe6644c3..a11dd46e99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -723,7 +723,7 @@ dependencies = [ [[package]] name = "boa_ast" version = "0.17.0" -source = "git+https://github.com/boa-dev/boa#c2df31b781c115d6bdb5de64979d247af329ffcd" +source = "git+https://github.com/boa-dev/boa#9665f8be3be60f475d816ca10430631f43d6c962" dependencies = [ "bitflags 2.3.3", "boa_interner", @@ -736,7 +736,7 @@ dependencies = [ [[package]] name = "boa_engine" version = "0.17.0" -source = "git+https://github.com/boa-dev/boa#c2df31b781c115d6bdb5de64979d247af329ffcd" +source = "git+https://github.com/boa-dev/boa#9665f8be3be60f475d816ca10430631f43d6c962" dependencies = [ "bitflags 2.3.3", "boa_ast", @@ -774,7 +774,7 @@ dependencies = [ [[package]] name = "boa_gc" version = "0.17.0" -source = "git+https://github.com/boa-dev/boa#c2df31b781c115d6bdb5de64979d247af329ffcd" +source = "git+https://github.com/boa-dev/boa#9665f8be3be60f475d816ca10430631f43d6c962" dependencies = [ "boa_macros", "boa_profiler", @@ -785,7 +785,7 @@ dependencies = [ [[package]] name = "boa_icu_provider" version = "0.17.0" -source = "git+https://github.com/boa-dev/boa#c2df31b781c115d6bdb5de64979d247af329ffcd" +source = "git+https://github.com/boa-dev/boa#9665f8be3be60f475d816ca10430631f43d6c962" dependencies = [ "icu_collections", "icu_normalizer", @@ -798,7 +798,7 @@ dependencies = [ [[package]] name = "boa_interner" version = "0.17.0" -source = "git+https://github.com/boa-dev/boa#c2df31b781c115d6bdb5de64979d247af329ffcd" +source = "git+https://github.com/boa-dev/boa#9665f8be3be60f475d816ca10430631f43d6c962" dependencies = [ "boa_gc", "boa_macros", @@ -813,7 +813,7 @@ dependencies = [ [[package]] name = "boa_macros" version = "0.17.0" -source = "git+https://github.com/boa-dev/boa#c2df31b781c115d6bdb5de64979d247af329ffcd" +source = "git+https://github.com/boa-dev/boa#9665f8be3be60f475d816ca10430631f43d6c962" dependencies = [ "proc-macro2 1.0.66", "quote 1.0.32", @@ -824,7 +824,7 @@ dependencies = [ [[package]] name = "boa_parser" version = "0.17.0" -source = "git+https://github.com/boa-dev/boa#c2df31b781c115d6bdb5de64979d247af329ffcd" +source = "git+https://github.com/boa-dev/boa#9665f8be3be60f475d816ca10430631f43d6c962" dependencies = [ "bitflags 2.3.3", "boa_ast", @@ -844,7 +844,7 @@ dependencies = [ [[package]] name = "boa_profiler" version = "0.17.0" -source = "git+https://github.com/boa-dev/boa#c2df31b781c115d6bdb5de64979d247af329ffcd" +source = "git+https://github.com/boa-dev/boa#9665f8be3be60f475d816ca10430631f43d6c962" [[package]] name = "brotli" @@ -989,9 +989,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6b2562119bf28c3439f7f02db99faf0aa1a8cdfe5772a2ee155d32227239f0" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" dependencies = [ "jobserver", "libc", @@ -1084,9 +1084,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.19" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" +checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" dependencies = [ "clap_builder", "clap_derive", @@ -1095,9 +1095,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.19" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" dependencies = [ "anstream", "anstyle", @@ -1635,9 +1635,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "zeroize", @@ -1810,7 +1810,7 @@ dependencies = [ [[package]] name = "discv5" version = "0.3.1" -source = "git+https://github.com/sigp/discv5#a9f1e99321aec746fb9d6e8df889aa515a5e1254" +source = "git+https://github.com/sigp/discv5#1439decd4e7d7c9de78ef61b5d67be3fee688510" dependencies = [ "aes 0.7.5", "aes-gcm", @@ -4565,18 +4565,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2 1.0.66", "quote 1.0.32", @@ -4585,9 +4585,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c" [[package]] name = "pin-utils" @@ -5978,6 +5978,7 @@ dependencies = [ "reth-rpc-api", "reth-rpc-engine-api", "reth-rpc-types", + "reth-rpc-types-compat", "reth-tasks", "reth-transaction-pool", "revm", @@ -6088,6 +6089,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "reth-rpc-types-compat" +version = "0.1.0-alpha.5" +dependencies = [ + "reth-primitives", + "reth-rlp", + "reth-rpc-types", +] + [[package]] name = "reth-stages" version = "0.1.0-alpha.5" @@ -6685,9 +6695,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.181" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d3e73c93c3240c0bda063c239298e633114c69a888c3e37ca8bb33f343e9890" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] @@ -6705,9 +6715,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.181" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be02f6cb0cd3a5ec20bbcfbcbd749f57daddb1a0882dc2e46a6c236c90b977ed" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2 1.0.66", "quote 1.0.32", @@ -7149,7 +7159,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" dependencies = [ - "strum_macros 0.25.1", + "strum_macros 0.25.2", ] [[package]] @@ -7167,9 +7177,9 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6069ca09d878a33f883cc06aaa9718ede171841d3832450354410b718b097232" +checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" dependencies = [ "heck", "proc-macro2 1.0.66", @@ -7304,9 +7314,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.7.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" +checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" dependencies = [ "cfg-if", "fastrand 2.0.0", @@ -7352,7 +7362,7 @@ dependencies = [ "proc-macro2 1.0.66", "quote 1.0.32", "serde", - "strum_macros 0.25.1", + "strum_macros 0.25.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index aac12498b5..ad0431f2ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ members = [ "crates/transaction-pool", "crates/trie", "testing/ef-tests", - + "crates/rpc/rpc-types-compat", "examples", "examples/additional-rpc-namespace-in-cli", ] @@ -102,6 +102,8 @@ reth-transaction-pool = { path = "./crates/transaction-pool" } reth-tasks = { path = "./crates/tasks" } reth-network = { path = "./crates/net/network" } reth-network-api = { path = "./crates/net/network-api" } +reth-rpc-types-compat = { path = "./crates/rpc/rpc-types-compat"} + ## eth ethers-core = { version = "2.0.8", default-features = false } diff --git a/crates/rpc/rpc-types-compat/Cargo.toml b/crates/rpc/rpc-types-compat/Cargo.toml new file mode 100644 index 0000000000..a7997e3410 --- /dev/null +++ b/crates/rpc/rpc-types-compat/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "reth-rpc-types-compat" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +description = """ +Compatibility layer for reth-primitives and ethereum RPC types +""" + +[dependencies] +reth-primitives.workspace = true +reth-rpc-types.workspace = true +reth-rlp.workspace = true diff --git a/crates/rpc/rpc-types-compat/src/block.rs b/crates/rpc/rpc-types-compat/src/block.rs new file mode 100644 index 0000000000..6551124d9f --- /dev/null +++ b/crates/rpc/rpc-types-compat/src/block.rs @@ -0,0 +1,114 @@ +//! Compatibility functions for rpc `Block` type. + +use crate::transaction::from_recovered_with_block_context; +use reth_primitives::{Block as PrimitiveBlock, Header as PrimitiveHeader, H256, U256}; +use reth_rlp::Encodable; +use reth_rpc_types::{Block, BlockError, BlockTransactions, BlockTransactionsKind, Header}; + +/// Converts the given primitive block into a [Block] response with the given +/// [BlockTransactionsKind] +/// +/// If a `block_hash` is provided, then this is used, otherwise the block hash is computed. +pub fn from_block( + block: PrimitiveBlock, + total_difficulty: U256, + kind: BlockTransactionsKind, + block_hash: Option, +) -> Result { + match kind { + BlockTransactionsKind::Hashes => { + Ok(from_block_with_tx_hashes(block, total_difficulty, block_hash)) + } + BlockTransactionsKind::Full => from_block_full(block, total_difficulty, block_hash), + } +} + +/// Create a new [Block] response from a [primitive block](reth_primitives::Block), using the +/// total difficulty to populate its field in the rpc response. +/// +/// This will populate the `transactions` field with only the hashes of the transactions in the +/// block: [BlockTransactions::Hashes] +pub fn from_block_with_tx_hashes( + block: PrimitiveBlock, + total_difficulty: U256, + block_hash: Option, +) -> Block { + let block_hash = block_hash.unwrap_or_else(|| block.header.hash_slow()); + let transactions = block.body.iter().map(|tx| tx.hash()).collect(); + + from_block_with_transactions( + block_hash, + block, + total_difficulty, + BlockTransactions::Hashes(transactions), + ) +} + +/// Create a new [Block] response from a [primitive block](reth_primitives::Block), using the +/// total difficulty to populate its field in the rpc response. +/// +/// This will populate the `transactions` field with the _full_ +/// [Transaction](reth_rpc_types::Transaction) objects: [BlockTransactions::Full] +pub fn from_block_full( + block: PrimitiveBlock, + total_difficulty: U256, + block_hash: Option, +) -> Result { + let block_hash = block_hash.unwrap_or_else(|| block.header.hash_slow()); + let block_number = block.number; + let mut transactions = Vec::with_capacity(block.body.len()); + for (idx, tx) in block.body.iter().enumerate() { + let signed_tx = tx.clone().into_ecrecovered().ok_or(BlockError::InvalidSignature)?; + transactions.push(from_recovered_with_block_context( + signed_tx, + block_hash, + block_number, + block.base_fee_per_gas, + U256::from(idx), + )) + } + + Ok(from_block_with_transactions( + block_hash, + block, + total_difficulty, + BlockTransactions::Full(transactions), + )) +} + +fn from_block_with_transactions( + block_hash: H256, + block: PrimitiveBlock, + total_difficulty: U256, + transactions: BlockTransactions, +) -> Block { + let block_length = block.length(); + let uncles = block.ommers.into_iter().map(|h| h.hash_slow()).collect(); + let header = Header::from_primitive_with_hash(block.header.seal(block_hash)); + let withdrawals = if header.withdrawals_root.is_some() { block.withdrawals } else { None }; + Block { + header, + uncles, + transactions, + total_difficulty: Some(total_difficulty), + size: Some(U256::from(block_length)), + withdrawals, + } +} + +/// Build an RPC block response representing +/// an Uncle from its header. +pub fn uncle_block_from_header(header: PrimitiveHeader) -> Block { + let hash = header.hash_slow(); + let rpc_header = Header::from_primitive_with_hash(header.clone().seal(hash)); + let uncle_block = PrimitiveBlock { header, ..Default::default() }; + let size = Some(U256::from(uncle_block.length())); + Block { + uncles: vec![], + header: rpc_header, + transactions: BlockTransactions::Uncle, + withdrawals: Some(vec![]), + size, + total_difficulty: None, + } +} diff --git a/crates/rpc/rpc-types-compat/src/lib.rs b/crates/rpc/rpc-types-compat/src/lib.rs new file mode 100644 index 0000000000..b4628cfcba --- /dev/null +++ b/crates/rpc/rpc-types-compat/src/lib.rs @@ -0,0 +1,21 @@ +#![cfg_attr(docsrs, feature(doc_cfg))] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", + html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", + issue_tracker_base_url = "https://github.com/paradigmxzy/reth/issues/" +)] +#![warn(missing_debug_implementations, missing_docs, unreachable_pub, unused_crate_dependencies)] +#![deny(unused_must_use, rust_2018_idioms)] +#![doc(test( + no_crate_inject, + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) +))] + +//! Reth compatibility and utils for RPC types +//! +//! This crate various helper functions to convert between reth primitive types and rpc types. + +pub mod block; +pub use block::*; +pub mod transaction; +pub use transaction::*; diff --git a/crates/rpc/rpc-types-compat/src/transaction/mod.rs b/crates/rpc/rpc-types-compat/src/transaction/mod.rs new file mode 100644 index 0000000000..02026b04fb --- /dev/null +++ b/crates/rpc/rpc-types-compat/src/transaction/mod.rs @@ -0,0 +1,126 @@ +//! Compatibility functions for rpc `Transaction` type. + +use reth_primitives::{ + AccessListItem, BlockNumber, Transaction as PrimitiveTransaction, + TransactionKind as PrimitiveTransactionKind, TransactionSignedEcRecovered, TxType, H256, U128, + U256, U64, +}; +use reth_rpc_types::{Signature, Transaction}; + +/// Create a new rpc transaction result for a mined transaction, using the given block hash, +/// number, and tx index fields to populate the corresponding fields in the rpc result. +/// +/// The block hash, number, and tx index fields should be from the original block where the +/// transaction was mined. +pub fn from_recovered_with_block_context( + tx: TransactionSignedEcRecovered, + block_hash: H256, + block_number: BlockNumber, + base_fee: Option, + tx_index: U256, +) -> Transaction { + fill(tx, Some(block_hash), Some(block_number), base_fee, Some(tx_index)) +} + +/// Create a new rpc transaction result for a _pending_ signed transaction, setting block +/// environment related fields to `None`. +pub fn from_recovered(tx: TransactionSignedEcRecovered) -> Transaction { + fill(tx, None, None, None, None) +} + +/// Create a new rpc transaction result for a _pending_ signed transaction, setting block +/// environment related fields to `None`. +fn fill( + tx: TransactionSignedEcRecovered, + block_hash: Option, + block_number: Option, + base_fee: Option, + transaction_index: Option, +) -> Transaction { + let signer = tx.signer(); + let signed_tx = tx.into_signed(); + + let to = match signed_tx.kind() { + PrimitiveTransactionKind::Create => None, + PrimitiveTransactionKind::Call(to) => Some(*to), + }; + + let (gas_price, max_fee_per_gas) = match signed_tx.tx_type() { + TxType::Legacy => (Some(U128::from(signed_tx.max_fee_per_gas())), None), + TxType::EIP2930 => (Some(U128::from(signed_tx.max_fee_per_gas())), None), + TxType::EIP1559 | TxType::EIP4844 => { + // the gas price field for EIP1559 is set to `min(tip, gasFeeCap - baseFee) + + // baseFee` + let gas_price = base_fee + .and_then(|base_fee| { + signed_tx.effective_tip_per_gas(base_fee).map(|tip| tip + base_fee as u128) + }) + .unwrap_or_else(|| signed_tx.max_fee_per_gas()); + + (Some(U128::from(gas_price)), Some(U128::from(signed_tx.max_fee_per_gas()))) + } + }; + + let chain_id = signed_tx.chain_id().map(U64::from); + let access_list = match &signed_tx.transaction { + PrimitiveTransaction::Legacy(_) => None, + PrimitiveTransaction::Eip2930(tx) => Some( + tx.access_list + .0 + .iter() + .map(|item| AccessListItem { + address: item.address.0.into(), + storage_keys: item.storage_keys.iter().map(|key| key.0.into()).collect(), + }) + .collect(), + ), + PrimitiveTransaction::Eip1559(tx) => Some( + tx.access_list + .0 + .iter() + .map(|item| AccessListItem { + address: item.address.0.into(), + storage_keys: item.storage_keys.iter().map(|key| key.0.into()).collect(), + }) + .collect(), + ), + PrimitiveTransaction::Eip4844(tx) => Some( + tx.access_list + .0 + .iter() + .map(|item| AccessListItem { + address: item.address.0.into(), + storage_keys: item.storage_keys.iter().map(|key| key.0.into()).collect(), + }) + .collect(), + ), + }; + + let signature = Signature::from_primitive_signature( + *signed_tx.signature(), + signed_tx.tx_type(), + signed_tx.chain_id(), + ); + + Transaction { + hash: signed_tx.hash(), + nonce: U256::from(signed_tx.nonce()), + from: signer, + to, + value: U256::from(signed_tx.value()), + gas_price, + max_fee_per_gas, + max_priority_fee_per_gas: signed_tx.max_priority_fee_per_gas().map(U128::from), + signature: Some(signature), + gas: U256::from(signed_tx.gas_limit()), + input: signed_tx.input().clone(), + chain_id, + access_list, + transaction_type: Some(U64::from(signed_tx.tx_type() as u8)), + + // These fields are set to None because they are not stored as part of the transaction + block_hash, + block_number: block_number.map(U256::from), + transaction_index, + } +} diff --git a/crates/rpc/rpc-types/Cargo.toml b/crates/rpc/rpc-types/Cargo.toml index 31a09d60b5..3cce6c1a84 100644 --- a/crates/rpc/rpc-types/Cargo.toml +++ b/crates/rpc/rpc-types/Cargo.toml @@ -14,7 +14,6 @@ Reth RPC types # reth reth-primitives.workspace = true reth-rlp.workspace = true - # errors thiserror.workspace = true diff --git a/crates/rpc/rpc-types/src/eth/block.rs b/crates/rpc/rpc-types/src/eth/block.rs index a3762aef76..5588d55611 100644 --- a/crates/rpc/rpc-types/src/eth/block.rs +++ b/crates/rpc/rpc-types/src/eth/block.rs @@ -1,13 +1,11 @@ //! Contains types that represent ethereum types in [reth_primitives] when used in RPC use crate::Transaction; use reth_primitives::{ - Address, Block as PrimitiveBlock, Bloom, Bytes, Header as PrimitiveHeader, SealedHeader, - Withdrawal, H256, H64, U256, U64, + Address, Bloom, Bytes, Header as PrimitiveHeader, SealedHeader, Withdrawal, H256, H64, U256, + U64, }; -use reth_rlp::Encodable; use serde::{ser::Error, Deserialize, Serialize, Serializer}; use std::{collections::BTreeMap, ops::Deref}; - /// Block Transactions depending on the boolean attribute of `eth_getBlockBy*`, /// or if used by `eth_getUncle*` #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] @@ -84,118 +82,6 @@ pub struct Block { pub withdrawals: Option>, } -impl Block { - /// Converts the given primitive block into a [Block] response with the given - /// [BlockTransactionsKind] - /// - /// If a `block_hash` is provided, then this is used, otherwise the block hash is computed. - pub fn from_block( - block: PrimitiveBlock, - total_difficulty: U256, - kind: BlockTransactionsKind, - block_hash: Option, - ) -> Result { - match kind { - BlockTransactionsKind::Hashes => { - Ok(Self::from_block_with_tx_hashes(block, total_difficulty, block_hash)) - } - BlockTransactionsKind::Full => { - Self::from_block_full(block, total_difficulty, block_hash) - } - } - } - - /// Create a new [Block] response from a [primitive block](reth_primitives::Block), using the - /// total difficulty to populate its field in the rpc response. - /// - /// This will populate the `transactions` field with only the hashes of the transactions in the - /// block: [BlockTransactions::Hashes] - pub fn from_block_with_tx_hashes( - block: PrimitiveBlock, - total_difficulty: U256, - block_hash: Option, - ) -> Self { - let block_hash = block_hash.unwrap_or_else(|| block.header.hash_slow()); - let transactions = block.body.iter().map(|tx| tx.hash()).collect(); - - Self::from_block_with_transactions( - block_hash, - block, - total_difficulty, - BlockTransactions::Hashes(transactions), - ) - } - - /// Create a new [Block] response from a [primitive block](reth_primitives::Block), using the - /// total difficulty to populate its field in the rpc response. - /// - /// This will populate the `transactions` field with the _full_ [Transaction] objects: - /// [BlockTransactions::Full] - pub fn from_block_full( - block: PrimitiveBlock, - total_difficulty: U256, - block_hash: Option, - ) -> Result { - let block_hash = block_hash.unwrap_or_else(|| block.header.hash_slow()); - let block_number = block.number; - let mut transactions = Vec::with_capacity(block.body.len()); - for (idx, tx) in block.body.iter().enumerate() { - let signed_tx = tx.clone().into_ecrecovered().ok_or(BlockError::InvalidSignature)?; - transactions.push(Transaction::from_recovered_with_block_context( - signed_tx, - block_hash, - block_number, - block.base_fee_per_gas, - U256::from(idx), - )) - } - - Ok(Self::from_block_with_transactions( - block_hash, - block, - total_difficulty, - BlockTransactions::Full(transactions), - )) - } - - fn from_block_with_transactions( - block_hash: H256, - block: PrimitiveBlock, - total_difficulty: U256, - transactions: BlockTransactions, - ) -> Self { - let block_length = block.length(); - let uncles = block.ommers.into_iter().map(|h| h.hash_slow()).collect(); - let header = Header::from_primitive_with_hash(block.header.seal(block_hash)); - let withdrawals = if header.withdrawals_root.is_some() { block.withdrawals } else { None }; - Self { - header, - uncles, - transactions, - total_difficulty: Some(total_difficulty), - size: Some(U256::from(block_length)), - withdrawals, - } - } - - /// Build an RPC block response representing - /// an Uncle from its header. - pub fn uncle_block_from_header(header: PrimitiveHeader) -> Self { - let hash = header.hash_slow(); - let rpc_header = Header::from_primitive_with_hash(header.clone().seal(hash)); - let uncle_block = PrimitiveBlock { header, ..Default::default() }; - let size = Some(U256::from(uncle_block.length())); - Self { - uncles: vec![], - header: rpc_header, - transactions: BlockTransactions::Uncle, - withdrawals: Some(vec![]), - size, - total_difficulty: None, - } - } -} - /// Block header representation. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/crates/rpc/rpc-types/src/eth/transaction/mod.rs b/crates/rpc/rpc-types/src/eth/transaction/mod.rs index 734d33f1d2..1e8b09aecb 100644 --- a/crates/rpc/rpc-types/src/eth/transaction/mod.rs +++ b/crates/rpc/rpc-types/src/eth/transaction/mod.rs @@ -1,22 +1,17 @@ +pub use common::TransactionInfo; +pub use receipt::TransactionReceipt; +pub use request::TransactionRequest; +use reth_primitives::{AccessListItem, Address, Bytes, H256, U128, U256, U64}; +use serde::{Deserialize, Serialize}; +pub use signature::Signature; +pub use typed::*; + mod common; mod receipt; mod request; mod signature; mod typed; -pub use common::TransactionInfo; -pub use receipt::TransactionReceipt; -pub use request::TransactionRequest; -pub use signature::Signature; -pub use typed::*; - -use reth_primitives::{ - AccessListItem, Address, BlockNumber, Bytes, Transaction as PrimitiveTransaction, - TransactionKind as PrimitiveTransactionKind, TransactionSignedEcRecovered, TxType, H256, U128, - U256, U64, -}; -use serde::{Deserialize, Serialize}; - /// Transaction object used in RPC #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -70,131 +65,10 @@ pub struct Transaction { pub transaction_type: Option, } -impl Transaction { - /// Create a new rpc transaction result for a mined transaction, using the given block hash, - /// number, and tx index fields to populate the corresponding fields in the rpc result. - /// - /// The block hash, number, and tx index fields should be from the original block where the - /// transaction was mined. - pub fn from_recovered_with_block_context( - tx: TransactionSignedEcRecovered, - block_hash: H256, - block_number: BlockNumber, - base_fee: Option, - tx_index: U256, - ) -> Self { - Self::fill(tx, Some(block_hash), Some(block_number), base_fee, Some(tx_index)) - } - - /// Create a new rpc transaction result for a _pending_ signed transaction, setting block - /// environment related fields to `None`. - pub fn from_recovered(tx: TransactionSignedEcRecovered) -> Self { - Self::fill(tx, None, None, None, None) - } - - /// Create a new rpc transaction result for a _pending_ signed transaction, setting block - /// environment related fields to `None`. - fn fill( - tx: TransactionSignedEcRecovered, - block_hash: Option, - block_number: Option, - base_fee: Option, - transaction_index: Option, - ) -> Self { - let signer = tx.signer(); - let signed_tx = tx.into_signed(); - - let to = match signed_tx.kind() { - PrimitiveTransactionKind::Create => None, - PrimitiveTransactionKind::Call(to) => Some(*to), - }; - - let (gas_price, max_fee_per_gas) = match signed_tx.tx_type() { - TxType::Legacy => (Some(U128::from(signed_tx.max_fee_per_gas())), None), - TxType::EIP2930 => (Some(U128::from(signed_tx.max_fee_per_gas())), None), - TxType::EIP1559 | TxType::EIP4844 => { - // the gas price field for EIP1559 is set to `min(tip, gasFeeCap - baseFee) + - // baseFee` - let gas_price = base_fee - .and_then(|base_fee| { - signed_tx.effective_tip_per_gas(base_fee).map(|tip| tip + base_fee as u128) - }) - .unwrap_or_else(|| signed_tx.max_fee_per_gas()); - - (Some(U128::from(gas_price)), Some(U128::from(signed_tx.max_fee_per_gas()))) - } - }; - - let chain_id = signed_tx.chain_id().map(U64::from); - let access_list = match &signed_tx.transaction { - PrimitiveTransaction::Legacy(_) => None, - PrimitiveTransaction::Eip2930(tx) => Some( - tx.access_list - .0 - .iter() - .map(|item| AccessListItem { - address: item.address.0.into(), - storage_keys: item.storage_keys.iter().map(|key| key.0.into()).collect(), - }) - .collect(), - ), - PrimitiveTransaction::Eip1559(tx) => Some( - tx.access_list - .0 - .iter() - .map(|item| AccessListItem { - address: item.address.0.into(), - storage_keys: item.storage_keys.iter().map(|key| key.0.into()).collect(), - }) - .collect(), - ), - PrimitiveTransaction::Eip4844(tx) => Some( - tx.access_list - .0 - .iter() - .map(|item| AccessListItem { - address: item.address.0.into(), - storage_keys: item.storage_keys.iter().map(|key| key.0.into()).collect(), - }) - .collect(), - ), - }; - - let signature = Signature::from_primitive_signature( - *signed_tx.signature(), - signed_tx.tx_type(), - signed_tx.chain_id(), - ); - - Self { - hash: signed_tx.hash(), - nonce: U256::from(signed_tx.nonce()), - from: signer, - to, - value: U256::from(signed_tx.value()), - gas_price, - max_fee_per_gas, - max_priority_fee_per_gas: signed_tx.max_priority_fee_per_gas().map(U128::from), - signature: Some(signature), - gas: U256::from(signed_tx.gas_limit()), - input: signed_tx.input().clone(), - chain_id, - access_list, - transaction_type: Some(U64::from(signed_tx.tx_type() as u8)), - - // These fields are set to None because they are not stored as part of the transaction - block_hash, - block_number: block_number.map(U256::from), - transaction_index, - } - } -} - #[cfg(test)] mod tests { - use crate::eth::transaction::signature::Parity; - use super::*; + use crate::eth::transaction::signature::Parity; #[test] fn serde_transaction() { diff --git a/crates/rpc/rpc/Cargo.toml b/crates/rpc/rpc/Cargo.toml index 1791821f1c..756fefd8a1 100644 --- a/crates/rpc/rpc/Cargo.toml +++ b/crates/rpc/rpc/Cargo.toml @@ -24,6 +24,7 @@ reth-revm = { path = "../../revm" } reth-tasks.workspace = true reth-metrics.workspace = true reth-consensus-common = { path = "../../consensus/common" } +reth-rpc-types-compat.workspace = true # eth revm = { workspace = true, features = [ diff --git a/crates/rpc/rpc/src/eth/api/block.rs b/crates/rpc/rpc/src/eth/api/block.rs index ab297add71..f575998fc3 100644 --- a/crates/rpc/rpc/src/eth/api/block.rs +++ b/crates/rpc/rpc/src/eth/api/block.rs @@ -9,10 +9,12 @@ use crate::{ }; use reth_network_api::NetworkInfo; use reth_primitives::{BlockId, BlockNumberOrTag, TransactionMeta}; -use reth_provider::{BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderFactory}; -use reth_rpc_types::{Block, Index, RichBlock, TransactionReceipt}; -use reth_transaction_pool::TransactionPool; +use reth_provider::{BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderFactory}; +use reth_rpc_types::{Index, RichBlock, TransactionReceipt}; + +use reth_rpc_types_compat::block::{from_block, uncle_block_from_header}; +use reth_transaction_pool::TransactionPool; impl EthApi where Provider: @@ -47,10 +49,8 @@ where .unwrap_or_default(); let index = usize::from(index); - let uncle = uncles - .into_iter() - .nth(index) - .map(|header| Block::uncle_block_from_header(header).into()); + let uncle = + uncles.into_iter().nth(index).map(|header| uncle_block_from_header(header).into()); Ok(uncle) } @@ -160,8 +160,7 @@ where .provider() .header_td_by_number(block.number)? .ok_or(EthApiError::UnknownBlockNumber)?; - let block = - Block::from_block(block.into(), total_difficulty, full.into(), Some(block_hash))?; + let block = from_block(block.into(), total_difficulty, full.into(), Some(block_hash))?; Ok(Some(block.into())) } } diff --git a/crates/rpc/rpc/src/eth/api/transactions.rs b/crates/rpc/rpc/src/eth/api/transactions.rs index 6784b62ec0..770a9e8c1e 100644 --- a/crates/rpc/rpc/src/eth/api/transactions.rs +++ b/crates/rpc/rpc/src/eth/api/transactions.rs @@ -19,6 +19,8 @@ use reth_primitives::{ TransactionKind::{Call, Create}, TransactionMeta, TransactionSigned, TransactionSignedEcRecovered, H256, U128, U256, U64, }; +use reth_rpc_types_compat::from_recovered_with_block_context; + use reth_provider::{ BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderBox, StateProviderFactory, }; @@ -732,7 +734,7 @@ where if let Some(tx_signed) = block.body.into_iter().nth(index.into()) { let tx = tx_signed.into_ecrecovered().ok_or(EthApiError::InvalidTransactionSignature)?; - return Ok(Some(Transaction::from_recovered_with_block_context( + return Ok(Some(from_recovered_with_block_context( tx, block_hash, block.header.number, @@ -820,9 +822,9 @@ impl From for TransactionSignedEcRecovered { impl From for Transaction { fn from(value: TransactionSource) -> Self { match value { - TransactionSource::Pool(tx) => Transaction::from_recovered(tx), + TransactionSource::Pool(tx) => reth_rpc_types_compat::transaction::from_recovered(tx), TransactionSource::Block { transaction, index, block_hash, block_number, base_fee } => { - Transaction::from_recovered_with_block_context( + from_recovered_with_block_context( transaction, block_hash, block_number, diff --git a/crates/rpc/rpc/src/eth/pubsub.rs b/crates/rpc/rpc/src/eth/pubsub.rs index d5c0231ef8..4d71d3810d 100644 --- a/crates/rpc/rpc/src/eth/pubsub.rs +++ b/crates/rpc/rpc/src/eth/pubsub.rs @@ -11,7 +11,7 @@ use reth_rpc_types::{ Params, PubSubSyncStatus, SubscriptionKind, SubscriptionResult as EthSubscriptionResult, SyncStatusMetadata, }, - FilteredParams, Header, Log, Transaction, + FilteredParams, Header, Log, }; use reth_tasks::{TaskSpawner, TokioTaskExecutor}; use reth_transaction_pool::{NewTransactionEvent, TransactionPool}; @@ -128,7 +128,7 @@ where // full transaction objects requested let stream = pubsub.full_pending_transaction_stream().map(|tx| { EthSubscriptionResult::FullTransaction(Box::new( - Transaction::from_recovered( + reth_rpc_types_compat::transaction::from_recovered( tx.transaction.to_recovered_transaction(), ), )) diff --git a/crates/rpc/rpc/src/txpool.rs b/crates/rpc/rpc/src/txpool.rs index 8ca4c13729..6458b015fb 100644 --- a/crates/rpc/rpc/src/txpool.rs +++ b/crates/rpc/rpc/src/txpool.rs @@ -39,7 +39,7 @@ where let entry = content.entry(tx.sender()).or_default(); let key = tx.nonce().to_string(); let tx = tx.to_recovered_transaction(); - let tx = Transaction::from_recovered(tx); + let tx = reth_rpc_types_compat::transaction::from_recovered(tx); entry.insert(key, tx); }