From 901813dcbb626e5a3047b2e33097f76a9106f685 Mon Sep 17 00:00:00 2001 From: Bjerg Date: Fri, 24 Feb 2023 20:27:27 +0100 Subject: [PATCH] perf: save a hashing step for bytecodes (#1547) --- crates/revm/src/database.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/revm/src/database.rs b/crates/revm/src/database.rs index 9740f6475b..c90a7b111b 100644 --- a/crates/revm/src/database.rs +++ b/crates/revm/src/database.rs @@ -47,8 +47,23 @@ impl DatabaseRef for State { } fn code_by_hash(&self, code_hash: H256) -> Result { - let bytecode = self.0.bytecode_by_hash(code_hash)?.unwrap_or_default(); - Ok(Bytecode::new_raw(bytecode.0)) + let bytecode = self.0.bytecode_by_hash(code_hash)?; + + // SAFETY: We are requesting the code by its hash, so it is almost tautological why this + // would be safe. If the bytecode is not found, we return an empty bytecode with the + // appropriate hash. + // + // In an ideal world we would return analysed bytecode here, but analysed bytecode in revm + // depends on the current active hard fork, since it calculates gas blocks... + if let Some(bytecode) = bytecode { + Ok(unsafe { Bytecode::new_raw_with_hash(bytecode.0, code_hash) }) + } else { + // NOTE(onbjerg): This corresponds to an empty analysed bytecode with a hash of + // `KECCAK_EMPTY`. In the case where the bytecode is not found, we would + // return empty bytes anyway: this simply skips the hashing and analysis steps, which + // would otherwise be present if we simply did an `.unwrap_or_default()` above. + Ok(Bytecode::new()) + } } fn storage(&self, address: H160, index: U256) -> Result {