Skip to content

Commit

Permalink
feat: expose precompile address in Journal, DB::Error: StdError (blue…
Browse files Browse the repository at this point in the history
…alloy#1956)

* chore: relax some impl and exec_with_tx

* add helper created_address

* add error to database error

* ext journal with state

* fix: handle inspector final return

* call final_return

* expose precompile addresses to Journal

* precompile addresses fn for journal
  • Loading branch information
rakita authored Dec 26, 2024
1 parent d634f31 commit 7d060e1
Show file tree
Hide file tree
Showing 20 changed files with 127 additions and 32 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions crates/context/interface/src/journaled_state.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::ops::{Deref, DerefMut};
use database_interface::{Database, DatabaseGetter};
use primitives::{Address, Log, B256, U256};
use primitives::{Address, HashSet, Log, B256, U256};
use specification::hardfork::SpecId;
use state::{Account, Bytecode};
use std::boxed::Box;
Expand All @@ -17,10 +17,10 @@ pub trait Journal {
fn new(database: Self::Database) -> Self;

/// Returns the database.
fn db(&self) -> &Self::Database;
fn db_ref(&self) -> &Self::Database;

/// Returns the mutable database.
fn db_mut(&mut self) -> &mut Self::Database;
fn db(&mut self) -> &mut Self::Database;

/// Returns the storage value from Journal state.
///
Expand Down Expand Up @@ -63,6 +63,10 @@ pub trait Journal {

fn warm_account(&mut self, address: Address);

fn warm_precompiles(&mut self, addresses: HashSet<Address>);

fn precompile_addresses(&self) -> &HashSet<Address>;

fn set_spec_id(&mut self, spec_id: SpecId);

fn touch_account(&mut self, address: Address);
Expand Down
13 changes: 11 additions & 2 deletions crates/context/interface/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ impl<HaltReasonT: HaltReasonTrait> ExecutionResult<HaltReasonT> {
matches!(self, Self::Success { .. })
}

/// Returns created address if execution is Create transaction
/// and Contract was created.
pub fn created_address(&self) -> Option<Address> {
match self {
Self::Success { output, .. } => output.address().cloned(),
_ => None,
}
}

/// Returns true if execution result is a Halt.
pub fn is_halt(&self) -> bool {
matches!(self, Self::Halt { .. })
Expand Down Expand Up @@ -175,9 +184,9 @@ impl<DB, TX> FromStringError for EVMError<DB, TX> {
}
}

impl<DB, TXERROR: From<InvalidTransaction>> From<InvalidTransaction> for EVMError<DB, TXERROR> {
impl<DB> From<InvalidTransaction> for EVMError<DB, InvalidTransaction> {
fn from(value: InvalidTransaction) -> Self {
Self::Transaction(value.into())
Self::Transaction(value)
}
}

Expand Down
10 changes: 7 additions & 3 deletions crates/context/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ where
where
F: FnOnce(&mut DB),
{
f(self.journaled_state.db_mut());
f(self.journaled_state.db());
}

pub fn modify_journal<F>(&mut self, f: F)
Expand Down Expand Up @@ -395,7 +395,7 @@ where
if diff <= BLOCK_HASH_HISTORY {
return self
.journaled_state
.db_mut()
.db()
.block_hash(requested_number)
.map_err(|e| self.error = Err(e))
.ok();
Expand Down Expand Up @@ -508,7 +508,11 @@ where
type Database = DB;

fn db(&mut self) -> &mut Self::Database {
self.journaled_state.db_mut()
self.journaled_state.db()
}

fn db_ref(&self) -> &Self::Database {
self.journaled_state.db_ref()
}
}

Expand Down
19 changes: 17 additions & 2 deletions crates/context/src/journaled_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pub struct JournaledState<DB> {
/// Note that this not include newly loaded accounts, account and storage
/// is considered warm if it is found in the `State`.
pub warm_preloaded_addresses: HashSet<Address>,
/// Precompile addresses
pub precompiles: HashSet<Address>,
}

impl<DB: Database> Journal for JournaledState<DB> {
Expand All @@ -63,11 +65,11 @@ impl<DB: Database> Journal for JournaledState<DB> {
Self::new(SpecId::LATEST, database)
}

fn db(&self) -> &Self::Database {
fn db_ref(&self) -> &Self::Database {
&self.database
}

fn db_mut(&mut self) -> &mut Self::Database {
fn db(&mut self) -> &mut Self::Database {
&mut self.database
}

Expand Down Expand Up @@ -112,6 +114,17 @@ impl<DB: Database> Journal for JournaledState<DB> {
self.warm_preloaded_addresses.insert(address);
}

fn warm_precompiles(&mut self, address: HashSet<Address>) {
self.precompiles = address;
self.warm_preloaded_addresses
.extend(self.precompiles.iter());
}

#[inline]
fn precompile_addresses(&self) -> &HashSet<Address> {
&self.precompiles
}

/// Returns call depth.
#[inline]
fn depth(&self) -> usize {
Expand Down Expand Up @@ -212,6 +225,7 @@ impl<DB: Database> Journal for JournaledState<DB> {
spec: _,
database: _,
warm_preloaded_addresses: _,
precompiles: _,
} = self;

*transient_storage = TransientStorage::default();
Expand Down Expand Up @@ -243,6 +257,7 @@ impl<DB: Database> JournaledState<DB> {
depth: 0,
spec,
warm_preloaded_addresses: HashSet::default(),
precompiles: HashSet::default(),
}
}

Expand Down
8 changes: 4 additions & 4 deletions crates/database/interface/src/async_db.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
use core::future::Future;

use crate::{DBErrorMarker, Database, DatabaseRef};
use core::error::Error;
use primitives::{Address, B256, U256};
use state::{AccountInfo, Bytecode};
use tokio::runtime::{Handle, Runtime};

use crate::{DBErrorMarker, Database, DatabaseRef};

/// The async EVM database interface
///
/// Contains the same methods as [Database], but it returns [Future] type instead.
///
/// Use [WrapDatabaseAsync] to provide [Database] implementation for a type that only implements this trait.
pub trait DatabaseAsync {
/// The database error type
type Error: Send + DBErrorMarker;
type Error: Send + DBErrorMarker + Error;

/// Gets basic account information.
fn basic_async(
Expand Down Expand Up @@ -48,7 +48,7 @@ pub trait DatabaseAsync {
/// Use [WrapDatabaseAsync] to provide [DatabaseRef] implementation for a type that only implements this trait.
pub trait DatabaseAsyncRef {
/// The database error type
type Error: Send + DBErrorMarker;
type Error: Send + DBErrorMarker + Error;

/// Gets basic account information.
fn basic_async_ref(
Expand Down
5 changes: 3 additions & 2 deletions crates/database/interface/src/empty_db.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{DBErrorMarker, Database, DatabaseRef};
use core::error::Error;
use core::{convert::Infallible, fmt, marker::PhantomData};
use primitives::{keccak256, Address, B256, U256};
use state::{AccountInfo, Bytecode};
Expand Down Expand Up @@ -52,7 +53,7 @@ impl<E> EmptyDBTyped<E> {
}
}

impl<E: DBErrorMarker> Database for EmptyDBTyped<E> {
impl<E: DBErrorMarker + Error> Database for EmptyDBTyped<E> {
type Error = E;

#[inline]
Expand All @@ -76,7 +77,7 @@ impl<E: DBErrorMarker> Database for EmptyDBTyped<E> {
}
}

impl<E: DBErrorMarker> DatabaseRef for EmptyDBTyped<E> {
impl<E: DBErrorMarker + Error> DatabaseRef for EmptyDBTyped<E> {
type Error = E;

#[inline]
Expand Down
7 changes: 5 additions & 2 deletions crates/database/interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ extern crate alloc as std;
use core::convert::Infallible;

use auto_impl::auto_impl;
use core::error::Error;
use primitives::{Address, HashMap, B256, U256};
use state::{Account, AccountInfo, Bytecode};
use std::string::String;
Expand Down Expand Up @@ -35,7 +36,7 @@ impl DBErrorMarker for String {}
#[auto_impl(&mut, Box)]
pub trait Database {
/// The database error type.
type Error: DBErrorMarker;
type Error: DBErrorMarker + Error;
//type Bytecode: BytecodeTrait;

/// Gets basic account information.
Expand Down Expand Up @@ -67,7 +68,7 @@ pub trait DatabaseCommit {
#[auto_impl(&, &mut, Box, Rc, Arc)]
pub trait DatabaseRef {
/// The database error type.
type Error: DBErrorMarker;
type Error: DBErrorMarker + Error;

/// Gets basic account information.
fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error>;
Expand Down Expand Up @@ -129,4 +130,6 @@ pub trait DatabaseGetter {
type Database: Database;

fn db(&mut self) -> &mut Self::Database;

fn db_ref(&self) -> &Self::Database;
}
10 changes: 10 additions & 0 deletions crates/database/src/alloydb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,25 @@ use alloy_provider::{
Network, Provider,
};
use alloy_transport::{Transport, TransportError};
use core::error::Error;
use database_interface::{async_db::DatabaseAsyncRef, DBErrorMarker};
use primitives::{Address, B256, U256};
use state::{AccountInfo, Bytecode};
use std::fmt::Display;

#[derive(Debug)]
pub struct DBTransportError(pub TransportError);

impl DBErrorMarker for DBTransportError {}

impl Display for DBTransportError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Transport error: {}", self.0)
}
}

impl Error for DBTransportError {}

impl From<TransportError> for DBTransportError {
fn from(e: TransportError) -> Self {
Self(e)
Expand Down
2 changes: 1 addition & 1 deletion crates/database/src/states/state_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<DB: Database> StateBuilder<DB> {
}

/// With boxed version of database.
pub fn with_database_boxed<Error: DBErrorMarker>(
pub fn with_database_boxed<Error: DBErrorMarker + core::error::Error>(
self,
database: DBBox<'_, Error>,
) -> StateBuilder<DBBox<'_, Error>> {
Expand Down
3 changes: 2 additions & 1 deletion crates/handler/interface/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub trait ExecutionHandler {
let frame = frame_stack.last_mut().unwrap();
let call_or_result = frame.run(context)?;

let result = match call_or_result {
let mut result = match call_or_result {
FrameOrResultGen::Frame(init) => match frame.init(context, init)? {
FrameOrResultGen::Frame(new_frame) => {
frame_stack.push(new_frame);
Expand All @@ -49,6 +49,7 @@ pub trait ExecutionHandler {
};

let Some(frame) = frame_stack.last_mut() else {
Self::Frame::final_return(context, &mut result)?;
return self.last_frame_result(context, result);
};
frame.return_result(context, result)?;
Expand Down
5 changes: 5 additions & 0 deletions crates/handler/interface/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ pub trait Frame: Sized {
frame_input: Self::FrameInit,
) -> Result<FrameOrResultGen<Self, Self::FrameResult>, Self::Error>;

fn final_return(
context: &mut Self::Context,
result: &mut Self::FrameResult,
) -> Result<(), Self::Error>;

fn init(
&self,
context: &mut Self::Context,
Expand Down
7 changes: 7 additions & 0 deletions crates/handler/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,13 @@ where
Self::init_with_context(0, frame_input, memory, precompiles, instructions, context)
}

fn final_return(
_context: &mut Self::Context,
_result: &mut Self::FrameResult,
) -> Result<(), Self::Error> {
Ok(())
}

fn init(
&self,
context: &mut CTX,
Expand Down
29 changes: 25 additions & 4 deletions crates/inspector/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use revm::{
},
precompile::PrecompileErrors,
primitives::{Address, Bytes, Log, B256, U256},
state::EvmState,
Context, Error, Evm, JournalEntry,
};
use std::{rc::Rc, vec::Vec};
Expand Down Expand Up @@ -396,6 +397,10 @@ where
fn db(&mut self) -> &mut Self::Database {
self.inner.db()
}

fn db_ref(&self) -> &Self::Database {
self.inner.db_ref()
}
}

impl<INSP, DB, CTX> ErrorGetter for InspectorContext<INSP, DB, CTX>
Expand Down Expand Up @@ -527,6 +532,10 @@ pub trait JournalExt {
fn logs(&self) -> &[Log];

fn last_journal(&self) -> &[JournalEntry];

fn evm_state(&self) -> &EvmState;

fn evm_state_mut(&mut self) -> &mut EvmState;
}

impl<DB: Database> JournalExt for JournaledState<DB> {
Expand All @@ -537,6 +546,14 @@ impl<DB: Database> JournalExt for JournaledState<DB> {
fn last_journal(&self) -> &[JournalEntry] {
self.journal.last().expect("Journal is never empty")
}

fn evm_state(&self) -> &EvmState {
&self.state
}

fn evm_state_mut(&mut self) -> &mut EvmState {
&mut self.state
}
}

#[auto_impl(&, &mut, Box, Arc)]
Expand Down Expand Up @@ -699,10 +716,17 @@ where
}
_ => (),
}

ret
}

fn final_return(
context: &mut Self::Context,
result: &mut Self::FrameResult,
) -> Result<(), Self::Error> {
context.frame_end(result);
Ok(())
}

fn init(
&self,
context: &mut CTX,
Expand All @@ -719,9 +743,6 @@ where
if let Ok(FrameOrResultGen::Frame(frame)) = &mut ret {
context.initialize_interp(&mut frame.eth_frame.interpreter);
}

// TODO : Handle last frame_end. MAKE a separate function for `last_return_result`.

ret
}

Expand Down
Loading

0 comments on commit 7d060e1

Please sign in to comment.