Skip to content

Commit

Permalink
fix: blockchash for devnet-0 (#1427)
Browse files Browse the repository at this point in the history
* fix: load blockchash only from serve_window

* fix: devnet-0 blockchash behaviour
  • Loading branch information
rakita committed May 16, 2024
1 parent eed27d9 commit 7046d5e
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 36 deletions.
36 changes: 5 additions & 31 deletions crates/interpreter/src/instructions/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::{
Host, InstructionResult, SStoreResult,
};
use core::cmp::min;
use revm_primitives::{BLOCKHASH_SERVE_WINDOW, BLOCKHASH_STORAGE_ADDRESS, BLOCK_HASH_HISTORY};
use std::vec::Vec;

pub fn balance<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
Expand Down Expand Up @@ -108,36 +107,11 @@ pub fn blockhash<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, ho
pop_top!(interpreter, number);

let block_number = host.env().block.number;

match block_number.checked_sub(*number) {
// blockhash should push zero if number is same as current block number.
Some(diff) if !diff.is_zero() => {
let diff = as_usize_saturated!(diff);

if SPEC::enabled(PRAGUE) && diff <= BLOCKHASH_SERVE_WINDOW {
let index = number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW));
let Some((value, _)) = host.sload(BLOCKHASH_STORAGE_ADDRESS, index) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
};
*number = value;
return;
} else if diff <= BLOCK_HASH_HISTORY {
let Some(hash) = host.block_hash(*number) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
};
*number = U256::from_be_bytes(hash.0);
return;
}
}
_ => {
// If blockhash is requested for the current block, the hash should be 0, so we fall
// through.
}
}

*number = U256::ZERO;
let Some(hash) = host.block_hash(block_number) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
};
*number = U256::from_be_bytes(hash.0);
}

pub fn sload<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
Expand Down
44 changes: 39 additions & 5 deletions crates/revm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ pub use context_precompiles::{
};
pub use evm_context::EvmContext;
pub use inner_evm_context::InnerEvmContext;
use revm_interpreter::as_usize_saturated;

use crate::{
db::{Database, EmptyDB},
interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult},
primitives::{Address, Bytecode, Env, HandlerCfg, Log, B256, U256},
primitives::{
Address, Bytecode, EVMError, Env, HandlerCfg, Log, B256, BLOCKHASH_SERVE_WINDOW,
BLOCKHASH_STORAGE_ADDRESS, BLOCK_HASH_HISTORY, PRAGUE, U256,
},
};
use std::boxed::Box;

Expand Down Expand Up @@ -106,10 +110,40 @@ impl<EXT, DB: Database> Host for Context<EXT, DB> {
}

fn block_hash(&mut self, number: U256) -> Option<B256> {
self.evm
.block_hash(number)
.map_err(|e| self.evm.error = Err(e))
.ok()
let block_number = self.env().block.number;

match block_number.checked_sub(number) {
// blockhash should push zero if number is same as current block number.
Some(diff) if !diff.is_zero() => {
let diff = as_usize_saturated!(diff);

if diff <= BLOCK_HASH_HISTORY {
return self
.evm
.block_hash(number)
.map_err(|e| self.evm.error = Err(e))
.ok();
}

if self.evm.journaled_state.spec.is_enabled_in(PRAGUE)
&& diff <= BLOCKHASH_SERVE_WINDOW
{
let index = number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW));
return self
.evm
.db
.storage(BLOCKHASH_STORAGE_ADDRESS, index)
.map_err(|e| self.evm.error = Err(EVMError::Database(e)))
.ok()
.map(|v| v.into());
}
}
_ => {
// If blockhash is requested for the current block, the hash should be 0, so we fall
// through.
}
}
Some(B256::ZERO)
}

fn load_account(&mut self, address: Address) -> Option<LoadAccountResult> {
Expand Down

0 comments on commit 7046d5e

Please sign in to comment.