Skip to content

Commit 319fe0a

Browse files
committed
Merge remote-tracking branch 'origin/main' into rakita/state-gas
2 parents 5001497 + ce911a2 commit 319fe0a

9 files changed

Lines changed: 65 additions & 82 deletions

File tree

book/src/awesome.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ A curated list of excellent Revm-related resources. Feel free to contribute to t
2727
- [**Foundry:**](https://github.com/foundry-rs/foundry) A portable and modular toolkit for rapid Ethereum application development in Rust.
2828
- [**Hardhat:**](https://github.com/NomicFoundation/hardhat) A comprehensive development environment for compiling, deploying, testing, and debugging Ethereum software.
2929
- [**Arbiter:**](https://github.com/harnesslabs/arbiter) smart-contract simulation.
30+
- [**OpTrace:**](https://github.com/tanghaosuan11/op_trace) A high-performance, GUI-based EVM debugger with a programmable engine for deep-dive trace analysis.
3031

3132
#### Frameworks and Libraries
3233
- [**revm-inspectors:**](https://github.com/paradigmxyz/revm-inspectors) Hooks for EVM execution.

crates/context/interface/src/local.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,7 @@ pub trait LocalContextTr {
218218

219219
/// Slice of the shared memory buffer returns None if range is not valid or buffer can't be borrowed.
220220
fn shared_memory_buffer_slice(&self, range: Range<usize>) -> Option<Ref<'_, [u8]>> {
221-
let buffer = self.shared_memory_buffer();
222-
buffer.borrow().get(range.clone())?;
223-
Some(Ref::map(buffer.borrow(), |b| {
224-
b.get(range).unwrap_or_default()
225-
}))
221+
Ref::filter_map(self.shared_memory_buffer().borrow(), |b| b.get(range)).ok()
226222
}
227223

228224
/// Clear the local context.

crates/database/src/states/state_builder.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,6 @@ pub struct StateBuilder<DB> {
2121
///
2222
/// Default is false.
2323
with_bundle_update: bool,
24-
/// Do we want to merge transitions in background?
25-
///
26-
/// This will allow evm to continue executing.
27-
///
28-
/// Default is false.
29-
with_background_transition_merge: bool,
3024
/// If we want to set different block hashes,
3125
with_block_hashes: BlockHashCache,
3226
/// BAL state.
@@ -57,7 +51,6 @@ impl<DB: Database> StateBuilder<DB> {
5751
with_cache_prestate: None,
5852
with_bundle_prestate: None,
5953
with_bundle_update: false,
60-
with_background_transition_merge: false,
6154
with_block_hashes: BlockHashCache::new(),
6255
bal_state: BalState::default(),
6356
}
@@ -72,7 +65,6 @@ impl<DB: Database> StateBuilder<DB> {
7265
with_cache_prestate: self.with_cache_prestate,
7366
with_bundle_prestate: self.with_bundle_prestate,
7467
with_bundle_update: self.with_bundle_update,
75-
with_background_transition_merge: self.with_background_transition_merge,
7668
with_block_hashes: self.with_block_hashes,
7769
bal_state: self.bal_state,
7870
}
@@ -132,15 +124,6 @@ impl<DB: Database> StateBuilder<DB> {
132124
}
133125
}
134126

135-
/// Starts the thread that will take transitions and do merge to the bundle state
136-
/// in the background.
137-
pub fn with_background_transition_merge(self) -> Self {
138-
Self {
139-
with_background_transition_merge: true,
140-
..self
141-
}
142-
}
143-
144127
/// Sets the block hashes for the state.
145128
pub fn with_block_hashes(self, block_hashes: BlockHashCache) -> Self {
146129
Self {

crates/handler/src/precompile_provider.rs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use auto_impl::auto_impl;
22
use context::{Cfg, LocalContextTr};
33
use context_interface::{ContextTr, JournalTr};
4-
use interpreter::{CallInput, CallInputs, Gas, InstructionResult, InterpreterResult};
4+
use interpreter::{CallInputs, Gas, InstructionResult, InterpreterResult};
55
use precompile::{PrecompileSpecId, Precompiles};
66
use primitives::{hardfork::SpecId, Address, Bytes};
77
use std::{
@@ -101,22 +101,7 @@ impl<CTX: ContextTr> PrecompileProvider<CTX> for EthPrecompiles {
101101
output: Bytes::new(),
102102
};
103103

104-
let exec_result = {
105-
let r;
106-
let input_bytes = match &inputs.input {
107-
CallInput::SharedBuffer(range) => {
108-
if let Some(slice) = context.local().shared_memory_buffer_slice(range.clone()) {
109-
r = slice;
110-
r.as_ref()
111-
} else {
112-
&[]
113-
}
114-
}
115-
CallInput::Bytes(bytes) => bytes.0.iter().as_slice(),
116-
};
117-
precompile.execute(input_bytes, inputs.gas_limit)
118-
};
119-
104+
let exec_result = precompile.execute(&inputs.input.as_bytes(context), inputs.gas_limit);
120105
match exec_result {
121106
Ok(output) => {
122107
*result.gas.tracker_mut() = output.gas;

crates/interpreter/src/instructions/system.rs

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -111,28 +111,12 @@ pub fn calldataload<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionConte
111111
let input_len = input.len();
112112
if offset < input_len {
113113
let count = 32.min(input_len - offset);
114-
114+
let input = &*input.as_bytes_memory(&context.interpreter.memory);
115115
// SAFETY: `count` is bounded by the calldata length.
116116
// This is `word[..count].copy_from_slice(input[offset..offset + count])`, written using
117117
// raw pointers as apparently the compiler cannot optimize the slice version, and using
118118
// `get_unchecked` twice is uglier.
119-
match context.interpreter.input.input() {
120-
CallInput::Bytes(bytes) => {
121-
unsafe {
122-
ptr::copy_nonoverlapping(bytes.as_ptr().add(offset), word.as_mut_ptr(), count)
123-
};
124-
}
125-
CallInput::SharedBuffer(range) => {
126-
let input_slice = context.interpreter.memory.global_slice(range.clone());
127-
unsafe {
128-
ptr::copy_nonoverlapping(
129-
input_slice.as_ptr().add(offset),
130-
word.as_mut_ptr(),
131-
count,
132-
)
133-
};
134-
}
135-
}
119+
unsafe { ptr::copy_nonoverlapping(input.as_ptr().add(offset), word.as_mut_ptr(), count) };
136120
}
137121
*offset_ptr = word.into();
138122
}

crates/interpreter/src/interpreter/shared_memory.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,10 @@ impl SharedMemory {
226226
fn slice_range_with_base(&self, range: Range<usize>, base: usize) -> Ref<'_, [u8]> {
227227
let buffer = self.buffer_ref();
228228
Ref::map(buffer, |b| {
229-
match b.get(range.start + base..range.end + base) {
229+
let range = range.start + base..range.end + base;
230+
match b.get(range.clone()) {
230231
Some(slice) => slice,
231-
None => debug_unreachable!("slice OOB: range; len: {}", self.len()),
232+
None => debug_unreachable!("slice OOB: {range:?}; len: {}", self.len()),
232233
}
233234
})
234235
}

crates/interpreter/src/interpreter_action/call_inputs.rs

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
use crate::interpreter_types::MemoryTr;
12
use context_interface::{ContextTr, LocalContextTr};
23
use core::ops::Range;
34
use primitives::{Address, Bytes, B256, U256};
45
use state::Bytecode;
6+
57
/// Input enum for a call.
68
///
79
/// As CallInput uses shared memory buffer it can get overridden if not used directly when call happens.
810
#[derive(Clone, Debug, PartialEq, Eq)]
911
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1012
pub enum CallInput {
13+
/// Bytes of the call data.
14+
Bytes(Bytes),
1115
/// The Range points to the SharedMemory buffer. Buffer can be found in [`context_interface::LocalContextTr::shared_memory_buffer_slice`] function.
1216
/// And can be accessed with `evm.ctx().local().shared_memory_buffer()`
1317
///
@@ -16,12 +20,11 @@ pub enum CallInput {
1620
/// Use it with caution, CallInput shared buffer can be overridden if context from child call is returned so
1721
/// recommendation is to fetch buffer at first Inspector call and clone it from [`context_interface::LocalContextTr::shared_memory_buffer_slice`] function.
1822
SharedBuffer(Range<usize>),
19-
/// Bytes of the call data.
20-
Bytes(Bytes),
2123
}
2224

2325
impl CallInput {
2426
/// Returns the length of the call input.
27+
#[inline]
2528
pub fn len(&self) -> usize {
2629
match self {
2730
Self::Bytes(bytes) => bytes.len(),
@@ -30,10 +33,39 @@ impl CallInput {
3033
}
3134

3235
/// Returns `true` if the call input is empty.
36+
#[inline]
3337
pub fn is_empty(&self) -> bool {
3438
self.len() == 0
3539
}
3640

41+
/// Returns the bytes of the call input from the given context.
42+
#[inline]
43+
pub fn as_bytes<'a, CTX: ContextTr>(
44+
&'a self,
45+
ctx: &'a CTX,
46+
) -> impl core::ops::Deref<Target = [u8]> + 'a {
47+
match self {
48+
Self::Bytes(bytes) => CallInputRef::Bytes(bytes.as_ref()),
49+
Self::SharedBuffer(range) => {
50+
CallInputRef::SharedBuffer(ctx.local().shared_memory_buffer_slice(range.clone()))
51+
}
52+
}
53+
}
54+
55+
/// Returns the bytes of the call input from the given memory.
56+
#[inline]
57+
pub fn as_bytes_memory<'a, M: MemoryTr>(
58+
&'a self,
59+
memory: &'a M,
60+
) -> impl core::ops::Deref<Target = [u8]> + 'a {
61+
match self {
62+
Self::Bytes(bytes) => CallInputRef::Bytes(bytes.as_ref()),
63+
Self::SharedBuffer(range) => {
64+
CallInputRef::SharedBuffer(Some(memory.global_slice(range.clone())))
65+
}
66+
}
67+
}
68+
3769
/// Returns the bytes of the call input.
3870
///
3971
/// SharedMemory buffer can be shrunked or overwritten if the child call returns the
@@ -43,10 +75,7 @@ impl CallInput {
4375
///
4476
/// If this `CallInput` is a `SharedBuffer`, the slice will be copied
4577
/// into a fresh `Bytes` buffer, which can pose a performance penalty.
46-
pub fn bytes<CTX>(&self, ctx: &CTX) -> Bytes
47-
where
48-
CTX: ContextTr,
49-
{
78+
pub fn bytes<CTX: ContextTr>(&self, ctx: &CTX) -> Bytes {
5079
match self {
5180
CallInput::Bytes(bytes) => bytes.clone(),
5281
CallInput::SharedBuffer(range) => ctx
@@ -61,7 +90,24 @@ impl CallInput {
6190
impl Default for CallInput {
6291
#[inline]
6392
fn default() -> Self {
64-
CallInput::SharedBuffer(0..0)
93+
CallInput::Bytes(Bytes::new())
94+
}
95+
}
96+
97+
enum CallInputRef<'a> {
98+
Bytes(&'a [u8]),
99+
SharedBuffer(Option<core::cell::Ref<'a, [u8]>>),
100+
}
101+
102+
impl core::ops::Deref for CallInputRef<'_> {
103+
type Target = [u8];
104+
105+
#[inline]
106+
fn deref(&self) -> &Self::Target {
107+
match self {
108+
Self::Bytes(x) => x,
109+
Self::SharedBuffer(x) => x.as_deref().unwrap_or_default(),
110+
}
65111
}
66112
}
67113

crates/op-revm/src/handler.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,7 @@ where
157157

158158
if !cfg.is_fee_charge_disabled() {
159159
let Some(additional_cost) = chain.tx_cost_with_tx(tx, spec) else {
160-
return Err(ERROR::from_string(
161-
"[OPTIMISM] Failed to load enveloped transaction.".into(),
162-
));
160+
return Err(OpTransactionError::MissingEnvelopedTx.into());
163161
};
164162
let Some(new_balance) = balance.checked_sub(additional_cost) else {
165163
return Err(InvalidTransaction::LackOfFundForMaxFee {
@@ -319,9 +317,7 @@ where
319317
let spec = cfg.spec();
320318

321319
let Some(enveloped_tx) = tx.enveloped_tx() else {
322-
return Err(ERROR::from_string(
323-
"[OPTIMISM] Failed to load enveloped transaction.".into(),
324-
));
320+
return Err(OpTransactionError::MissingEnvelopedTx.into());
325321
};
326322

327323
let l1_cost = l1_block_info.calculate_tx_l1_cost(enveloped_tx, spec);

examples/custom_precompile_journal/src/precompile_provider.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,7 @@ fn run_custom_precompile<CTX: ContextTr>(
7979
context: &mut CTX,
8080
inputs: &CallInputs,
8181
) -> Result<InterpreterResult, String> {
82-
let input_bytes = match &inputs.input {
83-
revm::interpreter::CallInput::SharedBuffer(range) => {
84-
if let Some(slice) = context.local().shared_memory_buffer_slice(range.clone()) {
85-
slice.to_vec()
86-
} else {
87-
vec![]
88-
}
89-
}
90-
revm::interpreter::CallInput::Bytes(bytes) => bytes.0.to_vec(),
91-
};
82+
let input_bytes = inputs.input.bytes(context);
9283

9384
// For this example, we'll implement a simple precompile that:
9485
// - If called with empty data: reads a storage value

0 commit comments

Comments
 (0)