mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: add revm-inspectors crate and accesslist inspector (#1529)
This commit is contained in:
@ -11,5 +11,6 @@ description = "reth specific revm utilities"
|
||||
reth-primitives = { path = "../primitives" }
|
||||
reth-interfaces = { path = "../interfaces" }
|
||||
reth-provider = { path = "../storage/provider" }
|
||||
reth-revm-primitives = { path = "./revm-primitives" }
|
||||
|
||||
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.
|
||||
|
||||
pub mod config;
|
||||
|
||||
/// Contains glue code for integrating reth database into revm's [Database](revm::Database).
|
||||
pub mod database;
|
||||
|
||||
/// 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::*;
|
||||
/// reexport for convenience
|
||||
pub use reth_revm_primitives::*;
|
||||
|
||||
Reference in New Issue
Block a user