diff --git a/Cargo.lock b/Cargo.lock index d26cc4b..fc1591c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -838,6 +838,15 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "buddy_system_allocator" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0108968a3a2dab95b089c0fc3f1afa7759aa5ebe6f1d86d206d6f7ba726eb" +dependencies = [ + "spin 0.9.8", +] + [[package]] name = "byte-slice-cast" version = "1.2.2" @@ -1789,10 +1798,49 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "kona-client" +version = "1.0.1" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-evm", + "alloy-op-evm", + "alloy-primitives 1.1.0", + "alloy-rlp", + "alloy-rpc-types-engine", + "async-trait", + "cfg-if", + "kona-derive", + "kona-driver", + "kona-executor", + "kona-genesis", + "kona-interop", + "kona-mpt", + "kona-preimage", + "kona-proof", + "kona-proof-interop", + "kona-protocol", + "kona-registry", + "kona-std-fpvm", + "kona-std-fpvm-proc", + "lru", + "op-alloy-consensus", + "op-alloy-rpc-types-engine", + "op-revm", + "revm", + "serde", + "serde_json", + "spin 0.10.0", + "thiserror 2.0.12", + "tracing", +] + [[package]] name = "kona-derive" version = "0.3.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ "alloy-consensus", "alloy-eips", @@ -1803,7 +1851,7 @@ dependencies = [ "kona-genesis", "kona-hardforks", "kona-protocol", - "kona-rpc", + "op-alloy-consensus", "op-alloy-rpc-types-engine", "thiserror 2.0.12", "tracing", @@ -1812,7 +1860,7 @@ dependencies = [ [[package]] name = "kona-driver" version = "0.3.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ "alloy-consensus", "alloy-evm", @@ -1823,7 +1871,6 @@ dependencies = [ "kona-executor", "kona-genesis", "kona-protocol", - "kona-rpc", "op-alloy-consensus", "op-alloy-rpc-types-engine", "spin 0.10.0", @@ -1834,7 +1881,7 @@ dependencies = [ [[package]] name = "kona-executor" version = "0.3.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ "alloy-consensus", "alloy-eips", @@ -1858,7 +1905,7 @@ dependencies = [ [[package]] name = "kona-genesis" version = "0.3.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ "alloy-consensus", "alloy-eips", @@ -1877,7 +1924,7 @@ dependencies = [ [[package]] name = "kona-hardforks" version = "0.3.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ "alloy-eips", "alloy-primitives 1.1.0", @@ -1885,10 +1932,31 @@ dependencies = [ "op-alloy-consensus", ] +[[package]] +name = "kona-interop" +version = "0.3.0" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives 1.1.0", + "alloy-rlp", + "alloy-sol-types 1.1.0", + "async-trait", + "derive_more 2.0.1", + "kona-genesis", + "kona-protocol", + "kona-registry", + "op-alloy-consensus", + "serde", + "thiserror 2.0.12", + "tracing", +] + [[package]] name = "kona-mpt" version = "0.2.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ "alloy-primitives 1.1.0", "alloy-rlp", @@ -1900,7 +1968,7 @@ dependencies = [ [[package]] name = "kona-preimage" version = "0.3.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ "alloy-primitives 1.1.0", "async-trait", @@ -1911,7 +1979,7 @@ dependencies = [ [[package]] name = "kona-proof" version = "0.3.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ "alloy-consensus", "alloy-eips", @@ -1931,7 +1999,6 @@ dependencies = [ "kona-preimage", "kona-protocol", "kona-registry", - "kona-rpc", "lazy_static", "lru", "op-alloy-consensus", @@ -1944,10 +2011,42 @@ dependencies = [ "tracing", ] +[[package]] +name = "kona-proof-interop" +version = "0.2.0" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-evm", + "alloy-op-evm", + "alloy-primitives 1.1.0", + "alloy-rlp", + "alloy-rpc-types-engine", + "async-trait", + "kona-executor", + "kona-genesis", + "kona-interop", + "kona-mpt", + "kona-preimage", + "kona-proof", + "kona-protocol", + "kona-registry", + "op-alloy-consensus", + "op-alloy-rpc-types-engine", + "op-revm", + "revm", + "serde", + "serde_json", + "spin 0.10.0", + "thiserror 2.0.12", + "tracing", +] + [[package]] name = "kona-protocol" version = "0.3.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ "alloc-no-stdlib", "alloy-consensus", @@ -1963,6 +2062,7 @@ dependencies = [ "miniz_oxide", "op-alloy-consensus", "op-alloy-rpc-types", + "op-alloy-rpc-types-engine", "rand 0.9.1", "thiserror 2.0.12", "tracing", @@ -1972,7 +2072,7 @@ dependencies = [ [[package]] name = "kona-registry" version = "0.3.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ "alloy-chains", "alloy-primitives 1.1.0", @@ -1984,27 +2084,37 @@ dependencies = [ ] [[package]] -name = "kona-rpc" +name = "kona-serde" version = "0.2.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ - "alloy-eips", "alloy-primitives 1.1.0", - "derive_more 2.0.1", - "kona-protocol", - "op-alloy-consensus", - "op-alloy-rpc-types-engine", + "serde", + "serde_json", +] + +[[package]] +name = "kona-std-fpvm" +version = "0.2.0" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" +dependencies = [ + "async-trait", + "buddy_system_allocator", + "cfg-if", + "kona-preimage", "thiserror 2.0.12", ] [[package]] -name = "kona-serde" +name = "kona-std-fpvm-proc" version = "0.2.0" -source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.0#a1172e46a743c63c9f0a0f13a444144e38d29355" +source = "git+https://github.com/anton-rs/kona?rev=kona-client%2Fv1.0.1#9d1ace6bd9a8bfac650f3323a3f1b3c91db46135" dependencies = [ - "alloy-primitives 1.1.0", - "serde", - "serde_json", + "cfg-if", + "kona-std-fpvm", + "proc-macro2", + "quote", + "syn 2.0.100", ] [[package]] @@ -2412,16 +2522,15 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "optimism-derivation" -version = "0.1.0" +version = "0.1.1" dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-evm", - "alloy-op-evm", "alloy-primitives 1.1.0", "ark-ff", "async-trait", "hashbrown 0.15.2", + "kona-client", "kona-derive", "kona-driver", "kona-executor", @@ -2429,7 +2538,6 @@ dependencies = [ "kona-preimage", "kona-proof", "kzg-rs", - "op-revm", "prost", "prost-derive", "revm", @@ -2441,7 +2549,7 @@ dependencies = [ [[package]] name = "optimism-elc" -version = "0.1.0" +version = "0.1.1" dependencies = [ "alloy-consensus", "alloy-primitives 1.1.0", @@ -3472,6 +3580,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spin" diff --git a/Cargo.toml b/Cargo.toml index 199ab45..5a98b3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,27 +22,27 @@ ethereum-consensus = { git = "https://github.com/datachainlab/ethereum-light-cli ethereum-light-client-verifier = { git = "https://github.com/datachainlab/ethereum-light-client-rs", rev = "v0.2.0", default-features = false } # Kona -kona-mpt = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } -kona-client = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } -kona-host = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } -kona-proof = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } -kona-preimage = {git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } -kona-executor = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } -kona-driver = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } -kona-providers-alloy= { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } -kona-genesis = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } -kona-protocol = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } -kona-derive = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.0", default-features = false } +kona-mpt = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } +kona-client = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } +kona-host = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } +kona-proof = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } +kona-preimage = {git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } +kona-executor = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } +kona-driver = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } +kona-providers-alloy= { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } +kona-genesis = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } +kona-protocol = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } +kona-derive = { git="https://github.com/anton-rs/kona", rev= "kona-client/v1.0.1", default-features = false } # Alloy -alloy-consensus = { version = "0.15.6", default-features = false } -alloy-primitives = { version = "1.0.0", default-features = false } -alloy-eips = { version = "0.15.6", default-features = false } +alloy-consensus = { version = "0.15.8", default-features = false } +alloy-primitives = { version = "1.1.0", default-features = false } +alloy-eips = { version = "0.15.8", default-features = false } alloy-trie = { version = "0.8.0", default-features = false } # OP Alloy -op-alloy-rpc-types-engine = { version = "0.15.1", default-features = false } -op-alloy-consensus= { version = "0.15.1", default-features = false } +op-alloy-rpc-types-engine = { version = "0.15.2", default-features = false } +op-alloy-consensus= { version = "0.15.2", default-features = false } # Ethereum revm = { version = "22.0.1", default-features = false } @@ -54,7 +54,7 @@ alloy-op-evm = { version = "0.6.0", default-features = false } sha2 = { version = "0.10.8", default-features = false } c-kzg = { version = "2.0.0", default-features = false } ark-ff = { version = "0.5.0", default-features = false } -secp256k1 = { version = "0.30.0", default-features = false } +secp256k1 = { version = "0.31.0", default-features = false } ark-bls12-381 = { version = "0.5.0", default-features = false } [patch."crates-io"] diff --git a/derivation/Cargo.toml b/derivation/Cargo.toml index bdf7fdd..640e701 100644 --- a/derivation/Cargo.toml +++ b/derivation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "optimism-derivation" -version = "0.1.0" +version = "0.1.1" edition = "2021" [dependencies] @@ -14,18 +14,13 @@ kona-driver = { workspace = true } kona-derive = { workspace = true } kona-proof = { workspace = true } kona-genesis = { workspace = true, features = ["serde"] } +kona-client = { workspace = true } # Alloy alloy-primitives = { workspace = true } alloy-consensus = { workspace = true} alloy-eips = { workspace = true } -# Revm -revm = { workspace = true } -op-revm = { workspace = true } -alloy-evm = { workspace = true } -alloy-op-evm = { workspace = true } - # Cryptography ark-ff = { workspace = true } sha2 = { workspace = true} diff --git a/derivation/src/derivation.rs b/derivation/src/derivation.rs index f0ee173..c5d7c3a 100644 --- a/derivation/src/derivation.rs +++ b/derivation/src/derivation.rs @@ -1,23 +1,23 @@ use crate::errors; use crate::errors::Error; -use crate::fpvm_evm::FpvmOpEvmFactory; -use crate::oracle::MemoryOracleClient; +use crate::oracle::{MemoryOracleClient, NopeHintWriter}; use alloc::sync::Arc; use alloy_consensus::Header; use alloy_primitives::{Sealed, B256}; use core::clone::Clone; use core::fmt::Debug; +use kona_client::fpvm_evm::FpvmOpEvmFactory; +use kona_client::single::fetch_safe_head_hash; +use kona_derive::sources::EthereumDataSource; use kona_driver::Driver; use kona_executor::TrieDBProvider; use kona_genesis::RollupConfig; -use kona_preimage::{CommsClient, PreimageKey}; -use kona_proof::errors::OracleProviderError; +use kona_proof::sync::new_oracle_pipeline_cursor; use kona_proof::{ executor::KonaExecutor, l1::{OracleBlobProvider, OracleL1ChainProvider, OraclePipeline}, l2::OracleL2ChainProvider, - sync::new_pipeline_cursor, - BootInfo, HintType, + BootInfo, }; use serde::{Deserialize, Serialize}; @@ -82,7 +82,7 @@ impl Derivation { .header_by_hash(safe_head_hash) .map(|header| Sealed::new_unchecked(header, safe_head_hash))?; - let cursor = new_pipeline_cursor( + let cursor = new_oracle_pipeline_cursor( rollup_config.as_ref(), safe_head, &mut l1_provider, @@ -91,17 +91,19 @@ impl Derivation { .await?; l2_provider.set_cursor(cursor.clone()); + let da_provider = + EthereumDataSource::new_from_parts(l1_provider.clone(), beacon, &rollup_config); let pipeline = OraclePipeline::new( rollup_config.clone(), cursor.clone(), oracle.clone(), - beacon, + da_provider, l1_provider.clone(), l2_provider.clone(), ) .await?; - let evm_factory = FpvmOpEvmFactory::new(oracle_for_preimage); + let evm_factory = FpvmOpEvmFactory::new(NopeHintWriter, oracle_for_preimage); let executor = KonaExecutor::new( rollup_config.as_ref(), l2_provider.clone(), @@ -133,27 +135,3 @@ impl Derivation { Ok(header) } } - -pub async fn fetch_safe_head_hash( - caching_oracle: &O, - agreed_l2_output_root: B256, -) -> Result -where - O: CommsClient, -{ - let mut output_preimage = [0u8; 128]; - HintType::StartingL2Output - .with_data(&[agreed_l2_output_root.as_ref()]) - .send(caching_oracle) - .await?; - caching_oracle - .get_exact( - PreimageKey::new_keccak256(*agreed_l2_output_root), - output_preimage.as_mut(), - ) - .await?; - - output_preimage[96..128] - .try_into() - .map_err(OracleProviderError::SliceConversion) -} diff --git a/derivation/src/fpvm_evm/factory.rs b/derivation/src/fpvm_evm/factory.rs deleted file mode 100644 index acff515..0000000 --- a/derivation/src/fpvm_evm/factory.rs +++ /dev/null @@ -1,82 +0,0 @@ -//! [`EvmFactory`] implementation for the EVM in the FPVM environment. - -use super::precompiles::OpFpvmPrecompiles; -use crate::oracle::MemoryOracleClient; -use alloy_evm::{Database, EvmEnv, EvmFactory}; -use alloy_op_evm::OpEvm; -use op_revm::{ - DefaultOp, OpContext, OpEvm as RevmOpEvm, OpHaltReason, OpSpecId, OpTransaction, - OpTransactionError, -}; -use revm::{ - context::{result::EVMError, Evm as RevmEvm, EvmData, TxEnv}, - handler::instructions::EthInstructions, - inspector::NoOpInspector, - Context, Inspector, -}; - -/// Factory producing [`OpEvm`]s with FPVM-accelerated precompile overrides enabled. -#[derive(Debug, Clone)] -pub struct FpvmOpEvmFactory { - /// The oracle reader. - oracle_reader: MemoryOracleClient, -} - -impl FpvmOpEvmFactory { - /// Creates a new [`FpvmOpEvmFactory`]. - pub fn new(oracle_reader: MemoryOracleClient) -> Self { - Self { oracle_reader } - } -} - -impl EvmFactory for FpvmOpEvmFactory { - type Evm>> = OpEvm; - type Context = OpContext; - type Tx = OpTransaction; - type Error = - EVMError; - type HaltReason = OpHaltReason; - type Spec = OpSpecId; - - fn create_evm( - &self, - db: DB, - input: EvmEnv, - ) -> Self::Evm { - let spec_id = *input.spec_id(); - let ctx = Context::op() - .with_db(db) - .with_block(input.block_env) - .with_cfg(input.cfg_env); - let revm_evm = RevmOpEvm(RevmEvm { - data: EvmData { - ctx, - inspector: NoOpInspector {}, - }, - instruction: EthInstructions::new_mainnet(), - precompiles: OpFpvmPrecompiles::new_with_spec(spec_id, self.oracle_reader.clone()), - }); - - OpEvm::new(revm_evm, false) - } - - fn create_evm_with_inspector>>( - &self, - db: DB, - input: EvmEnv, - inspector: I, - ) -> Self::Evm { - let spec_id = *input.spec_id(); - let ctx = Context::op() - .with_db(db) - .with_block(input.block_env) - .with_cfg(input.cfg_env); - let revm_evm = RevmOpEvm(RevmEvm { - data: EvmData { ctx, inspector }, - instruction: EthInstructions::new_mainnet(), - precompiles: OpFpvmPrecompiles::new_with_spec(spec_id, self.oracle_reader.clone()), - }); - - OpEvm::new(revm_evm, true) - } -} diff --git a/derivation/src/fpvm_evm/mod.rs b/derivation/src/fpvm_evm/mod.rs deleted file mode 100644 index 12e30bb..0000000 --- a/derivation/src/fpvm_evm/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! Custom [`EvmFactory`] for the fault proof virtual machine's EVM. -//! -//! [`EvmFactory`]: alloy_evm::EvmFactory - -mod precompiles; - -mod factory; -pub use factory::FpvmOpEvmFactory; diff --git a/derivation/src/fpvm_evm/precompiles/bls12_g1_add.rs b/derivation/src/fpvm_evm/precompiles/bls12_g1_add.rs deleted file mode 100644 index 620d3aa..0000000 --- a/derivation/src/fpvm_evm/precompiles/bls12_g1_add.rs +++ /dev/null @@ -1,83 +0,0 @@ -//! Contains the accelerated precompile for the BLS12-381 curve G1 Point Addition. -//! -//! BLS12-381 is introduced in [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537). -//! -//! For constants and logic, see the [revm implementation]. -//! -//! [revm implementation]: https://github.com/bluealloy/revm/blob/main/crates/precompile/src/bls12_381/g1_add.rs - -use crate::fpvm_evm::precompiles::utils::precompile_run; -use alloc::string::ToString; -use kona_preimage::{HintWriterClient, PreimageOracleClient}; -use revm::precompile::{ - bls12_381, - bls12_381_const::{G1_ADD_BASE_GAS_FEE, G1_ADD_INPUT_LENGTH}, - PrecompileError, PrecompileOutput, PrecompileResult, -}; - -/// Performs an FPVM-accelerated BLS12-381 G1 addition check. -/// -/// Notice, there is no input size limit for this precompile. -/// See: -pub(crate) fn fpvm_bls12_g1_add( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - if G1_ADD_BASE_GAS_FEE > gas_limit { - return Err(PrecompileError::OutOfGas); - } - - let input_len = input.len(); - if input_len != G1_ADD_INPUT_LENGTH { - return Err(PrecompileError::Other(alloc::format!( - "G1 addition input length should be {G1_ADD_INPUT_LENGTH} bytes, was {input_len}" - ))); - } - - let result_data = kona_proof::block_on(precompile_run! { - oracle_reader, - &[bls12_381::g1_add::PRECOMPILE.address().as_slice(), &G1_ADD_BASE_GAS_FEE.to_be_bytes(), input] - }) - .map_err(|e| PrecompileError::Other(e.to_string()))?; - - Ok(PrecompileOutput::new( - G1_ADD_BASE_GAS_FEE, - result_data.into(), - )) -} - -#[cfg(test)] -mod test { - use super::*; - use crate::fpvm_evm::precompiles::test_utils::{execute_native_precompile, TestOracleReader}; - - #[test] - fn test_accelerated_bls12_381_g1_add() { - let oracle = TestOracleReader::new(); - - // G1.INF + G1.INF = G1.INF - let input = [0u8; G1_ADD_INPUT_LENGTH]; - let accelerated_result = fpvm_bls12_g1_add(&input, u64::MAX, &oracle).unwrap(); - let native_result = - execute_native_precompile(*bls12_381::g1_add::PRECOMPILE.address(), input, u64::MAX) - .unwrap(); - - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_bls12_381_g1_add_bad_input_len() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_bls12_g1_add(&[], u64::MAX, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::Other(_))); - } - - #[test] - fn test_accelerated_bls12_381_g1_add_bad_gas_limit() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_bls12_g1_add(&[], 0, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::OutOfGas)); - } -} diff --git a/derivation/src/fpvm_evm/precompiles/bls12_g1_msm.rs b/derivation/src/fpvm_evm/precompiles/bls12_g1_msm.rs deleted file mode 100644 index 5b5e703..0000000 --- a/derivation/src/fpvm_evm/precompiles/bls12_g1_msm.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! Contains the accelerated precompile for the BLS12-381 curve G1 MSM. -//! -//! BLS12-381 is introduced in [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537). -//! -//! For constants and logic, see the [revm implementation]. -//! -//! [revm implementation]: https://github.com/bluealloy/revm/blob/main/crates/precompile/src/bls12_381/g1_msm.rs - -use crate::fpvm_evm::precompiles::utils::{msm_required_gas, precompile_run}; -use alloc::string::ToString; -use kona_preimage::{HintWriterClient, PreimageOracleClient}; -use revm::precompile::{ - bls12_381, - bls12_381_const::{DISCOUNT_TABLE_G1_MSM, G1_MSM_BASE_GAS_FEE, G1_MSM_INPUT_LENGTH}, - PrecompileError, PrecompileOutput, PrecompileResult, -}; - -/// The maximum input size for the BLS12-381 g1 msm operation after the Isthmus Hardfork. -/// -/// See: -const BLS12_MAX_G1_MSM_SIZE_ISTHMUS: usize = 513760; - -/// Performs an FPVM-accelerated `bls12` g1 msm check precompile call after the Isthmus Hardfork. -pub(crate) fn fpvm_bls12_g1_msm( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - if input.len() > BLS12_MAX_G1_MSM_SIZE_ISTHMUS { - return Err(PrecompileError::Other(alloc::format!( - "G1MSM input length must be at most {}", - BLS12_MAX_G1_MSM_SIZE_ISTHMUS - ))); - } - - let input_len = input.len(); - if input_len == 0 || input_len % G1_MSM_INPUT_LENGTH != 0 { - return Err(PrecompileError::Other(alloc::format!( - "G1MSM input length should be multiple of {}, was {}", - G1_MSM_INPUT_LENGTH, - input_len - ))); - } - - let k = input_len / G1_MSM_INPUT_LENGTH; - let required_gas = msm_required_gas(k, &DISCOUNT_TABLE_G1_MSM, G1_MSM_BASE_GAS_FEE); - if required_gas > gas_limit { - return Err(PrecompileError::OutOfGas); - } - - let result_data = kona_proof::block_on(precompile_run! { - oracle_reader, - &[bls12_381::g1_msm::PRECOMPILE.address().as_slice(), &required_gas.to_be_bytes(), input] - }) - .map_err(|e| PrecompileError::Other(e.to_string()))?; - - Ok(PrecompileOutput::new(required_gas, result_data.into())) -} - -#[cfg(test)] -mod test { - use alloy_primitives::hex; - - use super::*; - use crate::fpvm_evm::precompiles::test_utils::{execute_native_precompile, TestOracleReader}; - - #[test] - fn test_accelerated_bls12_381_g1_msm() { - let oracle = TestOracleReader::new(); - // https://raw.githubusercontent.com/ethereum/execution-spec-tests/a1c4eeff347a64ad6c5aedd51314d4ffc067346b/tests/prague/eip2537_bls_12_381_precompiles/vectors/msm_G1_bls.json - let input = hex!("0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000002"); - let expected = hex!("000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28"); - - let accelerated_result = fpvm_bls12_g1_msm(&input, 12000, &oracle).unwrap(); - let native_result = - execute_native_precompile(*bls12_381::g1_msm::PRECOMPILE.address(), input, 12000) - .unwrap(); - - assert_eq!(accelerated_result.bytes.as_ref(), expected.as_ref()); - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_bls12_381_g1_msm_bad_input_len_isthmus() { - let oracle = TestOracleReader::new(); - let accelerated_result = - fpvm_bls12_g1_msm(&[0u8; BLS12_MAX_G1_MSM_SIZE_ISTHMUS + 1], u64::MAX, &oracle) - .unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::Other(_))); - } - - #[test] - fn test_accelerated_bls12_381_g1_msm_bad_input_len() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_bls12_g1_msm(&[], u64::MAX, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::Other(_))); - } - - #[test] - fn test_accelerated_bls12_381_g1_msm_bad_gas_limit() { - let oracle = TestOracleReader::new(); - let accelerated_result = - fpvm_bls12_g1_msm(&[0u8; G1_MSM_INPUT_LENGTH], 0, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::OutOfGas)); - } -} diff --git a/derivation/src/fpvm_evm/precompiles/bls12_g2_add.rs b/derivation/src/fpvm_evm/precompiles/bls12_g2_add.rs deleted file mode 100644 index 4f87a7f..0000000 --- a/derivation/src/fpvm_evm/precompiles/bls12_g2_add.rs +++ /dev/null @@ -1,82 +0,0 @@ -//! Contains the accelerated precompile for the BLS12-381 curve G2 Point Addition. -//! -//! BLS12-381 is introduced in [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537). -//! -//! For constants and logic, see the [revm implementation]. -//! -//! [revm implementation]: https://github.com/bluealloy/revm/blob/main/crates/precompile/src/bls12_381/g2_add.rs - -use crate::fpvm_evm::precompiles::utils::precompile_run; -use alloc::string::ToString; -use kona_preimage::{HintWriterClient, PreimageOracleClient}; -use revm::precompile::{ - bls12_381, - bls12_381_const::{G2_ADD_BASE_GAS_FEE, G2_ADD_INPUT_LENGTH}, - PrecompileError, PrecompileOutput, PrecompileResult, -}; - -/// Performs an FPVM-accelerated BLS12-381 G2 addition check. -/// -/// Notice, there is no input size limit for this precompile. -/// See: -pub(crate) fn fpvm_bls12_g2_add( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - if G2_ADD_BASE_GAS_FEE > gas_limit { - return Err(PrecompileError::OutOfGas); - } - - let input_len = input.len(); - if input_len != G2_ADD_INPUT_LENGTH { - return Err(PrecompileError::Other(alloc::format!( - "G2 addition input length should be {G2_ADD_INPUT_LENGTH} bytes, was {input_len}" - ))); - } - - let result_data = kona_proof::block_on(precompile_run! { - oracle_reader, - &[bls12_381::g2_add::PRECOMPILE.address().as_slice(), &G2_ADD_BASE_GAS_FEE.to_be_bytes(), input] - }) - .map_err(|e| PrecompileError::Other(e.to_string()))?; - - Ok(PrecompileOutput::new( - G2_ADD_BASE_GAS_FEE, - result_data.into(), - )) -} - -#[cfg(test)] -mod test { - use super::*; - use crate::fpvm_evm::precompiles::test_utils::{execute_native_precompile, TestOracleReader}; - - #[test] - fn test_accelerated_bls12_381_g2_add() { - let oracle = TestOracleReader::new(); - // G2.INF + G2.INF = G2.INF - let input = [0u8; G2_ADD_INPUT_LENGTH]; - let accelerated_result = fpvm_bls12_g2_add(&input, u64::MAX, &oracle).unwrap(); - let native_result = - execute_native_precompile(*bls12_381::g2_add::PRECOMPILE.address(), input, u64::MAX) - .unwrap(); - - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_bls12_381_g2_add_bad_input_len() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_bls12_g2_add(&[], u64::MAX, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::Other(_))); - } - - #[test] - fn test_accelerated_bls12_381_g2_add_bad_gas_limit() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_bls12_g2_add(&[], 0, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::OutOfGas)); - } -} diff --git a/derivation/src/fpvm_evm/precompiles/bls12_g2_msm.rs b/derivation/src/fpvm_evm/precompiles/bls12_g2_msm.rs deleted file mode 100644 index f13a395..0000000 --- a/derivation/src/fpvm_evm/precompiles/bls12_g2_msm.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Contains the accelerated precompile for the BLS12-381 curve G2 MSM. -//! -//! BLS12-381 is introduced in [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537). -//! -//! For constants and logic, see the [revm implementation]. -//! -//! [revm implementation]: https://github.com/bluealloy/revm/blob/main/crates/precompile/src/bls12_381/g2_msm.rs - -use crate::fpvm_evm::precompiles::utils::{msm_required_gas, precompile_run}; -use alloc::string::ToString; -use kona_preimage::{HintWriterClient, PreimageOracleClient}; -use revm::precompile::{ - bls12_381, - bls12_381_const::{DISCOUNT_TABLE_G2_MSM, G2_MSM_BASE_GAS_FEE, G2_MSM_INPUT_LENGTH}, - PrecompileError, PrecompileOutput, PrecompileResult, -}; - -/// The maximum input size for the BLS12-381 g2 msm operation after the Isthmus Hardfork. -/// -/// See: -const BLS12_MAX_G2_MSM_SIZE_ISTHMUS: usize = 488448; - -/// Performs an FPVM-accelerated BLS12-381 G2 msm check. -pub(crate) fn fpvm_bls12_g2_msm( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - let input_len = input.len(); - - if input_len > BLS12_MAX_G2_MSM_SIZE_ISTHMUS { - return Err(PrecompileError::Other(alloc::format!( - "G2MSM input length must be at most {}", - BLS12_MAX_G2_MSM_SIZE_ISTHMUS - ))); - } - - if input_len == 0 || input_len % G2_MSM_INPUT_LENGTH != 0 { - return Err(PrecompileError::Other(alloc::format!( - "G2MSM input length should be multiple of {}, was {}", - G2_MSM_INPUT_LENGTH, - input_len - ))); - } - - let k = input_len / G2_MSM_INPUT_LENGTH; - let required_gas = msm_required_gas(k, &DISCOUNT_TABLE_G2_MSM, G2_MSM_BASE_GAS_FEE); - if required_gas > gas_limit { - return Err(PrecompileError::OutOfGas); - } - - let result_data = kona_proof::block_on(precompile_run! { - oracle_reader, - &[bls12_381::g2_msm::PRECOMPILE.address().as_slice(), &required_gas.to_be_bytes(), input] - }) - .map_err(|e| PrecompileError::Other(e.to_string()))?; - - Ok(PrecompileOutput::new(required_gas, result_data.into())) -} - -#[cfg(test)] -mod test { - use alloy_primitives::hex; - - use super::*; - use crate::fpvm_evm::precompiles::test_utils::{execute_native_precompile, TestOracleReader}; - - #[test] - fn test_accelerated_bls12_381_g2_msm() { - let oracle = TestOracleReader::new(); - // https://raw.githubusercontent.com/ethereum/execution-spec-tests/a1c4eeff347a64ad6c5aedd51314d4ffc067346b/tests/prague/eip2537_bls_12_381_precompiles/vectors/msm_G2_bls.json - let input = hex!("00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000002"); - let expected = hex!("000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3"); - - let accelerated_result = fpvm_bls12_g2_msm(&input, 22500, &oracle).unwrap(); - let native_result = - execute_native_precompile(*bls12_381::g2_msm::PRECOMPILE.address(), input, 22500) - .unwrap(); - - assert_eq!(accelerated_result.bytes.as_ref(), expected.as_ref()); - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_bls12_381_g2_msm_bad_input_len_isthmus() { - let oracle = TestOracleReader::new(); - let accelerated_result = - fpvm_bls12_g2_msm(&[0u8; BLS12_MAX_G2_MSM_SIZE_ISTHMUS + 1], u64::MAX, &oracle) - .unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::Other(_))); - } - - #[test] - fn test_accelerated_bls12_381_g2_msm_bad_input_len() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_bls12_g2_msm(&[], u64::MAX, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::Other(_))); - } - - #[test] - fn test_accelerated_bls12_381_g2_msm_bad_gas_limit() { - let oracle = TestOracleReader::new(); - let accelerated_result = - fpvm_bls12_g2_msm(&[0u8; G2_MSM_INPUT_LENGTH], 0, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::OutOfGas)); - } -} diff --git a/derivation/src/fpvm_evm/precompiles/bls12_map_fp.rs b/derivation/src/fpvm_evm/precompiles/bls12_map_fp.rs deleted file mode 100644 index f8c4347..0000000 --- a/derivation/src/fpvm_evm/precompiles/bls12_map_fp.rs +++ /dev/null @@ -1,87 +0,0 @@ -//! Contains the accelerated precompile for the BLS12-381 curve FP to G1 Mapping. -//! -//! BLS12-381 is introduced in [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537). -//! -//! For constants and logic, see the [revm implementation]. -//! -//! [revm implementation]: https://github.com/bluealloy/revm/blob/main/crates/precompile/src/bls12_381/map_fp_to_g1.rs - -use crate::fpvm_evm::precompiles::utils::precompile_run; -use alloc::string::ToString; -use kona_preimage::{HintWriterClient, PreimageOracleClient}; -use revm::precompile::{ - bls12_381, - bls12_381_const::{MAP_FP_TO_G1_BASE_GAS_FEE, PADDED_FP_LENGTH}, - PrecompileError, PrecompileOutput, PrecompileResult, -}; - -/// Performs an FPVM-accelerated BLS12-381 map fp check. -/// -/// Notice, there is no input size limit for this precompile. -/// See: -pub(crate) fn fpvm_bls12_map_fp( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - if MAP_FP_TO_G1_BASE_GAS_FEE > gas_limit { - return Err(PrecompileError::OutOfGas); - } - - if input.len() != PADDED_FP_LENGTH { - return Err(PrecompileError::Other(alloc::format!( - "MAP_FP_TO_G1 input should be {PADDED_FP_LENGTH} bytes, was {}", - input.len() - ))); - } - - let result_data = kona_proof::block_on(precompile_run! { - oracle_reader, - &[bls12_381::map_fp_to_g1::PRECOMPILE.address().as_slice(), &MAP_FP_TO_G1_BASE_GAS_FEE.to_be_bytes(), input] - }) - .map_err(|e| PrecompileError::Other(e.to_string()))?; - - Ok(PrecompileOutput::new( - MAP_FP_TO_G1_BASE_GAS_FEE, - result_data.into(), - )) -} - -#[cfg(test)] -mod test { - use alloy_primitives::hex; - - use super::*; - use crate::fpvm_evm::precompiles::test_utils::{execute_native_precompile, TestOracleReader}; - - #[test] - fn test_accelerated_bls12_381_map_fp_g1() { - let oracle = TestOracleReader::new(); - // https://github.com/ethereum/execution-spec-tests/blob/a1c4eeff347a64ad6c5aedd51314d4ffc067346b/tests/prague/eip2537_bls_12_381_precompiles/vectors/map_fp_to_G1_bls.json - let input = hex!("00000000000000000000000000000000156c8a6a2c184569d69a76be144b5cdc5141d2d2ca4fe341f011e25e3969c55ad9e9b9ce2eb833c81a908e5fa4ac5f03"); - let expected = hex!("00000000000000000000000000000000184bb665c37ff561a89ec2122dd343f20e0f4cbcaec84e3c3052ea81d1834e192c426074b02ed3dca4e7676ce4ce48ba0000000000000000000000000000000004407b8d35af4dacc809927071fc0405218f1401a6d15af775810e4e460064bcc9468beeba82fdc751be70476c888bf3"); - - let accelerated_result = fpvm_bls12_map_fp(&input, 5500, &oracle).unwrap(); - let native_result = - execute_native_precompile(*bls12_381::map_fp_to_g1::PRECOMPILE.address(), input, 5500) - .unwrap(); - - assert_eq!(accelerated_result.bytes.as_ref(), expected.as_ref()); - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_bls12_381_map_fp_g1_bad_gas_limit() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_bls12_map_fp(&[], 0, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::OutOfGas)); - } - - #[test] - fn test_accelerated_bls12_381_map_fp_g1_bad_input_size() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_bls12_map_fp(&[], u64::MAX, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::Other(_))); - } -} diff --git a/derivation/src/fpvm_evm/precompiles/bls12_map_fp2.rs b/derivation/src/fpvm_evm/precompiles/bls12_map_fp2.rs deleted file mode 100644 index e36e2d2..0000000 --- a/derivation/src/fpvm_evm/precompiles/bls12_map_fp2.rs +++ /dev/null @@ -1,91 +0,0 @@ -//! Contains the accelerated precompile for the BLS12-381 curve FP2 to G2 Mapping. -//! -//! BLS12-381 is introduced in [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537). -//! -//! For constants and logic, see the [revm implementation]. -//! -//! [revm implementation]: https://github.com/bluealloy/revm/blob/main/crates/precompile/src/bls12_381/map_fp_to_g1.rs - -use crate::fpvm_evm::precompiles::utils::precompile_run; -use alloc::string::ToString; -use kona_preimage::{HintWriterClient, PreimageOracleClient}; -use revm::precompile::{ - bls12_381, - bls12_381_const::{MAP_FP2_TO_G2_BASE_GAS_FEE, PADDED_FP2_LENGTH}, - PrecompileError, PrecompileOutput, PrecompileResult, -}; - -/// Performs an FPVM-accelerated BLS12-381 map fp2 check. -/// -/// Notice, there is no input size limit for this precompile. -/// See: -pub(crate) fn fpvm_bls12_map_fp2( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - if MAP_FP2_TO_G2_BASE_GAS_FEE > gas_limit { - return Err(PrecompileError::OutOfGas); - } - - if input.len() != PADDED_FP2_LENGTH { - return Err(PrecompileError::Other(alloc::format!( - "MAP_FP2_TO_G2 input should be {PADDED_FP2_LENGTH} bytes, was {}", - input.len() - ))); - } - - let result_data = kona_proof::block_on(precompile_run! { - oracle_reader, - &[bls12_381::map_fp2_to_g2::PRECOMPILE.address().as_slice(), &MAP_FP2_TO_G2_BASE_GAS_FEE.to_be_bytes(), input] - }) - .map_err(|e| PrecompileError::Other(e.to_string()))?; - - Ok(PrecompileOutput::new( - MAP_FP2_TO_G2_BASE_GAS_FEE, - result_data.into(), - )) -} - -#[cfg(test)] -mod test { - use alloy_primitives::hex; - - use super::*; - use crate::fpvm_evm::precompiles::test_utils::execute_native_precompile; - use crate::fpvm_evm::precompiles::test_utils::TestOracleReader; - - #[test] - fn test_accelerated_bls12_381_map_fp_g2() { - let oracle = TestOracleReader::new(); - // https://github.com/ethereum/execution-spec-tests/blob/a1c4eeff347a64ad6c5aedd51314d4ffc067346b/tests/prague/eip2537_bls_12_381_precompiles/vectors/map_fp2_to_G2_bls.json - let input = hex!("0000000000000000000000000000000007355d25caf6e7f2f0cb2812ca0e513bd026ed09dda65b177500fa31714e09ea0ded3a078b526bed3307f804d4b93b040000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b78c"); - let expected = hex!("0000000000000000000000000000000000e7f4568a82b4b7dc1f14c6aaa055edf51502319c723c4dc2688c7fe5944c213f510328082396515734b6612c4e7bb700000000000000000000000000000000126b855e9e69b1f691f816e48ac6977664d24d99f8724868a184186469ddfd4617367e94527d4b74fc86413483afb35b000000000000000000000000000000000caead0fd7b6176c01436833c79d305c78be307da5f6af6c133c47311def6ff1e0babf57a0fb5539fce7ee12407b0a42000000000000000000000000000000001498aadcf7ae2b345243e281ae076df6de84455d766ab6fcdaad71fab60abb2e8b980a440043cd305db09d283c895e3d"); - - let accelerated_result = fpvm_bls12_map_fp2(&input, 23800, &oracle).unwrap(); - let native_result = execute_native_precompile( - *bls12_381::map_fp2_to_g2::PRECOMPILE.address(), - input, - 23800, - ) - .unwrap(); - - assert_eq!(accelerated_result.bytes.as_ref(), expected.as_ref()); - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_bls12_381_map_fp_g2_bad_gas_limit() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_bls12_map_fp2(&[], 0, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::OutOfGas)); - } - - #[test] - fn test_accelerated_bls12_381_map_fp_g2_bad_input_size() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_bls12_map_fp2(&[], u64::MAX, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::Other(_))); - } -} diff --git a/derivation/src/fpvm_evm/precompiles/bls12_pair.rs b/derivation/src/fpvm_evm/precompiles/bls12_pair.rs deleted file mode 100644 index c6405a3..0000000 --- a/derivation/src/fpvm_evm/precompiles/bls12_pair.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! Contains the accelerated precompile for the BLS12-381 curve. -//! -//! BLS12-381 is introduced in [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537). -//! -//! For constants and logic, see the [revm implementation]. -//! -//! [revm implementation]: https://github.com/bluealloy/revm/blob/main/crates/precompile/src/bls12_381/pairing.rs - -use crate::fpvm_evm::precompiles::utils::precompile_run; -use alloc::string::ToString; -use kona_preimage::{HintWriterClient, PreimageOracleClient}; -use revm::precompile::{ - bls12_381, - bls12_381_const::{PAIRING_INPUT_LENGTH, PAIRING_MULTIPLIER_BASE, PAIRING_OFFSET_BASE}, - PrecompileError, PrecompileOutput, PrecompileResult, -}; - -/// The max pairing size for BLS12-381 input given a 20M gas limit. -const BLS12_MAX_PAIRING_SIZE_ISTHMUS: usize = 235_008; - -/// Performs an FPVM-accelerated BLS12-381 pairing check. -pub(crate) fn fpvm_bls12_pairing( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - let input_len = input.len(); - - if input_len > BLS12_MAX_PAIRING_SIZE_ISTHMUS { - return Err(PrecompileError::Other(alloc::format!( - "Pairing input length must be at most {}", - BLS12_MAX_PAIRING_SIZE_ISTHMUS - ))); - } - - if input_len % PAIRING_INPUT_LENGTH != 0 { - return Err(PrecompileError::Other(alloc::format!( - "Pairing input length should be multiple of {PAIRING_INPUT_LENGTH}, was {input_len}" - ))); - } - - let k = input_len / PAIRING_INPUT_LENGTH; - let required_gas: u64 = PAIRING_MULTIPLIER_BASE * k as u64 + PAIRING_OFFSET_BASE; - if required_gas > gas_limit { - return Err(PrecompileError::OutOfGas); - } - - let result_data = kona_proof::block_on(precompile_run! { - oracle_reader, - &[bls12_381::pairing::PRECOMPILE.address().as_slice(), &required_gas.to_be_bytes(), input] - }) - .map_err(|e| PrecompileError::Other(e.to_string()))?; - - Ok(PrecompileOutput::new(required_gas, result_data.into())) -} - -#[cfg(test)] -mod test { - use super::*; - use crate::fpvm_evm::precompiles::test_utils::execute_native_precompile; - use crate::fpvm_evm::precompiles::test_utils::TestOracleReader; - use alloy_primitives::hex; - - #[test] - fn test_accelerated_bls12_381_pairing() { - let oracle = TestOracleReader::new(); - // https://github.com/ethereum/execution-spec-tests/blob/a1c4eeff347a64ad6c5aedd51314d4ffc067346b/tests/prague/eip2537_bls_12_381_precompiles/vectors/pairing_check_bls.json - let input = hex!("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let expected = hex!("0000000000000000000000000000000000000000000000000000000000000001"); - - let accelerated_result = fpvm_bls12_pairing(&input, 70300, &oracle).unwrap(); - let native_result = - execute_native_precompile(*bls12_381::pairing::PRECOMPILE.address(), input, 70300) - .unwrap(); - - assert_eq!(accelerated_result.bytes.as_ref(), expected.as_ref()); - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_bls12_381_pairing_bad_input_len_isthmus() { - let oracle = TestOracleReader::new(); - let accelerated_result = - fpvm_bls12_pairing(&[0u8; BLS12_MAX_PAIRING_SIZE_ISTHMUS + 1], 0, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::Other(_))); - } - - #[test] - fn test_accelerated_bls12_381_pairing_bad_input_len() { - let oracle = TestOracleReader::new(); - let accelerated_result = - fpvm_bls12_pairing(&[0u8; PAIRING_INPUT_LENGTH - 1], 0, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::Other(_))); - } - - #[test] - fn test_accelerated_bls12_381_pairing_bad_gas_limit() { - let oracle = TestOracleReader::new(); - let accelerated_result = - fpvm_bls12_pairing(&[0u8; PAIRING_INPUT_LENGTH], 0, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::OutOfGas)); - } -} diff --git a/derivation/src/fpvm_evm/precompiles/bn128_pair.rs b/derivation/src/fpvm_evm/precompiles/bn128_pair.rs deleted file mode 100644 index 2a37920..0000000 --- a/derivation/src/fpvm_evm/precompiles/bn128_pair.rs +++ /dev/null @@ -1,130 +0,0 @@ -//! Contains the accelerated version of the `ecPairing` precompile. - -use crate::fpvm_evm::precompiles::utils::precompile_run; -use alloc::string::ToString; -use kona_preimage::{HintWriterClient, PreimageOracleClient}; -use revm::precompile::{ - bn128::{ - pair::{self, ISTANBUL_PAIR_BASE, ISTANBUL_PAIR_PER_POINT}, - PAIR_ELEMENT_LEN, - }, - PrecompileError, PrecompileOutput, PrecompileResult, -}; - -const BN256_MAX_PAIRING_SIZE_GRANITE: usize = 112_687; - -/// Runs the FPVM-accelerated `ecpairing` precompile call. -pub(crate) fn fpvm_bn128_pair( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - let gas_used = - (input.len() / PAIR_ELEMENT_LEN) as u64 * ISTANBUL_PAIR_PER_POINT + ISTANBUL_PAIR_BASE; - - if gas_used > gas_limit { - return Err(PrecompileError::OutOfGas); - } - - if input.len() % PAIR_ELEMENT_LEN != 0 { - return Err(PrecompileError::Bn128PairLength); - } - - let result_data = kona_proof::block_on(precompile_run! { - oracle_reader, - &[pair::ISTANBUL.address().as_slice(), &gas_used.to_be_bytes(), input] - }) - .map_err(|e| PrecompileError::Other(e.to_string()))?; - - Ok(PrecompileOutput::new(gas_used, result_data.into())) -} - -/// Runs the FPVM-accelerated `ecpairing` precompile call, with the input size limited by the -/// Granite hardfork. -pub(crate) fn fpvm_bn128_pair_granite( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - if input.len() > BN256_MAX_PAIRING_SIZE_GRANITE { - return Err(PrecompileError::Bn128PairLength); - } - - fpvm_bn128_pair(input, gas_limit, oracle_reader) -} - -#[cfg(test)] -mod test { - use super::*; - use crate::fpvm_evm::precompiles::test_utils::{execute_native_precompile, TestOracleReader}; - use alloy_primitives::hex; - - #[test] - fn test_accelerated_bn128_pairing() { - let oracle = TestOracleReader::new(); - const EXPECTED_RESULT: [u8; 32] = - hex!("0000000000000000000000000000000000000000000000000000000000000001"); - - let input = hex!( - "2cf44499d5d27bb186308b7af7af02ac5bc9eeb6a3d147c186b21fb1b76e18da2c0f001f52110ccfe69108924926e45f0b0c868df0e7bde1fe16d3242dc715f61fb19bb476f6b9e44e2a32234da8212f61cd63919354bc06aef31e3cfaff3ebc22606845ff186793914e03e21df544c34ffe2f2f3504de8a79d9159eca2d98d92bd368e28381e8eccb5fa81fc26cf3f048eea9abfdd85d7ed3ab3698d63e4f902fe02e47887507adf0ff1743cbac6ba291e66f59be6bd763950bb16041a0a85e000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd451971ff0471b09fa93caaf13cbf443c1aede09cc4328f5a62aad45f40ec133eb4091058a3141822985733cbdddfed0fd8d6c104e9e9eff40bf5abfef9ab163bc72a23af9a5ce2ba2796c1f4e453a370eb0af8c212d9dc9acd8fc02c2e907baea223a8eb0b0996252cb548a4487da97b02422ebc0e834613f954de6c7e0afdc1fc" - ); - let accelerated_result = fpvm_bn128_pair(&input, u64::MAX, &oracle).unwrap(); - let native_result = - execute_native_precompile(*pair::ISTANBUL.address(), input, u64::MAX).unwrap(); - - assert_eq!(accelerated_result.bytes.as_ref(), EXPECTED_RESULT.as_ref()); - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_bn128_pairing_granite() { - let oracle = TestOracleReader::new(); - const EXPECTED_RESULT: [u8; 32] = - hex!("0000000000000000000000000000000000000000000000000000000000000001"); - - let input = hex!( - "2cf44499d5d27bb186308b7af7af02ac5bc9eeb6a3d147c186b21fb1b76e18da2c0f001f52110ccfe69108924926e45f0b0c868df0e7bde1fe16d3242dc715f61fb19bb476f6b9e44e2a32234da8212f61cd63919354bc06aef31e3cfaff3ebc22606845ff186793914e03e21df544c34ffe2f2f3504de8a79d9159eca2d98d92bd368e28381e8eccb5fa81fc26cf3f048eea9abfdd85d7ed3ab3698d63e4f902fe02e47887507adf0ff1743cbac6ba291e66f59be6bd763950bb16041a0a85e000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd451971ff0471b09fa93caaf13cbf443c1aede09cc4328f5a62aad45f40ec133eb4091058a3141822985733cbdddfed0fd8d6c104e9e9eff40bf5abfef9ab163bc72a23af9a5ce2ba2796c1f4e453a370eb0af8c212d9dc9acd8fc02c2e907baea223a8eb0b0996252cb548a4487da97b02422ebc0e834613f954de6c7e0afdc1fc" - ); - let accelerated_result = fpvm_bn128_pair_granite(&input, u64::MAX, &oracle).unwrap(); - let native_result = - execute_native_precompile(*pair::ISTANBUL.address(), input, u64::MAX).unwrap(); - - assert_eq!(accelerated_result.bytes.as_ref(), EXPECTED_RESULT.as_ref()); - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_bn128_pairing_not_enough_gas() { - let oracle = TestOracleReader::new(); - let input = hex!("0badc0de"); - let accelerated_result = fpvm_bn128_pair(&input, 0, &oracle).unwrap_err(); - - assert!(matches!(accelerated_result, PrecompileError::OutOfGas)); - } - - #[test] - fn test_accelerated_bn128_pairing_bad_input_len() { - let oracle = TestOracleReader::new(); - let input = hex!("0badc0de"); - let accelerated_result = fpvm_bn128_pair(&input, u64::MAX, &oracle).unwrap_err(); - - assert!(matches!( - accelerated_result, - PrecompileError::Bn128PairLength - )); - } - - #[test] - fn test_accelerated_bn128_pairing_bad_input_len_granite() { - let oracle = TestOracleReader::new(); - let input = [0u8; BN256_MAX_PAIRING_SIZE_GRANITE + 1]; - let accelerated_result = fpvm_bn128_pair(&input, u64::MAX, &oracle).unwrap_err(); - - assert!(matches!( - accelerated_result, - PrecompileError::Bn128PairLength - )); - } -} diff --git a/derivation/src/fpvm_evm/precompiles/ecrecover.rs b/derivation/src/fpvm_evm/precompiles/ecrecover.rs deleted file mode 100644 index 0b6839c..0000000 --- a/derivation/src/fpvm_evm/precompiles/ecrecover.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! Contains the accelerated version of the `ecrecover` precompile. - -use crate::fpvm_evm::precompiles::utils::precompile_run; -use alloc::string::ToString; -use alloy_primitives::Address; -use kona_preimage::{HintWriterClient, PreimageOracleClient}; -use revm::precompile::{PrecompileError, PrecompileOutput, PrecompileResult}; - -/// Address of the `ecrecover` precompile. -pub(crate) const ECRECOVER_ADDR: Address = revm::precompile::u64_to_address(1); - -/// Runs the FPVM-accelerated `ecrecover` precompile call. -pub(crate) fn fpvm_ec_recover( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - const ECRECOVER_BASE: u64 = 3_000; - - if ECRECOVER_BASE > gas_limit { - return Err(PrecompileError::OutOfGas); - } - - let result_data = kona_proof::block_on(precompile_run! { - oracle_reader, - &[ECRECOVER_ADDR.as_slice(), &ECRECOVER_BASE.to_be_bytes(), input] - }) - .map_err(|e| PrecompileError::Other(e.to_string())) - .unwrap_or_default(); - - Ok(PrecompileOutput::new(ECRECOVER_BASE, result_data.into())) -} - -#[cfg(test)] -mod test { - use super::*; - use crate::fpvm_evm::precompiles::test_utils::{execute_native_precompile, TestOracleReader}; - use alloy_primitives::hex; - - #[test] - fn test_accelerated_ecrecover() { - let oracle = TestOracleReader::new(); - const EXPECTED_RESULT: [u8; 32] = - hex!("0000000000000000000000007156526fbd7a3c72969b54f64e42c10fbb768c8a"); - - let input = hex!( - "456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3000000000000000000000000000000000000000000000000000000000000001c9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac80388256084f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada" - ); - let accelerated_result = fpvm_ec_recover(&input, u64::MAX, &oracle).unwrap(); - let native_result = execute_native_precompile(ECRECOVER_ADDR, input, u64::MAX).unwrap(); - - assert_eq!(accelerated_result.bytes.as_ref(), EXPECTED_RESULT.as_ref()); - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_ecrecover_out_of_gas() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_ec_recover(&[], 0, &oracle).unwrap_err(); - - assert!(matches!(accelerated_result, PrecompileError::OutOfGas)); - } -} diff --git a/derivation/src/fpvm_evm/precompiles/kzg_point_eval.rs b/derivation/src/fpvm_evm/precompiles/kzg_point_eval.rs deleted file mode 100644 index a3af24d..0000000 --- a/derivation/src/fpvm_evm/precompiles/kzg_point_eval.rs +++ /dev/null @@ -1,84 +0,0 @@ -//! Contains the accelerated version of the KZG point evaluation precompile. - -use crate::fpvm_evm::precompiles::utils::precompile_run; -use alloc::string::ToString; -use alloy_primitives::Address; -use kona_preimage::{HintWriterClient, PreimageOracleClient}; -use revm::precompile::{PrecompileError, PrecompileOutput, PrecompileResult}; - -/// Address of the KZG point evaluation precompile. -pub(crate) const KZG_POINT_EVAL_ADDR: Address = revm::precompile::u64_to_address(0x0A); - -/// Runs the FPVM-accelerated `kzgPointEval` precompile call. -pub(crate) fn fpvm_kzg_point_eval( - input: &[u8], - gas_limit: u64, - oracle_reader: &T, -) -> PrecompileResult { - const GAS_COST: u64 = 50_000; - - if gas_limit < GAS_COST { - return Err(PrecompileError::OutOfGas); - } - - if input.len() != 192 { - return Err(PrecompileError::BlobInvalidInputLength); - } - - let result_data = kona_proof::block_on(precompile_run! { - oracle_reader, - &[KZG_POINT_EVAL_ADDR.as_slice(), &GAS_COST.to_be_bytes(), input] - }) - .map_err(|e| PrecompileError::Other(e.to_string()))?; - - Ok(PrecompileOutput::new(GAS_COST, result_data.into())) -} - -#[cfg(test)] -mod test { - use super::*; - use crate::fpvm_evm::precompiles::test_utils::{execute_native_precompile, TestOracleReader}; - use alloy_eips::eip4844::VERSIONED_HASH_VERSION_KZG; - use alloy_primitives::hex; - use sha2::{Digest, Sha256}; - - #[test] - fn test_accelerated_kzg_point_eval() { - let oracle = TestOracleReader::new(); - let commitment = hex!("8f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7").to_vec(); - let mut versioned_hash = Sha256::digest(&commitment).to_vec(); - versioned_hash[0] = VERSIONED_HASH_VERSION_KZG; - let z = hex!("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000").to_vec(); - let y = hex!("1522a4a7f34e1ea350ae07c29c96c7e79655aa926122e95fe69fcbd932ca49e9").to_vec(); - let proof = hex!("a62ad71d14c5719385c0686f1871430475bf3a00f0aa3f7b8dd99a9abc2160744faf0070725e00b60ad9a026a15b1a8c").to_vec(); - - let input = [versioned_hash, z, y, commitment, proof].concat(); - - let expected_result = hex!("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); - - let accelerated_result = fpvm_kzg_point_eval(&input, u64::MAX, &oracle).unwrap(); - let native_result = - execute_native_precompile(KZG_POINT_EVAL_ADDR, input, u64::MAX).unwrap(); - - assert_eq!(accelerated_result.bytes.as_ref(), expected_result.as_ref()); - assert_eq!(accelerated_result.bytes, native_result.bytes); - assert_eq!(accelerated_result.gas_used, native_result.gas_used); - } - - #[test] - fn test_accelerated_kzg_point_eval_out_of_gas() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_kzg_point_eval(&[], 0, &oracle).unwrap_err(); - assert!(matches!(accelerated_result, PrecompileError::OutOfGas)); - } - - #[test] - fn test_accelerated_kzg_point_eval_bad_input_size() { - let oracle = TestOracleReader::new(); - let accelerated_result = fpvm_kzg_point_eval(&[], u64::MAX, &oracle).unwrap_err(); - assert!(matches!( - accelerated_result, - PrecompileError::BlobInvalidInputLength - )); - } -} diff --git a/derivation/src/fpvm_evm/precompiles/mod.rs b/derivation/src/fpvm_evm/precompiles/mod.rs deleted file mode 100644 index 402a552..0000000 --- a/derivation/src/fpvm_evm/precompiles/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! Contains the [`PrecompileProvider`] implementation that serves FPVM-accelerated OP Stack -//! precompiles. -//! -//! [`PrecompileProvider`]: revm::handler::PrecompileProvider - -mod provider; -pub(crate) use provider::OpFpvmPrecompiles; - -mod bls12_g1_add; -mod bls12_g1_msm; -mod bls12_g2_add; -mod bls12_g2_msm; -mod bls12_map_fp; -mod bls12_map_fp2; -mod bls12_pair; -mod bn128_pair; -mod ecrecover; -mod kzg_point_eval; -mod utils; - -#[cfg(test)] -mod test_utils; diff --git a/derivation/src/fpvm_evm/precompiles/provider.rs b/derivation/src/fpvm_evm/precompiles/provider.rs deleted file mode 100644 index 3b2cdd3..0000000 --- a/derivation/src/fpvm_evm/precompiles/provider.rs +++ /dev/null @@ -1,224 +0,0 @@ -//! [`PrecompileProvider`] for FPVM-accelerated OP Stack precompiles. - -use crate::fpvm_evm::precompiles::{ - ecrecover::ECRECOVER_ADDR, kzg_point_eval::KZG_POINT_EVAL_ADDR, -}; -use crate::oracle::MemoryOracleClient; -use alloc::{boxed::Box, string::String, vec, vec::Vec}; -use alloy_primitives::{Address, Bytes}; -use op_revm::{ - precompiles::{fjord, granite, isthmus}, - OpSpecId, -}; -use revm::{ - context::{Cfg, ContextTr}, - handler::{EthPrecompiles, PrecompileProvider}, - interpreter::{Gas, InputsImpl, InstructionResult, InterpreterResult}, - precompile::{bls12_381_const, bn128, PrecompileError, PrecompileResult, Precompiles}, - primitives::{hardfork::SpecId, hash_map::HashMap}, -}; - -/// The FPVM-accelerated precompiles. -#[derive(Debug)] -pub struct OpFpvmPrecompiles { - /// The default [`EthPrecompiles`] provider. - inner: EthPrecompiles, - /// The accelerated precompiles for the current [`OpSpecId`]. - accelerated_precompiles: HashMap, - /// The [`OpSpecId`] of the precompiles. - spec: OpSpecId, - /// The inner [`OracleReader`]. - oracle_reader: MemoryOracleClient, -} - -impl OpFpvmPrecompiles { - /// Create a new precompile provider with the given [`OpSpecId`]. - #[inline] - pub fn new_with_spec(spec: OpSpecId, oracle_reader: MemoryOracleClient) -> Self { - let precompiles = match spec { - spec @ (OpSpecId::BEDROCK - | OpSpecId::REGOLITH - | OpSpecId::CANYON - | OpSpecId::ECOTONE) => Precompiles::new(spec.into_eth_spec().into()), - OpSpecId::FJORD => fjord(), - OpSpecId::GRANITE | OpSpecId::HOLOCENE => granite(), - OpSpecId::ISTHMUS | OpSpecId::INTEROP | OpSpecId::OSAKA => isthmus(), - }; - - let accelerated_precompiles = match spec { - OpSpecId::BEDROCK | OpSpecId::REGOLITH | OpSpecId::CANYON => accelerated_bedrock(), - OpSpecId::ECOTONE | OpSpecId::FJORD => accelerated_ecotone(), - OpSpecId::GRANITE | OpSpecId::HOLOCENE => accelerated_granite(), - OpSpecId::ISTHMUS | OpSpecId::INTEROP | OpSpecId::OSAKA => accelerated_isthmus(), - }; - - Self { - inner: EthPrecompiles { - precompiles, - spec: SpecId::default(), - }, - accelerated_precompiles: accelerated_precompiles - .into_iter() - .map(|p| (p.address, p.precompile)) - .collect(), - spec, - oracle_reader, - } - } -} - -impl PrecompileProvider for OpFpvmPrecompiles -where - CTX: ContextTr>, -{ - type Output = InterpreterResult; - - #[inline] - fn set_spec(&mut self, spec: ::Spec) -> bool { - if spec == self.spec { - return false; - } - *self = Self::new_with_spec(spec, self.oracle_reader.clone()); - true - } - - #[inline] - fn run( - &mut self, - _context: &mut CTX, - address: &Address, - inputs: &InputsImpl, - _is_static: bool, - gas_limit: u64, - ) -> Result, String> { - let mut result = InterpreterResult { - result: InstructionResult::Return, - gas: Gas::new(gas_limit), - output: Bytes::new(), - }; - - // Priority: - // 1. If the precompile has an accelerated version, use that. - // 2. If the precompile is not accelerated, use the default version. - // 3. If the precompile is not found, return None. - let output = if let Some(accelerated) = self.accelerated_precompiles.get(address) { - (accelerated)(&inputs.input, gas_limit, &self.oracle_reader) - } else if let Some(precompile) = self.inner.precompiles.get(address) { - (*precompile)(&inputs.input, gas_limit) - } else { - return Ok(None); - }; - - match output { - Ok(output) => { - let underflow = result.gas.record_cost(output.gas_used); - assert!(underflow, "Gas underflow is not possible"); - result.result = InstructionResult::Return; - result.output = output.bytes; - } - Err(PrecompileError::Fatal(e)) => return Err(e), - Err(e) => { - result.result = if e.is_oog() { - InstructionResult::PrecompileOOG - } else { - InstructionResult::PrecompileError - }; - } - } - - Ok(Some(result)) - } - - #[inline] - fn warm_addresses(&self) -> Box> { - self.inner.warm_addresses() - } - - #[inline] - fn contains(&self, address: &Address) -> bool { - self.inner.contains(address) - } -} - -/// A precompile function that can be accelerated by the FPVM. -type AcceleratedPrecompileFn = fn(&[u8], u64, &MemoryOracleClient) -> PrecompileResult; - -/// A tuple type for accelerated precompiles with an associated [`Address`]. -struct AcceleratedPrecompile { - /// The address of the precompile. - address: Address, - /// The precompile function. - precompile: AcceleratedPrecompileFn, -} - -impl AcceleratedPrecompile { - /// Create a new accelerated precompile. - fn new(address: Address, precompile: AcceleratedPrecompileFn) -> Self { - Self { - address, - precompile, - } - } -} - -/// The accelerated precompiles for the bedrock spec. -fn accelerated_bedrock() -> Vec { - vec![ - AcceleratedPrecompile::new(ECRECOVER_ADDR, super::ecrecover::fpvm_ec_recover), - AcceleratedPrecompile::new(bn128::pair::ADDRESS, super::bn128_pair::fpvm_bn128_pair), - ] -} - -/// The accelerated precompiles for the ecotone spec. -fn accelerated_ecotone() -> Vec { - let mut base = accelerated_bedrock(); - base.push(AcceleratedPrecompile::new( - KZG_POINT_EVAL_ADDR, - super::kzg_point_eval::fpvm_kzg_point_eval, - )); - base -} - -/// The accelerated precompiles for the granite spec. -fn accelerated_granite() -> Vec { - let mut base = accelerated_ecotone(); - base.push(AcceleratedPrecompile::new( - bn128::pair::ADDRESS, - super::bn128_pair::fpvm_bn128_pair_granite, - )); - base -} - -/// The accelerated precompiles for the isthmus spec. -fn accelerated_isthmus() -> Vec { - let mut base = accelerated_granite(); - base.push(AcceleratedPrecompile::new( - bls12_381_const::G1_ADD_ADDRESS, - super::bls12_g1_add::fpvm_bls12_g1_add, - )); - base.push(AcceleratedPrecompile::new( - bls12_381_const::G1_MSM_ADDRESS, - super::bls12_g1_msm::fpvm_bls12_g1_msm, - )); - base.push(AcceleratedPrecompile::new( - bls12_381_const::G2_ADD_ADDRESS, - super::bls12_g2_add::fpvm_bls12_g2_add, - )); - base.push(AcceleratedPrecompile::new( - bls12_381_const::G2_MSM_ADDRESS, - super::bls12_g2_msm::fpvm_bls12_g2_msm, - )); - base.push(AcceleratedPrecompile::new( - bls12_381_const::MAP_FP_TO_G1_ADDRESS, - super::bls12_map_fp::fpvm_bls12_map_fp, - )); - base.push(AcceleratedPrecompile::new( - bls12_381_const::MAP_FP2_TO_G2_ADDRESS, - super::bls12_map_fp2::fpvm_bls12_map_fp2, - )); - base.push(AcceleratedPrecompile::new( - bls12_381_const::PAIRING_ADDRESS, - super::bls12_pair::fpvm_bls12_pairing, - )); - base -} diff --git a/derivation/src/fpvm_evm/precompiles/test_utils.rs b/derivation/src/fpvm_evm/precompiles/test_utils.rs deleted file mode 100644 index 0b479fa..0000000 --- a/derivation/src/fpvm_evm/precompiles/test_utils.rs +++ /dev/null @@ -1,92 +0,0 @@ -//! Test utilities for accelerated precompiles. -use crate::oracle::MemoryOracleClient; -use crate::types::Preimage; -use alloc::boxed::Box; -use alloc::sync::Arc; -use alloc::vec; -use alloc::vec::Vec; -use alloy_primitives::{keccak256, Address, Bytes}; -use async_trait::async_trait; -use kona_preimage::{ - errors::PreimageOracleResult, HintWriterClient, PreimageKey, PreimageKeyType, - PreimageOracleClient, -}; -use kona_proof::{Hint, HintType}; -use revm::precompile::PrecompileResult; - -/// Runs a test with a mock host that serves [`HintType::L1Precompile`] hints and preimages. The -/// closure accepts the client's [`HintWriter`] and [`OracleReader`] as arguments. -/// Executes a precompile on [`revm`]. -pub(crate) fn execute_native_precompile>( - address: Address, - input: T, - gas: u64, -) -> PrecompileResult { - let precompiles = revm::handler::EthPrecompiles::default(); - let Some(precompile) = precompiles.precompiles.get(&address) else { - panic!("Precompile not found"); - }; - precompile(&input.into(), gas) -} - -#[derive(Clone, Debug, Default)] -pub struct TestOracleReader { - inner: Arc>, -} - -impl TestOracleReader { - pub fn new() -> Self { - Self { - inner: Arc::new(spin::RwLock::new(MemoryOracleClient::default())), - } - } -} - -#[async_trait] -impl PreimageOracleClient for TestOracleReader { - async fn get(&self, key: PreimageKey) -> PreimageOracleResult> { - self.inner.read().get(key).await - } - - async fn get_exact(&self, key: PreimageKey, buf: &mut [u8]) -> PreimageOracleResult<()> { - self.inner.read().get_exact(key, buf).await - } -} - -#[async_trait] -impl HintWriterClient for TestOracleReader { - async fn write(&self, last_hint: &str) -> PreimageOracleResult<()> { - let parsed_hint = last_hint.parse::>().unwrap(); - if matches!(parsed_hint.ty, HintType::L1Precompile) { - let address = Address::from_slice(&parsed_hint.data.as_ref()[..20]); - let gas = u64::from_be_bytes(parsed_hint.data.as_ref()[20..28].try_into().unwrap()); - let input = parsed_hint.data[28..].to_vec(); - let input_hash = keccak256(parsed_hint.data.as_ref()); - - let result = execute_native_precompile(address, input, gas).map_or_else( - |_| vec![0u8; 1], - |raw_res| { - let mut res = Vec::with_capacity(1 + raw_res.bytes.len()); - res.push(0x01); - res.extend_from_slice(&raw_res.bytes); - res - }, - ); - - let preimage_hash = Preimage::new( - PreimageKey::new_keccak256(*input_hash), - parsed_hint.data.into(), - ); - let preimage_data = Preimage::new( - PreimageKey::new(*input_hash, PreimageKeyType::Precompile), - result, - ); - - let mut lock = self.inner.write(); - *lock = MemoryOracleClient::try_from(vec![preimage_hash, preimage_data]).unwrap(); - Ok(()) - } else { - panic!("Unexpected hint type: {:?}", parsed_hint.ty); - } - } -} diff --git a/derivation/src/fpvm_evm/precompiles/utils.rs b/derivation/src/fpvm_evm/precompiles/utils.rs deleted file mode 100644 index 5110a0e..0000000 --- a/derivation/src/fpvm_evm/precompiles/utils.rs +++ /dev/null @@ -1,84 +0,0 @@ -//! Utility functions for precompiles - -// TODO: replace this with revm::precompiles::bls12_381::msm::msm_required_gas -// once the `msm` module is public. As of v19.4.0 the `msm` module is private. -/// Implements the gas schedule for G1/G2 Multiscalar-multiplication assuming 30 -/// MGas/second, see also: -#[inline] -pub(crate) fn msm_required_gas(k: usize, discount_table: &[u16], multiplication_cost: u64) -> u64 { - /// Amount used to calculate the multi-scalar-multiplication discount - const MSM_MULTIPLIER: u64 = 1000; - - if k == 0 { - return 0; - } - - let index = core::cmp::min(k - 1, discount_table.len() - 1); - let discount = discount_table[index] as u64; - - (k as u64 * discount * multiplication_cost) / MSM_MULTIPLIER -} - -/// A macro that generates an async block that sends a hint to the host, constructs a key hash -/// from the hint data, fetches the result of the precompile run from the host, and returns the -/// result data. -/// -/// The macro takes the following arguments: -/// - `hint_data`: The hint data to send to the host. -#[macro_export] -macro_rules! precompile_run { - ($oracle_reader:expr, $hint_data:expr) => { - async move { - use alloc::{string::ToString, vec::Vec}; - use kona_preimage::{errors::PreimageOracleError, PreimageKey, PreimageKeyType}; - use kona_proof::errors::OracleProviderError; - - // Write the hint for the precompile run. - let hint_data = $hint_data; - #[cfg(test)] - { - $oracle_reader - .write( - &kona_proof::HintType::L1Precompile - .with_data(hint_data) - .encode(), - ) - .await?; - } - - // Construct the key hash for the precompile run. - let raw_key_data = hint_data - .iter() - .copied() - .flatten() - .copied() - .collect::>(); - let key_hash = alloy_primitives::keccak256(&raw_key_data); - - // Fetch the result of the precompile run from the host. - let result_data = $oracle_reader - .get(PreimageKey::new(*key_hash, PreimageKeyType::Precompile)) - .await - .map_err(OracleProviderError::Preimage)?; - - // Ensure we've received valid result data. - if result_data.is_empty() { - return Err(OracleProviderError::Preimage(PreimageOracleError::Other( - "Invalid result data".to_string(), - ))); - } - - // Ensure we've not received an error from the host. - if result_data[0] == 0 { - return Err(OracleProviderError::Preimage(PreimageOracleError::Other( - "Error executing precompile in host".to_string(), - ))); - } - - // Return the result data. - Ok(result_data[1..].to_vec()) - } - }; -} - -pub(crate) use precompile_run; diff --git a/derivation/src/lib.rs b/derivation/src/lib.rs index 57e29eb..bb6d352 100644 --- a/derivation/src/lib.rs +++ b/derivation/src/lib.rs @@ -3,7 +3,6 @@ extern crate alloc; pub mod derivation; pub mod errors; -pub mod fpvm_evm; pub mod oracle; pub mod types; diff --git a/derivation/src/oracle.rs b/derivation/src/oracle.rs index 3385087..f7aa28b 100644 --- a/derivation/src/oracle.rs +++ b/derivation/src/oracle.rs @@ -62,6 +62,15 @@ impl PreimageOracleClient for MemoryOracleClient { } } +#[async_trait::async_trait] +impl HintWriterClient for NopeHintWriter { + async fn write(&self, _hint: &str) -> PreimageOracleResult<()> { + Ok(()) + } +} + +#[derive(Clone, Debug)] +pub struct NopeHintWriter; #[async_trait::async_trait] impl HintWriterClient for MemoryOracleClient { async fn write(&self, _hint: &str) -> PreimageOracleResult<()> { diff --git a/light-client/Cargo.toml b/light-client/Cargo.toml index 84a3ad3..447a9d1 100644 --- a/light-client/Cargo.toml +++ b/light-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "optimism-elc" -version = "0.1.0" +version = "0.1.1" edition = "2021" [dependencies] @@ -11,7 +11,7 @@ rlp = { workspace = true } prost = { workspace = true } # derivation -optimism-derivation = { version = "0.1.0", path = "../derivation", default-features = false } +optimism-derivation = { version = "0.1.1", path = "../derivation", default-features = false } optimism-ibc-proto = { version = "0.1.0", path = "../proto", default-features = false } # LCP