feat: integrate SignedTx AT into StaticFileProviderRW (#12764)

This commit is contained in:
Arsenii Kulikov
2024-11-22 15:49:25 +04:00
committed by GitHub
parent 3d93b81a7e
commit 7f5fd80cb7
21 changed files with 105 additions and 75 deletions

3
Cargo.lock generated
View File

@ -6456,6 +6456,7 @@ dependencies = [
"reth-blockchain-tree",
"reth-blockchain-tree-api",
"reth-chainspec",
"reth-codecs",
"reth-config",
"reth-consensus",
"reth-db",
@ -9159,8 +9160,10 @@ dependencies = [
"assert_matches",
"parking_lot",
"rayon",
"reth-codecs",
"reth-db",
"reth-db-api",
"reth-primitives-traits",
"reth-provider",
"reth-prune-types",
"reth-stages",

View File

@ -1424,7 +1424,7 @@ mod tests {
}
fn setup_genesis<
N: ProviderNodeTypes<Primitives: FullNodePrimitives<Block = reth_primitives::Block>>,
N: ProviderNodeTypes<Primitives: FullNodePrimitives<BlockBody = reth_primitives::BlockBody>>,
>(
factory: &ProviderFactory<N>,
mut genesis: SealedBlock,

View File

@ -4,7 +4,7 @@ use alloy_primitives::{BlockHash, BlockNumber};
use reth_consensus::Consensus;
use reth_db::{static_file::HeaderMask, tables};
use reth_db_api::{cursor::DbCursorRO, transaction::DbTx};
use reth_node_types::{Block, FullNodePrimitives, NodeTypesWithDB};
use reth_node_types::{FullNodePrimitives, NodeTypesWithDB};
use reth_primitives::{BlockBody, StaticFileSegment};
use reth_provider::{
providers::ProviderNodeTypes, ChainStateBlockReader, ChainStateBlockWriter, ProviderFactory,
@ -15,11 +15,11 @@ use std::{collections::BTreeMap, sync::Arc};
/// A helper trait with requirements for [`ProviderNodeTypes`] to be used within [`TreeExternals`].
pub trait TreeNodeTypes:
ProviderNodeTypes<Primitives: FullNodePrimitives<Block: Block<Body = BlockBody>>>
ProviderNodeTypes<Primitives: FullNodePrimitives<BlockBody = BlockBody>>
{
}
impl<T> TreeNodeTypes for T where
T: ProviderNodeTypes<Primitives: FullNodePrimitives<Block: Block<Body = BlockBody>>>
T: ProviderNodeTypes<Primitives: FullNodePrimitives<BlockBody = BlockBody>>
{
}

View File

@ -197,19 +197,11 @@ impl AccessRights {
/// [`NodeTypes`](reth_node_builder::NodeTypes) in CLI.
pub trait CliNodeTypes:
NodeTypesWithEngine
+ NodeTypesForProvider<
Primitives: FullNodePrimitives<
Block: reth_node_api::Block<Body = reth_primitives::BlockBody>,
>,
>
+ NodeTypesForProvider<Primitives: FullNodePrimitives<BlockBody = reth_primitives::BlockBody>>
{
}
impl<N> CliNodeTypes for N where
N: NodeTypesWithEngine
+ NodeTypesForProvider<
Primitives: FullNodePrimitives<
Block: reth_node_api::Block<Body = reth_primitives::BlockBody>,
>,
>
+ NodeTypesForProvider<Primitives: FullNodePrimitives<BlockBody = reth_primitives::BlockBody>>
{
}

View File

@ -14,6 +14,8 @@ workspace = true
# reth
reth-ethereum-consensus.workspace = true
reth-blockchain-tree-api.workspace = true
reth-codecs.workspace = true
reth-db-api.workspace = true
reth-primitives.workspace = true
reth-stages-api.workspace = true
reth-errors.workspace = true
@ -80,6 +82,7 @@ assert_matches.workspace = true
[features]
optimism = [
"reth-blockchain-tree/optimism",
"reth-codecs/optimism",
"reth-chainspec",
"reth-db-api/optimism",
"reth-db/optimism",

View File

@ -6,8 +6,10 @@ use crate::{
};
use alloy_primitives::BlockNumber;
use futures::FutureExt;
use reth_codecs::Compact;
use reth_db_api::table::Value;
use reth_errors::RethResult;
use reth_primitives::static_file::HighestStaticFiles;
use reth_primitives::{static_file::HighestStaticFiles, NodePrimitives};
use reth_provider::{
BlockReader, ChainStateBlockReader, DatabaseProviderFactory, StageCheckpointReader,
StaticFileProviderFactory,
@ -33,8 +35,9 @@ impl<Provider> StaticFileHook<Provider>
where
Provider: StaticFileProviderFactory
+ DatabaseProviderFactory<
Provider: StaticFileProviderFactory
+ StageCheckpointReader
Provider: StaticFileProviderFactory<
Primitives: NodePrimitives<SignedTx: Value + Compact>,
> + StageCheckpointReader
+ BlockReader
+ ChainStateBlockReader,
> + 'static,
@ -148,8 +151,9 @@ impl<Provider> EngineHook for StaticFileHook<Provider>
where
Provider: StaticFileProviderFactory
+ DatabaseProviderFactory<
Provider: StaticFileProviderFactory
+ StageCheckpointReader
Provider: StaticFileProviderFactory<
Primitives: NodePrimitives<SignedTx: Value + Compact>,
> + StageCheckpointReader
+ BlockReader
+ ChainStateBlockReader,
> + 'static,

View File

@ -2172,7 +2172,7 @@ mod tests {
fn insert_blocks<
'a,
N: ProviderNodeTypes<Primitives: FullNodePrimitives<Block = reth_primitives::Block>>,
N: ProviderNodeTypes<Primitives: FullNodePrimitives<BlockBody = reth_primitives::BlockBody>>,
>(
provider_factory: ProviderFactory<N>,
mut blocks: impl Iterator<Item = &'a SealedBlock>,

View File

@ -3,7 +3,7 @@ use alloy_eips::BlockNumHash;
use reth_chain_state::ExecutedBlock;
use reth_errors::ProviderError;
use reth_primitives::BlockBody;
use reth_primitives_traits::{Block, FullNodePrimitives};
use reth_primitives_traits::FullNodePrimitives;
use reth_provider::{
providers::ProviderNodeTypes, writer::UnifiedStorageWriter, BlockHashReader,
ChainStateBlockWriter, DatabaseProviderFactory, ProviderFactory, StaticFileProviderFactory,
@ -21,11 +21,11 @@ use tracing::{debug, error};
/// A helper trait with requirements for [`ProviderNodeTypes`] to be used within
/// [`PersistenceService`].
pub trait PersistenceNodeTypes:
ProviderNodeTypes<Primitives: FullNodePrimitives<Block: Block<Body = BlockBody>>>
ProviderNodeTypes<Primitives: FullNodePrimitives<BlockBody = BlockBody>>
{
}
impl<T> PersistenceNodeTypes for T where
T: ProviderNodeTypes<Primitives: FullNodePrimitives<Block: Block<Body = BlockBody>>>
T: ProviderNodeTypes<Primitives: FullNodePrimitives<BlockBody = BlockBody>>
{
}
/// Writes parts of reth's in memory tree state to the database and static files.

View File

@ -58,7 +58,7 @@ pub(crate) fn execute_block_and_commit_to_database<N>(
block: &BlockWithSenders,
) -> eyre::Result<BlockExecutionOutput<Receipt>>
where
N: ProviderNodeTypes<Primitives: FullNodePrimitives<Block = reth_primitives::Block>>,
N: ProviderNodeTypes<Primitives: FullNodePrimitives<BlockBody = reth_primitives::BlockBody>>,
{
let provider = provider_factory.provider()?;
@ -162,7 +162,7 @@ pub(crate) fn blocks_and_execution_outputs<N>(
key_pair: Keypair,
) -> eyre::Result<Vec<(SealedBlockWithSenders, BlockExecutionOutput<Receipt>)>>
where
N: ProviderNodeTypes<Primitives: FullNodePrimitives<Block = reth_primitives::Block>>,
N: ProviderNodeTypes<Primitives: FullNodePrimitives<BlockBody = reth_primitives::BlockBody>>,
{
let (block1, block2) = blocks(chain_spec.clone(), key_pair)?;
@ -184,7 +184,7 @@ pub(crate) fn blocks_and_execution_outcome<N>(
) -> eyre::Result<(Vec<SealedBlockWithSenders>, ExecutionOutcome)>
where
N: ProviderNodeTypes,
N::Primitives: FullNodePrimitives<Block = reth_primitives::Block>,
N::Primitives: FullNodePrimitives<BlockBody = reth_primitives::BlockBody>,
{
let (block1, block2) = blocks(chain_spec.clone(), key_pair)?;

View File

@ -14,7 +14,7 @@ use reth_exex::ExExManagerHandle;
use reth_network_p2p::{
bodies::downloader::BodyDownloader, headers::downloader::HeaderDownloader, EthBlockClient,
};
use reth_node_api::FullNodePrimitives;
use reth_node_api::{FullNodePrimitives, NodePrimitives};
use reth_provider::{providers::ProviderNodeTypes, ProviderFactory};
use reth_stages::{prelude::DefaultStages, stages::ExecutionStage, Pipeline, StageSet};
use reth_static_file::StaticFileProducer;
@ -88,7 +88,7 @@ where
N: ProviderNodeTypes,
H: HeaderDownloader<Header = alloy_consensus::Header> + 'static,
B: BodyDownloader<
Body = <<N::Primitives as FullNodePrimitives>::Block as reth_node_api::Block>::Body,
Body = <<N::Primitives as NodePrimitives>::Block as reth_node_api::Block>::Body,
> + 'static,
Executor: BlockExecutorProvider,
N::Primitives: FullNodePrimitives<BlockBody = reth_primitives::BlockBody>,

View File

@ -14,14 +14,14 @@ pub mod tx_type;
pub use tx_type::OpTxType;
use alloy_consensus::Header;
use reth_node_types::FullNodePrimitives;
use reth_node_types::NodePrimitives;
use reth_primitives::{Block, BlockBody, Receipt, TransactionSigned};
/// Optimism primitive types.
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct OpPrimitives;
impl FullNodePrimitives for OpPrimitives {
impl NodePrimitives for OpPrimitives {
type Block = Block;
type BlockHeader = Header;
type BlockBody = BlockBody;

View File

@ -77,33 +77,45 @@ impl NodePrimitives for () {
}
/// Helper trait that sets trait bounds on [`NodePrimitives`].
pub trait FullNodePrimitives:
Send + Sync + Unpin + Clone + Default + fmt::Debug + PartialEq + Eq + 'static
pub trait FullNodePrimitives
where
Self: NodePrimitives<
Block: FullBlock<Header = Self::BlockHeader, Body = Self::BlockBody>,
BlockHeader: FullBlockHeader,
BlockBody: FullBlockBody<Transaction = Self::SignedTx>,
SignedTx: FullSignedTx,
TxType: FullTxType,
Receipt: FullReceipt,
> + Send
+ Sync
+ Unpin
+ Clone
+ Default
+ fmt::Debug
+ PartialEq
+ Eq
+ 'static,
{
/// Block primitive.
type Block: FullBlock<Header = Self::BlockHeader, Body = Self::BlockBody>;
/// Block header primitive.
type BlockHeader: FullBlockHeader + 'static;
/// Block body primitive.
type BlockBody: FullBlockBody<Transaction = Self::SignedTx> + 'static;
/// Signed version of the transaction type.
type SignedTx: FullSignedTx;
/// Transaction envelope type ID.
type TxType: FullTxType;
/// A receipt.
type Receipt: FullReceipt;
}
impl<T> NodePrimitives for T
where
T: FullNodePrimitives,
impl<T> FullNodePrimitives for T where
T: NodePrimitives<
Block: FullBlock<Header = Self::BlockHeader, Body = Self::BlockBody>,
BlockHeader: FullBlockHeader,
BlockBody: FullBlockBody<Transaction = Self::SignedTx>,
SignedTx: FullSignedTx,
TxType: FullTxType,
Receipt: FullReceipt,
> + Send
+ Sync
+ Unpin
+ Clone
+ Default
+ fmt::Debug
+ PartialEq
+ Eq
+ 'static
{
type Block = T::Block;
type BlockHeader = T::BlockHeader;
type BlockBody = T::BlockBody;
type SignedTx = T::SignedTx;
type TxType = T::TxType;
type Receipt = T::Receipt;
}
/// Helper adapter type for accessing [`NodePrimitives`] receipt type.

View File

@ -79,7 +79,7 @@ pub mod serde_bincode_compat {
#[derive(Debug, Clone, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct EthPrimitives;
impl reth_primitives_traits::FullNodePrimitives for EthPrimitives {
impl reth_primitives_traits::NodePrimitives for EthPrimitives {
type Block = crate::Block;
type BlockHeader = alloy_consensus::Header;
type BlockBody = crate::BlockBody;

View File

@ -63,7 +63,8 @@ impl AccountHashingStage {
opts: SeedOpts,
) -> Result<Vec<(alloy_primitives::Address, reth_primitives::Account)>, StageError>
where
N::Primitives: reth_primitives_traits::FullNodePrimitives<Block = reth_primitives::Block>,
N::Primitives:
reth_primitives_traits::FullNodePrimitives<BlockBody = reth_primitives::BlockBody>,
{
use alloy_primitives::U256;
use reth_db_api::models::AccountBeforeTx;

View File

@ -13,12 +13,14 @@ workspace = true
[dependencies]
# reth
reth-codecs.workspace = true
reth-db.workspace = true
reth-db-api.workspace = true
reth-provider.workspace = true
reth-storage-errors.workspace = true
reth-tokio-util.workspace = true
reth-prune-types.workspace = true
reth-primitives-traits.workspace = true
reth-static-file-types.workspace = true
reth-stages-types.workspace = true

View File

@ -1,7 +1,9 @@
use crate::segments::Segment;
use alloy_primitives::BlockNumber;
use reth_db::tables;
use reth_codecs::Compact;
use reth_db::{table::Value, tables};
use reth_db_api::{cursor::DbCursorRO, transaction::DbTx};
use reth_primitives_traits::NodePrimitives;
use reth_provider::{
providers::StaticFileWriter, BlockReader, DBProvider, StaticFileProviderFactory,
};
@ -13,8 +15,11 @@ use std::ops::RangeInclusive;
#[derive(Debug, Default)]
pub struct Transactions;
impl<Provider: StaticFileProviderFactory + DBProvider + BlockReader> Segment<Provider>
for Transactions
impl<Provider> Segment<Provider> for Transactions
where
Provider: StaticFileProviderFactory<Primitives: NodePrimitives<SignedTx: Value + Compact>>
+ DBProvider
+ BlockReader,
{
fn segment(&self) -> StaticFileSegment {
StaticFileSegment::Transactions
@ -38,8 +43,9 @@ impl<Provider: StaticFileProviderFactory + DBProvider + BlockReader> Segment<Pro
.block_body_indices(block)?
.ok_or(ProviderError::BlockBodyIndicesNotFound(block))?;
let mut transactions_cursor =
provider.tx_ref().cursor_read::<tables::Transactions>()?;
let mut transactions_cursor = provider.tx_ref().cursor_read::<tables::Transactions<
<<Provider as StaticFileProviderFactory>::Primitives as NodePrimitives>::SignedTx,
>>()?;
let transactions_walker =
transactions_cursor.walk_range(block_body_indices.tx_num_range())?;

View File

@ -4,6 +4,9 @@ use crate::{segments, segments::Segment, StaticFileProducerEvent};
use alloy_primitives::BlockNumber;
use parking_lot::Mutex;
use rayon::prelude::*;
use reth_codecs::Compact;
use reth_db::table::Value;
use reth_primitives_traits::NodePrimitives;
use reth_provider::{
providers::StaticFileWriter, BlockReader, ChainStateBlockReader, DBProvider,
DatabaseProviderFactory, StageCheckpointReader, StaticFileProviderFactory,
@ -86,7 +89,10 @@ impl<Provider> StaticFileProducerInner<Provider>
where
Provider: StaticFileProviderFactory
+ DatabaseProviderFactory<
Provider: StaticFileProviderFactory + StageCheckpointReader + BlockReader,
Provider: StaticFileProviderFactory<
Primitives: NodePrimitives<SignedTx: Value + Compact>,
> + StageCheckpointReader
+ BlockReader,
>,
{
/// Listen for events on the `static_file_producer`.

View File

@ -889,8 +889,7 @@ mod tests {
static_file_provider.latest_writer(StaticFileSegment::Transactions)?;
transactions_writer.increment_block(block.number)?;
for tx in block.body.transactions() {
let tx: TransactionSignedNoHash = tx.clone().into();
transactions_writer.append_transaction(tx_num, &tx)?;
transactions_writer.append_transaction(tx_num, tx)?;
tx_num += 1;
}

View File

@ -48,11 +48,11 @@ use reth_execution_types::{Chain, ExecutionOutcome};
use reth_network_p2p::headers::downloader::SyncTarget;
use reth_node_types::NodeTypes;
use reth_primitives::{
Account, Block, BlockBody, BlockWithSenders, Bytecode, GotExpected, Receipt, SealedBlock,
SealedBlockWithSenders, SealedHeader, StaticFileSegment, StorageEntry, TransactionMeta,
TransactionSigned, TransactionSignedNoHash,
Account, Block, BlockBody, BlockWithSenders, Bytecode, GotExpected, NodePrimitives, Receipt,
SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment, StorageEntry,
TransactionMeta, TransactionSigned, TransactionSignedNoHash,
};
use reth_primitives_traits::{BlockBody as _, FullNodePrimitives, SignedTransaction};
use reth_primitives_traits::{BlockBody as _, SignedTransaction};
use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{StateProvider, StorageChangeSetReader, TryIntoHistoricalStateProvider};
@ -2778,8 +2778,7 @@ impl<TX: DbTxMut + DbTx + 'static, N: ProviderNodeTypes + 'static> BlockExecutio
impl<TX: DbTxMut + DbTx + 'static, N: ProviderNodeTypes + 'static> BlockWriter
for DatabaseProvider<TX, N>
{
type Body =
<<N::Primitives as FullNodePrimitives>::Block as reth_primitives_traits::Block>::Body;
type Body = <<N::Primitives as NodePrimitives>::Block as reth_primitives_traits::Block>::Body;
/// Inserts the block into the database, always modifying the following tables:
/// * [`CanonicalHeaders`](tables::CanonicalHeaders)

View File

@ -68,7 +68,7 @@ mod tests {
use reth_db_api::transaction::DbTxMut;
use reth_primitives::{
static_file::{find_fixed_range, SegmentRangeInclusive, DEFAULT_BLOCKS_PER_STATIC_FILE},
Receipt, TransactionSignedNoHash,
EthPrimitives, Receipt, TransactionSigned,
};
use reth_storage_api::{ReceiptProvider, TransactionsProvider};
use reth_testing_utils::generators::{self, random_header_range};
@ -304,20 +304,20 @@ mod tests {
/// * `10..=19`: no txs/receipts
/// * `20..=29`: only one tx/receipt
fn setup_tx_based_scenario(
sf_rw: &StaticFileProvider<()>,
sf_rw: &StaticFileProvider<EthPrimitives>,
segment: StaticFileSegment,
blocks_per_file: u64,
) {
fn setup_block_ranges(
writer: &mut StaticFileProviderRWRefMut<'_, ()>,
sf_rw: &StaticFileProvider<()>,
writer: &mut StaticFileProviderRWRefMut<'_, EthPrimitives>,
sf_rw: &StaticFileProvider<EthPrimitives>,
segment: StaticFileSegment,
block_range: &Range<u64>,
mut tx_count: u64,
next_tx_num: &mut u64,
) {
let mut receipt = Receipt::default();
let mut tx = TransactionSignedNoHash::default();
let mut tx = TransactionSigned::default();
for block in block_range.clone() {
writer.increment_block(block).unwrap();

View File

@ -558,7 +558,10 @@ impl<N: NodePrimitives> StaticFileProviderRW<N> {
/// empty blocks and this function wouldn't be called.
///
/// Returns the current [`TxNumber`] as seen in the static file.
pub fn append_transaction(&mut self, tx_num: TxNumber, tx: impl Compact) -> ProviderResult<()> {
pub fn append_transaction(&mut self, tx_num: TxNumber, tx: &N::SignedTx) -> ProviderResult<()>
where
N::SignedTx: Compact,
{
let start = Instant::now();
self.ensure_no_queued_prune()?;