Skip to content

Commit

Permalink
grevm: introduce grevm to reth
Browse files Browse the repository at this point in the history
  • Loading branch information
nekomoto911 committed Oct 15, 2024
1 parent c228fe1 commit 52472e6
Show file tree
Hide file tree
Showing 12 changed files with 165 additions and 11 deletions.
3 changes: 3 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ rustflags = [
# in line with Linux (whereas default for Windows is 1MB)
"-Clink-arg=/STACK:10000000",
]

[net]
git-fetch-with-cli = true
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ reth-provider = { path = "crates/storage/provider" }
reth-prune = { path = "crates/prune/prune" }
reth-prune-types = { path = "crates/prune/types" }
reth-revm = { path = "crates/revm" }
reth-grevm = { package = "grevm", git = "ssh://[email protected]/Galxe/grevm.git", branch = "main" }
reth-rpc = { path = "crates/rpc/rpc" }
reth-rpc-api = { path = "crates/rpc/rpc-api" }
reth-rpc-api-testing-util = { path = "crates/rpc/rpc-testing-util" }
Expand Down
4 changes: 2 additions & 2 deletions crates/blockchain-tree/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl AppendableChain {
let provider = BundleStateProvider::new(state_provider, bundle_state_data_provider);

let db = StateProviderDatabase::new(&provider);
let executor = externals.executor_factory.executor(db);
let executor = externals.executor_factory.parallel_executor(db);
let block_hash = block.hash();
let block = block.unseal();

Expand Down Expand Up @@ -241,7 +241,7 @@ impl AppendableChain {
return Err(ConsensusError::BodyStateRootDiff(
GotExpected { got: state_root, expected: block.state_root }.into(),
)
.into())
.into());
}

tracing::debug!(
Expand Down
6 changes: 3 additions & 3 deletions crates/consensus/auto-seal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,13 +370,13 @@ impl StorageInner {

trace!(target: "consensus::auto", transactions=?&block.body, "executing transactions");

let mut db = StateProviderDatabase::new(
let db = Arc::new(StateProviderDatabase::new(
provider.latest().map_err(InternalBlockExecutionError::LatestBlock)?,
);
));

// execute the block
let block_execution_output =
executor.executor(&mut db).execute((&block, U256::ZERO).into())?;
executor.parallel_executor(db.clone()).execute((&block, U256::ZERO).into())?;
let gas_used = block_execution_output.gas_used;
let execution_outcome = ExecutionOutcome::from((block_execution_output, block.number));
let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state);
Expand Down
1 change: 1 addition & 0 deletions crates/ethereum/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ reth-ethereum-forks.workspace = true
reth-evm.workspace = true
reth-primitives = { workspace = true, features = ["reth-codec"] }
reth-revm.workspace = true
reth-grevm.workspace = true
reth-ethereum-consensus.workspace = true
reth-prune-types.workspace = true
reth-execution-types.workspace = true
Expand Down
15 changes: 13 additions & 2 deletions crates/ethereum/evm/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::{
dao_fork::{DAO_HARDFORK_BENEFICIARY, DAO_HARDKFORK_ACCOUNTS},
parallel_execute::EthGrevmExecutor,
EthEvmConfig,
};
use core::fmt::Display;
Expand All @@ -10,7 +11,7 @@ use reth_ethereum_consensus::validate_block_post_execution;
use reth_evm::{
execute::{
BatchExecutor, BlockExecutionError, BlockExecutionInput, BlockExecutionOutput,
BlockExecutorProvider, BlockValidationError, Executor, ProviderError,
BlockExecutorProvider, BlockValidationError, Executor, ParallelDatabase, ProviderError,
},
system_calls::{
apply_beacon_root_contract_call, apply_blockhashes_contract_call,
Expand Down Expand Up @@ -89,6 +90,9 @@ where
type BatchExecutor<DB: Database<Error: Into<ProviderError> + Display>> =
EthBatchExecutor<EvmConfig, DB>;

type ParallelExecutor<DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>> =
EthGrevmExecutor<EvmConfig, DB>;

fn executor<DB>(&self, db: DB) -> Self::Executor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>,
Expand All @@ -103,6 +107,13 @@ where
let executor = self.eth_executor(db);
EthBatchExecutor { executor, batch_record: BlockBatchRecord::default() }
}

fn parallel_executor<DB>(&self, db: DB) -> Self::ParallelExecutor<DB>
where
DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>,
{
EthGrevmExecutor::new(self.chain_spec.clone(), self.evm_config.clone(), db)
}
}

/// Helper type for the output of executing a block.
Expand Down Expand Up @@ -175,7 +186,7 @@ where
transaction_gas_limit: transaction.gas_limit(),
block_available_gas,
}
.into())
.into());
}

self.evm_config.fill_tx_env(evm.tx_mut(), transaction, *sender);
Expand Down
1 change: 1 addition & 0 deletions crates/ethereum/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mod config;
pub use config::{revm_spec, revm_spec_by_timestamp_after_merge};

pub mod execute;
pub mod parallel_execute;

/// Ethereum DAO hardfork state change data.
pub mod dao_fork;
Expand Down
80 changes: 80 additions & 0 deletions crates/ethereum/evm/src/parallel_execute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use core::fmt::{Debug, Display};
use std::sync::Arc;

use reth_chainspec::ChainSpec;
use reth_evm::{
execute::{BlockExecutionError, Executor, ParallelDatabase},
ConfigureEvm,
};
use reth_execution_types::{BlockExecutionInput, BlockExecutionOutput};
use reth_grevm::{new_grevm_scheduler, GrevmScheduler};

use reth_primitives::{BlockWithSenders, Receipt};
use revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, TxEnv};

pub struct EthGrevmExecutor<EvmConfig, DB> {
chain_spec: Arc<ChainSpec>,
evm_config: EvmConfig,
database: DB,
}

impl<EvmConfig, DB> EthGrevmExecutor<EvmConfig, DB> {
pub fn new(chain_spec: Arc<ChainSpec>, evm_config: EvmConfig, database: DB) -> Self {
Self { chain_spec, evm_config, database }
}
}

impl<EvmConfig, DB> Executor<DB> for EthGrevmExecutor<EvmConfig, DB>
where
EvmConfig: ConfigureEvm,
DB: ParallelDatabase<Error: Display + Clone>,
{
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>;
type Output = BlockExecutionOutput<Receipt>;
type Error = BlockExecutionError;

fn execute(self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
// Initialize evm env
let mut cfg = CfgEnvWithHandlerCfg::new(Default::default(), Default::default());
let mut block_env = BlockEnv::default();
self.evm_config.fill_cfg_and_block_env(
&mut cfg,
&mut block_env,
self.chain_spec.as_ref(),
&input.block.header,
input.total_difficulty,
);
let env = EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, Default::default());

// Fill TxEnv from transaction
let mut txs = vec![TxEnv::default(); input.block.body.len()];
for (tx_env, (sender, tx)) in txs.iter_mut().zip(input.block.transactions_with_sender()) {
self.evm_config.fill_tx_env(tx_env, tx, *sender);
}

let executor = new_grevm_scheduler(env.spec_id(), *env.env, self.database, txs);
let output = executor.parallel_execute().map_err(|e| BlockExecutionError::msg(e))?;

let mut receipts = Vec::with_capacity(output.results.len());
let mut cumulative_gas_used = 0;
for (result, tx_type) in
output.results.into_iter().zip(input.block.transactions().map(|tx| tx.tx_type()))
{
cumulative_gas_used += result.gas_used();
receipts.push(Receipt {
tx_type,
success: result.is_success(),
cumulative_gas_used,
logs: result.into_logs(),
..Default::default()
});
}

Ok(BlockExecutionOutput {
state: output.state,
receipts,
requests: vec![],
gas_used: cumulative_gas_used,
})
}
}
16 changes: 14 additions & 2 deletions crates/evm/src/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use core::fmt::Display;

use crate::execute::{BatchExecutor, BlockExecutorProvider, Executor};
use crate::execute::{BatchExecutor, BlockExecutorProvider, Executor, ParallelDatabase};
use reth_execution_errors::BlockExecutionError;
use reth_execution_types::{BlockExecutionInput, BlockExecutionOutput, ExecutionOutcome};
use reth_primitives::{BlockNumber, BlockWithSenders, Receipt};
Expand All @@ -24,6 +24,9 @@ where
type BatchExecutor<DB: Database<Error: Into<ProviderError> + Display>> =
Either<A::BatchExecutor<DB>, B::BatchExecutor<DB>>;

type ParallelExecutor<DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>> =
Either<A::ParallelExecutor<DB>, B::ParallelExecutor<DB>>;

fn executor<DB>(&self, db: DB) -> Self::Executor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>,
Expand All @@ -43,6 +46,16 @@ where
Self::Right(b) => Either::Right(b.batch_executor(db)),
}
}

fn parallel_executor<DB>(&self, db: DB) -> Self::ParallelExecutor<DB>
where
DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>,
{
match self {
Self::Left(a) => Either::Left(a.parallel_executor(db)),
Self::Right(b) => Either::Right(b.parallel_executor(db)),
}
}
}

impl<A, B, DB> Executor<DB> for Either<A, B>
Expand All @@ -59,7 +72,6 @@ where
Output = BlockExecutionOutput<Receipt>,
Error = BlockExecutionError,
>,
DB: Database<Error: Into<ProviderError> + Display>,
{
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>;
type Output = BlockExecutionOutput<Receipt>;
Expand Down
26 changes: 25 additions & 1 deletion crates/evm/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::fmt::Display;

use reth_primitives::{BlockNumber, BlockWithSenders, Receipt};
use reth_prune_types::PruneModes;
use revm_primitives::db::Database;
use revm_primitives::db::{Database, DatabaseRef};

/// A general purpose executor trait that executes an input (e.g. block) and produces an output
/// (e.g. state changes and receipts).
Expand Down Expand Up @@ -94,6 +94,10 @@ pub trait BatchExecutor<DB> {
fn size_hint(&self) -> Option<usize>;
}

pub trait ParallelDatabase: DatabaseRef<Error: Send + Sync + 'static> + Send + Sync {}

impl<T: DatabaseRef<Error: Send + Sync + 'static> + Send + Sync> ParallelDatabase for T {}

/// A type that can create a new executor for block execution.
pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static {
/// An executor that can execute a single block given a database.
Expand Down Expand Up @@ -122,6 +126,13 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static {
Error = BlockExecutionError,
>;

type ParallelExecutor<DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>>: for<'a> Executor<
DB,
Input<'a> = BlockExecutionInput<'a, BlockWithSenders>,
Output = BlockExecutionOutput<Receipt>,
Error = BlockExecutionError,
>;

/// Creates a new executor for single block execution.
///
/// This is used to execute a single block and get the changed state.
Expand All @@ -136,6 +147,10 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static {
fn batch_executor<DB>(&self, db: DB) -> Self::BatchExecutor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>;

fn parallel_executor<DB>(&self, db: DB) -> Self::ParallelExecutor<DB>
where
DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>;
}

#[cfg(test)]
Expand All @@ -152,6 +167,8 @@ mod tests {
impl BlockExecutorProvider for TestExecutorProvider {
type Executor<DB: Database<Error: Into<ProviderError> + Display>> = TestExecutor<DB>;
type BatchExecutor<DB: Database<Error: Into<ProviderError> + Display>> = TestExecutor<DB>;
type ParallelExecutor<DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>> =
TestExecutor<DB>;

fn executor<DB>(&self, _db: DB) -> Self::Executor<DB>
where
Expand All @@ -166,6 +183,13 @@ mod tests {
{
TestExecutor(PhantomData)
}

fn parallel_executor<DB>(&self, _db: DB) -> Self::ParallelExecutor<DB>
where
DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>,
{
TestExecutor(PhantomData)
}
}

struct TestExecutor<DB>(PhantomData<DB>);
Expand Down
12 changes: 11 additions & 1 deletion crates/evm/src/noop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use reth_prune_types::PruneModes;
use reth_storage_errors::provider::ProviderError;
use revm_primitives::db::Database;

use crate::execute::{BatchExecutor, BlockExecutorProvider, Executor};
use crate::execute::{BatchExecutor, BlockExecutorProvider, Executor, ParallelDatabase};

const UNAVAILABLE_FOR_NOOP: &str = "execution unavailable for noop";

Expand All @@ -23,6 +23,9 @@ impl BlockExecutorProvider for NoopBlockExecutorProvider {

type BatchExecutor<DB: Database<Error: Into<ProviderError> + Display>> = Self;

type ParallelExecutor<DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>> =
Self;

fn executor<DB>(&self, _: DB) -> Self::Executor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>,
Expand All @@ -36,6 +39,13 @@ impl BlockExecutorProvider for NoopBlockExecutorProvider {
{
Self
}

fn parallel_executor<DB>(&self, _: DB) -> Self::ParallelExecutor<DB>
where
DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>,
{
Self
}
}

impl<DB> Executor<DB> for NoopBlockExecutorProvider {
Expand Down
11 changes: 11 additions & 0 deletions crates/evm/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::execute::{
BatchExecutor, BlockExecutionInput, BlockExecutionOutput, BlockExecutorProvider, Executor,
ParallelDatabase,
};
use parking_lot::Mutex;
use reth_execution_errors::BlockExecutionError;
Expand Down Expand Up @@ -30,6 +31,9 @@ impl BlockExecutorProvider for MockExecutorProvider {

type BatchExecutor<DB: Database<Error: Into<ProviderError> + Display>> = Self;

type ParallelExecutor<DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>> =
Self;

fn executor<DB>(&self, _: DB) -> Self::Executor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>,
Expand All @@ -43,6 +47,13 @@ impl BlockExecutorProvider for MockExecutorProvider {
{
self.clone()
}

fn parallel_executor<DB>(&self, _: DB) -> Self::ParallelExecutor<DB>
where
DB: ParallelDatabase<Error: Into<ProviderError> + Display + Clone>,
{
self.clone()
}
}

impl<DB> Executor<DB> for MockExecutorProvider {
Expand Down

0 comments on commit 52472e6

Please sign in to comment.