reth_e2e_test_utils/testsuite/actions/
reorg.rs1use crate::testsuite::{
4 actions::{produce_blocks::broadcast_forkchoice, Action},
5 BlockInfo, Environment,
6};
7use alloy_primitives::B256;
8use alloy_rpc_types_engine::ForkchoiceState;
9use eyre::Result;
10use futures_util::future::BoxFuture;
11use reth_node_api::EngineTypes;
12use std::marker::PhantomData;
13use tracing::debug;
14
15#[derive(Debug, Clone)]
17pub enum ReorgTarget {
18 Hash(B256),
20 Tag(String),
22}
23
24#[derive(Debug)]
30pub struct ReorgTo<Engine> {
31 pub target: ReorgTarget,
33 _phantom: PhantomData<Engine>,
35}
36
37impl<Engine> ReorgTo<Engine> {
38 pub const fn new(target_hash: B256) -> Self {
40 Self { target: ReorgTarget::Hash(target_hash), _phantom: PhantomData }
41 }
42
43 pub fn new_from_tag(tag: impl Into<String>) -> Self {
45 Self { target: ReorgTarget::Tag(tag.into()), _phantom: PhantomData }
46 }
47}
48
49impl<Engine> Action<Engine> for ReorgTo<Engine>
50where
51 Engine: EngineTypes,
52{
53 fn execute<'a>(&'a mut self, env: &'a mut Environment<Engine>) -> BoxFuture<'a, Result<()>> {
54 Box::pin(async move {
55 let target_block_info = match &self.target {
57 ReorgTarget::Hash(_hash) => {
58 return Err(eyre::eyre!(
59 "Direct hash reorgs are not supported. Use CaptureBlock to tag the target block first, then use ReorgTo::new_from_tag()"
60 ));
61 }
62 ReorgTarget::Tag(tag) => {
63 let (block_info, _node_idx) =
64 env.block_registry.get(tag).copied().ok_or_else(|| {
65 eyre::eyre!("Block tag '{}' not found in registry", tag)
66 })?;
67 block_info
68 }
69 };
70
71 let mut set_target = SetReorgTarget::new(target_block_info);
72 set_target.execute(env).await?;
73
74 broadcast_forkchoice(env, target_block_info.hash).await
77 })
78 }
79}
80
81#[derive(Debug)]
83pub struct SetReorgTarget {
84 pub target_block_info: BlockInfo,
86}
87
88impl SetReorgTarget {
89 pub const fn new(target_block_info: BlockInfo) -> Self {
91 Self { target_block_info }
92 }
93}
94
95impl<Engine> Action<Engine> for SetReorgTarget
96where
97 Engine: EngineTypes,
98{
99 fn execute<'a>(&'a mut self, env: &'a mut Environment<Engine>) -> BoxFuture<'a, Result<()>> {
100 Box::pin(async move {
101 let block_info = self.target_block_info;
102
103 debug!(
104 "Setting reorg target to block {} (hash: {})",
105 block_info.number, block_info.hash
106 );
107
108 let active_node_state = env.active_node_state_mut()?;
110 active_node_state.current_block_info = Some(block_info);
111 active_node_state.latest_header_time = block_info.timestamp;
112
113 active_node_state.latest_fork_choice_state =
115 ForkchoiceState::same_hash(block_info.hash);
116
117 debug!("Set reorg target to block {}", block_info.hash);
118 Ok(())
119 })
120 }
121}