Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(executor): Expose full revm Handler #475

Merged
merged 2 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions bin/client/src/fault/handler/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//! Contains the [KonaHandleRegister] function for registering the FPVM-accelerated precompiles.
//!
//! [KonaHandleRegister]: kona_executor::KonaHandleRegister

use alloc::sync::Arc;
use kona_mpt::{TrieDB, TrieDBFetcher, TrieDBHinter};
use revm::{
handler::register::EvmHandler, precompile::PrecompileSpecId, primitives::SpecId,
ContextPrecompiles, State,
};

mod bn128_pair;
mod ecrecover;
mod kzg_point_eval;

/// The [KonaHandleRegister] function for registering the FPVM-accelerated precompiles.
///
/// [KonaHandleRegister]: kona_executor::KonaHandleRegister
pub(crate) fn fpvm_handle_register<F, H>(
handler: &mut EvmHandler<'_, (), &mut State<&mut TrieDB<F, H>>>,
) where
F: TrieDBFetcher,
H: TrieDBHinter,
{
let spec_id = handler.cfg.spec_id;

handler.pre_execution.load_precompiles = Arc::new(move || {
let mut ctx_precompiles =
ContextPrecompiles::new(PrecompileSpecId::from_spec_id(spec_id)).clone();

// Extend with FPVM-accelerated precompiles
let override_precompiles = [
ecrecover::FPVM_ECRECOVER,
bn128_pair::FPVM_ECPAIRING,
kzg_point_eval::FPVM_KZG_POINT_EVAL,
];
ctx_precompiles.extend(override_precompiles);

// Ensure the secp256r1 P256verify precompile is enabled in the FJORD spec
if spec_id.is_enabled_in(SpecId::FJORD) {
ctx_precompiles.extend([
// EIP-7212: secp256r1 P256verify
revm::precompile::secp256r1::P256VERIFY,
]);
}

ctx_precompiles
});
}
4 changes: 2 additions & 2 deletions bin/client/src/fault/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use kona_common::FileDescriptor;
use kona_preimage::{HintWriter, OracleReader, PipeHandle};

mod precompiles;
pub(crate) use precompiles::FPVMPrecompileOverride;
mod handler;
pub(crate) use handler::fpvm_handle_register;

/// The global preimage oracle reader pipe.
static ORACLE_READER_PIPE: PipeHandle =
Expand Down
65 changes: 0 additions & 65 deletions bin/client/src/fault/precompiles/mod.rs

This file was deleted.

9 changes: 2 additions & 7 deletions bin/client/src/kona.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ use kona_client::{
};
use kona_common_proc::client_entry;
use kona_executor::StatelessL2BlockExecutor;
use kona_preimage::{HintWriter, OracleReader};
use kona_primitives::L2AttributesWithParent;

pub(crate) mod fault;
use fault::{FPVMPrecompileOverride, HINT_WRITER, ORACLE_READER};
use fault::{fpvm_handle_register, HINT_WRITER, ORACLE_READER};

/// The size of the LRU cache in the oracle.
const ORACLE_LRU_SIZE: usize = 1024;
Expand Down Expand Up @@ -61,15 +60,11 @@ fn main() -> Result<()> {
.await?;
let L2AttributesWithParent { attributes, .. } = driver.produce_disputed_payload().await?;

let precompile_overrides = FPVMPrecompileOverride::<
OracleL2ChainProvider<CachingOracle<OracleReader, HintWriter>>,
OracleL2ChainProvider<CachingOracle<OracleReader, HintWriter>>,
>::default();
let mut executor = StatelessL2BlockExecutor::builder(&boot.rollup_config)
.with_parent_header(driver.take_l2_safe_head_header())
.with_fetcher(l2_provider.clone())
.with_hinter(l2_provider)
.with_precompile_overrides(precompile_overrides)
.with_handle_register(fpvm_handle_register)
.build()?;
let Header { number, .. } = *executor.execute_payload(attributes)?;
let output_root = executor.compute_output_root()?;
Expand Down
3 changes: 1 addition & 2 deletions crates/executor/benches/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use alloy_primitives::{address, b256, hex, Bytes, B256};
use alloy_rlp::Decodable;
use anyhow::{anyhow, Result};
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use kona_executor::{NoPrecompileOverride, StatelessL2BlockExecutor};
use kona_executor::StatelessL2BlockExecutor;
use kona_mpt::{NoopTrieDBHinter, TrieDBFetcher};
use kona_primitives::{
L2PayloadAttributes, RollupConfig, OP_BASE_FEE_PARAMS, OP_CANYON_BASE_FEE_PARAMS,
Expand Down Expand Up @@ -81,7 +81,6 @@ fn op_mainnet_exec_bench(
.with_parent_header(pre_state_header.clone().seal_slow())
.with_fetcher(TestdataTrieDBFetcher::new(data_folder))
.with_hinter(NoopTrieDBHinter)
.with_precompile_overrides(NoPrecompileOverride)
.build()
.unwrap();
l2_block_executor.execute_payload(payload_attrs.clone()).unwrap();
Expand Down
36 changes: 16 additions & 20 deletions crates/executor/src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,43 @@
//! Contains the builder pattern for the [StatelessL2BlockExecutor].

use crate::{PrecompileOverride, StatelessL2BlockExecutor};
use crate::StatelessL2BlockExecutor;
use alloy_consensus::{Header, Sealable, Sealed};
use anyhow::Result;
use kona_mpt::{TrieDB, TrieDBFetcher, TrieDBHinter};
use kona_primitives::RollupConfig;
use revm::{db::State, handler::register::EvmHandler};

/// A type alias for the [revm::handler::register::HandleRegister] for kona's block executor.
pub type KonaHandleRegister<F, H> =
for<'i> fn(&mut EvmHandler<'i, (), &mut State<&mut TrieDB<F, H>>>);

/// The builder pattern for the [StatelessL2BlockExecutor].
#[derive(Debug)]
pub struct StatelessL2BlockExecutorBuilder<'a, F, H, PO>
pub struct StatelessL2BlockExecutorBuilder<'a, F, H>
where
F: TrieDBFetcher,
H: TrieDBHinter,
PO: PrecompileOverride<F, H>,
{
/// The [RollupConfig].
config: &'a RollupConfig,
/// The parent [Header] to begin execution from.
parent_header: Option<Sealed<Header>>,
/// The precompile overrides to use during execution.
precompile_overrides: Option<PO>,
/// The [KonaHandleRegister] to use during execution.
handler_register: Option<KonaHandleRegister<F, H>>,
/// The [TrieDBFetcher] to fetch the state trie preimages.
fetcher: Option<F>,
/// The [TrieDBHinter] to hint the state trie preimages.
hinter: Option<H>,
}

impl<'a, F, H, PO> StatelessL2BlockExecutorBuilder<'a, F, H, PO>
impl<'a, F, H> StatelessL2BlockExecutorBuilder<'a, F, H>
where
F: TrieDBFetcher,
H: TrieDBHinter,
PO: PrecompileOverride<F, H>,
{
/// Instantiate a new builder with the given [RollupConfig].
pub fn with_config(config: &'a RollupConfig) -> Self {
Self {
config,
parent_header: None,
precompile_overrides: None,
fetcher: None,
hinter: None,
}
Self { config, parent_header: None, handler_register: None, fetcher: None, hinter: None }
}

/// Set the [Header] to begin execution from.
Expand All @@ -61,14 +58,14 @@
self
}

/// Set the precompile overrides to use during execution.
pub fn with_precompile_overrides(mut self, precompile_overrides: PO) -> Self {
self.precompile_overrides = Some(precompile_overrides);
/// Set the [KonaHandleRegister] for execution.
pub fn with_handle_register(mut self, handler_register: KonaHandleRegister<F, H>) -> Self {
self.handler_register = Some(handler_register);

Check warning on line 63 in crates/executor/src/builder.rs

View check run for this annotation

Codecov / codecov/patch

crates/executor/src/builder.rs#L62-L63

Added lines #L62 - L63 were not covered by tests
self
}

/// Build the [StatelessL2BlockExecutor] from the builder configuration.
pub fn build(self) -> Result<StatelessL2BlockExecutor<'a, F, H, PO>> {
pub fn build(self) -> Result<StatelessL2BlockExecutor<'a, F, H>> {
let fetcher = self.fetcher.ok_or(anyhow::anyhow!("Fetcher not set"))?;
let hinter = self.hinter.ok_or(anyhow::anyhow!("Hinter not set"))?;
let parent_header = self.parent_header.unwrap_or_else(|| {
Expand All @@ -77,11 +74,10 @@
});

let trie_db = TrieDB::new(parent_header.state_root, parent_header, fetcher, hinter);

Ok(StatelessL2BlockExecutor {
config: self.config,
trie_db,
_phantom: core::marker::PhantomData::<PO>,
handler_register: self.handler_register,
})
}
}
50 changes: 23 additions & 27 deletions crates/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@
use tracing::{debug, info};

mod builder;
pub use builder::StatelessL2BlockExecutorBuilder;

mod precompile;
pub use precompile::{NoPrecompileOverride, PrecompileOverride};
pub use builder::{KonaHandleRegister, StatelessL2BlockExecutorBuilder};

mod eip4788;
use eip4788::pre_block_beacon_root_contract_call;
Expand All @@ -43,28 +40,26 @@
/// The block executor for the L2 client program. Operates off of a [TrieDB] backed [State],
/// allowing for stateless block execution of OP Stack blocks.
#[derive(Debug)]
pub struct StatelessL2BlockExecutor<'a, F, H, PO>
pub struct StatelessL2BlockExecutor<'a, F, H>
where
F: TrieDBFetcher,
H: TrieDBHinter,
PO: PrecompileOverride<F, H>,
{
/// The [RollupConfig].
config: &'a RollupConfig,
/// The inner state database component.
trie_db: TrieDB<F, H>,
/// Phantom data for the precompile overrides.
_phantom: core::marker::PhantomData<PO>,
/// The [KonaHandleRegister] to use during execution.
handler_register: Option<KonaHandleRegister<F, H>>,
}

impl<'a, F, H, PO> StatelessL2BlockExecutor<'a, F, H, PO>
impl<'a, F, H> StatelessL2BlockExecutor<'a, F, H>
where
F: TrieDBFetcher,
H: TrieDBHinter,
PO: PrecompileOverride<F, H>,
{
/// Constructs a new [StatelessL2BlockExecutorBuilder] with the given [RollupConfig].
pub fn builder(config: &'a RollupConfig) -> StatelessL2BlockExecutorBuilder<'a, F, H, PO> {
pub fn builder(config: &'a RollupConfig) -> StatelessL2BlockExecutorBuilder<'a, F, H> {
StatelessL2BlockExecutorBuilder::with_config(config)
}

Expand Down Expand Up @@ -128,15 +123,22 @@

// Construct the block-scoped EVM with the given configuration.
// The transaction environment is set within the loop for each transaction.
let mut evm = Evm::builder()
.with_db(&mut state)
.with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(
initialized_cfg.clone(),
initialized_block_env.clone(),
Default::default(),
))
.append_handler_register(PO::set_precompiles)
.build();
let mut evm = {
let mut base = Evm::builder().with_db(&mut state).with_env_with_handler_cfg(
EnvWithHandlerCfg::new_with_cfg_env(
initialized_cfg.clone(),
initialized_block_env.clone(),
Default::default(),
),
);

// If a handler register is provided, append it to the base EVM.
if let Some(handler) = self.handler_register {
base = base.append_handler_register(handler);

Check warning on line 137 in crates/executor/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/executor/src/lib.rs#L137

Added line #L137 was not covered by tests
}

base.build()
};

// Execute the transactions in the payload.
let transactions = payload
Expand Down Expand Up @@ -223,7 +225,7 @@
cumulative_gas_used = cumulative_gas_used
);

// Drop the EVM to rid the exclusive reference to the database.
// Drop the EVM to free the exclusive reference to the database.
drop(evm);

// Merge all state transitions into the cache state.
Expand Down Expand Up @@ -699,7 +701,6 @@
.with_parent_header(header.seal_slow())
.with_fetcher(TestdataTrieDBFetcher::new("block_120794432_exec"))
.with_hinter(NoopTrieDBHinter)
.with_precompile_overrides(NoPrecompileOverride)
.build()
.unwrap();

Expand Down Expand Up @@ -753,7 +754,6 @@
.with_parent_header(parent_header.seal_slow())
.with_fetcher(TestdataTrieDBFetcher::new("block_121049889_exec"))
.with_hinter(NoopTrieDBHinter)
.with_precompile_overrides(NoPrecompileOverride)
.build()
.unwrap();

Expand Down Expand Up @@ -811,7 +811,6 @@
.with_parent_header(parent_header.seal_slow())
.with_fetcher(TestdataTrieDBFetcher::new("block_121003241_exec"))
.with_hinter(NoopTrieDBHinter)
.with_precompile_overrides(NoPrecompileOverride)
.build()
.unwrap();

Expand Down Expand Up @@ -876,7 +875,6 @@
.with_parent_header(parent_header.seal_slow())
.with_fetcher(TestdataTrieDBFetcher::new("block_121057303_exec"))
.with_hinter(NoopTrieDBHinter)
.with_precompile_overrides(NoPrecompileOverride)
.build()
.unwrap();

Expand Down Expand Up @@ -935,7 +933,6 @@
.with_parent_header(parent_header.seal_slow())
.with_fetcher(TestdataTrieDBFetcher::new("block_121065789_exec"))
.with_hinter(NoopTrieDBHinter)
.with_precompile_overrides(NoPrecompileOverride)
.build()
.unwrap();

Expand Down Expand Up @@ -1003,7 +1000,6 @@
.with_parent_header(parent_header.seal_slow())
.with_fetcher(TestdataTrieDBFetcher::new("block_121135704_exec"))
.with_hinter(NoopTrieDBHinter)
.with_precompile_overrides(NoPrecompileOverride)
.build()
.unwrap();

Expand Down
Loading