mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-28 08:37:59 -05:00
standalone rpc_types (#4088)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
76
Cargo.lock
generated
76
Cargo.lock
generated
@@ -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]]
|
||||
|
||||
@@ -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 }
|
||||
|
||||
16
crates/rpc/rpc-types-compat/Cargo.toml
Normal file
16
crates/rpc/rpc-types-compat/Cargo.toml
Normal 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
|
||||
114
crates/rpc/rpc-types-compat/src/block.rs
Normal file
114
crates/rpc/rpc-types-compat/src/block.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
21
crates/rpc/rpc-types-compat/src/lib.rs
Normal file
21
crates/rpc/rpc-types-compat/src/lib.rs
Normal 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::*;
|
||||
126
crates/rpc/rpc-types-compat/src/transaction/mod.rs
Normal file
126
crates/rpc/rpc-types-compat/src/transaction/mod.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ Reth RPC types
|
||||
# reth
|
||||
reth-primitives.workspace = true
|
||||
reth-rlp.workspace = true
|
||||
|
||||
# errors
|
||||
thiserror.workspace = true
|
||||
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
),
|
||||
))
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user