From a195b777ebc6e7a31bb3f1ef3fcc92065f591d45 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Tue, 17 Feb 2026 16:48:06 -0800 Subject: [PATCH] perf(storage): skip plain state conversion in write_state for storage v2 (#22294) Co-authored-by: Amp Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com> --- .../src/providers/database/provider.rs | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 5659d3b250..aff09f4f02 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -843,6 +843,18 @@ impl DatabaseProvider, + ) -> ProviderResult<()> { + let mut bytecodes_cursor = self.tx_ref().cursor_write::()?; + for (hash, bytecode) in bytecodes { + bytecodes_cursor.upsert(hash, &bytecode)?; + } + Ok(()) + } } impl TryIntoHistoricalStateProvider for DatabaseProvider { @@ -2366,8 +2378,22 @@ impl StateWriter config: StateWriteConfig, ) -> ProviderResult<()> { let execution_outcome = execution_outcome.into(); - let first_block = execution_outcome.first_block(); + if self.cached_storage_settings().use_hashed_state() && + !config.write_receipts && + !config.write_account_changesets && + !config.write_storage_changesets + { + // In storage v2 with all outputs directed to static files, plain state and changesets + // are written elsewhere. Only bytecodes need MDBX writes, so skip the expensive + // to_plain_state_and_reverts conversion that iterates all accounts and storage. + self.write_bytecodes( + execution_outcome.state().contracts.iter().map(|(h, b)| (*h, Bytecode(b.clone()))), + )?; + return Ok(()); + } + + let first_block = execution_outcome.first_block(); let (plain_state, reverts) = execution_outcome.state().to_plain_state_and_reverts(is_value_known); @@ -2624,10 +2650,9 @@ impl StateWriter // Write bytecode tracing::trace!(len = changes.contracts.len(), "Writing bytecodes"); - let mut bytecodes_cursor = self.tx_ref().cursor_write::()?; - for (hash, bytecode) in changes.contracts { - bytecodes_cursor.upsert(hash, &Bytecode(bytecode))?; - } + self.write_bytecodes( + changes.contracts.into_iter().map(|(hash, bytecode)| (hash, Bytecode(bytecode))), + )?; Ok(()) }