@@ -13,21 +13,39 @@ use reth_rpc_api::clients::EthApiClient;
1313use  std:: marker:: PhantomData ; 
1414use  tracing:: debug; 
1515
16- /// Action to create a fork from a specified block number and produce blocks on top 
16+ /// Fork base target for fork creation 
17+ #[ derive( Debug ,  Clone ) ]  
18+ pub  enum  ForkBase  { 
19+     /// Block number 
20+      Number ( u64 ) , 
21+     /// Tagged block reference 
22+      Tag ( String ) , 
23+ } 
24+ 
25+ /// Action to create a fork from a specified block and produce blocks on top 
1726#[ derive( Debug ) ]  
1827pub  struct  CreateFork < Engine >  { 
19-     /// Block number to use as the base of the fork  
20-      pub  fork_base_block :   u64 , 
28+     /// Fork base specification (either block number or tag)  
29+      pub  fork_base :   ForkBase , 
2130    /// Number of blocks to produce on top of the fork base 
2231     pub  num_blocks :  u64 , 
2332    /// Tracks engine type 
2433     _phantom :  PhantomData < Engine > , 
2534} 
2635
2736impl < Engine >  CreateFork < Engine >  { 
28-     /// Create a new `CreateFork` action 
37+     /// Create a new `CreateFork` action from a block number  
2938     pub  fn  new ( fork_base_block :  u64 ,  num_blocks :  u64 )  -> Self  { 
30-         Self  {  fork_base_block,  num_blocks,  _phantom :  Default :: default ( )  } 
39+         Self  { 
40+             fork_base :  ForkBase :: Number ( fork_base_block) , 
41+             num_blocks, 
42+             _phantom :  Default :: default ( ) , 
43+         } 
44+     } 
45+ 
46+     /// Create a new `CreateFork` action from a tagged block 
47+      pub  fn  new_from_tag ( tag :  impl  Into < String > ,  num_blocks :  u64 )  -> Self  { 
48+         Self  {  fork_base :  ForkBase :: Tag ( tag. into ( ) ) ,  num_blocks,  _phantom :  Default :: default ( )  } 
3149    } 
3250} 
3351
@@ -40,18 +58,34 @@ where
4058{ 
4159    fn  execute < ' a > ( & ' a  mut  self ,  env :  & ' a  mut  Environment < Engine > )  -> BoxFuture < ' a ,  Result < ( ) > >  { 
4260        Box :: pin ( async  move  { 
43-             // store the fork base for later validation 
44-             env. current_fork_base  = Some ( self . fork_base_block ) ; 
45- 
46-             let  mut  sequence = Sequence :: new ( vec ! [ 
47-                 Box :: new( SetForkBase :: new( self . fork_base_block) ) , 
48-                 Box :: new( ProduceBlocks :: new( self . num_blocks) ) , 
49-                 // Note: ValidateFork is not called here because fork blocks are not accessible 
50-                 // via RPC until they are made canonical. Validation will be done automatically 
51-                 // as part of MakeCanonical or ReorgTo actions. 
52-             ] ) ; 
53- 
54-             sequence. execute ( env) . await 
61+             // resolve the fork base and execute the appropriate sequence 
62+             match  & self . fork_base  { 
63+                 ForkBase :: Number ( block_number)  => { 
64+                     // store the fork base for later validation 
65+                     env. current_fork_base  = Some ( * block_number) ; 
66+ 
67+                     let  mut  sequence = Sequence :: new ( vec ! [ 
68+                         Box :: new( SetForkBase :: new( * block_number) ) , 
69+                         Box :: new( ProduceBlocks :: new( self . num_blocks) ) , 
70+                     ] ) ; 
71+                     sequence. execute ( env) . await 
72+                 } 
73+                 ForkBase :: Tag ( tag)  => { 
74+                     let  block_info =
75+                         env. block_registry . get ( tag) . copied ( ) . ok_or_else ( || { 
76+                             eyre:: eyre!( "Block tag '{}' not found in registry" ,  tag) 
77+                         } ) ?; 
78+ 
79+                     // store the fork base for later validation 
80+                     env. current_fork_base  = Some ( block_info. number ) ; 
81+ 
82+                     let  mut  sequence = Sequence :: new ( vec ! [ 
83+                         Box :: new( SetForkBaseFromBlockInfo :: new( block_info) ) , 
84+                         Box :: new( ProduceBlocks :: new( self . num_blocks) ) , 
85+                     ] ) ; 
86+                     sequence. execute ( env) . await 
87+                 } 
88+             } 
5589        } ) 
5690    } 
5791} 
@@ -63,13 +97,27 @@ pub struct SetForkBase {
6397     pub  fork_base_block :  u64 , 
6498} 
6599
100+ /// Sub-action to set the fork base block from existing block info 
101+ #[ derive( Debug ) ]  
102+ pub  struct  SetForkBaseFromBlockInfo  { 
103+     /// Complete block info to use as the base of the fork 
104+      pub  fork_base_info :  BlockInfo , 
105+ } 
106+ 
66107impl  SetForkBase  { 
67108    /// Create a new `SetForkBase` action 
68109     pub  const  fn  new ( fork_base_block :  u64 )  -> Self  { 
69110        Self  {  fork_base_block } 
70111    } 
71112} 
72113
114+ impl  SetForkBaseFromBlockInfo  { 
115+     /// Create a new `SetForkBaseFromBlockInfo` action 
116+      pub  const  fn  new ( fork_base_info :  BlockInfo )  -> Self  { 
117+         Self  {  fork_base_info } 
118+     } 
119+ } 
120+ 
73121impl < Engine >  Action < Engine >  for  SetForkBase 
74122where 
75123    Engine :  EngineTypes , 
@@ -117,6 +165,37 @@ where
117165    } 
118166} 
119167
168+ impl < Engine >  Action < Engine >  for  SetForkBaseFromBlockInfo 
169+ where 
170+     Engine :  EngineTypes , 
171+ { 
172+     fn  execute < ' a > ( & ' a  mut  self ,  env :  & ' a  mut  Environment < Engine > )  -> BoxFuture < ' a ,  Result < ( ) > >  { 
173+         Box :: pin ( async  move  { 
174+             let  block_info = self . fork_base_info ; 
175+ 
176+             debug ! ( 
177+                 "Set fork base from block info: block {} (hash: {})" , 
178+                 block_info. number,  block_info. hash
179+             ) ; 
180+ 
181+             // update environment to point to the fork base block 
182+             env. current_block_info  = Some ( block_info) ; 
183+             env. latest_header_time  = block_info. timestamp ; 
184+ 
185+             // update fork choice state to the fork base 
186+             env. latest_fork_choice_state  = ForkchoiceState  { 
187+                 head_block_hash :  block_info. hash , 
188+                 safe_block_hash :  block_info. hash , 
189+                 finalized_block_hash :  block_info. hash , 
190+             } ; 
191+ 
192+             debug ! ( "Set fork base to block {} (hash: {})" ,  block_info. number,  block_info. hash) ; 
193+ 
194+             Ok ( ( ) ) 
195+         } ) 
196+     } 
197+ } 
198+ 
120199/// Sub-action to validate that a fork was created correctly 
121200#[ derive( Debug ) ]  
122201pub  struct  ValidateFork  { 
0 commit comments