mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 19:09:54 +00:00
feat: add revm-inspectors crate and accesslist inspector (#1529)
This commit is contained in:
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -4851,6 +4851,24 @@ dependencies = [
|
|||||||
"reth-interfaces",
|
"reth-interfaces",
|
||||||
"reth-primitives",
|
"reth-primitives",
|
||||||
"reth-provider",
|
"reth-provider",
|
||||||
|
"reth-revm-primitives",
|
||||||
|
"revm",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reth-revm-inspectors"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown 0.13.2",
|
||||||
|
"reth-primitives",
|
||||||
|
"revm",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reth-revm-primitives"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"reth-primitives",
|
||||||
"revm",
|
"revm",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,8 @@ members = [
|
|||||||
"crates/net/downloaders",
|
"crates/net/downloaders",
|
||||||
"crates/primitives",
|
"crates/primitives",
|
||||||
"crates/revm",
|
"crates/revm",
|
||||||
|
"crates/revm/revm-primitives",
|
||||||
|
"crates/revm/revm-inspectors",
|
||||||
"crates/rlp",
|
"crates/rlp",
|
||||||
"crates/rlp/rlp-derive",
|
"crates/rlp/rlp-derive",
|
||||||
"crates/rpc/ipc",
|
"crates/rpc/ipc",
|
||||||
|
|||||||
@ -11,5 +11,6 @@ description = "reth specific revm utilities"
|
|||||||
reth-primitives = { path = "../primitives" }
|
reth-primitives = { path = "../primitives" }
|
||||||
reth-interfaces = { path = "../interfaces" }
|
reth-interfaces = { path = "../interfaces" }
|
||||||
reth-provider = { path = "../storage/provider" }
|
reth-provider = { path = "../storage/provider" }
|
||||||
|
reth-revm-primitives = { path = "./revm-primitives" }
|
||||||
|
|
||||||
revm = { version = "3.0.0"}
|
revm = { version = "3.0.0"}
|
||||||
15
crates/revm/revm-inspectors/Cargo.toml
Normal file
15
crates/revm/revm-inspectors/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "reth-revm-inspectors"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/paradigmxyz/reth"
|
||||||
|
description = "revm inspector implementations used by reth"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# reth
|
||||||
|
reth-primitives = { path = "../../primitives" }
|
||||||
|
|
||||||
|
revm = { version = "3.0.0" }
|
||||||
|
# remove from reth and reexport from revm
|
||||||
|
hashbrown = "0.13"
|
||||||
108
crates/revm/revm-inspectors/src/access_list.rs
Normal file
108
crates/revm/revm-inspectors/src/access_list.rs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
use hashbrown::{HashMap, HashSet};
|
||||||
|
use reth_primitives::{AccessList, AccessListItem, Address, H256};
|
||||||
|
use revm::{
|
||||||
|
interpreter::{opcode, InstructionResult, Interpreter},
|
||||||
|
Database, EVMData, Inspector,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// An [Inspector] that collects touched accounts and storage slots.
|
||||||
|
///
|
||||||
|
/// This can be used to construct an [AccessList] for a transaction via `eth_createAccessList`
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
pub struct AccessListInspector {
|
||||||
|
/// All addresses that should be excluded from the final accesslist
|
||||||
|
excluded: HashSet<Address>,
|
||||||
|
/// All addresses and touched slots
|
||||||
|
access_list: HashMap<Address, HashSet<H256>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AccessListInspector {
|
||||||
|
/// Creates a new inspector instance
|
||||||
|
///
|
||||||
|
/// The `access_list` is the provided access list from the call request
|
||||||
|
pub fn new(
|
||||||
|
access_list: AccessList,
|
||||||
|
from: Address,
|
||||||
|
to: Address,
|
||||||
|
precompiles: Vec<Address>,
|
||||||
|
) -> Self {
|
||||||
|
AccessListInspector {
|
||||||
|
excluded: vec![from, to].iter().chain(precompiles.iter()).copied().collect(),
|
||||||
|
access_list: access_list
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.map(|v| (v.address, v.storage_keys.iter().copied().collect()))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns list of addresses and storage keys used by the transaction. It gives you the list of
|
||||||
|
/// addresses and storage keys that were touched during execution.
|
||||||
|
pub fn into_access_list(self) -> AccessList {
|
||||||
|
let items = self.access_list.into_iter().map(|(address, slots)| AccessListItem {
|
||||||
|
address,
|
||||||
|
storage_keys: slots.into_iter().collect(),
|
||||||
|
});
|
||||||
|
AccessList(items.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns list of addresses and storage keys used by the transaction. It gives you the list of
|
||||||
|
/// addresses and storage keys that were touched during execution.
|
||||||
|
pub fn access_list(&self) -> AccessList {
|
||||||
|
let items = self.access_list.iter().map(|(address, slots)| AccessListItem {
|
||||||
|
address: *address,
|
||||||
|
storage_keys: slots.iter().copied().collect(),
|
||||||
|
});
|
||||||
|
AccessList(items.collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<DB> Inspector<DB> for AccessListInspector
|
||||||
|
where
|
||||||
|
DB: Database,
|
||||||
|
{
|
||||||
|
fn step(
|
||||||
|
&mut self,
|
||||||
|
interpreter: &mut Interpreter,
|
||||||
|
_data: &mut EVMData<'_, DB>,
|
||||||
|
_is_static: bool,
|
||||||
|
) -> InstructionResult {
|
||||||
|
let pc = interpreter.program_counter();
|
||||||
|
let op = interpreter.contract.bytecode.bytecode()[pc];
|
||||||
|
|
||||||
|
match op {
|
||||||
|
opcode::SLOAD | opcode::SSTORE => {
|
||||||
|
if let Ok(slot) = interpreter.stack().peek(0) {
|
||||||
|
let cur_contract = interpreter.contract.address;
|
||||||
|
self.access_list
|
||||||
|
.entry(cur_contract)
|
||||||
|
.or_default()
|
||||||
|
.insert(H256::from(slot.to_be_bytes()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opcode::EXTCODECOPY |
|
||||||
|
opcode::EXTCODEHASH |
|
||||||
|
opcode::EXTCODESIZE |
|
||||||
|
opcode::BALANCE |
|
||||||
|
opcode::SELFDESTRUCT => {
|
||||||
|
if let Ok(slot) = interpreter.stack().peek(0) {
|
||||||
|
let addr: Address = H256::from(slot.to_be_bytes()).into();
|
||||||
|
if !self.excluded.contains(&addr) {
|
||||||
|
self.access_list.entry(addr).or_default();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opcode::DELEGATECALL | opcode::CALL | opcode::STATICCALL | opcode::CALLCODE => {
|
||||||
|
if let Ok(slot) = interpreter.stack().peek(1) {
|
||||||
|
let addr: Address = H256::from(slot.to_be_bytes()).into();
|
||||||
|
if !self.excluded.contains(&addr) {
|
||||||
|
self.access_list.entry(addr).or_default();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
InstructionResult::Continue
|
||||||
|
}
|
||||||
|
}
|
||||||
11
crates/revm/revm-inspectors/src/lib.rs
Normal file
11
crates/revm/revm-inspectors/src/lib.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#![warn(missing_docs, unreachable_pub, unused_crate_dependencies)]
|
||||||
|
#![deny(unused_must_use, rust_2018_idioms)]
|
||||||
|
#![doc(test(
|
||||||
|
no_crate_inject,
|
||||||
|
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
|
||||||
|
))]
|
||||||
|
|
||||||
|
//! revm [Inspector](revm::Inspector) implementations
|
||||||
|
|
||||||
|
/// An inspector implementation for an EIP2930 Accesslist
|
||||||
|
pub mod access_list;
|
||||||
13
crates/revm/revm-primitives/Cargo.toml
Normal file
13
crates/revm/revm-primitives/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "reth-revm-primitives"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/paradigmxyz/reth"
|
||||||
|
description = "core reth specific revm utilities"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# reth
|
||||||
|
reth-primitives = { path = "../../primitives" }
|
||||||
|
|
||||||
|
revm = { version = "3.0.0" }
|
||||||
17
crates/revm/revm-primitives/src/lib.rs
Normal file
17
crates/revm/revm-primitives/src/lib.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#![warn(missing_docs, unreachable_pub, unused_crate_dependencies)]
|
||||||
|
#![deny(unused_must_use, rust_2018_idioms)]
|
||||||
|
#![doc(test(
|
||||||
|
no_crate_inject,
|
||||||
|
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
|
||||||
|
))]
|
||||||
|
|
||||||
|
//! revm utils and implementations specific to reth.
|
||||||
|
|
||||||
|
pub mod config;
|
||||||
|
|
||||||
|
/// Helpers for configuring revm [Env](revm::primitives::Env)
|
||||||
|
pub mod env;
|
||||||
|
|
||||||
|
/// Helpers for type compatibility between reth and revm types
|
||||||
|
mod compat;
|
||||||
|
pub use compat::*;
|
||||||
@ -7,14 +7,8 @@
|
|||||||
|
|
||||||
//! revm utils and implementations specific to reth.
|
//! revm utils and implementations specific to reth.
|
||||||
|
|
||||||
pub mod config;
|
|
||||||
|
|
||||||
/// Contains glue code for integrating reth database into revm's [Database](revm::Database).
|
/// Contains glue code for integrating reth database into revm's [Database](revm::Database).
|
||||||
pub mod database;
|
pub mod database;
|
||||||
|
|
||||||
/// Helpers for configuring revm [Env](revm::primitives::Env)
|
/// reexport for convenience
|
||||||
pub mod env;
|
pub use reth_revm_primitives::*;
|
||||||
|
|
||||||
/// Helpers for type compatibility between reth and revm types
|
|
||||||
mod compat;
|
|
||||||
pub use compat::*;
|
|
||||||
|
|||||||
Reference in New Issue
Block a user