mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-02-19 03:04:27 -05:00
refactor: replace TryFrom*Response traits with unified RpcResponseConverter (#22320)
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
6
.changelog/evil-fish-smile.md
Normal file
6
.changelog/evil-fish-smile.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
reth-rpc-convert: minor
|
||||
reth-storage-rpc-provider: minor
|
||||
---
|
||||
|
||||
Replaced the separate `TryFromBlockResponse`, `TryFromReceiptResponse`, and `TryFromTransactionResponse` traits with a unified `RpcResponseConverter` trait and default `EthRpcConverter` implementation. Removed the `op-alloy-network` dependency and refactored `RpcBlockchainProvider` to store a dynamic converter instance instead of relying on per-type trait bounds.
|
||||
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -9934,9 +9934,7 @@ dependencies = [
|
||||
"dyn-clone",
|
||||
"jsonrpsee-types",
|
||||
"op-alloy-consensus",
|
||||
"op-alloy-network",
|
||||
"op-alloy-rpc-types",
|
||||
"reth-ethereum-primitives",
|
||||
"reth-evm",
|
||||
"reth-primitives-traits",
|
||||
"serde_json",
|
||||
@@ -10328,12 +10326,12 @@ dependencies = [
|
||||
"reth-chainspec",
|
||||
"reth-db-api",
|
||||
"reth-errors",
|
||||
"reth-ethereum-primitives",
|
||||
"reth-execution-types",
|
||||
"reth-node-types",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
"reth-prune-types",
|
||||
"reth-rpc-convert",
|
||||
"reth-stages-types",
|
||||
"reth-storage-api",
|
||||
"reth-trie",
|
||||
|
||||
@@ -15,7 +15,6 @@ workspace = true
|
||||
# reth
|
||||
reth-primitives-traits.workspace = true
|
||||
reth-evm.workspace = true
|
||||
reth-ethereum-primitives.workspace = true
|
||||
|
||||
# ethereum
|
||||
alloy-primitives.workspace = true
|
||||
@@ -29,7 +28,6 @@ alloy-evm = { workspace = true, features = ["rpc"] }
|
||||
# optimism
|
||||
op-alloy-consensus = { workspace = true, optional = true }
|
||||
op-alloy-rpc-types = { workspace = true, optional = true }
|
||||
op-alloy-network = { workspace = true, optional = true }
|
||||
|
||||
# io
|
||||
jsonrpsee-types.workspace = true
|
||||
@@ -48,7 +46,6 @@ default = []
|
||||
op = [
|
||||
"dep:op-alloy-consensus",
|
||||
"dep:op-alloy-rpc-types",
|
||||
"dep:op-alloy-network",
|
||||
"reth-evm/op",
|
||||
"reth-primitives-traits/op",
|
||||
"alloy-evm/op",
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
//! Conversion traits for block responses to primitive block types.
|
||||
|
||||
use alloy_network::Network;
|
||||
use std::convert::Infallible;
|
||||
|
||||
/// Trait for converting network block responses to primitive block types.
|
||||
pub trait TryFromBlockResponse<N: Network> {
|
||||
/// The error type returned if the conversion fails.
|
||||
type Error: core::error::Error + Send + Sync + Unpin;
|
||||
|
||||
/// Converts a network block response to a primitive block type.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(Self)` on successful conversion, or `Err(Self::Error)` if the conversion fails.
|
||||
fn from_block_response(block_response: N::BlockResponse) -> Result<Self, Self::Error>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl<N: Network, T> TryFromBlockResponse<N> for alloy_consensus::Block<T>
|
||||
where
|
||||
N::BlockResponse: Into<Self>,
|
||||
{
|
||||
type Error = Infallible;
|
||||
|
||||
fn from_block_response(block_response: N::BlockResponse) -> Result<Self, Self::Error> {
|
||||
Ok(block_response.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use alloy_consensus::{Block, TxEnvelope};
|
||||
use alloy_network::Ethereum;
|
||||
use alloy_rpc_types_eth::BlockTransactions;
|
||||
|
||||
#[test]
|
||||
fn test_try_from_block_response() {
|
||||
let rpc_block: alloy_rpc_types_eth::Block =
|
||||
alloy_rpc_types_eth::Block::new(Default::default(), BlockTransactions::Full(vec![]));
|
||||
let result =
|
||||
<Block<TxEnvelope> as TryFromBlockResponse<Ethereum>>::from_block_response(rpc_block);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
@@ -10,17 +10,12 @@
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
pub mod block;
|
||||
pub mod receipt;
|
||||
mod rpc;
|
||||
pub mod transaction;
|
||||
|
||||
pub use block::TryFromBlockResponse;
|
||||
pub use receipt::TryFromReceiptResponse;
|
||||
pub use rpc::*;
|
||||
pub use transaction::{
|
||||
RpcConvert, RpcConverter, TransactionConversionError, TryFromTransactionResponse, TryIntoSimTx,
|
||||
TxInfoMapper,
|
||||
RpcConvert, RpcConverter, TransactionConversionError, TryIntoSimTx, TxInfoMapper,
|
||||
};
|
||||
|
||||
pub use alloy_evm::rpc::{CallFees, CallFeesError, EthTxEnvError, TryIntoTxEnv};
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
//! Conversion traits for receipt responses to primitive receipt types.
|
||||
|
||||
use alloy_network::Network;
|
||||
use std::convert::Infallible;
|
||||
|
||||
/// Trait for converting network receipt responses to primitive receipt types.
|
||||
pub trait TryFromReceiptResponse<N: Network> {
|
||||
/// The error type returned if the conversion fails.
|
||||
type Error: core::error::Error + Send + Sync + Unpin;
|
||||
|
||||
/// Converts a network receipt response to a primitive receipt type.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(Self)` on successful conversion, or `Err(Self::Error)` if the conversion fails.
|
||||
fn from_receipt_response(receipt_response: N::ReceiptResponse) -> Result<Self, Self::Error>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl TryFromReceiptResponse<alloy_network::Ethereum> for reth_ethereum_primitives::Receipt {
|
||||
type Error = Infallible;
|
||||
|
||||
fn from_receipt_response(
|
||||
receipt_response: alloy_rpc_types_eth::TransactionReceipt,
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(receipt_response.into_inner().into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "op")]
|
||||
impl TryFromReceiptResponse<op_alloy_network::Optimism> for op_alloy_consensus::OpReceipt {
|
||||
type Error = Infallible;
|
||||
|
||||
fn from_receipt_response(
|
||||
receipt_response: op_alloy_rpc_types::OpTransactionReceipt,
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(receipt_response.inner.inner.into_components().0.map_logs(Into::into))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use alloy_consensus::ReceiptEnvelope;
|
||||
use alloy_network::Ethereum;
|
||||
use reth_ethereum_primitives::Receipt;
|
||||
|
||||
#[test]
|
||||
fn test_try_from_receipt_response() {
|
||||
let rpc_receipt = alloy_rpc_types_eth::TransactionReceipt {
|
||||
inner: ReceiptEnvelope::Eip1559(Default::default()),
|
||||
transaction_hash: Default::default(),
|
||||
transaction_index: None,
|
||||
block_hash: None,
|
||||
block_number: None,
|
||||
gas_used: 0,
|
||||
effective_gas_price: 0,
|
||||
blob_gas_used: None,
|
||||
blob_gas_price: None,
|
||||
from: Default::default(),
|
||||
to: None,
|
||||
contract_address: None,
|
||||
};
|
||||
let result =
|
||||
<Receipt as TryFromReceiptResponse<Ethereum>>::from_receipt_response(rpc_receipt);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[cfg(feature = "op")]
|
||||
#[test]
|
||||
fn test_try_from_receipt_response_optimism() {
|
||||
use alloy_consensus::ReceiptWithBloom;
|
||||
use op_alloy_consensus::OpReceipt;
|
||||
use op_alloy_network::Optimism;
|
||||
use op_alloy_rpc_types::OpTransactionReceipt;
|
||||
|
||||
let op_receipt = OpTransactionReceipt {
|
||||
inner: alloy_rpc_types_eth::TransactionReceipt {
|
||||
inner: ReceiptWithBloom {
|
||||
receipt: OpReceipt::Eip1559(Default::default()),
|
||||
logs_bloom: Default::default(),
|
||||
},
|
||||
transaction_hash: Default::default(),
|
||||
transaction_index: None,
|
||||
block_hash: None,
|
||||
block_number: None,
|
||||
gas_used: 0,
|
||||
effective_gas_price: 0,
|
||||
blob_gas_used: None,
|
||||
blob_gas_price: None,
|
||||
from: Default::default(),
|
||||
to: None,
|
||||
contract_address: None,
|
||||
},
|
||||
l1_block_info: Default::default(),
|
||||
};
|
||||
let result =
|
||||
<OpReceipt as TryFromReceiptResponse<Optimism>>::from_receipt_response(op_receipt);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ use crate::{
|
||||
use alloy_consensus::{
|
||||
error::ValueError, transaction::Recovered, EthereumTxEnvelope, Sealable, TxEip4844,
|
||||
};
|
||||
use alloy_network::Network;
|
||||
use alloy_primitives::{Address, U256};
|
||||
use alloy_rpc_types_eth::{request::TransactionRequest, Transaction, TransactionInfo};
|
||||
use core::error;
|
||||
@@ -903,112 +902,3 @@ pub mod op {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for converting network transaction responses to primitive transaction types.
|
||||
pub trait TryFromTransactionResponse<N: Network> {
|
||||
/// The error type returned if the conversion fails.
|
||||
type Error: core::error::Error + Send + Sync + Unpin;
|
||||
|
||||
/// Converts a network transaction response to a primitive transaction type.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(Self)` on successful conversion, or `Err(Self::Error)` if the conversion fails.
|
||||
fn from_transaction_response(
|
||||
transaction_response: N::TransactionResponse,
|
||||
) -> Result<Self, Self::Error>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl TryFromTransactionResponse<alloy_network::Ethereum>
|
||||
for reth_ethereum_primitives::TransactionSigned
|
||||
{
|
||||
type Error = Infallible;
|
||||
|
||||
fn from_transaction_response(transaction_response: Transaction) -> Result<Self, Self::Error> {
|
||||
Ok(transaction_response.into_inner().into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "op")]
|
||||
impl TryFromTransactionResponse<op_alloy_network::Optimism> for op_alloy_consensus::OpTxEnvelope {
|
||||
type Error = Infallible;
|
||||
|
||||
fn from_transaction_response(
|
||||
transaction_response: op_alloy_rpc_types::Transaction,
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(transaction_response.inner.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod transaction_response_tests {
|
||||
use super::*;
|
||||
use alloy_consensus::{transaction::Recovered, EthereumTxEnvelope, Signed, TxLegacy};
|
||||
use alloy_network::Ethereum;
|
||||
use alloy_primitives::{Address, Signature, B256, U256};
|
||||
use alloy_rpc_types_eth::Transaction;
|
||||
|
||||
#[test]
|
||||
fn test_ethereum_transaction_conversion() {
|
||||
let signed_tx = Signed::new_unchecked(
|
||||
TxLegacy::default(),
|
||||
Signature::new(U256::ONE, U256::ONE, false),
|
||||
B256::ZERO,
|
||||
);
|
||||
let envelope = EthereumTxEnvelope::Legacy(signed_tx);
|
||||
|
||||
let tx_response = Transaction {
|
||||
inner: Recovered::new_unchecked(envelope, Address::ZERO),
|
||||
block_hash: None,
|
||||
block_number: None,
|
||||
transaction_index: None,
|
||||
effective_gas_price: None,
|
||||
};
|
||||
|
||||
let result = <reth_ethereum_primitives::TransactionSigned as TryFromTransactionResponse<
|
||||
Ethereum,
|
||||
>>::from_transaction_response(tx_response);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[cfg(feature = "op")]
|
||||
mod op {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_optimism_transaction_conversion() {
|
||||
use op_alloy_consensus::OpTxEnvelope;
|
||||
use op_alloy_network::Optimism;
|
||||
|
||||
let signed_tx = Signed::new_unchecked(
|
||||
TxLegacy::default(),
|
||||
Signature::new(U256::ONE, U256::ONE, false),
|
||||
B256::ZERO,
|
||||
);
|
||||
let envelope = OpTxEnvelope::Legacy(signed_tx);
|
||||
|
||||
let inner_tx = Transaction {
|
||||
inner: Recovered::new_unchecked(envelope, Address::ZERO),
|
||||
block_hash: None,
|
||||
block_number: None,
|
||||
transaction_index: None,
|
||||
effective_gas_price: None,
|
||||
};
|
||||
|
||||
let tx_response = op_alloy_rpc_types::Transaction {
|
||||
inner: inner_tx,
|
||||
deposit_nonce: None,
|
||||
deposit_receipt_version: None,
|
||||
};
|
||||
|
||||
let result =
|
||||
<OpTxEnvelope as TryFromTransactionResponse<Optimism>>::from_transaction_response(
|
||||
tx_response,
|
||||
);
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ workspace = true
|
||||
reth-storage-api.workspace = true
|
||||
reth-chainspec.workspace = true
|
||||
reth-primitives.workspace = true
|
||||
reth-ethereum-primitives.workspace = true
|
||||
reth-provider.workspace = true
|
||||
reth-errors.workspace = true
|
||||
reth-execution-types.workspace = true
|
||||
@@ -24,7 +25,6 @@ reth-node-types.workspace = true
|
||||
reth-trie.workspace = true
|
||||
reth-stages-types.workspace = true
|
||||
reth-db-api.workspace = true
|
||||
reth-rpc-convert.workspace = true
|
||||
|
||||
# alloy
|
||||
alloy-provider = { workspace = true, features = ["debug-api"] }
|
||||
|
||||
@@ -51,13 +51,14 @@ use reth_provider::{
|
||||
TransactionVariant, TransactionsProvider,
|
||||
};
|
||||
use reth_prune_types::{PruneCheckpoint, PruneSegment};
|
||||
use reth_rpc_convert::{TryFromBlockResponse, TryFromReceiptResponse, TryFromTransactionResponse};
|
||||
pub mod rpc_response;
|
||||
use reth_stages_types::{StageCheckpoint, StageId};
|
||||
use reth_storage_api::{
|
||||
BlockBodyIndicesProvider, BlockReaderIdExt, BlockSource, DBProvider, NodePrimitivesProvider,
|
||||
ReceiptProviderIdExt, StatsReader,
|
||||
};
|
||||
use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, MultiProof, TrieInput};
|
||||
pub use rpc_response::{EthRpcConverter, RpcResponseConverter};
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
future::{Future, IntoFuture},
|
||||
@@ -100,6 +101,14 @@ impl RpcBlockchainProviderConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Type-erased RPC response converter stored in [`RpcBlockchainProvider`].
|
||||
type DynRpcConverter<Node, N> = dyn RpcResponseConverter<
|
||||
N,
|
||||
Block = BlockTy<Node>,
|
||||
Transaction = TxTy<Node>,
|
||||
Receipt = ReceiptTy<Node>,
|
||||
>;
|
||||
|
||||
/// An RPC-based blockchain provider that fetches blockchain data via remote RPC calls.
|
||||
///
|
||||
/// This is the RPC equivalent of
|
||||
@@ -119,6 +128,7 @@ impl RpcBlockchainProviderConfig {
|
||||
pub struct RpcBlockchainProvider<P, Node, N = alloy_network::AnyNetwork>
|
||||
where
|
||||
Node: NodeTypes,
|
||||
N: Network,
|
||||
{
|
||||
/// The underlying Alloy provider
|
||||
provider: P,
|
||||
@@ -132,25 +142,66 @@ where
|
||||
config: RpcBlockchainProviderConfig,
|
||||
/// Cached chain spec
|
||||
chain_spec: Arc<Node::ChainSpec>,
|
||||
/// Converts RPC responses to primitive types.
|
||||
converter: Arc<DynRpcConverter<Node, N>>,
|
||||
}
|
||||
|
||||
impl<P, Node: NodeTypes, N> std::fmt::Debug for RpcBlockchainProvider<P, Node, N> {
|
||||
impl<P, Node: NodeTypes, N: Network> std::fmt::Debug for RpcBlockchainProvider<P, Node, N> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("RpcBlockchainProvider").field("config", &self.config).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, Node: NodeTypes, N> RpcBlockchainProvider<P, Node, N> {
|
||||
/// Creates a new `RpcBlockchainProvider` with default configuration
|
||||
impl<P, Node: NodeTypes, N: Network> RpcBlockchainProvider<P, Node, N>
|
||||
where
|
||||
EthRpcConverter: RpcResponseConverter<
|
||||
N,
|
||||
Block = BlockTy<Node>,
|
||||
Transaction = TxTy<Node>,
|
||||
Receipt = ReceiptTy<Node>,
|
||||
>,
|
||||
{
|
||||
/// Creates a new `RpcBlockchainProvider` with the default [`EthRpcConverter`].
|
||||
pub fn new(provider: P) -> Self
|
||||
where
|
||||
Node::ChainSpec: Default,
|
||||
{
|
||||
Self::new_with_config(provider, RpcBlockchainProviderConfig::default())
|
||||
Self::new_with_converter(provider, EthRpcConverter)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, Node: NodeTypes, N: Network> RpcBlockchainProvider<P, Node, N> {
|
||||
/// Creates a new `RpcBlockchainProvider` with default configuration and the given converter.
|
||||
pub fn new_with_converter(
|
||||
provider: P,
|
||||
converter: impl RpcResponseConverter<
|
||||
N,
|
||||
Block = BlockTy<Node>,
|
||||
Transaction = TxTy<Node>,
|
||||
Receipt = ReceiptTy<Node>,
|
||||
>,
|
||||
) -> Self
|
||||
where
|
||||
Node::ChainSpec: Default,
|
||||
{
|
||||
Self::new_with_converter_and_config(
|
||||
provider,
|
||||
converter,
|
||||
RpcBlockchainProviderConfig::default(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a new `RpcBlockchainProvider` with custom configuration
|
||||
pub fn new_with_config(provider: P, config: RpcBlockchainProviderConfig) -> Self
|
||||
/// Creates a new `RpcBlockchainProvider` with custom configuration and the given converter.
|
||||
pub fn new_with_converter_and_config(
|
||||
provider: P,
|
||||
converter: impl RpcResponseConverter<
|
||||
N,
|
||||
Block = BlockTy<Node>,
|
||||
Transaction = TxTy<Node>,
|
||||
Receipt = ReceiptTy<Node>,
|
||||
>,
|
||||
config: RpcBlockchainProviderConfig,
|
||||
) -> Self
|
||||
where
|
||||
Node::ChainSpec: Default,
|
||||
{
|
||||
@@ -162,19 +213,13 @@ impl<P, Node: NodeTypes, N> RpcBlockchainProvider<P, Node, N> {
|
||||
canon_state_notification,
|
||||
config,
|
||||
chain_spec: Arc::new(Node::ChainSpec::default()),
|
||||
converter: Arc::new(converter),
|
||||
}
|
||||
}
|
||||
|
||||
/// Use a custom chain spec for the provider
|
||||
pub fn with_chain_spec(self, chain_spec: Arc<Node::ChainSpec>) -> Self {
|
||||
Self {
|
||||
provider: self.provider,
|
||||
node_types: std::marker::PhantomData,
|
||||
network: std::marker::PhantomData,
|
||||
canon_state_notification: self.canon_state_notification,
|
||||
config: self.config,
|
||||
chain_spec,
|
||||
}
|
||||
Self { chain_spec, ..self }
|
||||
}
|
||||
|
||||
/// Helper function to execute async operations in a blocking context
|
||||
@@ -332,7 +377,6 @@ where
|
||||
P: Provider<N> + Clone + 'static,
|
||||
N: Network,
|
||||
Node: NodeTypes,
|
||||
BlockTy<Node>: TryFromBlockResponse<N>,
|
||||
{
|
||||
type Header = HeaderTy<Node>;
|
||||
|
||||
@@ -347,8 +391,7 @@ where
|
||||
};
|
||||
|
||||
// Convert the network block response to primitive block
|
||||
let block = <BlockTy<Node> as TryFromBlockResponse<N>>::from_block_response(block_response)
|
||||
.map_err(ProviderError::other)?;
|
||||
let block = self.converter.block(block_response).map_err(ProviderError::other)?;
|
||||
|
||||
Ok(Some(block.into_header()))
|
||||
}
|
||||
@@ -384,8 +427,7 @@ where
|
||||
let block_hash = block_response.header().hash();
|
||||
|
||||
// Convert the network block response to primitive block
|
||||
let block = <BlockTy<Node> as TryFromBlockResponse<N>>::from_block_response(block_response)
|
||||
.map_err(ProviderError::other)?;
|
||||
let block = self.converter.block(block_response).map_err(ProviderError::other)?;
|
||||
|
||||
Ok(Some(SealedHeader::new(block.into_header(), block_hash)))
|
||||
}
|
||||
@@ -422,9 +464,6 @@ where
|
||||
P: Provider<N> + Clone + 'static,
|
||||
N: Network,
|
||||
Node: NodeTypes,
|
||||
BlockTy<Node>: TryFromBlockResponse<N>,
|
||||
TxTy<Node>: TryFromTransactionResponse<N>,
|
||||
ReceiptTy<Node>: TryFromReceiptResponse<N>,
|
||||
{
|
||||
type Block = BlockTy<Node>;
|
||||
|
||||
@@ -447,8 +486,7 @@ where
|
||||
};
|
||||
|
||||
// Convert the network block response to primitive block
|
||||
let block = <BlockTy<Node> as TryFromBlockResponse<N>>::from_block_response(block_response)
|
||||
.map_err(ProviderError::other)?;
|
||||
let block = self.converter.block(block_response).map_err(ProviderError::other)?;
|
||||
|
||||
Ok(Some(block))
|
||||
}
|
||||
@@ -507,9 +545,6 @@ where
|
||||
P: Provider<N> + Clone + 'static,
|
||||
N: Network,
|
||||
Node: NodeTypes,
|
||||
BlockTy<Node>: TryFromBlockResponse<N>,
|
||||
TxTy<Node>: TryFromTransactionResponse<N>,
|
||||
ReceiptTy<Node>: TryFromReceiptResponse<N>,
|
||||
{
|
||||
fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>> {
|
||||
match id {
|
||||
@@ -541,7 +576,6 @@ where
|
||||
P: Provider<N> + Clone + 'static,
|
||||
N: Network,
|
||||
Node: NodeTypes,
|
||||
ReceiptTy<Node>: TryFromReceiptResponse<N>,
|
||||
{
|
||||
type Receipt = ReceiptTy<Node>;
|
||||
|
||||
@@ -555,15 +589,10 @@ where
|
||||
})?;
|
||||
|
||||
let Some(receipt_response) = receipt_response else {
|
||||
// If the receipt was not found, return None
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// Convert the network receipt response to primitive receipt
|
||||
let receipt =
|
||||
<ReceiptTy<Node> as TryFromReceiptResponse<N>>::from_receipt_response(receipt_response)
|
||||
.map_err(ProviderError::other)?;
|
||||
|
||||
let receipt = self.converter.receipt(receipt_response).map_err(ProviderError::other)?;
|
||||
Ok(Some(receipt))
|
||||
}
|
||||
|
||||
@@ -579,19 +608,12 @@ where
|
||||
.map_err(ProviderError::other)?;
|
||||
|
||||
let Some(receipts) = receipts_response else {
|
||||
// If the receipts were not found, return None
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// Convert the network receipts response to primitive receipts
|
||||
let receipts = receipts
|
||||
.into_iter()
|
||||
.map(|receipt_response| {
|
||||
<ReceiptTy<Node> as TryFromReceiptResponse<N>>::from_receipt_response(
|
||||
receipt_response,
|
||||
)
|
||||
.map_err(ProviderError::other)
|
||||
})
|
||||
.map(|r| self.converter.receipt(r).map_err(ProviderError::other))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(Some(receipts))
|
||||
@@ -618,7 +640,6 @@ where
|
||||
P: Provider<N> + Clone + 'static,
|
||||
N: Network,
|
||||
Node: NodeTypes,
|
||||
ReceiptTy<Node>: TryFromReceiptResponse<N>,
|
||||
{
|
||||
}
|
||||
|
||||
@@ -627,8 +648,6 @@ where
|
||||
P: Provider<N> + Clone + 'static,
|
||||
N: Network,
|
||||
Node: NodeTypes,
|
||||
BlockTy<Node>: TryFromBlockResponse<N>,
|
||||
TxTy<Node>: TryFromTransactionResponse<N>,
|
||||
{
|
||||
type Transaction = TxTy<Node>;
|
||||
|
||||
@@ -653,16 +672,11 @@ where
|
||||
})?;
|
||||
|
||||
let Some(transaction_response) = transaction_response else {
|
||||
// If the transaction was not found, return None
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// Convert the network transaction response to primitive transaction
|
||||
let transaction = <TxTy<Node> as TryFromTransactionResponse<N>>::from_transaction_response(
|
||||
transaction_response,
|
||||
)
|
||||
.map_err(ProviderError::other)?;
|
||||
|
||||
let transaction =
|
||||
self.converter.transaction(transaction_response).map_err(ProviderError::other)?;
|
||||
Ok(Some(transaction))
|
||||
}
|
||||
|
||||
@@ -682,14 +696,10 @@ where
|
||||
})?;
|
||||
|
||||
let Some(block_response) = block_response else {
|
||||
// If the block was not found, return None
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// Convert the network block response to primitive block
|
||||
let block = <BlockTy<Node> as TryFromBlockResponse<N>>::from_block_response(block_response)
|
||||
.map_err(ProviderError::other)?;
|
||||
|
||||
let block = self.converter.block(block_response).map_err(ProviderError::other)?;
|
||||
Ok(Some(block.into_body().into_transactions()))
|
||||
}
|
||||
|
||||
@@ -855,7 +865,7 @@ where
|
||||
impl<P, Node, N> NodePrimitivesProvider for RpcBlockchainProvider<P, Node, N>
|
||||
where
|
||||
P: Send + Sync,
|
||||
N: Send + Sync,
|
||||
N: Network,
|
||||
Node: NodeTypes,
|
||||
{
|
||||
type Primitives = PrimitivesTy<Node>;
|
||||
@@ -876,7 +886,7 @@ where
|
||||
impl<P, Node, N> ChainSpecProvider for RpcBlockchainProvider<P, Node, N>
|
||||
where
|
||||
P: Send + Sync,
|
||||
N: Send + Sync,
|
||||
N: Network,
|
||||
Node: NodeTypes,
|
||||
Node::ChainSpec: Default,
|
||||
{
|
||||
@@ -1834,7 +1844,7 @@ where
|
||||
impl<P, Node, N> ChainSpecProvider for RpcBlockchainStateProvider<P, Node, N>
|
||||
where
|
||||
P: Send + Sync + std::fmt::Debug,
|
||||
N: Send + Sync,
|
||||
N: Network,
|
||||
Node: NodeTypes,
|
||||
Node::ChainSpec: Default,
|
||||
{
|
||||
@@ -1888,7 +1898,7 @@ where
|
||||
impl<P, Node, N> NodePrimitivesProvider for RpcBlockchainStateProvider<P, Node, N>
|
||||
where
|
||||
P: Send + Sync + std::fmt::Debug,
|
||||
N: Send + Sync,
|
||||
N: Network,
|
||||
Node: NodeTypes,
|
||||
{
|
||||
type Primitives = PrimitivesTy<Node>;
|
||||
|
||||
75
crates/storage/rpc-provider/src/rpc_response.rs
Normal file
75
crates/storage/rpc-provider/src/rpc_response.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
//! Unified converter for RPC network responses to primitive types.
|
||||
|
||||
use alloy_network::Network;
|
||||
use alloy_rpc_types::eth::{Block, Transaction, TransactionReceipt};
|
||||
use core::fmt::Debug;
|
||||
use reth_ethereum_primitives::{Receipt, TransactionSigned};
|
||||
|
||||
/// Error type used by [`RpcResponseConverter`].
|
||||
#[derive(Debug)]
|
||||
pub struct RpcResponseConverterError(pub Box<dyn core::error::Error + Send + Sync>);
|
||||
|
||||
impl core::fmt::Display for RpcResponseConverterError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
core::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::error::Error for RpcResponseConverterError {
|
||||
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
|
||||
self.0.source()
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts RPC network responses (blocks, transactions, receipts) into primitive types.
|
||||
pub trait RpcResponseConverter<N: Network>: Send + Sync + Debug + 'static {
|
||||
/// Primitive block type.
|
||||
type Block;
|
||||
/// Primitive transaction type.
|
||||
type Transaction;
|
||||
/// Primitive receipt type.
|
||||
type Receipt;
|
||||
|
||||
/// Converts a network block response to a primitive block.
|
||||
fn block(&self, response: N::BlockResponse) -> Result<Self::Block, RpcResponseConverterError>;
|
||||
|
||||
/// Converts a network transaction response to a primitive transaction.
|
||||
fn transaction(
|
||||
&self,
|
||||
response: N::TransactionResponse,
|
||||
) -> Result<Self::Transaction, RpcResponseConverterError>;
|
||||
|
||||
/// Converts a network receipt response to a primitive receipt.
|
||||
fn receipt(
|
||||
&self,
|
||||
response: N::ReceiptResponse,
|
||||
) -> Result<Self::Receipt, RpcResponseConverterError>;
|
||||
}
|
||||
|
||||
/// Default Ethereum converter using upstream `From` impls.
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct EthRpcConverter;
|
||||
|
||||
impl RpcResponseConverter<alloy_network::Ethereum> for EthRpcConverter {
|
||||
type Block = alloy_consensus::Block<TransactionSigned>;
|
||||
type Transaction = TransactionSigned;
|
||||
type Receipt = Receipt;
|
||||
|
||||
fn block(&self, response: Block) -> Result<Self::Block, RpcResponseConverterError> {
|
||||
Ok(response.into())
|
||||
}
|
||||
|
||||
fn transaction(
|
||||
&self,
|
||||
response: Transaction,
|
||||
) -> Result<Self::Transaction, RpcResponseConverterError> {
|
||||
Ok(response.into_inner().into())
|
||||
}
|
||||
|
||||
fn receipt(
|
||||
&self,
|
||||
response: TransactionReceipt,
|
||||
) -> Result<Self::Receipt, RpcResponseConverterError> {
|
||||
Ok(response.into_inner().into())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user