reth_consensus/
test_utils.rs

1use crate::{Consensus, ConsensusError, FullConsensus, HeaderValidator};
2use alloy_primitives::U256;
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}
17
18impl Default for TestConsensus {
19    fn default() -> Self {
20        Self {
21            fail_validation: AtomicBool::new(false),
22            fail_body_against_header: AtomicBool::new(false),
23        }
24    }
25}
26
27impl TestConsensus {
28    /// Get the failed validation flag.
29    pub fn fail_validation(&self) -> bool {
30        self.fail_validation.load(Ordering::SeqCst)
31    }
32
33    /// Update the validation flag.
34    pub fn set_fail_validation(&self, val: bool) {
35        self.fail_validation.store(val, Ordering::SeqCst);
36        self.fail_body_against_header.store(val, Ordering::SeqCst);
37    }
38
39    /// Returns the body validation flag.
40    pub fn fail_body_against_header(&self) -> bool {
41        self.fail_body_against_header.load(Ordering::SeqCst)
42    }
43
44    /// Update the body validation flag.
45    pub fn set_fail_body_against_header(&self, val: bool) {
46        self.fail_body_against_header.store(val, Ordering::SeqCst);
47    }
48}
49
50impl<N: NodePrimitives> FullConsensus<N> for TestConsensus {
51    fn validate_block_post_execution(
52        &self,
53        _block: &RecoveredBlock<N::Block>,
54        _result: &BlockExecutionResult<N::Receipt>,
55    ) -> Result<(), ConsensusError> {
56        if self.fail_validation() {
57            Err(ConsensusError::BaseFeeMissing)
58        } else {
59            Ok(())
60        }
61    }
62}
63
64impl<B: Block> Consensus<B> for TestConsensus {
65    type Error = ConsensusError;
66
67    fn validate_body_against_header(
68        &self,
69        _body: &B::Body,
70        _header: &SealedHeader<B::Header>,
71    ) -> Result<(), Self::Error> {
72        if self.fail_body_against_header() {
73            Err(ConsensusError::BaseFeeMissing)
74        } else {
75            Ok(())
76        }
77    }
78
79    fn validate_block_pre_execution(&self, _block: &SealedBlock<B>) -> Result<(), Self::Error> {
80        if self.fail_validation() {
81            Err(ConsensusError::BaseFeeMissing)
82        } else {
83            Ok(())
84        }
85    }
86}
87
88impl<H> HeaderValidator<H> for TestConsensus {
89    fn validate_header(&self, _header: &SealedHeader<H>) -> Result<(), ConsensusError> {
90        if self.fail_validation() {
91            Err(ConsensusError::BaseFeeMissing)
92        } else {
93            Ok(())
94        }
95    }
96
97    fn validate_header_against_parent(
98        &self,
99        _header: &SealedHeader<H>,
100        _parent: &SealedHeader<H>,
101    ) -> Result<(), ConsensusError> {
102        if self.fail_validation() {
103            Err(ConsensusError::BaseFeeMissing)
104        } else {
105            Ok(())
106        }
107    }
108
109    fn validate_header_with_total_difficulty(
110        &self,
111        _header: &H,
112        _total_difficulty: U256,
113    ) -> Result<(), ConsensusError> {
114        if self.fail_validation() {
115            Err(ConsensusError::BaseFeeMissing)
116        } else {
117            Ok(())
118        }
119    }
120}