Skip to content

Commit 7d060e1

Browse files
authored
feat: expose precompile address in Journal, DB::Error: StdError (#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
1 parent d634f31 commit 7d060e1

File tree

20 files changed

+127
-32
lines changed

20 files changed

+127
-32
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/context/interface/src/journaled_state.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use core::ops::{Deref, DerefMut};
22
use database_interface::{Database, DatabaseGetter};
3-
use primitives::{Address, Log, B256, U256};
3+
use primitives::{Address, HashSet, Log, B256, U256};
44
use specification::hardfork::SpecId;
55
use state::{Account, Bytecode};
66
use std::boxed::Box;
@@ -17,10 +17,10 @@ pub trait Journal {
1717
fn new(database: Self::Database) -> Self;
1818

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

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

2525
/// Returns the storage value from Journal state.
2626
///
@@ -63,6 +63,10 @@ pub trait Journal {
6363

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

66+
fn warm_precompiles(&mut self, addresses: HashSet<Address>);
67+
68+
fn precompile_addresses(&self) -> &HashSet<Address>;
69+
6670
fn set_spec_id(&mut self, spec_id: SpecId);
6771

6872
fn touch_account(&mut self, address: Address);

crates/context/interface/src/result.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ impl<HaltReasonT: HaltReasonTrait> ExecutionResult<HaltReasonT> {
5454
matches!(self, Self::Success { .. })
5555
}
5656

57+
/// Returns created address if execution is Create transaction
58+
/// and Contract was created.
59+
pub fn created_address(&self) -> Option<Address> {
60+
match self {
61+
Self::Success { output, .. } => output.address().cloned(),
62+
_ => None,
63+
}
64+
}
65+
5766
/// Returns true if execution result is a Halt.
5867
pub fn is_halt(&self) -> bool {
5968
matches!(self, Self::Halt { .. })
@@ -175,9 +184,9 @@ impl<DB, TX> FromStringError for EVMError<DB, TX> {
175184
}
176185
}
177186

178-
impl<DB, TXERROR: From<InvalidTransaction>> From<InvalidTransaction> for EVMError<DB, TXERROR> {
187+
impl<DB> From<InvalidTransaction> for EVMError<DB, InvalidTransaction> {
179188
fn from(value: InvalidTransaction) -> Self {
180-
Self::Transaction(value.into())
189+
Self::Transaction(value)
181190
}
182191
}
183192

crates/context/src/context.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ where
313313
where
314314
F: FnOnce(&mut DB),
315315
{
316-
f(self.journaled_state.db_mut());
316+
f(self.journaled_state.db());
317317
}
318318

319319
pub fn modify_journal<F>(&mut self, f: F)
@@ -395,7 +395,7 @@ where
395395
if diff <= BLOCK_HASH_HISTORY {
396396
return self
397397
.journaled_state
398-
.db_mut()
398+
.db()
399399
.block_hash(requested_number)
400400
.map_err(|e| self.error = Err(e))
401401
.ok();
@@ -508,7 +508,11 @@ where
508508
type Database = DB;
509509

510510
fn db(&mut self) -> &mut Self::Database {
511-
self.journaled_state.db_mut()
511+
self.journaled_state.db()
512+
}
513+
514+
fn db_ref(&self) -> &Self::Database {
515+
self.journaled_state.db_ref()
512516
}
513517
}
514518

crates/context/src/journaled_state.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ pub struct JournaledState<DB> {
5252
/// Note that this not include newly loaded accounts, account and storage
5353
/// is considered warm if it is found in the `State`.
5454
pub warm_preloaded_addresses: HashSet<Address>,
55+
/// Precompile addresses
56+
pub precompiles: HashSet<Address>,
5557
}
5658

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

66-
fn db(&self) -> &Self::Database {
68+
fn db_ref(&self) -> &Self::Database {
6769
&self.database
6870
}
6971

70-
fn db_mut(&mut self) -> &mut Self::Database {
72+
fn db(&mut self) -> &mut Self::Database {
7173
&mut self.database
7274
}
7375

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

117+
fn warm_precompiles(&mut self, address: HashSet<Address>) {
118+
self.precompiles = address;
119+
self.warm_preloaded_addresses
120+
.extend(self.precompiles.iter());
121+
}
122+
123+
#[inline]
124+
fn precompile_addresses(&self) -> &HashSet<Address> {
125+
&self.precompiles
126+
}
127+
115128
/// Returns call depth.
116129
#[inline]
117130
fn depth(&self) -> usize {
@@ -212,6 +225,7 @@ impl<DB: Database> Journal for JournaledState<DB> {
212225
spec: _,
213226
database: _,
214227
warm_preloaded_addresses: _,
228+
precompiles: _,
215229
} = self;
216230

217231
*transient_storage = TransientStorage::default();
@@ -243,6 +257,7 @@ impl<DB: Database> JournaledState<DB> {
243257
depth: 0,
244258
spec,
245259
warm_preloaded_addresses: HashSet::default(),
260+
precompiles: HashSet::default(),
246261
}
247262
}
248263

crates/database/interface/src/async_db.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
use core::future::Future;
22

3+
use crate::{DBErrorMarker, Database, DatabaseRef};
4+
use core::error::Error;
35
use primitives::{Address, B256, U256};
46
use state::{AccountInfo, Bytecode};
57
use tokio::runtime::{Handle, Runtime};
68

7-
use crate::{DBErrorMarker, Database, DatabaseRef};
8-
99
/// The async EVM database interface
1010
///
1111
/// Contains the same methods as [Database], but it returns [Future] type instead.
1212
///
1313
/// Use [WrapDatabaseAsync] to provide [Database] implementation for a type that only implements this trait.
1414
pub trait DatabaseAsync {
1515
/// The database error type
16-
type Error: Send + DBErrorMarker;
16+
type Error: Send + DBErrorMarker + Error;
1717

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

5353
/// Gets basic account information.
5454
fn basic_async_ref(

crates/database/interface/src/empty_db.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::{DBErrorMarker, Database, DatabaseRef};
2+
use core::error::Error;
23
use core::{convert::Infallible, fmt, marker::PhantomData};
34
use primitives::{keccak256, Address, B256, U256};
45
use state::{AccountInfo, Bytecode};
@@ -52,7 +53,7 @@ impl<E> EmptyDBTyped<E> {
5253
}
5354
}
5455

55-
impl<E: DBErrorMarker> Database for EmptyDBTyped<E> {
56+
impl<E: DBErrorMarker + Error> Database for EmptyDBTyped<E> {
5657
type Error = E;
5758

5859
#[inline]
@@ -76,7 +77,7 @@ impl<E: DBErrorMarker> Database for EmptyDBTyped<E> {
7677
}
7778
}
7879

79-
impl<E: DBErrorMarker> DatabaseRef for EmptyDBTyped<E> {
80+
impl<E: DBErrorMarker + Error> DatabaseRef for EmptyDBTyped<E> {
8081
type Error = E;
8182

8283
#[inline]

crates/database/interface/src/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern crate alloc as std;
88
use core::convert::Infallible;
99

1010
use auto_impl::auto_impl;
11+
use core::error::Error;
1112
use primitives::{Address, HashMap, B256, U256};
1213
use state::{Account, AccountInfo, Bytecode};
1314
use std::string::String;
@@ -35,7 +36,7 @@ impl DBErrorMarker for String {}
3536
#[auto_impl(&mut, Box)]
3637
pub trait Database {
3738
/// The database error type.
38-
type Error: DBErrorMarker;
39+
type Error: DBErrorMarker + Error;
3940
//type Bytecode: BytecodeTrait;
4041

4142
/// Gets basic account information.
@@ -67,7 +68,7 @@ pub trait DatabaseCommit {
6768
#[auto_impl(&, &mut, Box, Rc, Arc)]
6869
pub trait DatabaseRef {
6970
/// The database error type.
70-
type Error: DBErrorMarker;
71+
type Error: DBErrorMarker + Error;
7172

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

131132
fn db(&mut self) -> &mut Self::Database;
133+
134+
fn db_ref(&self) -> &Self::Database;
132135
}

crates/database/src/alloydb.rs

+10
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,25 @@ use alloy_provider::{
77
Network, Provider,
88
};
99
use alloy_transport::{Transport, TransportError};
10+
use core::error::Error;
1011
use database_interface::{async_db::DatabaseAsyncRef, DBErrorMarker};
1112
use primitives::{Address, B256, U256};
1213
use state::{AccountInfo, Bytecode};
14+
use std::fmt::Display;
1315

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

1719
impl DBErrorMarker for DBTransportError {}
1820

21+
impl Display for DBTransportError {
22+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
23+
write!(f, "Transport error: {}", self.0)
24+
}
25+
}
26+
27+
impl Error for DBTransportError {}
28+
1929
impl From<TransportError> for DBTransportError {
2030
fn from(e: TransportError) -> Self {
2131
Self(e)

crates/database/src/states/state_builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl<DB: Database> StateBuilder<DB> {
8585
}
8686

8787
/// With boxed version of database.
88-
pub fn with_database_boxed<Error: DBErrorMarker>(
88+
pub fn with_database_boxed<Error: DBErrorMarker + core::error::Error>(
8989
self,
9090
database: DBBox<'_, Error>,
9191
) -> StateBuilder<DBBox<'_, Error>> {

crates/handler/interface/src/execution.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub trait ExecutionHandler {
3232
let frame = frame_stack.last_mut().unwrap();
3333
let call_or_result = frame.run(context)?;
3434

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

5151
let Some(frame) = frame_stack.last_mut() else {
52+
Self::Frame::final_return(context, &mut result)?;
5253
return self.last_frame_result(context, result);
5354
};
5455
frame.return_result(context, result)?;

crates/handler/interface/src/frame.rs

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ pub trait Frame: Sized {
1212
frame_input: Self::FrameInit,
1313
) -> Result<FrameOrResultGen<Self, Self::FrameResult>, Self::Error>;
1414

15+
fn final_return(
16+
context: &mut Self::Context,
17+
result: &mut Self::FrameResult,
18+
) -> Result<(), Self::Error>;
19+
1520
fn init(
1621
&self,
1722
context: &mut Self::Context,

crates/handler/src/frame.rs

+7
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,13 @@ where
483483
Self::init_with_context(0, frame_input, memory, precompiles, instructions, context)
484484
}
485485

486+
fn final_return(
487+
_context: &mut Self::Context,
488+
_result: &mut Self::FrameResult,
489+
) -> Result<(), Self::Error> {
490+
Ok(())
491+
}
492+
486493
fn init(
487494
&self,
488495
context: &mut CTX,

crates/inspector/src/inspector.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use revm::{
2727
},
2828
precompile::PrecompileErrors,
2929
primitives::{Address, Bytes, Log, B256, U256},
30+
state::EvmState,
3031
Context, Error, Evm, JournalEntry,
3132
};
3233
use std::{rc::Rc, vec::Vec};
@@ -396,6 +397,10 @@ where
396397
fn db(&mut self) -> &mut Self::Database {
397398
self.inner.db()
398399
}
400+
401+
fn db_ref(&self) -> &Self::Database {
402+
self.inner.db_ref()
403+
}
399404
}
400405

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

529534
fn last_journal(&self) -> &[JournalEntry];
535+
536+
fn evm_state(&self) -> &EvmState;
537+
538+
fn evm_state_mut(&mut self) -> &mut EvmState;
530539
}
531540

532541
impl<DB: Database> JournalExt for JournaledState<DB> {
@@ -537,6 +546,14 @@ impl<DB: Database> JournalExt for JournaledState<DB> {
537546
fn last_journal(&self) -> &[JournalEntry] {
538547
self.journal.last().expect("Journal is never empty")
539548
}
549+
550+
fn evm_state(&self) -> &EvmState {
551+
&self.state
552+
}
553+
554+
fn evm_state_mut(&mut self) -> &mut EvmState {
555+
&mut self.state
556+
}
540557
}
541558

542559
#[auto_impl(&, &mut, Box, Arc)]
@@ -699,10 +716,17 @@ where
699716
}
700717
_ => (),
701718
}
702-
703719
ret
704720
}
705721

722+
fn final_return(
723+
context: &mut Self::Context,
724+
result: &mut Self::FrameResult,
725+
) -> Result<(), Self::Error> {
726+
context.frame_end(result);
727+
Ok(())
728+
}
729+
706730
fn init(
707731
&self,
708732
context: &mut CTX,
@@ -719,9 +743,6 @@ where
719743
if let Ok(FrameOrResultGen::Frame(frame)) = &mut ret {
720744
context.initialize_interp(&mut frame.eth_frame.interpreter);
721745
}
722-
723-
// TODO : Handle last frame_end. MAKE a separate function for `last_return_result`.
724-
725746
ret
726747
}
727748

0 commit comments

Comments
 (0)