-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(client):
ecrecover
accelerated precompile
## Overview Adds a host-accelerated precompile for `ecrecover` with the FPVM backend.
- Loading branch information
Showing
6 changed files
with
114 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
//! Contains the accelerated version of the `ecrecover` precompile. | ||
|
||
use alloc::{string::ToString, vec::Vec}; | ||
use alloy_primitives::{keccak256, Address, Bytes}; | ||
use anyhow::ensure; | ||
use kona_preimage::{HintWriterClient, PreimageKey, PreimageKeyType, PreimageOracleClient}; | ||
use revm::{ | ||
precompile::{u64_to_address, Error as PrecompileError, PrecompileWithAddress}, | ||
primitives::{Precompile, PrecompileOutput, PrecompileResult}, | ||
}; | ||
|
||
use crate::{HintType, HINT_WRITER, ORACLE_READER}; | ||
|
||
const ECRECOVER_ADDRESS: Address = u64_to_address(1); | ||
|
||
pub(crate) const FPVM_ECRECOVER: PrecompileWithAddress = | ||
PrecompileWithAddress(ECRECOVER_ADDRESS, Precompile::Standard(fpvm_ecrecover)); | ||
|
||
/// Performs an FPVM-accelerated `ecrecover` precompile. | ||
fn fpvm_ecrecover(input: &Bytes, gas_limit: u64) -> PrecompileResult { | ||
const ECRECOVER_BASE: u64 = 3_000; | ||
|
||
if ECRECOVER_BASE > gas_limit { | ||
return Err(PrecompileError::OutOfGas.into()); | ||
} | ||
|
||
let result_data = kona_common::block_on(async move { | ||
// Write the hint for the ecrecover precompile run. | ||
let hint_data = &[ECRECOVER_ADDRESS.as_ref(), input.as_ref()]; | ||
HINT_WRITER.write(&HintType::L1Precompile.encode_with(hint_data)).await?; | ||
|
||
// Construct the key hash for the ecrecover precompile run. | ||
let raw_key_data = hint_data.iter().copied().flatten().copied().collect::<Vec<u8>>(); | ||
let key_hash = keccak256(&raw_key_data); | ||
|
||
// Fetch the result of the ecrecover precompile run from the host. | ||
let result_data = | ||
ORACLE_READER.get(PreimageKey::new(*key_hash, PreimageKeyType::Precompile)).await?; | ||
|
||
// Ensure we've received valid result data. | ||
ensure!(!result_data.is_empty(), "Invalid result data"); | ||
|
||
// Ensure we've not received an error from the host. | ||
ensure!(result_data[0] != 0, "Error executing ecrecover precompile in host"); | ||
|
||
// Return the result data. | ||
Ok(result_data[1..].to_vec()) | ||
}) | ||
.map_err(|e| PrecompileError::Other(e.to_string()))?; | ||
|
||
Ok(PrecompileOutput::new(ECRECOVER_BASE, result_data.into())) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
//! Contains the [PrecompileOverride] trait implementation for the FPVM-accelerated precompiles. | ||
|
||
use alloc::sync::Arc; | ||
use kona_executor::PrecompileOverride; | ||
use kona_mpt::{TrieDB, TrieDBFetcher, TrieDBHinter}; | ||
use revm::{ | ||
handler::register::EvmHandler, precompile::PrecompileSpecId, ContextPrecompiles, State, | ||
}; | ||
|
||
mod ecrecover; | ||
|
||
/// The [PrecompileOverride] implementation for the FPVM-accelerated precompiles. | ||
#[derive(Debug)] | ||
pub struct FPVMPrecompileOverride<F, H> | ||
where | ||
F: TrieDBFetcher, | ||
H: TrieDBHinter, | ||
{ | ||
_phantom: core::marker::PhantomData<(F, H)>, | ||
} | ||
|
||
impl<F, H> Default for FPVMPrecompileOverride<F, H> | ||
where | ||
F: TrieDBFetcher, | ||
H: TrieDBHinter, | ||
{ | ||
fn default() -> Self { | ||
Self { _phantom: core::marker::PhantomData::<(F, H)> } | ||
} | ||
} | ||
|
||
impl<F, H> PrecompileOverride<F, H> for FPVMPrecompileOverride<F, H> | ||
where | ||
F: TrieDBFetcher, | ||
H: TrieDBHinter, | ||
{ | ||
fn set_precompiles(handler: &mut EvmHandler<'_, (), &mut State<TrieDB<F, H>>>) { | ||
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]; | ||
ctx_precompiles.extend(override_precompiles); | ||
|
||
ctx_precompiles | ||
}); | ||
} | ||
} |