feat: add Transaction AT to TransactionsProvider (#12794)

This commit is contained in:
Arsenii Kulikov
2024-11-23 03:04:42 +04:00
committed by GitHub
parent 36db1c2407
commit 5db3ad1a67
33 changed files with 389 additions and 271 deletions

View File

@ -19,6 +19,7 @@
//! use alloy_consensus::Header;
//! use reth_evm::{execute::BlockExecutorProvider, ConfigureEvm};
//! use reth_network_api::{NetworkInfo, Peers};
//! use reth_primitives::TransactionSigned;
//! use reth_provider::{AccountReader, CanonStateSubscriptions, ChangeSetReader, FullRpcProvider};
//! use reth_rpc::EthApi;
//! use reth_rpc_builder::{
@ -36,7 +37,8 @@
//! block_executor: BlockExecutor,
//! consensus: Consensus,
//! ) where
//! Provider: FullRpcProvider + AccountReader + ChangeSetReader,
//! Provider:
//! FullRpcProvider<Transaction = TransactionSigned> + AccountReader + ChangeSetReader,
//! Pool: TransactionPool + Unpin + 'static,
//! Network: NetworkInfo + Peers + Clone + 'static,
//! Events: CanonStateSubscriptions + Clone + 'static,
@ -77,6 +79,7 @@
//! use reth_engine_primitives::EngineTypes;
//! use reth_evm::{execute::BlockExecutorProvider, ConfigureEvm};
//! use reth_network_api::{NetworkInfo, Peers};
//! use reth_primitives::TransactionSigned;
//! use reth_provider::{AccountReader, CanonStateSubscriptions, ChangeSetReader, FullRpcProvider};
//! use reth_rpc::EthApi;
//! use reth_rpc_api::EngineApiServer;
@ -109,7 +112,8 @@
//! block_executor: BlockExecutor,
//! consensus: Consensus,
//! ) where
//! Provider: FullRpcProvider + AccountReader + ChangeSetReader,
//! Provider:
//! FullRpcProvider<Transaction = TransactionSigned> + AccountReader + ChangeSetReader,
//! Pool: TransactionPool + Unpin + 'static,
//! Network: NetworkInfo + Peers + Clone + 'static,
//! Events: CanonStateSubscriptions + Clone + 'static,

View File

@ -2,18 +2,21 @@
//! loads receipt data w.r.t. network.
use futures::Future;
use reth_primitives::{Receipt, TransactionMeta, TransactionSigned};
use reth_primitives::{Receipt, TransactionMeta};
use reth_provider::TransactionsProvider;
use crate::{EthApiTypes, RpcNodeCoreExt, RpcReceipt};
/// Assembles transaction receipt data w.r.t to network.
///
/// Behaviour shared by several `eth_` RPC methods, not exclusive to `eth_` receipts RPC methods.
pub trait LoadReceipt: EthApiTypes + RpcNodeCoreExt + Send + Sync {
pub trait LoadReceipt:
EthApiTypes + RpcNodeCoreExt<Provider: TransactionsProvider> + Send + Sync
{
/// Helper method for `eth_getBlockReceipts` and `eth_getTransactionReceipt`.
fn build_transaction_receipt(
&self,
tx: TransactionSigned,
tx: <Self::Provider as TransactionsProvider>::Transaction,
meta: TransactionMeta,
receipt: Receipt,
) -> impl Future<Output = Result<RpcReceipt<Self::NetworkTypes>, Self::Error>> + Send;

View File

@ -9,7 +9,9 @@ use alloy_primitives::{Address, Bytes, TxHash, B256};
use alloy_rpc_types_eth::{transaction::TransactionRequest, BlockNumberOrTag, TransactionInfo};
use futures::Future;
use reth_primitives::{Receipt, SealedBlockWithSenders, TransactionMeta, TransactionSigned};
use reth_provider::{BlockNumReader, BlockReaderIdExt, ReceiptProvider, TransactionsProvider};
use reth_provider::{
BlockNumReader, BlockReaderIdExt, ProviderTx, ReceiptProvider, TransactionsProvider,
};
use reth_rpc_eth_types::{
utils::{binary_search, recover_raw_transaction},
EthApiError, SignError, TransactionSource,
@ -60,10 +62,13 @@ pub trait EthTransactions: LoadTransaction<Provider: BlockReaderIdExt> {
/// Checks the pool and state.
///
/// Returns `Ok(None)` if no matching transaction was found.
#[expect(clippy::complexity)]
fn transaction_by_hash(
&self,
hash: B256,
) -> impl Future<Output = Result<Option<TransactionSource>, Self::Error>> + Send {
) -> impl Future<
Output = Result<Option<TransactionSource<ProviderTx<Self::Provider>>>, Self::Error>,
> + Send {
LoadTransaction::transaction_by_hash(self, hash)
}
@ -148,11 +153,15 @@ pub trait EthTransactions: LoadTransaction<Provider: BlockReaderIdExt> {
}
/// Helper method that loads a transaction and its receipt.
#[expect(clippy::complexity)]
fn load_transaction_and_receipt(
&self,
hash: TxHash,
) -> impl Future<
Output = Result<Option<(TransactionSigned, TransactionMeta, Receipt)>, Self::Error>,
Output = Result<
Option<(ProviderTx<Self::Provider>, TransactionMeta, Receipt)>,
Self::Error,
>,
> + Send
where
Self: 'static,
@ -477,10 +486,13 @@ pub trait LoadTransaction:
/// Checks the pool and state.
///
/// Returns `Ok(None)` if no matching transaction was found.
#[expect(clippy::complexity)]
fn transaction_by_hash(
&self,
hash: B256,
) -> impl Future<Output = Result<Option<TransactionSource>, Self::Error>> + Send {
) -> impl Future<
Output = Result<Option<TransactionSource<ProviderTx<Self::Provider>>>, Self::Error>,
> + Send {
async move {
// Try to find the transaction on disk
let mut resp = self

View File

@ -7,9 +7,11 @@ use std::{
use alloy_network::Network;
use alloy_rpc_types_eth::Block;
use reth_primitives::TransactionSigned;
use reth_provider::TransactionsProvider;
use reth_rpc_types_compat::TransactionCompat;
use crate::{AsEthApiError, FromEthApiError, FromEvmError};
use crate::{AsEthApiError, FromEthApiError, FromEvmError, RpcNodeCore};
/// Network specific `eth` API types.
pub trait EthApiTypes: Send + Sync + Clone {
@ -43,22 +45,27 @@ pub type RpcReceipt<T> = <T as Network>::ReceiptResponse;
pub type RpcError<T> = <T as EthApiTypes>::Error;
/// Helper trait holds necessary trait bounds on [`EthApiTypes`] to implement `eth` API.
pub trait FullEthApiTypes:
EthApiTypes<
TransactionCompat: TransactionCompat<
Transaction = RpcTransaction<Self::NetworkTypes>,
Error = RpcError<Self>,
>,
>
pub trait FullEthApiTypes
where
Self: RpcNodeCore<Provider: TransactionsProvider<Transaction = TransactionSigned>>
+ EthApiTypes<
TransactionCompat: TransactionCompat<
<Self::Provider as TransactionsProvider>::Transaction,
Transaction = RpcTransaction<Self::NetworkTypes>,
Error = RpcError<Self>,
>,
>,
{
}
impl<T> FullEthApiTypes for T where
T: EthApiTypes<
TransactionCompat: TransactionCompat<
Transaction = RpcTransaction<T::NetworkTypes>,
Error = RpcError<T>,
>,
>
T: RpcNodeCore<Provider: TransactionsProvider<Transaction = TransactionSigned>>
+ EthApiTypes<
TransactionCompat: TransactionCompat<
<Self::Provider as TransactionsProvider>::Transaction,
Transaction = RpcTransaction<T::NetworkTypes>,
Error = RpcError<T>,
>,
>
{
}

View File

@ -19,6 +19,7 @@ reth-evm.workspace = true
reth-execution-types.workspace = true
reth-metrics.workspace = true
reth-primitives = { workspace = true, features = ["secp256k1"] }
reth-primitives-traits.workspace = true
reth-storage-api.workspace = true
reth-revm.workspace = true
reth-rpc-server-types.workspace = true

View File

@ -2,7 +2,7 @@
//!
//! Log parsing for building filter.
use alloy_eips::BlockNumHash;
use alloy_eips::{eip2718::Encodable2718, BlockNumHash};
use alloy_primitives::TxHash;
use alloy_rpc_types_eth::{FilteredParams, Log};
use reth_chainspec::ChainInfo;
@ -110,7 +110,7 @@ pub fn append_matching_block_logs<P: BlockReader>(
ProviderError::TransactionNotFound(transaction_id.into())
})?;
Some(transaction.hash())
Some(transaction.trie_hash())
}
};
}

View File

@ -4,7 +4,8 @@
use alloy_primitives::B256;
use alloy_rpc_types_eth::TransactionInfo;
use reth_primitives::TransactionSignedEcRecovered;
use reth_primitives::{TransactionSigned, TransactionSignedEcRecovered};
use reth_primitives_traits::SignedTransaction;
use reth_rpc_types_compat::{
transaction::{from_recovered, from_recovered_with_block_context},
TransactionCompat,
@ -12,15 +13,15 @@ use reth_rpc_types_compat::{
/// Represents from where a transaction was fetched.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum TransactionSource {
pub enum TransactionSource<T = TransactionSigned> {
/// Transaction exists in the pool (Pending)
Pool(TransactionSignedEcRecovered),
Pool(TransactionSignedEcRecovered<T>),
/// Transaction already included in a block
///
/// This can be a historical block or a pending block (received from the CL)
Block {
/// Transaction fetched via provider
transaction: TransactionSignedEcRecovered,
transaction: TransactionSignedEcRecovered<T>,
/// Index of the transaction in the block
index: u64,
/// Hash of the block.
@ -34,22 +35,22 @@ pub enum TransactionSource {
// === impl TransactionSource ===
impl TransactionSource {
impl<T: SignedTransaction> TransactionSource<T> {
/// Consumes the type and returns the wrapped transaction.
pub fn into_recovered(self) -> TransactionSignedEcRecovered {
pub fn into_recovered(self) -> TransactionSignedEcRecovered<T> {
self.into()
}
/// Conversion into network specific transaction type.
pub fn into_transaction<T: TransactionCompat>(
pub fn into_transaction<Builder: TransactionCompat<T>>(
self,
resp_builder: &T,
) -> Result<T::Transaction, T::Error> {
resp_builder: &Builder,
) -> Result<Builder::Transaction, Builder::Error> {
match self {
Self::Pool(tx) => from_recovered(tx, resp_builder),
Self::Block { transaction, index, block_hash, block_number, base_fee } => {
let tx_info = TransactionInfo {
hash: Some(transaction.hash()),
hash: Some(transaction.trie_hash()),
index: Some(index),
block_hash: Some(block_hash),
block_number: Some(block_number),
@ -62,14 +63,14 @@ impl TransactionSource {
}
/// Returns the transaction and block related info, if not pending
pub fn split(self) -> (TransactionSignedEcRecovered, TransactionInfo) {
pub fn split(self) -> (TransactionSignedEcRecovered<T>, TransactionInfo) {
match self {
Self::Pool(tx) => {
let hash = tx.hash();
let hash = tx.trie_hash();
(tx, TransactionInfo { hash: Some(hash), ..Default::default() })
}
Self::Block { transaction, index, block_hash, block_number, base_fee } => {
let hash = transaction.hash();
let hash = transaction.trie_hash();
(
transaction,
TransactionInfo {
@ -85,8 +86,8 @@ impl TransactionSource {
}
}
impl From<TransactionSource> for TransactionSignedEcRecovered {
fn from(value: TransactionSource) -> Self {
impl<T> From<TransactionSource<T>> for TransactionSignedEcRecovered<T> {
fn from(value: TransactionSource<T>) -> Self {
match value {
TransactionSource::Pool(tx) => tx,
TransactionSource::Block { transaction, .. } => transaction,

View File

@ -7,7 +7,7 @@ use alloy_rlp::Encodable;
use alloy_rpc_types_eth::{
Block, BlockTransactions, BlockTransactionsKind, Header, TransactionInfo,
};
use reth_primitives::{Block as PrimitiveBlock, BlockWithSenders};
use reth_primitives::{Block as PrimitiveBlock, BlockWithSenders, TransactionSigned};
use crate::{transaction::from_recovered_with_block_context, TransactionCompat};
@ -87,7 +87,11 @@ pub fn from_block_full<T: TransactionCompat>(
index: Some(idx as u64),
};
from_recovered_with_block_context::<T>(signed_tx_ec_recovered, tx_info, tx_resp_builder)
from_recovered_with_block_context::<TransactionSigned, T>(
signed_tx_ec_recovered,
tx_info,
tx_resp_builder,
)
})
.collect::<Result<Vec<_>, T::Error>>()?;

View File

@ -8,7 +8,7 @@ use alloy_rpc_types_eth::{
request::{TransactionInput, TransactionRequest},
TransactionInfo,
};
use reth_primitives::TransactionSignedEcRecovered;
use reth_primitives::{TransactionSigned, TransactionSignedEcRecovered};
use serde::{Deserialize, Serialize};
/// Create a new rpc transaction result for a mined transaction, using the given block hash,
@ -16,8 +16,8 @@ use serde::{Deserialize, Serialize};
///
/// 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<T: TransactionCompat>(
tx: TransactionSignedEcRecovered,
pub fn from_recovered_with_block_context<Tx, T: TransactionCompat<Tx>>(
tx: TransactionSignedEcRecovered<Tx>,
tx_info: TransactionInfo,
resp_builder: &T,
) -> Result<T::Transaction, T::Error> {
@ -26,15 +26,17 @@ pub fn from_recovered_with_block_context<T: TransactionCompat>(
/// Create a new rpc transaction result for a _pending_ signed transaction, setting block
/// environment related fields to `None`.
pub fn from_recovered<T: TransactionCompat>(
tx: TransactionSignedEcRecovered,
pub fn from_recovered<Tx, T: TransactionCompat<Tx>>(
tx: TransactionSignedEcRecovered<Tx>,
resp_builder: &T,
) -> Result<T::Transaction, T::Error> {
resp_builder.fill(tx, TransactionInfo::default())
}
/// Builds RPC transaction w.r.t. network.
pub trait TransactionCompat: Send + Sync + Unpin + Clone + fmt::Debug {
pub trait TransactionCompat<T = TransactionSigned>:
Send + Sync + Unpin + Clone + fmt::Debug
{
/// RPC transaction response type.
type Transaction: Serialize
+ for<'de> Deserialize<'de>
@ -51,7 +53,7 @@ pub trait TransactionCompat: Send + Sync + Unpin + Clone + fmt::Debug {
/// environment related fields to `None`.
fn fill(
&self,
tx: TransactionSignedEcRecovered,
tx: TransactionSignedEcRecovered<T>,
tx_inf: TransactionInfo,
) -> Result<Self::Transaction, Self::Error>;

View File

@ -1,6 +1,7 @@
//! Builds an RPC receipt response w.r.t. data layout of network.
use reth_primitives::{Receipt, TransactionMeta, TransactionSigned};
use reth_provider::TransactionsProvider;
use reth_rpc_eth_api::{helpers::LoadReceipt, FromEthApiError, RpcNodeCoreExt, RpcReceipt};
use reth_rpc_eth_types::{EthApiError, EthReceiptBuilder};
@ -8,7 +9,7 @@ use crate::EthApi;
impl<Provider, Pool, Network, EvmConfig> LoadReceipt for EthApi<Provider, Pool, Network, EvmConfig>
where
Self: RpcNodeCoreExt,
Self: RpcNodeCoreExt<Provider: TransactionsProvider<Transaction = TransactionSigned>>,
{
async fn build_transaction_receipt(
&self,