From 98b42470c7e025c115630ee86c8eee5615bc290c Mon Sep 17 00:00:00 2001 From: refcell Date: Wed, 29 Jan 2025 11:50:37 -0500 Subject: [PATCH] feat(optimism): Isthmus Precompiles --- Cargo.lock | 1 + crates/optimism/Cargo.toml | 1 + crates/optimism/src/bls12.rs | 29 ++++++++++++++++++++++ crates/optimism/src/handler/precompiles.rs | 20 ++++++++++++--- crates/optimism/src/lib.rs | 1 + crates/precompile/src/bls12_381/pairing.rs | 2 +- 6 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 crates/optimism/src/bls12.rs diff --git a/Cargo.lock b/Cargo.lock index 2081056e53..d2fbbe199d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3548,6 +3548,7 @@ dependencies = [ "revm-database", "revm-inspector", "revm-precompile", + "revm-primitives", "rstest 0.23.0", "serde", ] diff --git a/crates/optimism/Cargo.toml b/crates/optimism/Cargo.toml index 78e0250458..a6cd9c2dcc 100644 --- a/crates/optimism/Cargo.toml +++ b/crates/optimism/Cargo.toml @@ -24,6 +24,7 @@ all = "warn" [dependencies] # revm revm.workspace = true +primitives.workspace = true precompile = { workspace = true, features = ["secp256r1"] } inspector.workspace = true derive_more.workspace = true diff --git a/crates/optimism/src/bls12.rs b/crates/optimism/src/bls12.rs new file mode 100644 index 0000000000..8e186fa8ad --- /dev/null +++ b/crates/optimism/src/bls12.rs @@ -0,0 +1,29 @@ +//! BLS12-381 precompile with input size limits for Optimism. + +use precompile::{ + bls12_381, {PrecompileError, PrecompileResult, PrecompileWithAddress}, +}; +use primitives::Bytes; + +pub mod pair { + use super::*; + + pub const ISTHMUS_MAX_INPUT_SIZE: usize = 235008; + pub const ISTHMUS: PrecompileWithAddress = + PrecompileWithAddress(precompile::u64_to_address(bls12_381::pairing::ADDRESS), |input, gas_limit| { + run_pair(input, gas_limit) + }); + + pub fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { + if input.len() > ISTHMUS_MAX_INPUT_SIZE { + return Err(PrecompileError::Other( + "BLS12-381 pairing input is too large".into(), + ).into()); + } + let input = Bytes::copy_from_slice(input); + bls12_381::pairing::pairing( + &input, + gas_limit, + ) + } +} diff --git a/crates/optimism/src/handler/precompiles.rs b/crates/optimism/src/handler/precompiles.rs index 17e96c8695..016672ff85 100644 --- a/crates/optimism/src/handler/precompiles.rs +++ b/crates/optimism/src/handler/precompiles.rs @@ -60,11 +60,12 @@ impl OpPrecompileProvider { | OpSpecId::CANYON | OpSpecId::ECOTONE | OpSpecId::HOLOCENE - | OpSpecId::ISTHMUS, + )) => Self::new(Precompiles::new(spec.into_eth_spec().into())), OpSpec::Op(OpSpecId::FJORD) => Self::new(fjord()), - OpSpec::Op(OpSpecId::GRANITE) - | OpSpec::Eth(SpecId::PRAGUE | SpecId::OSAKA | SpecId::LATEST) => Self::new(granite()), + OpSpec::Op(OpSpecId::GRANITE) => Self::new(granite()), + OpSpec::Op(OpSpecId::ISTHMUS) + | OpSpec::Eth(SpecId::PRAGUE | SpecId::OSAKA | SpecId::LATEST) => Self::new(isthmus()), } } } @@ -91,6 +92,19 @@ pub fn granite() -> &'static Precompiles { }) } +/// Returns precompiles for Isthmus spec. +pub fn isthmus() -> &'static Precompiles { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Precompiles::cancun().clone(); + // Restrict bn256Pairing input size + precompiles.extend([secp256r1::P256VERIFY]); + // Restrict bls12Pairing input size + precompiles.extend([crate::bls12::pair::ISTHMUS]); + Box::new(precompiles) + }) +} + impl PrecompileProvider for OpPrecompileProvider where CTX: CfgGetter, diff --git a/crates/optimism/src/lib.rs b/crates/optimism/src/lib.rs index d3706700b0..094ecabf3d 100644 --- a/crates/optimism/src/lib.rs +++ b/crates/optimism/src/lib.rs @@ -7,6 +7,7 @@ extern crate alloc as std; pub mod api; pub mod bn128; +pub mod bls12; pub mod context; pub mod fast_lz; pub mod handler; diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index bb85f0414b..dbce80ebfd 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -33,7 +33,7 @@ const INPUT_LENGTH: usize = 384; /// target field and 0x00 otherwise. /// /// See also: -pub(super) fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { +pub fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { let input_len = input.len(); if input_len == 0 || input_len % INPUT_LENGTH != 0 { return Err(PrecompileError::Other(format!(