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(()) }