Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(Inspector): Add CreateOutcome in create/create_end return #980

Merged
merged 57 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
e35d741
rename main Evm structs, introduce wip external type
rakita Nov 8, 2023
fc03f9b
tests
rakita Nov 8, 2023
90a81f0
Split evm and external context
rakita Nov 16, 2023
fda7f8f
continue previous commit
rakita Nov 16, 2023
99ec673
wip inspector handle register
rakita Nov 21, 2023
ee65aa5
add few more handlers for frame and host
rakita Nov 21, 2023
006a9c2
Add instruction handle
rakita Nov 23, 2023
73f5ebd
add instruction handler registration and Inspector wrap
rakita Nov 24, 2023
42dfcf4
Rm Spec generic, more handlers, start factory
rakita Nov 25, 2023
6252606
move towards the builder, allow EVM modify
rakita Nov 27, 2023
a8eba54
wip on EvmBuilder and modify functionality
rakita Nov 28, 2023
ed188d7
EvmBuilder with stages wip
rakita Nov 29, 2023
85be2c5
Merge remote-tracking branch 'origin/main' into handlers
rakita Nov 29, 2023
64a1bd6
Add wip stages for builer
rakita Nov 29, 2023
45d7209
make handle register simple function, add raw instruction table, spli…
rakita Nov 30, 2023
5ca9580
wip on simple builder functions and handler registry
rakita Dec 1, 2023
aef8257
Examples and cleanup
rakita Dec 1, 2023
bebc79d
fix lifetime and fmt
rakita Dec 1, 2023
580ddf8
Add more handlers, deduct caller, validate tx agains state
rakita Dec 5, 2023
6352f90
All handlers counted, started on docs, some cleanup
rakita Dec 6, 2023
900ff89
renaming and docs
rakita Dec 7, 2023
55f8924
Support all Inspector functionality with Handler
rakita Dec 8, 2023
c930aeb
Handler restructured. Documentation added
rakita Dec 9, 2023
5dc55bd
more docs on registers
rakita Dec 9, 2023
238ea1b
integrate builder, fmt, move optimism l1block
rakita Dec 15, 2023
66b8642
add utility builder stage functions
rakita Dec 15, 2023
697a3e3
add precompiles, fix bugs with journal spec
rakita Dec 18, 2023
9375f35
spec to generic, optimism build
rakita Dec 18, 2023
65997b7
fix optimism test
rakita Dec 18, 2023
bfc5d8b
fuck macros
rakita Dec 26, 2023
8b23136
Merge remote-tracking branch 'origin/main' into handlers
rakita Dec 26, 2023
be3af16
clippy and fmt
rakita Dec 26, 2023
74ae8b0
fix trace block example
rakita Dec 26, 2023
55fc1f7
ci fixes
rakita Dec 26, 2023
b74f7e3
Flatten builder stages to generic and handler stage
rakita Dec 27, 2023
b24c19c
EvmBuilder doc and refactor fn access
rakita Dec 30, 2023
a6feb1a
Merge remote-tracking branch 'origin/main' into handlers
rakita Dec 30, 2023
7024cad
ignore rust code in book
rakita Dec 30, 2023
a704c70
make revme compile, will refactor this in future
rakita Jan 3, 2024
6fdf87a
Rename handles to Pre/Post Execution and ExecutionLoop
rakita Jan 4, 2024
62e9eaa
fix optimism clippy
rakita Jan 4, 2024
c6385be
small rename
rakita Jan 8, 2024
648ba93
FrameData and docs
rakita Jan 9, 2024
055f0f6
check links mdbook
rakita Jan 9, 2024
0b3be0e
comments and cleanup
rakita Jan 10, 2024
8fdcea9
comment
rakita Jan 10, 2024
6cd1414
Merge remote-tracking branch 'origin/main' into handlers
rakita Jan 11, 2024
fa4c712
Add initialize interepreter to first frame
rakita Jan 12, 2024
2133f7f
clippy
rakita Jan 12, 2024
d95dae5
clippy2
rakita Jan 12, 2024
f790587
feat: create outcome
loocapro Jan 15, 2024
e121c02
fix: createOutcome properties to pub and removed wrapper functions
loocapro Jan 15, 2024
c060651
review: fixed some review comments and added some improvement over in…
loocapro Jan 15, 2024
154d88f
fix: removed unused is_revert method
loocapro Jan 15, 2024
a6ad99a
review: adjusted comments, moved create_outcome to its own file
loocapro Jan 16, 2024
1b94b98
syncing main
loocapro Jan 17, 2024
1fe5e5b
fix: no std check
loocapro Jan 17, 2024
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
68 changes: 68 additions & 0 deletions crates/interpreter/src/create_outcome.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use crate::{Gas, InstructionResult, InterpreterResult};
use revm_primitives::{Address, Bytes};

/// Represents the outcome of a create operation in an interpreter.
///
/// This struct holds the result of the operation along with an optional address.
/// It provides methods to determine the next action based on the result of the operation.
pub struct CreateOutcome {
// The result of the interpreter operation.
pub result: InterpreterResult,
// An optional address associated with the create operation.
pub address: Option<Address>,
}

impl CreateOutcome {
/// Constructs a new `CreateOutcome`.
///
/// # Arguments
///
/// * `result` - An `InterpreterResult` representing the result of the interpreter operation.
/// * `address` - An optional `Address` associated with the create operation.
///
/// # Returns
///
/// A new `CreateOutcome` instance.
pub fn new(result: InterpreterResult, address: Option<Address>) -> Self {
Self { result, address }
}

/// Retrieves a reference to the `InstructionResult` from the `InterpreterResult`.
///
/// This method provides access to the `InstructionResult` which represents the
/// outcome of the instruction execution. It encapsulates the result information
/// such as whether the instruction was executed successfully, resulted in a revert,
/// or encountered a fatal error.
///
/// # Returns
///
/// A reference to the `InstructionResult`.
pub fn instruction_result(&self) -> &InstructionResult {
&self.result.result
}

/// Retrieves a reference to the output bytes from the `InterpreterResult`.
///
/// This method returns the output of the interpreted operation. The output is
/// typically used when the operation successfully completes and returns data.
///
/// # Returns
///
/// A reference to the output `Bytes`.
pub fn output(&self) -> &Bytes {
&self.result.output
}

/// Retrieves a reference to the `Gas` details from the `InterpreterResult`.
///
/// This method provides access to the gas details of the operation, which includes
/// information about gas used, remaining, and refunded. It is essential for
/// understanding the gas consumption of the operation.
///
/// # Returns
///
/// A reference to the `Gas` details.
pub fn gas(&self) -> &Gas {
&self.result.gas
}
}
53 changes: 41 additions & 12 deletions crates/interpreter/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ pub use contract::Contract;
pub use shared_memory::{next_multiple_of_32, SharedMemory};
pub use stack::{Stack, STACK_LIMIT};

use crate::alloc::borrow::ToOwned;
use crate::{
primitives::Bytes, push, push_b256, return_ok, return_revert, CallInputs, CreateInputs, Gas,
Host, InstructionResult,
primitives::Bytes, push, push_b256, return_ok, return_revert, CallInputs, CreateInputs,
CreateOutcome, Gas, Host, InstructionResult,
};
use alloc::boxed::Box;
use core::cmp::min;
use core::ops::Range;
use revm_primitives::{Address, U256};
use revm_primitives::U256;

pub use self::shared_memory::EMPTY_SHARED_MEMORY;

Expand Down Expand Up @@ -93,24 +94,52 @@ impl Interpreter {
}
}

/// When sub create call returns we can insert output of that call into this interpreter.
pub fn insert_create_output(&mut self, result: InterpreterResult, address: Option<Address>) {
self.return_data_buffer = match result.result {
/// Inserts the output of a `create` call into the interpreter.
///
/// This function is used after a `create` call has been executed. It processes the outcome
/// of that call and updates the state of the interpreter accordingly.
///
/// # Arguments
///
/// * `create_outcome` - A `CreateOutcome` struct containing the results of the `create` call.
///
/// # Behavior
///
/// The function updates the `return_data_buffer` with the data from `create_outcome`.
/// Depending on the `InstructionResult` indicated by `create_outcome`, it performs one of the following:
///
/// - `Ok`: Pushes the address from `create_outcome` to the stack, updates gas costs, and records any gas refunds.
/// - `Revert`: Pushes `U256::ZERO` to the stack and updates gas costs.
/// - `FatalExternalError`: Sets the `instruction_result` to `InstructionResult::FatalExternalError`.
/// - `Default`: Pushes `U256::ZERO` to the stack.
///
/// # Side Effects
///
/// - Updates `return_data_buffer` with the data from `create_outcome`.
/// - Modifies the stack by pushing values depending on the `InstructionResult`.
/// - Updates gas costs and records refunds in the interpreter's `gas` field.
/// - May alter `instruction_result` in case of external errors.
pub fn insert_create_outcome(&mut self, create_outcome: CreateOutcome) {
let instruction_result = create_outcome.instruction_result();

self.return_data_buffer = if instruction_result.is_revert() {
// Save data to return data buffer if the create reverted
return_revert!() => result.output,
create_outcome.output().to_owned()
} else {
// Otherwise clear it
_ => Bytes::new(),
Bytes::new()
};

match result.result {
match instruction_result {
return_ok!() => {
let address = create_outcome.address;
push_b256!(self, address.unwrap_or_default().into_word());
self.gas.erase_cost(result.gas.remaining());
self.gas.record_refund(result.gas.refunded());
self.gas.erase_cost(create_outcome.gas().remaining());
self.gas.record_refund(create_outcome.gas().refunded());
}
return_revert!() => {
push!(self, U256::ZERO);
self.gas.erase_cost(result.gas.remaining());
self.gas.erase_cost(create_outcome.gas().remaining());
}
InstructionResult::FatalExternalError => {
self.instruction_result = InstructionResult::FatalExternalError;
Expand Down
2 changes: 2 additions & 0 deletions crates/interpreter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extern crate alloc;
#[macro_use]
mod macros;

mod create_outcome;
pub mod gas;
mod host;
mod inner_models;
Expand All @@ -20,6 +21,7 @@ pub mod instructions;
mod interpreter;

// Reexport primary types.
pub use create_outcome::CreateOutcome;
pub use gas::Gas;
pub use host::{DummyHost, Host};
pub use inner_models::*;
Expand Down
8 changes: 5 additions & 3 deletions crates/revm/src/handler/mainnet/execution_loop.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
db::Database,
interpreter::{
return_ok, return_revert, CallInputs, CreateInputs, Gas, InstructionResult,
return_ok, return_revert, CallInputs, CreateInputs, CreateOutcome, Gas, InstructionResult,
InterpreterResult, SharedMemory,
},
primitives::{Env, Spec, TransactTo},
Expand Down Expand Up @@ -92,9 +92,10 @@ pub fn frame_return<SPEC: Spec, EXT, DB: Database>(
let Some(parent_stack_frame) = parent_stack_frame else {
return Some(result);
};
let create_outcome = CreateOutcome::new(result, Some(created_address));
parent_stack_frame
.interpreter
.insert_create_output(result, Some(created_address))
.insert_create_outcome(create_outcome)
}
FrameData::Call {
return_memory_range,
Expand Down Expand Up @@ -151,10 +152,11 @@ pub fn sub_create<SPEC: Spec, EXT, DB: Database>(
match context.evm.make_create_frame(SPEC::SPEC_ID, &inputs) {
FrameOrResult::Frame(new_frame) => Some(new_frame),
FrameOrResult::Result(result) => {
let create_outcome = CreateOutcome::new(result, None);
// insert result of the failed creation of create CallStackFrame.
curent_stack_frame
.interpreter
.insert_create_output(result, None);
.insert_create_outcome(create_outcome);
None
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/revm/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ mod noop;
// Exports.

pub use handler_register::{inspector_handle_register, inspector_instruction, GetInspector};
use revm_interpreter::InterpreterResult;
use revm_interpreter::{CreateOutcome, InterpreterResult};
/// [Inspector] implementations.
pub mod inspectors {
#[cfg(feature = "std")]
Expand Down Expand Up @@ -109,7 +109,7 @@ pub trait Inspector<DB: Database> {
&mut self,
context: &mut EvmContext<DB>,
inputs: &mut CreateInputs,
) -> Option<(InterpreterResult, Option<Address>)> {
) -> Option<CreateOutcome> {
let _ = context;
let _ = inputs;
None
Expand All @@ -125,9 +125,9 @@ pub trait Inspector<DB: Database> {
context: &mut EvmContext<DB>,
result: InterpreterResult,
address: Option<Address>,
) -> (InterpreterResult, Option<Address>) {
) -> CreateOutcome {
let _ = context;
(result, address)
CreateOutcome::new(result, address)
}

/// Called when a contract has been self-destructed with funds transferred to target.
Expand Down
5 changes: 3 additions & 2 deletions crates/revm/src/inspector/customprinter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! It is a great tool if some debugging is needed.

use core::ops::Range;
use revm_interpreter::CreateOutcome;

use crate::{
inspectors::GasInspector,
Expand Down Expand Up @@ -73,7 +74,7 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {
context: &mut EvmContext<DB>,
result: InterpreterResult,
address: Option<Address>,
) -> (InterpreterResult, Option<Address>) {
) -> CreateOutcome {
self.gas_inspector.create_end(context, result, address)
}

Expand All @@ -97,7 +98,7 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {
&mut self,
_context: &mut EvmContext<DB>,
inputs: &mut CreateInputs,
) -> Option<(InterpreterResult, Option<Address>)> {
) -> Option<CreateOutcome> {
println!(
"CREATE CALL: caller:{:?}, scheme:{:?}, value:{:?}, init_code:{:?}, gas:{:?}",
inputs.caller, inputs.scheme, inputs.value, inputs.init_code, inputs.gas_limit
Expand Down
5 changes: 3 additions & 2 deletions crates/revm/src/inspector/eip3155.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{
EvmContext, GetInspector, Inspector,
};
use core::ops::Range;
use revm_interpreter::CreateOutcome;
use serde_json::json;
use std::io::Write;

Expand Down Expand Up @@ -118,7 +119,7 @@ impl<DB: Database> Inspector<DB> for TracerEip3155 {
&mut self,
_context: &mut EvmContext<DB>,
_inputs: &mut CreateInputs,
) -> Option<(InterpreterResult, Option<Address>)> {
) -> Option<CreateOutcome> {
None
}

Expand All @@ -127,7 +128,7 @@ impl<DB: Database> Inspector<DB> for TracerEip3155 {
context: &mut EvmContext<DB>,
result: InterpreterResult,
address: Option<Address>,
) -> (InterpreterResult, Option<Address>) {
) -> CreateOutcome {
self.gas_inspector.create_end(context, result, address)
}
}
Expand Down
12 changes: 8 additions & 4 deletions crates/revm/src/inspector/gas.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! GasIspector. Helper Inspector to calculate gas for others.

use revm_interpreter::CreateOutcome;

use crate::{
interpreter::InterpreterResult,
primitives::{db::Database, Address},
Expand Down Expand Up @@ -59,13 +61,15 @@ impl<DB: Database> Inspector<DB> for GasInspector {
_context: &mut EvmContext<DB>,
result: InterpreterResult,
address: Option<Address>,
) -> (InterpreterResult, Option<Address>) {
(result, address)
) -> CreateOutcome {
CreateOutcome::new(result, address)
}
}

#[cfg(test)]
mod tests {
use revm_interpreter::CreateOutcome;

use crate::{
inspector::GetInspector,
inspectors::GasInspector,
Expand Down Expand Up @@ -128,7 +132,7 @@ mod tests {
&mut self,
context: &mut EvmContext<DB>,
call: &mut CreateInputs,
) -> Option<(InterpreterResult, Option<Address>)> {
) -> Option<CreateOutcome> {
self.gas_inspector.create(context, call);
None
}
Expand All @@ -138,7 +142,7 @@ mod tests {
context: &mut EvmContext<DB>,
result: InterpreterResult,
address: Option<Address>,
) -> (InterpreterResult, Option<Address>) {
) -> CreateOutcome {
self.gas_inspector.create_end(context, result, address)
}
}
Expand Down
Loading
Loading