Skip to content

Commit ae71b9d

Browse files
authored
fix: Don't hold onto intermediate execution cache across block boundaries (op-rs#396)
1 parent 5c30c4c commit ae71b9d

File tree

5 files changed

+40
-45
lines changed

5 files changed

+40
-45
lines changed

Diff for: bin/client/src/l2/precompiles/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ where
3636
F: TrieDBFetcher,
3737
H: TrieDBHinter,
3838
{
39-
fn set_precompiles(handler: &mut EvmHandler<'_, (), &mut State<TrieDB<F, H>>>) {
39+
fn set_precompiles(handler: &mut EvmHandler<'_, (), &mut State<&mut TrieDB<F, H>>>) {
4040
let spec_id = handler.cfg.spec_id;
4141

4242
handler.pre_execution.load_precompiles = Arc::new(move || {

Diff for: crates/executor/src/builder.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use alloy_consensus::{Header, Sealable, Sealed};
55
use anyhow::Result;
66
use kona_derive::types::RollupConfig;
77
use kona_mpt::{TrieDB, TrieDBFetcher, TrieDBHinter};
8-
use revm::StateBuilder;
98

109
/// The builder pattern for the [StatelessL2BlockExecutor].
1110
#[derive(Debug)]
@@ -78,11 +77,10 @@ where
7877
});
7978

8079
let trie_db = TrieDB::new(parent_header.state_root, parent_header, fetcher, hinter);
81-
let state = StateBuilder::new_with_database(trie_db).with_bundle_update().build();
8280

8381
Ok(StatelessL2BlockExecutor {
8482
config: self.config,
85-
state,
83+
trie_db,
8684
_phantom: core::marker::PhantomData::<PO>,
8785
})
8886
}

Diff for: crates/executor/src/canyon.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const CREATE_2_DEPLOYER_BYTECODE: [u8; 1584] = hex!("608060405260043610610043576
2323
/// deployer contract. This is done by directly setting the code of the create2 deployer account
2424
/// prior to executing any transactions on the timestamp activation of the fork.
2525
pub(crate) fn ensure_create2_deployer_canyon<F, H>(
26-
db: &mut State<TrieDB<F, H>>,
26+
db: &mut State<&mut TrieDB<F, H>>,
2727
config: &RollupConfig,
2828
timestamp: u64,
2929
) -> Result<()>

Diff for: crates/executor/src/lib.rs

+35-38
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ where
5151
/// The [RollupConfig].
5252
config: &'a RollupConfig,
5353
/// The inner state database component.
54-
state: State<TrieDB<F, H>>,
54+
trie_db: TrieDB<F, H>,
5555
/// Phantom data for the precompile overrides.
5656
_phantom: core::marker::PhantomData<PO>,
5757
}
@@ -67,11 +67,6 @@ where
6767
StatelessL2BlockExecutorBuilder::with_config(config)
6868
}
6969

70-
/// Returns a reference to the current [State] database of the executor.
71-
pub fn state_ref(&self) -> &State<TrieDB<F, H>> {
72-
&self.state
73-
}
74-
7570
/// Executes the given block, returning the resulting state root.
7671
///
7772
/// ## Steps
@@ -93,7 +88,7 @@ where
9388
let initialized_block_env = Self::prepare_block_env(
9489
self.revm_spec_id(payload.timestamp),
9590
self.config,
96-
self.state.database.parent_block_header(),
91+
self.trie_db.parent_block_header(),
9792
&payload,
9893
);
9994
let initialized_cfg = self.evm_cfg_env(payload.timestamp);
@@ -110,9 +105,12 @@ where
110105
tx_len = payload.transactions.len()
111106
);
112107

108+
let mut state =
109+
State::builder().with_database(&mut self.trie_db).with_bundle_update().build();
110+
113111
// Apply the pre-block EIP-4788 contract call.
114112
pre_block_beacon_root_contract_call(
115-
&mut self.state,
113+
&mut state,
116114
self.config,
117115
block_number,
118116
&initialized_cfg,
@@ -121,7 +119,7 @@ where
121119
)?;
122120

123121
// Ensure that the create2 contract is deployed upon transition to the Canyon hardfork.
124-
ensure_create2_deployer_canyon(&mut self.state, self.config, payload.timestamp)?;
122+
ensure_create2_deployer_canyon(&mut state, self.config, payload.timestamp)?;
125123

126124
let mut cumulative_gas_used = 0u64;
127125
let mut receipts: Vec<OpReceiptEnvelope> = Vec::with_capacity(payload.transactions.len());
@@ -130,7 +128,7 @@ where
130128
// Construct the block-scoped EVM with the given configuration.
131129
// The transaction environment is set within the loop for each transaction.
132130
let mut evm = Evm::builder()
133-
.with_db(&mut self.state)
131+
.with_db(&mut state)
134132
.with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(
135133
initialized_cfg.clone(),
136134
initialized_block_env.clone(),
@@ -229,13 +227,13 @@ where
229227

230228
// Merge all state transitions into the cache state.
231229
debug!(target: "client_executor", "Merging state transitions");
232-
self.state.merge_transitions(BundleRetention::Reverts);
230+
state.merge_transitions(BundleRetention::Reverts);
233231

234232
// Take the bundle state.
235-
let bundle = self.state.take_bundle();
233+
let bundle = state.take_bundle();
236234

237235
// Recompute the header roots.
238-
let state_root = self.state.database.state_root(&bundle)?;
236+
let state_root = state.database.state_root(&bundle)?;
239237

240238
let transactions_root = Self::compute_transactions_root(payload.transactions.as_slice());
241239
let receipts_root = Self::compute_receipts_root(&receipts, self.config, payload.timestamp);
@@ -257,7 +255,7 @@ where
257255
.config
258256
.is_ecotone_active(payload.timestamp)
259257
.then(|| {
260-
let parent_header = self.state.database.parent_block_header();
258+
let parent_header = state.database.parent_block_header();
261259
let excess_blob_gas = if self.config.is_ecotone_active(parent_header.timestamp) {
262260
let parent_excess_blob_gas = parent_header.excess_blob_gas.unwrap_or_default();
263261
let parent_blob_gas_used = parent_header.blob_gas_used.unwrap_or_default();
@@ -273,7 +271,7 @@ where
273271

274272
// Construct the new header.
275273
let header = Header {
276-
parent_hash: self.state.database.parent_block_header().seal(),
274+
parent_hash: state.database.parent_block_header().seal(),
277275
ommers_hash: EMPTY_OMMER_ROOT_HASH,
278276
beneficiary: payload.fee_recipient,
279277
state_root,
@@ -308,9 +306,9 @@ where
308306
);
309307

310308
// Update the parent block hash in the state database.
311-
self.state.database.set_parent_block_header(header);
309+
state.database.set_parent_block_header(header);
312310

313-
Ok(self.state.database.parent_block_header())
311+
Ok(state.database.parent_block_header())
314312
}
315313

316314
/// Computes the current output root of the executor, based on the parent header and the
@@ -331,27 +329,26 @@ where
331329
address!("4200000000000000000000000000000000000016");
332330

333331
// Fetch the L2 to L1 message passer account from the cache or underlying trie.
334-
let storage_root =
335-
match self.state.database.storage_roots().get(&L2_TO_L1_MESSAGE_PASSER_ADDRESS) {
336-
Some(storage_root) => storage_root
337-
.blinded_commitment()
338-
.ok_or(anyhow!("Account storage root is unblinded"))?,
339-
None => {
340-
self.state
341-
.database
342-
.get_trie_account(&L2_TO_L1_MESSAGE_PASSER_ADDRESS)?
343-
.ok_or(anyhow!("L2 to L1 message passer account not found in trie"))?
344-
.storage_root
345-
}
346-
};
332+
let storage_root = match self.trie_db.storage_roots().get(&L2_TO_L1_MESSAGE_PASSER_ADDRESS)
333+
{
334+
Some(storage_root) => storage_root
335+
.blinded_commitment()
336+
.ok_or(anyhow!("Account storage root is unblinded"))?,
337+
None => {
338+
self.trie_db
339+
.get_trie_account(&L2_TO_L1_MESSAGE_PASSER_ADDRESS)?
340+
.ok_or(anyhow!("L2 to L1 message passer account not found in trie"))?
341+
.storage_root
342+
}
343+
};
347344

348-
let parent_header = self.state.database.parent_block_header();
345+
let parent_header = self.trie_db.parent_block_header();
349346

350347
info!(
351348
target: "client_executor",
352349
"Computing output root | Version: {version} | State root: {state_root} | Storage root: {storage_root} | Block hash: {hash}",
353350
version = OUTPUT_ROOT_VERSION,
354-
state_root = self.state.database.parent_block_header().state_root,
351+
state_root = self.trie_db.parent_block_header().state_root,
355352
hash = parent_header.seal(),
356353
);
357354

@@ -742,7 +739,7 @@ mod test {
742739

743740
assert_eq!(produced_header, expected_header);
744741
assert_eq!(
745-
l2_block_executor.state.database.parent_block_header().seal(),
742+
l2_block_executor.trie_db.parent_block_header().seal(),
746743
expected_header.hash_slow()
747744
);
748745
}
@@ -800,7 +797,7 @@ mod test {
800797

801798
assert_eq!(produced_header, expected_header);
802799
assert_eq!(
803-
l2_block_executor.state.database.parent_block_header().seal(),
800+
l2_block_executor.trie_db.parent_block_header().seal(),
804801
expected_header.hash_slow()
805802
);
806803
}
@@ -865,7 +862,7 @@ mod test {
865862

866863
assert_eq!(produced_header, expected_header);
867864
assert_eq!(
868-
l2_block_executor.state.database.parent_block_header().seal(),
865+
l2_block_executor.trie_db.parent_block_header().seal(),
869866
expected_header.hash_slow()
870867
);
871868
}
@@ -924,7 +921,7 @@ mod test {
924921

925922
assert_eq!(produced_header, expected_header);
926923
assert_eq!(
927-
l2_block_executor.state.database.parent_block_header().seal(),
924+
l2_block_executor.trie_db.parent_block_header().seal(),
928925
expected_header.hash_slow()
929926
);
930927
}
@@ -992,7 +989,7 @@ mod test {
992989

993990
assert_eq!(produced_header, expected_header);
994991
assert_eq!(
995-
l2_block_executor.state.database.parent_block_header().seal(),
992+
l2_block_executor.trie_db.parent_block_header().seal(),
996993
expected_header.hash_slow()
997994
);
998995
}
@@ -1065,7 +1062,7 @@ mod test {
10651062

10661063
assert_eq!(produced_header, expected_header);
10671064
assert_eq!(
1068-
l2_block_executor.state.database.parent_block_header().seal(),
1065+
l2_block_executor.trie_db.parent_block_header().seal(),
10691066
expected_header.hash_slow()
10701067
);
10711068
}

Diff for: crates/executor/src/precompile.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ where
1010
H: TrieDBHinter,
1111
{
1212
/// Set the precompiles to use during execution.
13-
fn set_precompiles(handler: &mut EvmHandler<'_, (), &mut State<TrieDB<F, H>>>);
13+
fn set_precompiles(handler: &mut EvmHandler<'_, (), &mut State<&mut TrieDB<F, H>>>);
1414
}
1515

1616
/// Default implementation of [PrecompileOverride], which does not override any precompiles.
@@ -22,7 +22,7 @@ where
2222
F: TrieDBFetcher,
2323
H: TrieDBHinter,
2424
{
25-
fn set_precompiles(_: &mut EvmHandler<'_, (), &mut State<TrieDB<F, H>>>) {
25+
fn set_precompiles(_: &mut EvmHandler<'_, (), &mut State<&mut TrieDB<F, H>>>) {
2626
// Do nothing
2727
}
2828
}

0 commit comments

Comments
 (0)