diff --git a/Cargo.lock b/Cargo.lock index 9b965415d95..06db9a7be95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1024,7 +1024,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -1035,7 +1035,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -3434,7 +3434,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -5157,7 +5157,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -6127,7 +6127,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -6335,25 +6335,6 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "op-alloy-rpc-types" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9d16ec9f7810e0623a37edc293d1c05fe9c58a5647f6973fdd93e0b4795015" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", - "derive_more", - "op-alloy-consensus", - "serde", - "serde_json", - "thiserror 2.0.18", -] - [[package]] name = "op-alloy-rpc-types-engine" version = "0.24.0" @@ -9864,14 +9845,12 @@ dependencies = [ "alloy-network", "alloy-primitives", "alloy-rpc-types-eth", - "alloy-signer", "auto_impl", "dyn-clone", "jsonrpsee-types", - "op-alloy-consensus", - "op-alloy-rpc-types", "reth-evm", "reth-primitives-traits", + "reth-rpc-traits", "serde_json", "thiserror 2.0.18", ] @@ -10055,6 +10034,21 @@ dependencies = [ "strum", ] +[[package]] +name = "reth-rpc-traits" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9230acfd70f7f27bc52da3f397e1896432ce160f9bd460d9788f1a28d61588c" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-signer", + "reth-primitives-traits", + "thiserror 2.0.18", +] + [[package]] name = "reth-stages" version = "1.11.3" @@ -10993,7 +10987,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -11073,7 +11067,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs 1.0.6", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -11664,7 +11658,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -11864,7 +11858,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -13142,7 +13136,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index bbf994c29c0..7ff21d7a355 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -410,6 +410,7 @@ reth-rpc-eth-types = { path = "crates/rpc/rpc-eth-types", default-features = fal reth-rpc-layer = { path = "crates/rpc/rpc-layer" } reth-rpc-server-types = { path = "crates/rpc/rpc-server-types" } reth-rpc-convert = { path = "crates/rpc/rpc-convert" } +reth-rpc-traits = { version = "0.1.0", default-features = false } reth-stages = { path = "crates/stages/stages" } reth-stages-api = { path = "crates/stages/api" } reth-stages-types = { path = "crates/stages/types", default-features = false } diff --git a/crates/rpc/rpc-convert/Cargo.toml b/crates/rpc/rpc-convert/Cargo.toml index d6f8007ebd1..e33129daefb 100644 --- a/crates/rpc/rpc-convert/Cargo.toml +++ b/crates/rpc/rpc-convert/Cargo.toml @@ -15,20 +15,16 @@ workspace = true # reth reth-primitives-traits.workspace = true reth-evm.workspace = true +reth-rpc-traits.workspace = true # ethereum alloy-primitives.workspace = true alloy-rpc-types-eth = { workspace = true, features = ["serde"] } -alloy-signer.workspace = true alloy-consensus.workspace = true alloy-network.workspace = true alloy-json-rpc.workspace = true alloy-evm = { workspace = true, features = ["rpc"] } -# optimism -op-alloy-consensus = { workspace = true, optional = true } -op-alloy-rpc-types = { workspace = true, optional = true } - # io jsonrpsee-types.workspace = true @@ -43,7 +39,3 @@ serde_json.workspace = true [features] default = [] -op = [ - "dep:op-alloy-consensus", - "dep:op-alloy-rpc-types", -] diff --git a/crates/rpc/rpc-convert/src/lib.rs b/crates/rpc/rpc-convert/src/lib.rs index b905f00c24c..d6bd73fc3dc 100644 --- a/crates/rpc/rpc-convert/src/lib.rs +++ b/crates/rpc/rpc-convert/src/lib.rs @@ -14,8 +14,12 @@ mod rpc; pub mod transaction; pub use rpc::*; -pub use transaction::{ - RpcConvert, RpcConverter, TransactionConversionError, TryIntoSimTx, TxInfoMapper, -}; +pub use transaction::{RpcConvert, RpcConverter, TransactionConversionError}; pub use alloy_evm::rpc::{CallFees, CallFeesError, EthTxEnvError, TryIntoTxEnv}; + +// Re-export traits from reth-rpc-traits +pub use reth_rpc_traits::{ + FromConsensusHeader, FromConsensusTx, SignTxRequestError, SignableTxRequest, TryIntoSimTx, + TxInfoMapper, +}; diff --git a/crates/rpc/rpc-convert/src/rpc.rs b/crates/rpc/rpc-convert/src/rpc.rs index 7fe3ae8e199..b1425165f7a 100644 --- a/crates/rpc/rpc-convert/src/rpc.rs +++ b/crates/rpc/rpc-convert/src/rpc.rs @@ -1,11 +1,7 @@ -use std::{fmt::Debug, future::Future}; +use std::fmt::Debug; -use alloy_consensus::{EthereumTxEnvelope, SignableTransaction, TxEip4844}; use alloy_json_rpc::RpcObject; -use alloy_network::{ - primitives::HeaderResponse, Network, ReceiptResponse, TransactionResponse, TxSigner, -}; -use alloy_primitives::Signature; +use alloy_network::{primitives::HeaderResponse, Network, ReceiptResponse, TransactionResponse}; use alloy_rpc_types_eth::TransactionRequest; /// RPC types used by the `eth_` RPC API. @@ -46,58 +42,3 @@ pub type RpcBlock = alloy_rpc_types_eth::Block, RpcHeader = ::TransactionRequest; - -/// Error for [`SignableTxRequest`] trait. -#[derive(Debug, thiserror::Error)] -pub enum SignTxRequestError { - /// The transaction request is invalid. - #[error("invalid transaction request")] - InvalidTransactionRequest, - - /// The signer is not supported. - #[error(transparent)] - SignerNotSupported(#[from] alloy_signer::Error), -} - -/// An abstraction over transaction requests that can be signed. -pub trait SignableTxRequest: Send + Sync + 'static { - /// Attempts to build a transaction request and sign it with the given signer. - fn try_build_and_sign( - self, - signer: impl TxSigner + Send, - ) -> impl Future> + Send; -} - -impl SignableTxRequest> for TransactionRequest { - async fn try_build_and_sign( - self, - signer: impl TxSigner + Send, - ) -> Result, SignTxRequestError> { - let mut tx = - self.build_typed_tx().map_err(|_| SignTxRequestError::InvalidTransactionRequest)?; - let signature = signer.sign_transaction(&mut tx).await?; - Ok(tx.into_signed(signature).into()) - } -} - -#[cfg(feature = "op")] -impl SignableTxRequest - for op_alloy_rpc_types::OpTransactionRequest -{ - async fn try_build_and_sign( - self, - signer: impl TxSigner + Send, - ) -> Result { - let mut tx = - self.build_typed_tx().map_err(|_| SignTxRequestError::InvalidTransactionRequest)?; - - // sanity check: deposit transactions must not be signed by the user - if tx.is_deposit() { - return Err(SignTxRequestError::InvalidTransactionRequest); - } - - let signature = signer.sign_transaction(&mut tx).await?; - - Ok(tx.into_signed(signature).into()) - } -} diff --git a/crates/rpc/rpc-convert/src/transaction.rs b/crates/rpc/rpc-convert/src/transaction.rs index 856a02c2896..0067f6bcb0b 100644 --- a/crates/rpc/rpc-convert/src/transaction.rs +++ b/crates/rpc/rpc-convert/src/transaction.rs @@ -2,11 +2,9 @@ use crate::{ RpcHeader, RpcReceipt, RpcTransaction, RpcTxReq, RpcTypes, SignableTxRequest, TryIntoTxEnv, }; -use alloy_consensus::{ - error::ValueError, transaction::Recovered, EthereumTxEnvelope, Sealable, TxEip4844, -}; -use alloy_primitives::{Address, U256}; -use alloy_rpc_types_eth::{request::TransactionRequest, Transaction, TransactionInfo}; +use alloy_consensus::{error::ValueError, transaction::Recovered}; +use alloy_primitives::Address; +use alloy_rpc_types_eth::TransactionInfo; use core::error; use dyn_clone::DynClone; use reth_evm::{BlockEnvFor, ConfigureEvm, EvmEnvFor, SpecFor, TxEnvFor}; @@ -14,6 +12,7 @@ use reth_primitives_traits::{ BlockTy, HeaderTy, NodePrimitives, SealedBlock, SealedHeader, SealedHeaderFor, TransactionMeta, TxTy, }; +use reth_rpc_traits::{FromConsensusHeader, FromConsensusTx, TryIntoSimTx, TxInfoMapper}; use std::{convert::Infallible, error::Error, fmt, fmt::Debug, marker::PhantomData}; /// Input for [`RpcConvert::convert_receipts`]. @@ -102,18 +101,6 @@ where } } -/// Conversion trait for obtaining RPC header from a consensus header. -pub trait FromConsensusHeader { - /// Takes a consensus header and converts it into `self`. - fn from_consensus_header(header: SealedHeader, block_size: usize) -> Self; -} - -impl FromConsensusHeader for alloy_rpc_types_eth::Header { - fn from_consensus_header(header: SealedHeader, block_size: usize) -> Self { - Self::from_consensus(header.into(), None, Some(U256::from(block_size))) - } -} - /// Responsible for the conversions from and into RPC requests and responses. /// /// The JSON-RPC schema and the Node primitives are configurable using the [`RpcConvert::Network`] @@ -203,81 +190,6 @@ dyn_clone::clone_trait_object!( RpcConvert ); -/// Converts `self` into `T`. The opposite of [`FromConsensusTx`]. -/// -/// Should create an RPC transaction response object based on a consensus transaction, its signer -/// [`Address`] and an additional context [`IntoRpcTx::TxInfo`]. -/// -/// Avoid implementing [`IntoRpcTx`] and use [`FromConsensusTx`] instead. Implementing it -/// automatically provides an implementation of [`IntoRpcTx`] thanks to the blanket implementation -/// in this crate. -/// -/// Prefer using [`IntoRpcTx`] over [`FromConsensusTx`] when specifying trait bounds on a generic -/// function to ensure that types that only implement [`IntoRpcTx`] can be used as well. -pub trait IntoRpcTx { - /// An additional context, usually [`TransactionInfo`] in a wrapper that carries some - /// implementation specific extra information. - type TxInfo; - /// An associated RPC conversion error. - type Err: error::Error; - - /// Performs the conversion consuming `self` with `signer` and `tx_info`. See [`IntoRpcTx`] - /// for details. - fn into_rpc_tx(self, signer: Address, tx_info: Self::TxInfo) -> Result; -} - -/// Converts `T` into `self`. It is reciprocal of [`IntoRpcTx`]. -/// -/// Should create an RPC transaction response object based on a consensus transaction, its signer -/// [`Address`] and an additional context [`FromConsensusTx::TxInfo`]. -/// -/// Prefer implementing [`FromConsensusTx`] over [`IntoRpcTx`] because it automatically provides an -/// implementation of [`IntoRpcTx`] thanks to the blanket implementation in this crate. -/// -/// Prefer using [`IntoRpcTx`] over using [`FromConsensusTx`] when specifying trait bounds on a -/// generic function. This way, types that directly implement [`IntoRpcTx`] can be used as arguments -/// as well. -pub trait FromConsensusTx: Sized { - /// An additional context, usually [`TransactionInfo`] in a wrapper that carries some - /// implementation specific extra information. - type TxInfo; - /// An associated RPC conversion error. - type Err: error::Error; - - /// Performs the conversion consuming `tx` with `signer` and `tx_info`. See [`FromConsensusTx`] - /// for details. - fn from_consensus_tx(tx: T, signer: Address, tx_info: Self::TxInfo) -> Result; -} - -impl> - FromConsensusTx for Transaction -{ - type TxInfo = TransactionInfo; - type Err = Infallible; - - fn from_consensus_tx( - tx: TxIn, - signer: Address, - tx_info: Self::TxInfo, - ) -> Result { - Ok(Self::from_transaction(Recovered::new_unchecked(tx.into(), signer), tx_info)) - } -} - -impl IntoRpcTx for ConsensusTx -where - ConsensusTx: alloy_consensus::Transaction, - RpcTx: FromConsensusTx, - >::Err: Debug, -{ - type TxInfo = RpcTx::TxInfo; - type Err = >::Err; - - fn into_rpc_tx(self, signer: Address, tx_info: Self::TxInfo) -> Result { - RpcTx::from_consensus_tx(self, signer, tx_info) - } -} - /// Converts `Tx` into `RpcTx` /// /// Where: @@ -288,13 +200,15 @@ where /// context about a transaction in a block. /// /// The `RpcTxConverter` has two blanket implementations: -/// * `()` assuming `Tx` implements [`IntoRpcTx`] and is used as default for [`RpcConverter`]. +/// * `()` assuming `RpcTx` implements [`FromConsensusTx`] and is used as default for +/// [`RpcConverter`]. /// * `Fn(Tx, Address, TxInfo) -> RpcTx` and can be applied using /// [`RpcConverter::with_rpc_tx_converter`]. /// -/// One should prefer to implement [`IntoRpcTx`] for `Tx` to get the `RpcTxConverter` implementation -/// for free, thanks to the blanket implementation, unless the conversion requires more context. For -/// example, some configuration parameters or access handles to database, network, etc. +/// One should prefer to implement [`FromConsensusTx`] for `RpcTx` to get the `RpcTxConverter` +/// implementation for free, thanks to the blanket implementation, unless the conversion requires +/// more context. For example, some configuration parameters or access handles to database, network, +/// etc. pub trait RpcTxConverter: Clone + Unpin + Send + Sync + 'static { /// An associated error that can happen during the conversion. type Err; @@ -305,19 +219,19 @@ pub trait RpcTxConverter: Clone + Unpin + Send + Sync + 'stat fn convert_rpc_tx(&self, tx: Tx, signer: Address, tx_info: TxInfo) -> Result; } -impl RpcTxConverter for () +impl RpcTxConverter>::TxInfo> for () where - Tx: IntoRpcTx, + RpcTx: FromConsensusTx, { - type Err = Tx::Err; + type Err = RpcTx::Err; fn convert_rpc_tx( &self, tx: Tx, signer: Address, - tx_info: Tx::TxInfo, + tx_info: >::TxInfo, ) -> Result { - tx.into_rpc_tx(signer, tx_info) + RpcTx::from_consensus_tx(tx, signer, tx_info) } } @@ -381,49 +295,6 @@ where } } -/// Converts `self` into `T`. -/// -/// Should create a fake transaction for simulation using [`TransactionRequest`]. -pub trait TryIntoSimTx -where - Self: Sized, -{ - /// Performs the conversion. - /// - /// Should return a signed typed transaction envelope for the [`eth_simulateV1`] endpoint with a - /// dummy signature or an error if [required fields] are missing. - /// - /// [`eth_simulateV1`]: - /// [required fields]: TransactionRequest::buildable_type - fn try_into_sim_tx(self) -> Result>; -} - -/// Adds extra context to [`TransactionInfo`]. -pub trait TxInfoMapper { - /// An associated output type that carries [`TransactionInfo`] with some extra context. - type Out; - /// An associated error that can occur during the mapping. - type Err; - - /// Performs the conversion. - fn try_map(&self, tx: &T, tx_info: TransactionInfo) -> Result; -} - -impl TxInfoMapper for () { - type Out = TransactionInfo; - type Err = Infallible; - - fn try_map(&self, _tx: &T, tx_info: TransactionInfo) -> Result { - Ok(tx_info) - } -} - -impl TryIntoSimTx> for TransactionRequest { - fn try_into_sim_tx(self) -> Result, ValueError> { - Self::build_typed_simulate_transaction(self) - } -} - /// Converts `TxReq` into `TxEnv`. /// /// Where: @@ -886,41 +757,3 @@ where Ok(self.header_converter.convert_header(header, block_size)?) } } - -/// Optimism specific RPC transaction compatibility implementations. -#[cfg(feature = "op")] -pub mod op { - use super::*; - use alloy_consensus::SignableTransaction; - use alloy_signer::Signature; - use op_alloy_consensus::{transaction::OpTransactionInfo, OpTxEnvelope}; - use op_alloy_rpc_types::OpTransactionRequest; - - impl FromConsensusTx - for op_alloy_rpc_types::Transaction - { - type TxInfo = OpTransactionInfo; - type Err = Infallible; - - fn from_consensus_tx( - tx: T, - signer: Address, - tx_info: Self::TxInfo, - ) -> Result { - Ok(Self::from_transaction(Recovered::new_unchecked(tx, signer), tx_info)) - } - } - - impl TryIntoSimTx for OpTransactionRequest { - fn try_into_sim_tx(self) -> Result> { - let tx = self - .build_typed_tx() - .map_err(|request| ValueError::new(request, "Required fields missing"))?; - - // Create an empty signature for the transaction. - let signature = Signature::new(Default::default(), Default::default(), false); - - Ok(tx.into_signed(signature).into()) - } - } -} diff --git a/crates/rpc/rpc-eth-api/Cargo.toml b/crates/rpc/rpc-eth-api/Cargo.toml index 327cb7ae7a4..83ebd47ea64 100644 --- a/crates/rpc/rpc-eth-api/Cargo.toml +++ b/crates/rpc/rpc-eth-api/Cargo.toml @@ -62,6 +62,3 @@ tracing.workspace = true [features] js-tracer = ["revm-inspectors/js-tracer", "reth-rpc-eth-types/js-tracer"] client = ["jsonrpsee/client", "jsonrpsee/async-client"] -op = [ - "reth-rpc-convert/op", -]