11use alloy_consensus:: { transaction:: SignerRecoverable , BlockHeader , Transaction as _} ;
22use alloy_primitives:: { B256 , U256 } ;
33use eyre:: { eyre, Result as EyreResult } ;
4- use reth:: revm:: db:: { Cache , CacheDB , State } ;
4+ use reth:: revm:: db:: { BundleState , Cache , CacheDB , State } ;
5+ use revm_database:: states:: bundle_state:: BundleRetention ;
56use reth_evm:: execute:: BlockBuilder ;
67use reth_evm:: ConfigureEvm ;
78use reth_optimism_chainspec:: OpChainSpec ;
@@ -12,6 +13,15 @@ use std::time::Instant;
1213
1314use crate :: TransactionResult ;
1415
16+ /// State from pending flashblocks that is used as a base for metering
17+ #[ derive( Debug , Clone ) ]
18+ pub struct FlashblocksState {
19+ /// The cache of account and storage data
20+ pub cache : Cache ,
21+ /// The accumulated bundle of state changes
22+ pub bundle_state : BundleState ,
23+ }
24+
1525const BLOCK_TIME : u64 = 2 ; // 2 seconds per block
1626
1727/// Output from metering a bundle of transactions
@@ -43,36 +53,40 @@ pub fn meter_bundle<SP>(
4353 decoded_txs : Vec < op_alloy_consensus:: OpTxEnvelope > ,
4454 header : & SealedHeader ,
4555 bundle_with_metadata : & tips_core:: types:: BundleWithMetadata ,
46- db_cache : Option < Cache > ,
56+ flashblocks_state : Option < FlashblocksState > ,
4757) -> EyreResult < MeterBundleOutput >
4858where
4959 SP : reth_provider:: StateProvider ,
5060{
5161 // Get bundle hash from BundleWithMetadata
5262 let bundle_hash = bundle_with_metadata. bundle_hash ( ) ;
5363
54- // Create state database with optional flashblocks cache
64+ // Create state database
5565 let state_db = reth:: revm:: database:: StateProviderDatabase :: new ( state_provider) ;
56- let base_state = State :: builder ( )
57- . with_database ( state_db)
58- . with_bundle_update ( )
59- . build ( ) ;
6066
61- // If we have flashblocks cache, wrap with CacheDB to apply pending changes
62- let cache_db = if let Some ( cache ) = db_cache {
67+ // If we have flashblocks state, apply both cache and bundle prestate
68+ let cache_db = if let Some ( ref flashblocks ) = flashblocks_state {
6369 CacheDB {
64- cache,
65- db : base_state ,
70+ cache : flashblocks . cache . clone ( ) ,
71+ db : state_db ,
6672 }
6773 } else {
68- CacheDB :: new ( base_state )
74+ CacheDB :: new ( state_db )
6975 } ;
7076
71- // Wrap the CacheDB in a State for the EVM builder
72- let mut db = State :: builder ( )
73- . with_database ( cache_db)
74- . with_bundle_update ( )
75- . build ( ) ;
77+ // Wrap the CacheDB in a State to track bundle changes for state root calculation
78+ let mut db = if let Some ( flashblocks) = flashblocks_state. as_ref ( ) {
79+ State :: builder ( )
80+ . with_database ( cache_db)
81+ . with_bundle_update ( )
82+ . with_bundle_prestate ( flashblocks. bundle_state . clone ( ) )
83+ . build ( )
84+ } else {
85+ State :: builder ( )
86+ . with_database ( cache_db)
87+ . with_bundle_update ( )
88+ . build ( )
89+ } ;
7690
7791 // Set up next block attributes
7892 // Use bundle.min_timestamp if provided, otherwise use header timestamp + BLOCK_TIME
@@ -138,11 +152,14 @@ where
138152 }
139153
140154 // Calculate state root and measure its calculation time
155+ // The bundle already includes flashblocks state if it was provided via with_bundle_prestate
156+ db. merge_transitions ( BundleRetention :: Reverts ) ;
141157 let bundle = db. take_bundle ( ) ;
142- let state_provider = db. database . as_ref ( ) ;
158+ let state_provider = db. database . db . as_ref ( ) ;
143159 let state_root_start = Instant :: now ( ) ;
144- let hashed_state = state_provider. hashed_post_state ( & bundle) ;
145- let _ = state_provider. state_root_with_updates ( hashed_state) ;
160+
161+ let hashed_post_state = state_provider. hashed_post_state ( & bundle) ;
162+ let _ = state_provider. state_root_with_updates ( hashed_post_state) ;
146163 let state_root_time = state_root_start. elapsed ( ) . as_micros ( ) ;
147164
148165 let total_execution_time = execution_start. elapsed ( ) . as_micros ( ) ;
0 commit comments