Skip to content

Commit

Permalink
Specifying chain in for text_execute_revm (#445)
Browse files Browse the repository at this point in the history
  • Loading branch information
i1i1 authored Dec 25, 2024
1 parent 16c42d6 commit 8b164ab
Show file tree
Hide file tree
Showing 14 changed files with 63 additions and 30 deletions.
2 changes: 1 addition & 1 deletion bins/fetch/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ async fn main() -> Result<(), Box<dyn Error>> {

// Execute the block and track the pre-state in the RPC storage.
Pevm::default()
.execute(&storage, &chain, &block, NonZeroUsize::MIN, true)
.execute(&chain, &storage, &block, NonZeroUsize::MIN, true)
.map_err(|err| format!("Failed to execute block: {:?}", err))?;

let block_dir = format!("data/blocks/{}", block.header.number);
Expand Down
4 changes: 2 additions & 2 deletions crates/pevm/benches/gigagas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ pub fn bench(c: &mut Criterion, name: &str, storage: InMemoryStorage, txs: Vec<T
group.bench_function("Sequential", |b| {
b.iter(|| {
execute_revm_sequential(
black_box(&storage),
black_box(&chain),
black_box(&storage),
black_box(spec_id),
black_box(block_env.clone()),
black_box(txs.clone()),
Expand All @@ -55,8 +55,8 @@ pub fn bench(c: &mut Criterion, name: &str, storage: InMemoryStorage, txs: Vec<T
group.bench_function("Parallel", |b| {
b.iter(|| {
pevm.execute_revm_parallel(
black_box(&storage),
black_box(&chain),
black_box(&storage),
black_box(spec_id),
black_box(block_env.clone()),
black_box(txs.clone()),
Expand Down
4 changes: 2 additions & 2 deletions crates/pevm/benches/mainnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ pub fn criterion_benchmark(c: &mut Criterion) {
group.bench_function("Sequential", |b| {
b.iter(|| {
pevm.execute(
black_box(&storage),
black_box(&chain),
black_box(&storage),
black_box(&block),
black_box(concurrency_level),
black_box(true),
Expand All @@ -63,8 +63,8 @@ pub fn criterion_benchmark(c: &mut Criterion) {
group.bench_function("Parallel", |b| {
b.iter(|| {
pevm.execute(
black_box(&storage),
black_box(&chain),
black_box(&storage),
black_box(&block),
black_box(concurrency_level),
black_box(false),
Expand Down
29 changes: 19 additions & 10 deletions crates/pevm/src/pevm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::{
};

/// Errors when executing a block with pevm.
// TODO: implement traits explicitly due to trait bounds on `C` instead of types of `PevmChain`
#[derive(Debug, Clone, PartialEq)]
pub enum PevmError<C: PevmChain> {
/// Cannot derive the chain spec from the block header.
Expand Down Expand Up @@ -101,10 +102,10 @@ pub struct Pevm {
impl Pevm {
/// Execute an Alloy block, which is becoming the "standard" format in Rust.
/// TODO: Better error handling.
pub fn execute<S: Storage + Send + Sync, C: PevmChain + Send + Sync>(
pub fn execute<S, C>(
&mut self,
storage: &S,
chain: &C,
storage: &S,
// We assume the block is still needed afterwards like in most Reth cases
// so take in a reference and only copy values when needed. We may want
// to use a [`std::borrow::Cow`] to build [`BlockEnv`] and [`TxEnv`] without
Expand All @@ -114,7 +115,11 @@ impl Pevm {
block: &Block<C::Transaction>,
concurrency_level: NonZeroUsize,
force_sequential: bool,
) -> PevmResult<C> {
) -> PevmResult<C>
where
C: PevmChain + Send + Sync,
S: Storage + Send + Sync,
{
let spec_id = chain
.get_block_spec(&block.header)
.map_err(PevmError::BlockSpecError)?;
Expand All @@ -132,11 +137,11 @@ impl Pevm {
|| tx_envs.len() < concurrency_level.into()
|| block.header.gas_used < 4_000_000
{
execute_revm_sequential(storage, chain, spec_id, block_env, tx_envs)
execute_revm_sequential(chain, storage, spec_id, block_env, tx_envs)
} else {
self.execute_revm_parallel(
storage,
chain,
storage,
spec_id,
block_env,
tx_envs,
Expand All @@ -148,15 +153,19 @@ impl Pevm {
/// Execute an REVM block.
// Ideally everyone would go through the [Alloy] interface. This one is currently
// useful for testing, and for users that are heavily tied to Revm like Reth.
pub fn execute_revm_parallel<S: Storage + Send + Sync, C: PevmChain + Send + Sync>(
pub fn execute_revm_parallel<S, C>(
&mut self,
storage: &S,
chain: &C,
storage: &S,
spec_id: SpecId,
block_env: BlockEnv,
txs: Vec<TxEnv>,
concurrency_level: NonZeroUsize,
) -> PevmResult<C> {
) -> PevmResult<C>
where
C: PevmChain + Send + Sync,
S: Storage + Send + Sync,
{
if txs.is_empty() {
return Ok(Vec::new());
}
Expand Down Expand Up @@ -212,7 +221,7 @@ impl Pevm {
match abort_reason {
AbortReason::FallbackToSequential => {
self.dropper.drop((mv_memory, scheduler, Vec::new()));
return execute_revm_sequential(storage, chain, spec_id, block_env, txs);
return execute_revm_sequential(chain, storage, spec_id, block_env, txs);
}
AbortReason::ExecutionError(err) => {
self.dropper.drop((mv_memory, scheduler, txs));
Expand Down Expand Up @@ -421,8 +430,8 @@ fn try_validate(
// Useful for falling back for (small) blocks with many dependencies.
// TODO: Use this for a long chain of sequential transactions even in parallel mode.
pub fn execute_revm_sequential<S: Storage, C: PevmChain>(
storage: &S,
chain: &C,
storage: &S,
spec_id: SpecId,
block_env: BlockEnv,
txs: Vec<TxEnv>,
Expand Down
2 changes: 2 additions & 0 deletions crates/pevm/tests/beneficiary.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Tests for the beneficiary account, especially for the lazy update of its balance to avoid
//! "implicit" dependency among consecutive transactions.
use pevm::chain::PevmEthereum;
use pevm::InMemoryStorage;
use rand::random;
use revm::primitives::{alloy_primitives::U160, env::TxEnv, Address, TransactTo, U256};
Expand All @@ -11,6 +12,7 @@ const BLOCK_SIZE: usize = 100_000;

fn test_beneficiary(get_address: fn(usize) -> Address) {
common::test_execute_revm(
&PevmEthereum::mainnet(),
// Mock the beneficiary account (`Address:ZERO`) and the next `BLOCK_SIZE` user accounts.
InMemoryStorage::new(
(0..=BLOCK_SIZE).map(common::mock_account).collect(),
Expand Down
2 changes: 1 addition & 1 deletion crates/pevm/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,5 @@ where
..Block::<C::Transaction>::default()
};
let storage = InMemoryStorage::new(accounts, Default::default(), Default::default());
test_execute_alloy(&storage, chain, block, false);
test_execute_alloy(chain, &storage, block, false);
}
25 changes: 16 additions & 9 deletions crates/pevm/tests/common/runner.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloy_primitives::Bloom;
use alloy_rpc_types_eth::Block;
use pevm::{
chain::{CalculateReceiptRootError, PevmChain, PevmEthereum},
chain::{CalculateReceiptRootError, PevmChain},
EvmAccount, Pevm, Storage,
};
use revm::primitives::{alloy_primitives::U160, Address, BlockEnv, SpecId, TxEnv, U256};
Expand All @@ -23,19 +23,23 @@ pub fn mock_account(idx: usize) -> (Address, EvmAccount) {

/// Execute an REVM block sequentially and parallelly with PEVM and assert that
/// the execution results match.
pub fn test_execute_revm<S: Storage + Send + Sync>(storage: S, txs: Vec<TxEnv>) {
pub fn test_execute_revm<C, S>(chain: &C, storage: S, txs: Vec<TxEnv>)
where
C: PevmChain + PartialEq + Send + Sync,
S: Storage + Send + Sync,
{
let concurrency_level = thread::available_parallelism().unwrap_or(NonZeroUsize::MIN);
assert_eq!(
pevm::execute_revm_sequential(
chain,
&storage,
&PevmEthereum::mainnet(),
SpecId::LATEST,
BlockEnv::default(),
txs.clone(),
),
Pevm::default().execute_revm_parallel(
chain,
&storage,
&PevmEthereum::mainnet(),
SpecId::LATEST,
BlockEnv::default(),
txs,
Expand All @@ -46,16 +50,19 @@ pub fn test_execute_revm<S: Storage + Send + Sync>(storage: S, txs: Vec<TxEnv>)

/// Execute an Alloy block sequentially & with pevm and assert that
/// the execution results match.
pub fn test_execute_alloy<S: Storage + Send + Sync, C: PevmChain + Send + Sync + PartialEq>(
storage: &S,
pub fn test_execute_alloy<C, S>(
chain: &C,
storage: &S,
block: Block<C::Transaction>,
must_match_block_header: bool,
) {
) where
C: PevmChain + PartialEq + Send + Sync,
S: Storage + Send + Sync,
{
let concurrency_level = thread::available_parallelism().unwrap_or(NonZeroUsize::MIN);
let mut pevm = Pevm::default();
let sequential_result = pevm.execute(storage, chain, &block, concurrency_level, true);
let parallel_result = pevm.execute(storage, chain, &block, concurrency_level, false);
let sequential_result = pevm.execute(chain, storage, &block, concurrency_level, true);
let parallel_result = pevm.execute(chain, storage, &block, concurrency_level, false);
assert!(sequential_result.is_ok());
assert_eq!(&sequential_result, &parallel_result);

Expand Down
3 changes: 3 additions & 0 deletions crates/pevm/tests/erc20/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod erc20;

use common::test_execute_revm;
use erc20::generate_cluster;
use pevm::chain::PevmEthereum;
use pevm::{Bytecodes, ChainState, EvmAccount, InMemoryStorage};
use revm::primitives::{Address, TxEnv};
use std::sync::Arc;
Expand All @@ -20,6 +21,7 @@ fn erc20_independent() {
let (mut state, bytecodes, txs) = generate_cluster(N, 1, 1);
state.insert(Address::ZERO, EvmAccount::default()); // Beneficiary
test_execute_revm(
&PevmEthereum::mainnet(),
InMemoryStorage::new(state, Arc::new(bytecodes), Default::default()),
txs,
);
Expand Down Expand Up @@ -47,6 +49,7 @@ fn erc20_clusters() {
final_txs.extend(txs);
}
common::test_execute_revm(
&PevmEthereum::mainnet(),
InMemoryStorage::new(final_state, Arc::new(final_bytecodes), Default::default()),
final_txs,
)
Expand Down
2 changes: 1 addition & 1 deletion crates/pevm/tests/ethereum/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ fn run_test_unit(path: &Path, unit: TestUnit) {
match (
test.expect_exception.as_deref(),
Pevm::default().execute_revm_parallel(
&InMemoryStorage::new(chain_state.clone(), Arc::new(bytecodes), Default::default()),
&PevmEthereum::mainnet(),
&InMemoryStorage::new(chain_state.clone(), Arc::new(bytecodes), Default::default()),
spec_name.to_spec_id(),
build_block_env(&unit.env),
vec![tx_env.unwrap()],
Expand Down
6 changes: 3 additions & 3 deletions crates/pevm/tests/mainnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async fn mainnet_blocks_from_rpc() {
let spec_id = chain.get_block_spec(&block.header).unwrap();
let rpc_storage =
pevm::RpcStorage::new(provider, spec_id, BlockId::number(block_number - 1));
common::test_execute_alloy(&rpc_storage, &chain, block, true);
common::test_execute_alloy(&chain, &rpc_storage, block, true);
}
}

Expand All @@ -53,7 +53,7 @@ fn mainnet_blocks_from_disk() {
// Run several times to try catching a race condition if there is any.
// 1000~2000 is a better choice for local testing after major changes.
for _ in 0..3 {
common::test_execute_alloy(&storage, &PevmEthereum::mainnet(), block.clone(), true)
common::test_execute_alloy(&PevmEthereum::mainnet(), &storage, block.clone(), true)
}
});
}
Expand Down Expand Up @@ -92,6 +92,6 @@ async fn optimism_mainnet_blocks_from_rpc() {

let rpc_storage =
pevm::RpcStorage::new(provider, spec_id, BlockId::number(block_number - 1));
common::test_execute_alloy(&rpc_storage, &chain, block, true);
common::test_execute_alloy(&chain, &rpc_storage, block, true);
}
}
2 changes: 2 additions & 0 deletions crates/pevm/tests/mixed.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Test raw transfers -- A block with random raw transfers, ERC-20 transfers, and Uniswap swaps.
use pevm::chain::PevmEthereum;
use pevm::{Bytecodes, ChainState, EvmAccount, InMemoryStorage};
use rand::random;
use revm::primitives::{env::TxEnv, Address, TransactTo, U256};
Expand Down Expand Up @@ -59,6 +60,7 @@ fn mixed_block() {
}
}
common::test_execute_revm(
&PevmEthereum::mainnet(),
InMemoryStorage::new(final_state, Arc::new(final_bytecodes), Default::default()),
// TODO: Shuffle transactions to scatter dependencies around the block.
// Note that we'll need to guarantee that the nonces are increasing.
Expand Down
2 changes: 2 additions & 0 deletions crates/pevm/tests/raw_transfers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod common;
fn raw_transfers_independent() {
let block_size = 100_000; // number of transactions
common::test_execute_revm(
&PevmEthereum::mainnet(),
// Mock the beneficiary account (`Address:ZERO`) and the next `block_size` user accounts.
InMemoryStorage::new(
(0..=block_size).map(common::mock_account).collect(),
Expand Down Expand Up @@ -44,6 +45,7 @@ fn raw_transfers_same_sender_multiple_txs() {
let mut same_sender_nonce: u64 = 0;

common::test_execute_revm(
&PevmEthereum::mainnet(),
// Mock the beneficiary account (`Address:ZERO`) and the next `block_size` user accounts.
InMemoryStorage::new(
(0..=block_size).map(common::mock_account).collect(),
Expand Down
8 changes: 7 additions & 1 deletion crates/pevm/tests/small_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@
//! the concurrency level, falling back to sequential processing, etc.
use alloy_primitives::{Address, U256};
use pevm::chain::PevmEthereum;
use pevm::InMemoryStorage;
use revm::primitives::{TransactTo, TxEnv};

pub mod common;

#[test]
fn empty_revm_block() {
common::test_execute_revm(InMemoryStorage::default(), Vec::new());
common::test_execute_revm(
&PevmEthereum::mainnet(),
InMemoryStorage::default(),
Vec::new(),
);
}

#[test]
fn one_tx_revm_block() {
common::test_execute_revm(
&PevmEthereum::mainnet(),
InMemoryStorage::new(
[common::mock_account(0)].into_iter().collect(),
Default::default(),
Expand Down
2 changes: 2 additions & 0 deletions crates/pevm/tests/uniswap/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod erc20;
pub mod uniswap;

use crate::uniswap::generate_cluster;
use pevm::chain::PevmEthereum;
use pevm::{Bytecodes, ChainState, EvmAccount, InMemoryStorage};
use revm::primitives::{Address, TxEnv};
use std::sync::Arc;
Expand All @@ -34,6 +35,7 @@ fn uniswap_clusters() {
final_txs.extend(txs);
}
common::test_execute_revm(
&PevmEthereum::mainnet(),
InMemoryStorage::new(final_state, Arc::new(final_bytecodes), Default::default()),
final_txs,
)
Expand Down

0 comments on commit 8b164ab

Please sign in to comment.