@@ -33,7 +33,8 @@ use reth_payload_builder::PayloadBuilderHandle;
3333use reth_payload_primitives:: { PayloadAttributes , PayloadBuilder , PayloadBuilderAttributes } ;
3434use reth_payload_validator:: ExecutionPayloadValidator ;
3535use reth_primitives:: {
36- Block , GotExpected , Header , SealedBlock , SealedBlockWithSenders , SealedHeader ,
36+ revm_primitives:: EvmState , Block , GotExpected , Header , SealedBlock ,
37+ SealedBlockWithSenders , SealedHeader ,
3738} ;
3839use reth_provider:: {
3940 providers:: ConsistentDbView , BlockReader , DatabaseProviderFactory , ExecutionOutcome ,
@@ -44,6 +45,7 @@ use reth_revm::database::StateProviderDatabase;
4445use reth_stages_api:: ControlFlow ;
4546use reth_trie:: { updates:: TrieUpdates , HashedPostState , TrieInput } ;
4647use reth_trie_parallel:: parallel_root:: { ParallelStateRoot , ParallelStateRootError } ;
48+ use reth_trie_prefetch:: TriePrefetch ;
4749use std:: {
4850 cmp:: Ordering ,
4951 collections:: { btree_map, hash_map, BTreeMap , VecDeque } ,
@@ -505,6 +507,8 @@ pub struct EngineApiTreeHandler<P, E, T: EngineTypes, Spec> {
505507 engine_kind : EngineApiKind ,
506508 /// Flag indicating whether the state root validation should be skipped.
507509 skip_state_root_validation : bool ,
510+ /// Flag indicating whether to enable prefetch.
511+ enable_prefetch : bool ,
508512}
509513
510514impl < P : Debug , E : Debug , T : EngineTypes + Debug , Spec : Debug > std:: fmt:: Debug
@@ -527,6 +531,8 @@ impl<P: Debug, E: Debug, T: EngineTypes + Debug, Spec: Debug> std::fmt::Debug
527531 . field ( "metrics" , & self . metrics )
528532 . field ( "invalid_block_hook" , & format ! ( "{:p}" , self . invalid_block_hook) )
529533 . field ( "engine_kind" , & self . engine_kind )
534+ . field ( "skip_state_root_validation" , & self . skip_state_root_validation )
535+ . field ( "enable_prefetch" , & self . enable_prefetch )
530536 . finish ( )
531537 }
532538}
@@ -555,6 +561,7 @@ where
555561 config : TreeConfig ,
556562 engine_kind : EngineApiKind ,
557563 skip_state_root_validation : bool ,
564+ enable_prefetch : bool ,
558565 ) -> Self {
559566 let ( incoming_tx, incoming) = std:: sync:: mpsc:: channel ( ) ;
560567
@@ -577,6 +584,7 @@ where
577584 invalid_block_hook : Box :: new ( NoopInvalidBlockHook ) ,
578585 engine_kind,
579586 skip_state_root_validation,
587+ enable_prefetch,
580588 }
581589 }
582590
@@ -603,6 +611,7 @@ where
603611 invalid_block_hook : Box < dyn InvalidBlockHook > ,
604612 kind : EngineApiKind ,
605613 skip_state_root_validation : bool ,
614+ enable_prefetch : bool ,
606615 ) -> ( Sender < FromEngine < EngineApiRequest < T > > > , UnboundedReceiver < EngineApiEvent > ) {
607616 let best_block_number = provider. best_block_number ( ) . unwrap_or ( 0 ) ;
608617 let header = provider. sealed_header ( best_block_number) . ok ( ) . flatten ( ) . unwrap_or_default ( ) ;
@@ -634,10 +643,20 @@ where
634643 config,
635644 kind,
636645 skip_state_root_validation,
646+ enable_prefetch,
637647 ) ;
638648 task. set_invalid_block_hook ( invalid_block_hook) ;
639649 let incoming = task. incoming_tx . clone ( ) ;
640- std:: thread:: Builder :: new ( ) . name ( "Tree Task" . to_string ( ) ) . spawn ( || task. run ( ) ) . unwrap ( ) ;
650+ std:: thread:: Builder :: new ( )
651+ . name ( "Tree Task" . to_string ( ) )
652+ . spawn ( move || {
653+ let runtime =
654+ tokio:: runtime:: Builder :: new_current_thread ( ) . enable_all ( ) . build ( ) . unwrap ( ) ;
655+ runtime. block_on ( async {
656+ task. run ( ) ;
657+ } ) ;
658+ } )
659+ . unwrap ( ) ;
641660 ( incoming, outgoing)
642661 }
643662
@@ -2175,8 +2194,16 @@ where
21752194 }
21762195
21772196 trace ! ( target: "engine::tree" , block=?block. num_hash( ) , "Executing block" ) ;
2178- let executor =
2179- self . executor_provider . executor ( StateProviderDatabase :: new ( & state_provider) , None ) ;
2197+ let ( prefetch_tx, interrupt_tx) =
2198+ if self . enable_prefetch && !self . skip_state_root_validation {
2199+ self . setup_prefetch ( )
2200+ } else {
2201+ ( None , None )
2202+ } ;
2203+
2204+ let executor = self
2205+ . executor_provider
2206+ . executor ( StateProviderDatabase :: new ( & state_provider) , prefetch_tx) ;
21802207
21812208 let block_number = block. number ;
21822209 let block_hash = block. hash ( ) ;
@@ -2247,6 +2274,11 @@ where
22472274 state_provider. state_root_with_updates ( hashed_state. clone ( ) ) ?
22482275 } ;
22492276
2277+ // stop the prefetch task.
2278+ if let Some ( interrupt_tx) = interrupt_tx {
2279+ let _ = interrupt_tx. send ( ( ) ) ;
2280+ } ;
2281+
22502282 if state_root != block. state_root {
22512283 // call post-block hook
22522284 self . invalid_block_hook . on_invalid_block (
@@ -2575,6 +2607,22 @@ where
25752607 ) ;
25762608 Ok ( ( ) )
25772609 }
2610+
2611+ fn setup_prefetch ( & self ) -> ( Option < UnboundedSender < EvmState > > , Option < oneshot:: Sender < ( ) > > ) {
2612+ let ( prefetch_tx, prefetch_rx) = tokio:: sync:: mpsc:: unbounded_channel ( ) ;
2613+ let ( interrupt_tx, interrupt_rx) = oneshot:: channel ( ) ;
2614+
2615+ let mut trie_prefetch = TriePrefetch :: new ( ) ;
2616+ let provider_factory = self . provider . clone ( ) ;
2617+
2618+ tokio:: spawn ( {
2619+ async move {
2620+ trie_prefetch. run ( provider_factory, prefetch_rx, interrupt_rx) . await ;
2621+ }
2622+ } ) ;
2623+
2624+ ( Some ( prefetch_tx) , Some ( interrupt_tx) )
2625+ }
25782626}
25792627
25802628/// This is an error that can come from advancing persistence. Either this can be a
@@ -2728,6 +2776,7 @@ mod tests {
27282776 TreeConfig :: default ( ) ,
27292777 EngineApiKind :: Ethereum ,
27302778 false ,
2779+ false ,
27312780 ) ;
27322781
27332782 let block_builder = TestBlockBuilder :: default ( ) . with_chain_spec ( ( * chain_spec) . clone ( ) ) ;
0 commit comments