reth_engine_tree/
test_utils.rs

1use alloy_primitives::B256;
2use reth_chainspec::ChainSpec;
3use reth_ethereum_primitives::BlockBody;
4use reth_network_p2p::test_utils::TestFullBlockClient;
5use reth_primitives_traits::SealedHeader;
6use reth_provider::{
7    test_utils::{create_test_provider_factory_with_chain_spec, MockNodeTypesWithDB},
8    ExecutionOutcome,
9};
10use reth_prune_types::PruneModes;
11use reth_stages::{test_utils::TestStages, ExecOutput, StageError};
12use reth_stages_api::Pipeline;
13use reth_static_file::StaticFileProducer;
14use std::{collections::VecDeque, ops::Range, sync::Arc};
15use tokio::sync::watch;
16
17/// Test pipeline builder.
18#[derive(Default, Debug)]
19pub struct TestPipelineBuilder {
20    pipeline_exec_outputs: VecDeque<Result<ExecOutput, StageError>>,
21    executor_results: Vec<ExecutionOutcome>,
22}
23
24impl TestPipelineBuilder {
25    /// Create a new [`TestPipelineBuilder`].
26    pub const fn new() -> Self {
27        Self { pipeline_exec_outputs: VecDeque::new(), executor_results: Vec::new() }
28    }
29
30    /// Set the pipeline execution outputs to use for the test consensus engine.
31    pub fn with_pipeline_exec_outputs(
32        mut self,
33        pipeline_exec_outputs: VecDeque<Result<ExecOutput, StageError>>,
34    ) -> Self {
35        self.pipeline_exec_outputs = pipeline_exec_outputs;
36        self
37    }
38
39    /// Set the executor results to use for the test consensus engine.
40    #[allow(dead_code)]
41    pub fn with_executor_results(mut self, executor_results: Vec<ExecutionOutcome>) -> Self {
42        self.executor_results = executor_results;
43        self
44    }
45
46    /// Builds the pipeline.
47    pub fn build(self, chain_spec: Arc<ChainSpec>) -> Pipeline<MockNodeTypesWithDB> {
48        reth_tracing::init_test_tracing();
49
50        // Setup pipeline
51        let (tip_tx, _tip_rx) = watch::channel(B256::default());
52        let pipeline = Pipeline::<MockNodeTypesWithDB>::builder()
53            .add_stages(TestStages::new(self.pipeline_exec_outputs, Default::default()))
54            .with_tip_sender(tip_tx);
55
56        let provider_factory = create_test_provider_factory_with_chain_spec(chain_spec);
57
58        let static_file_producer =
59            StaticFileProducer::new(provider_factory.clone(), PruneModes::default());
60
61        pipeline.build(provider_factory, static_file_producer)
62    }
63}
64
65/// Starting from the given genesis header, inserts headers from the given
66/// range in the given test full block client.
67pub fn insert_headers_into_client(
68    client: &TestFullBlockClient,
69    genesis_header: SealedHeader,
70    range: Range<usize>,
71) {
72    let mut sealed_header = genesis_header;
73    let body = BlockBody::default();
74    for _ in range {
75        let (mut header, hash) = sealed_header.split();
76        // update to the next header
77        header.parent_hash = hash;
78        header.number += 1;
79        header.timestamp += 1;
80        sealed_header = SealedHeader::seal_slow(header);
81        client.insert(sealed_header.clone(), body.clone());
82    }
83}