Skip to main content

reth_consensus/
test_utils.rs

1use crate::{Consensus, ConsensusError, FullConsensus, HeaderValidator, ReceiptRootBloom};
2use alloy_primitives::B256;
3use core::sync::atomic::{AtomicBool, Ordering};
4use reth_execution_types::BlockExecutionResult;
5use reth_primitives_traits::{Block, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader};
6
7/// Consensus engine implementation for testing
8#[derive(Debug)]
9pub struct TestConsensus {
10    /// Flag whether the header validation should purposefully fail
11    fail_validation: AtomicBool,
12    /// Separate flag for setting whether `validate_body_against_header` should fail. It is needed
13    /// for testing networking logic for which the body failing this check is getting completely
14    /// rejected while more high-level failures are handled by the sync logic.
15    fail_body_against_header: AtomicBool,
16    /// Separate flag for setting whether `validate_header_against_parent` should fail, so a header
17    /// valid on its own can still be detached from its parent.
18    fail_header_against_parent: AtomicBool,
19}
20
21impl Default for TestConsensus {
22    fn default() -> Self {
23        Self {
24            fail_validation: AtomicBool::new(false),
25            fail_body_against_header: AtomicBool::new(false),
26            fail_header_against_parent: AtomicBool::new(false),
27        }
28    }
29}
30
31impl TestConsensus {
32    /// Get the failed validation flag.
33    pub fn fail_validation(&self) -> bool {
34        self.fail_validation.load(Ordering::SeqCst)
35    }
36
37    /// Update the validation flag.
38    pub fn set_fail_validation(&self, val: bool) {
39        self.fail_validation.store(val, Ordering::SeqCst);
40        self.fail_body_against_header.store(val, Ordering::SeqCst);
41        self.fail_header_against_parent.store(val, Ordering::SeqCst);
42    }
43
44    /// Returns the body validation flag.
45    pub fn fail_body_against_header(&self) -> bool {
46        self.fail_body_against_header.load(Ordering::SeqCst)
47    }
48
49    /// Update the body validation flag.
50    pub fn set_fail_body_against_header(&self, val: bool) {
51        self.fail_body_against_header.store(val, Ordering::SeqCst);
52    }
53
54    /// Returns the header-against-parent validation flag.
55    pub fn fail_header_against_parent(&self) -> bool {
56        self.fail_header_against_parent.load(Ordering::SeqCst)
57    }
58
59    /// Update the header-against-parent validation flag.
60    pub fn set_fail_header_against_parent(&self, val: bool) {
61        self.fail_header_against_parent.store(val, Ordering::SeqCst);
62    }
63}
64
65impl<N: NodePrimitives> FullConsensus<N> for TestConsensus {
66    fn validate_block_post_execution(
67        &self,
68        _block: &RecoveredBlock<N::Block>,
69        _result: &BlockExecutionResult<N::Receipt>,
70        _receipt_root_bloom: Option<ReceiptRootBloom>,
71        _block_access_list_hash: Option<B256>,
72    ) -> Result<(), ConsensusError> {
73        if self.fail_validation() {
74            Err(ConsensusError::BaseFeeMissing)
75        } else {
76            Ok(())
77        }
78    }
79}
80
81impl<B: Block> Consensus<B> for TestConsensus {
82    fn validate_body_against_header(
83        &self,
84        _body: &B::Body,
85        _header: &SealedHeader<B::Header>,
86    ) -> Result<(), ConsensusError> {
87        if self.fail_body_against_header() {
88            Err(ConsensusError::BaseFeeMissing)
89        } else {
90            Ok(())
91        }
92    }
93
94    fn validate_block_pre_execution(&self, _block: &SealedBlock<B>) -> Result<(), ConsensusError> {
95        if self.fail_validation() {
96            Err(ConsensusError::BaseFeeMissing)
97        } else {
98            Ok(())
99        }
100    }
101}
102
103impl<H> HeaderValidator<H> for TestConsensus {
104    fn validate_header(&self, _header: &SealedHeader<H>) -> Result<(), ConsensusError> {
105        if self.fail_validation() {
106            Err(ConsensusError::BaseFeeMissing)
107        } else {
108            Ok(())
109        }
110    }
111
112    fn validate_header_against_parent(
113        &self,
114        _header: &SealedHeader<H>,
115        _parent: &SealedHeader<H>,
116    ) -> Result<(), ConsensusError> {
117        if self.fail_header_against_parent() {
118            Err(ConsensusError::BaseFeeMissing)
119        } else {
120            Ok(())
121        }
122    }
123}