feat: add revm-inspectors crate and accesslist inspector (#1529)

This commit is contained in:
Matthias Seitz
2023-02-24 02:06:15 +01:00
committed by GitHub
parent 8299ca6fd6
commit 6d138daa11
12 changed files with 187 additions and 8 deletions

View File

@@ -1,34 +0,0 @@
use reth_primitives::{Account, Log as RethLog, H160, H256, KECCAK_EMPTY};
use revm::primitives::{AccountInfo, Log};
/// Check equality between [`reth_primitives::Log`] and [`revm::primitives::Log`]
pub fn is_log_equal(revm_log: &Log, reth_log: &reth_primitives::Log) -> bool {
revm_log.topics.len() == reth_log.topics.len() &&
revm_log.address.0 == reth_log.address.0 &&
revm_log.data == reth_log.data.0 &&
!revm_log
.topics
.iter()
.zip(reth_log.topics.iter())
.any(|(revm_topic, reth_topic)| revm_topic.0 != reth_topic.0)
}
/// Into reth primitive [Log] from [revm::primitives::Log].
pub fn into_reth_log(log: Log) -> RethLog {
RethLog {
address: H160(log.address.0),
topics: log.topics.into_iter().map(|h| H256(h.0)).collect(),
data: log.data.into(),
}
}
/// Create reth primitive [Account] from [revm::primitives::AccountInfo].
/// Check if revm bytecode hash is [KECCAK_EMPTY] and put None to reth [Account]
pub fn to_reth_acc(revm_acc: &AccountInfo) -> Account {
let code_hash = revm_acc.code_hash;
Account {
balance: revm_acc.balance,
nonce: revm_acc.nonce,
bytecode_hash: if code_hash == KECCAK_EMPTY { None } else { Some(code_hash) },
}
}

View File

@@ -1,158 +0,0 @@
//! Reth block execution/validation configuration and constants
use reth_primitives::{ChainSpec, Hardfork, Head};
/// Two ethereum worth of wei
pub const WEI_2ETH: u128 = 2000000000000000000u128;
/// Three ethereum worth of wei
pub const WEI_3ETH: u128 = 3000000000000000000u128;
/// Five ethereum worth of wei
pub const WEI_5ETH: u128 = 5000000000000000000u128;
/// return revm_spec from spec configuration.
pub fn revm_spec(chain_spec: &ChainSpec, block: Head) -> revm::primitives::SpecId {
if chain_spec.fork(Hardfork::Shanghai).active_at_head(&block) {
revm::primitives::SHANGHAI
} else if chain_spec.fork(Hardfork::Paris).active_at_head(&block) {
revm::primitives::MERGE
} else if chain_spec.fork(Hardfork::London).active_at_head(&block) {
revm::primitives::LONDON
} else if chain_spec.fork(Hardfork::Berlin).active_at_head(&block) {
revm::primitives::BERLIN
} else if chain_spec.fork(Hardfork::Istanbul).active_at_head(&block) {
revm::primitives::ISTANBUL
} else if chain_spec.fork(Hardfork::Petersburg).active_at_head(&block) {
revm::primitives::PETERSBURG
} else if chain_spec.fork(Hardfork::Byzantium).active_at_head(&block) {
revm::primitives::BYZANTIUM
} else if chain_spec.fork(Hardfork::SpuriousDragon).active_at_head(&block) {
revm::primitives::SPURIOUS_DRAGON
} else if chain_spec.fork(Hardfork::Tangerine).active_at_head(&block) {
revm::primitives::TANGERINE
} else if chain_spec.fork(Hardfork::Homestead).active_at_head(&block) {
revm::primitives::HOMESTEAD
} else if chain_spec.fork(Hardfork::Frontier).active_at_head(&block) {
revm::primitives::FRONTIER
} else {
panic!("wrong configuration")
}
}
#[cfg(test)]
mod tests {
use crate::config::revm_spec;
use reth_primitives::{ChainSpecBuilder, Head, MAINNET, U256};
#[test]
fn test_to_revm_spec() {
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().paris_activated().build(), Head::default()),
revm::primitives::MERGE
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().london_activated().build(), Head::default()),
revm::primitives::LONDON
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().berlin_activated().build(), Head::default()),
revm::primitives::BERLIN
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().istanbul_activated().build(), Head::default()),
revm::primitives::ISTANBUL
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().petersburg_activated().build(), Head::default()),
revm::primitives::PETERSBURG
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().byzantium_activated().build(), Head::default()),
revm::primitives::BYZANTIUM
);
assert_eq!(
revm_spec(
&ChainSpecBuilder::mainnet().spurious_dragon_activated().build(),
Head::default()
),
revm::primitives::SPURIOUS_DRAGON
);
assert_eq!(
revm_spec(
&ChainSpecBuilder::mainnet().tangerine_whistle_activated().build(),
Head::default()
),
revm::primitives::TANGERINE
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().homestead_activated().build(), Head::default()),
revm::primitives::HOMESTEAD
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().frontier_activated().build(), Head::default()),
revm::primitives::FRONTIER
);
}
#[test]
fn test_eth_spec() {
assert_eq!(
revm_spec(
&MAINNET,
Head {
total_difficulty: U256::from(58_750_000_000_000_000_000_010_u128),
difficulty: U256::from(10_u128),
..Default::default()
}
),
revm::primitives::MERGE
);
// TTD trumps the block number
assert_eq!(
revm_spec(
&MAINNET,
Head {
number: 15537394 - 10,
total_difficulty: U256::from(58_750_000_000_000_000_000_010_u128),
difficulty: U256::from(10_u128),
..Default::default()
}
),
revm::primitives::MERGE
);
assert_eq!(
revm_spec(&MAINNET, Head { number: 15537394 - 10, ..Default::default() }),
revm::primitives::LONDON
);
assert_eq!(
revm_spec(&MAINNET, Head { number: 12244000 + 10, ..Default::default() }),
revm::primitives::BERLIN
);
assert_eq!(
revm_spec(&MAINNET, Head { number: 12244000 - 10, ..Default::default() }),
revm::primitives::ISTANBUL
);
assert_eq!(
revm_spec(&MAINNET, Head { number: 7280000 + 10, ..Default::default() }),
revm::primitives::PETERSBURG
);
assert_eq!(
revm_spec(&MAINNET, Head { number: 7280000 - 10, ..Default::default() }),
revm::primitives::BYZANTIUM
);
assert_eq!(
revm_spec(&MAINNET, Head { number: 2675000 + 10, ..Default::default() }),
revm::primitives::SPURIOUS_DRAGON
);
assert_eq!(
revm_spec(&MAINNET, Head { number: 2675000 - 10, ..Default::default() }),
revm::primitives::TANGERINE
);
assert_eq!(
revm_spec(&MAINNET, Head { number: 1150000 + 10, ..Default::default() }),
revm::primitives::HOMESTEAD
);
assert_eq!(
revm_spec(&MAINNET, Head { number: 1150000 - 10, ..Default::default() }),
revm::primitives::FRONTIER
);
}
}

View File

@@ -1,144 +0,0 @@
use crate::config::revm_spec;
use reth_primitives::{
Address, ChainSpec, Head, Header, Transaction, TransactionKind, TransactionSigned, TxEip1559,
TxEip2930, TxLegacy, U256,
};
use revm::primitives::{AnalysisKind, BlockEnv, CfgEnv, TransactTo, TxEnv};
/// Fill [CfgEnv] fields according to the chain spec and given header
pub fn fill_cfg_env(
cfg_env: &mut CfgEnv,
chain_spec: &ChainSpec,
header: &Header,
total_difficulty: U256,
) {
let spec_id = revm_spec(
chain_spec,
Head {
number: header.number,
timestamp: header.timestamp,
difficulty: header.difficulty,
total_difficulty,
hash: Default::default(),
},
);
cfg_env.chain_id = U256::from(chain_spec.chain().id());
cfg_env.spec_id = spec_id;
cfg_env.perf_all_precompiles_have_balance = false;
cfg_env.perf_analyse_created_bytecodes = AnalysisKind::Raw;
}
/// Fill block environment from Block.
pub fn fill_block_env(block_env: &mut BlockEnv, header: &Header, after_merge: bool) {
block_env.number = U256::from(header.number);
block_env.coinbase = header.beneficiary;
block_env.timestamp = U256::from(header.timestamp);
if after_merge {
block_env.prevrandao = Some(header.mix_hash);
block_env.difficulty = U256::ZERO;
} else {
block_env.difficulty = header.difficulty;
block_env.prevrandao = None;
}
block_env.basefee = U256::from(header.base_fee_per_gas.unwrap_or_default());
block_env.gas_limit = U256::from(header.gas_limit);
}
/// Fill transaction environment from Transaction.
pub fn fill_tx_env(tx_env: &mut TxEnv, transaction: &TransactionSigned, sender: Address) {
tx_env.caller = sender;
match transaction.as_ref() {
Transaction::Legacy(TxLegacy {
nonce,
chain_id,
gas_price,
gas_limit,
to,
value,
input,
}) => {
tx_env.gas_limit = *gas_limit;
tx_env.gas_price = U256::from(*gas_price);
tx_env.gas_priority_fee = None;
tx_env.transact_to = match to {
TransactionKind::Call(to) => TransactTo::Call(*to),
TransactionKind::Create => TransactTo::create(),
};
tx_env.value = U256::from(*value);
tx_env.data = input.0.clone();
tx_env.chain_id = *chain_id;
tx_env.nonce = Some(*nonce);
}
Transaction::Eip2930(TxEip2930 {
nonce,
chain_id,
gas_price,
gas_limit,
to,
value,
input,
access_list,
}) => {
tx_env.gas_limit = *gas_limit;
tx_env.gas_price = U256::from(*gas_price);
tx_env.gas_priority_fee = None;
tx_env.transact_to = match to {
TransactionKind::Call(to) => TransactTo::Call(*to),
TransactionKind::Create => TransactTo::create(),
};
tx_env.value = U256::from(*value);
tx_env.data = input.0.clone();
tx_env.chain_id = Some(*chain_id);
tx_env.nonce = Some(*nonce);
tx_env.access_list = access_list
.0
.iter()
.map(|l| {
(
l.address,
l.storage_keys
.iter()
.map(|k| U256::from_be_bytes(k.to_fixed_bytes()))
.collect(),
)
})
.collect();
}
Transaction::Eip1559(TxEip1559 {
nonce,
chain_id,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
to,
value,
input,
access_list,
}) => {
tx_env.gas_limit = *gas_limit;
tx_env.gas_price = U256::from(*max_fee_per_gas);
tx_env.gas_priority_fee = Some(U256::from(*max_priority_fee_per_gas));
tx_env.transact_to = match to {
TransactionKind::Call(to) => TransactTo::Call(*to),
TransactionKind::Create => TransactTo::create(),
};
tx_env.value = U256::from(*value);
tx_env.data = input.0.clone();
tx_env.chain_id = Some(*chain_id);
tx_env.nonce = Some(*nonce);
tx_env.access_list = access_list
.0
.iter()
.map(|l| {
(
l.address,
l.storage_keys
.iter()
.map(|k| U256::from_be_bytes(k.to_fixed_bytes()))
.collect(),
)
})
.collect();
}
}
}

View File

@@ -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::*;