Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions crates/context/interface/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ pub trait Host {
fn gas_limit(&self) -> U256;
/// Block difficulty, calls ContextTr::block().difficulty()
fn difficulty(&self) -> U256;
/// Block prevrandao, calls ContextTr::block().prevrandao()
fn prevrandao(&self) -> Option<U256>;
/// Block prevrandao, calls ContextTr::block().prevrandao().
/// Caches the result in local context on first call.
fn prevrandao(&mut self) -> Option<U256>;
/// Block number, calls ContextTr::block().number()
fn block_number(&self) -> U256;
/// Block timestamp, calls ContextTr::block().timestamp()
Expand Down Expand Up @@ -240,7 +241,7 @@ impl Host for DummyHost {
U256::ZERO
}

fn prevrandao(&self) -> Option<U256> {
fn prevrandao(&mut self) -> Option<U256> {
None
}

Expand Down
6 changes: 5 additions & 1 deletion crates/context/interface/src/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use core::{
cell::{Ref, RefCell},
ops::Range,
};
use std::{rc::Rc, string::String, vec::Vec};
use primitives::U256;
use std::{boxed::Box, rc::Rc, string::String, vec::Vec};

/// Non-empty, item-pooling Vec.
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -234,6 +235,9 @@ pub trait LocalContextTr {
///
/// Returns `Some(String)` if a precompile error message was recorded.
fn take_precompile_error_context(&mut self) -> Option<String>;

/// Cached prevrandao value. Set on first PREVRANDAO call, cleared on clear.
fn prevrandao(&mut self) -> &mut Option<Box<U256>>;
}

#[cfg(test)]
Expand Down
11 changes: 9 additions & 2 deletions crates/context/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,15 @@ impl<
self.block().difficulty()
}

fn prevrandao(&self) -> Option<U256> {
self.block().prevrandao().map(|r| r.into())
fn prevrandao(&mut self) -> Option<U256> {
if let Some(cached) = self.local.prevrandao() {
return Some(**cached);
}
let val = self.block().prevrandao().map(|r| r.into());
if let Some(v) = val {
*self.local.prevrandao() = Some(Box::new(v));
}
val
}

#[inline]
Expand Down
11 changes: 10 additions & 1 deletion crates/context/src/local.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Local context that is filled by execution.
use context_interface::LocalContextTr;
use core::cell::RefCell;
use std::{rc::Rc, string::String, vec::Vec};
use primitives::U256;
use std::{boxed::Box, rc::Rc, string::String, vec::Vec};

/// Local context that is filled by execution.
#[derive(Clone, Debug)]
Expand All @@ -10,13 +11,16 @@ pub struct LocalContext {
pub shared_memory_buffer: Rc<RefCell<Vec<u8>>>,
/// Optional precompile error message to bubble up.
pub precompile_error_message: Option<String>,
/// Cached prevrandao value. Set on first PREVRANDAO call, cleared on clear.
pub prevrandao: Option<Box<U256>>,
}

impl Default for LocalContext {
fn default() -> Self {
Self {
shared_memory_buffer: Rc::new(RefCell::new(Vec::with_capacity(1024 * 4))),
precompile_error_message: None,
prevrandao: None,
}
}
}
Expand All @@ -26,6 +30,7 @@ impl LocalContextTr for LocalContext {
// Sets len to 0 but it will not shrink to drop the capacity.
unsafe { self.shared_memory_buffer.borrow_mut().set_len(0) };
self.precompile_error_message = None;
self.prevrandao = None;
}

fn shared_memory_buffer(&self) -> &Rc<RefCell<Vec<u8>>> {
Expand All @@ -39,6 +44,10 @@ impl LocalContextTr for LocalContext {
fn take_precompile_error_context(&mut self) -> Option<String> {
self.precompile_error_message.take()
}

fn prevrandao(&mut self) -> &mut Option<Box<U256>> {
&mut self.prevrandao
}
}

impl LocalContext {
Expand Down
6 changes: 6 additions & 0 deletions crates/interpreter/src/instructions/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,18 @@ pub fn selfbalance<WIRE: InterpreterTypes, H: Host + ?Sized>(
) {
check!(context.interpreter, ISTANBUL);

if let Some(cached) = &context.interpreter.selfbalance_cache {
push!(context.interpreter, **cached);
return;
}

let Some(balance) = context
.host
.balance(context.interpreter.input.target_address())
else {
return context.interpreter.halt_fatal();
};
context.interpreter.selfbalance_cache = Some(Box::new(balance.data));
push!(context.interpreter, balance.data);
}

Expand Down
7 changes: 6 additions & 1 deletion crates/interpreter/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::{
InstructionResult, InstructionTable, InterpreterAction,
};
use bytecode::Bytecode;
use primitives::{hardfork::SpecId, Bytes};
use primitives::{hardfork::SpecId, Bytes, U256};

/// Main interpreter structure that contains all components defined in [`InterpreterTypes`].
#[derive(Debug, Clone)]
Expand All @@ -46,6 +46,8 @@ pub struct Interpreter<WIRE: InterpreterTypes = EthInterpreter> {
pub runtime_flag: WIRE::RuntimeFlag,
/// Extended functionality and customizations.
pub extend: WIRE::Extend,
/// Cached self balance. Set on first SELFBALANCE call, cleared on init.
pub selfbalance_cache: Option<Box<U256>>,
}

impl<EXT: Default> Interpreter<EthInterpreter<EXT>> {
Expand Down Expand Up @@ -110,6 +112,7 @@ impl<EXT: Default> Interpreter<EthInterpreter<EXT>> {
input,
runtime_flag: RuntimeFlags { is_static, spec_id },
extend: Default::default(),
selfbalance_cache: None,
}
}

Expand All @@ -134,6 +137,7 @@ impl<EXT: Default> Interpreter<EthInterpreter<EXT>> {
input: input_ref,
runtime_flag,
extend,
selfbalance_cache,
} = self;
*bytecode_ref = bytecode;
*gas = Gas::new(gas_limit);
Expand All @@ -147,6 +151,7 @@ impl<EXT: Default> Interpreter<EthInterpreter<EXT>> {
*input_ref = input;
*runtime_flag = RuntimeFlags { spec_id, is_static };
*extend = EXT::default();
*selfbalance_cache = None;
}

/// Sets the bytecode that is going to be executed
Expand Down
Loading