standalone rpc_types (#4088)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
Supernovahs.eth
2023-08-09 17:28:37 +05:30
committed by GitHub
parent 058c55cd8c
commit ba7fa1a4ca
14 changed files with 351 additions and 301 deletions

76
Cargo.lock generated
View File

@@ -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]]

View File

@@ -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 }

View File

@@ -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

View File

@@ -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<H256>,
) -> Result<Block, BlockError> {
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<H256>,
) -> 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<H256>,
) -> Result<Block, BlockError> {
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,
}
}

View File

@@ -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::*;

View File

@@ -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<u64>,
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<H256>,
block_number: Option<BlockNumber>,
base_fee: Option<u64>,
transaction_index: Option<U256>,
) -> 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,
}
}

View File

@@ -14,7 +14,6 @@ Reth RPC types
# reth
reth-primitives.workspace = true
reth-rlp.workspace = true
# errors
thiserror.workspace = true

View File

@@ -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<Vec<Withdrawal>>,
}
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<H256>,
) -> Result<Self, BlockError> {
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<H256>,
) -> 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<H256>,
) -> Result<Self, BlockError> {
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")]

View File

@@ -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<U64>,
}
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<u64>,
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<H256>,
block_number: Option<BlockNumber>,
base_fee: Option<u64>,
transaction_index: Option<U256>,
) -> 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() {

View File

@@ -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 = [

View File

@@ -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<Provider, Pool, Network> EthApi<Provider, Pool, Network>
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()))
}
}

View File

@@ -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<TransactionSource> for TransactionSignedEcRecovered {
impl From<TransactionSource> 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,

View File

@@ -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(),
),
))

View File

@@ -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);
}