From ab42581b7462a4b71a88fa5708859071ceaabf8e Mon Sep 17 00:00:00 2001 From: Brian Bland Date: Tue, 6 Aug 2024 16:42:54 -0700 Subject: [PATCH] Add OP-Granite hardfork, limiting bn256Pairing input size (#1685) * Add OP-Granite hardfork, limiting bn256Pairing input size * Move optimism-specific bn128 precompile --- crates/precompile/src/bn128.rs | 2 +- crates/precompile/src/lib.rs | 2 +- crates/primitives/src/specification.rs | 45 ++++++++++- crates/revm/src/optimism.rs | 1 + crates/revm/src/optimism/bn128.rs | 85 ++++++++++++++++++++ crates/revm/src/optimism/handler_register.rs | 7 ++ 6 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 crates/revm/src/optimism/bn128.rs diff --git a/crates/precompile/src/bn128.rs b/crates/precompile/src/bn128.rs index 193cb48af8..416a41672f 100644 --- a/crates/precompile/src/bn128.rs +++ b/crates/precompile/src/bn128.rs @@ -45,7 +45,7 @@ pub mod mul { pub mod pair { use super::*; - const ADDRESS: Address = crate::u64_to_address(8); + pub const ADDRESS: Address = crate::u64_to_address(8); pub const ISTANBUL_PAIR_PER_POINT: u64 = 34_000; pub const ISTANBUL_PAIR_BASE: u64 = 45_000; diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 662dca6a21..488983bcb1 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -297,7 +297,7 @@ impl PrecompileSpecId { #[cfg(feature = "optimism")] BEDROCK | REGOLITH | CANYON => Self::BERLIN, #[cfg(feature = "optimism")] - ECOTONE | FJORD => Self::CANCUN, + ECOTONE | FJORD | GRANITE => Self::CANCUN, } } } diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index 7ab9f370a8..ac3c5a3ede 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -65,8 +65,9 @@ pub enum SpecId { CANCUN = 20, ECOTONE = 21, FJORD = 22, - PRAGUE = 23, - PRAGUE_EOF = 24, + GRANITE = 23, + PRAGUE = 24, + PRAGUE_EOF = 25, #[default] LATEST = u8::MAX, } @@ -120,6 +121,8 @@ impl From<&str> for SpecId { "Ecotone" => SpecId::ECOTONE, #[cfg(feature = "optimism")] "Fjord" => SpecId::FJORD, + #[cfg(feature = "optimism")] + "Granite" => SpecId::GRANITE, _ => Self::LATEST, } } @@ -158,6 +161,8 @@ impl From for &'static str { SpecId::ECOTONE => "Ecotone", #[cfg(feature = "optimism")] SpecId::FJORD => "Fjord", + #[cfg(feature = "optimism")] + SpecId::GRANITE => "Granite", SpecId::LATEST => "Latest", } } @@ -219,6 +224,8 @@ spec!(CANYON, CanyonSpec); spec!(ECOTONE, EcotoneSpec); #[cfg(feature = "optimism")] spec!(FJORD, FjordSpec); +#[cfg(feature = "optimism")] +spec!(GRANITE, GraniteSpec); #[cfg(not(feature = "optimism"))] #[macro_export] @@ -378,6 +385,10 @@ macro_rules! spec_to_generic { use $crate::FjordSpec as SPEC; $e } + $crate::SpecId::GRANITE => { + use $crate::GraniteSpec as SPEC; + $e + } } }}; } @@ -418,6 +429,8 @@ mod tests { spec_to_generic!(ECOTONE, assert_eq!(SPEC::SPEC_ID, ECOTONE)); #[cfg(feature = "optimism")] spec_to_generic!(FJORD, assert_eq!(SPEC::SPEC_ID, FJORD)); + #[cfg(feature = "optimism")] + spec_to_generic!(GRANITE, assert_eq!(SPEC::SPEC_ID, GRANITE)); spec_to_generic!(PRAGUE, assert_eq!(SPEC::SPEC_ID, PRAGUE)); spec_to_generic!(PRAGUE_EOF, assert_eq!(SPEC::SPEC_ID, PRAGUE_EOF)); spec_to_generic!(LATEST, assert_eq!(SPEC::SPEC_ID, LATEST)); @@ -540,4 +553,32 @@ mod optimism_tests { assert!(SpecId::enabled(SpecId::FJORD, SpecId::ECOTONE)); assert!(SpecId::enabled(SpecId::FJORD, SpecId::FJORD)); } + + #[test] + fn test_granite_post_merge_hardforks() { + assert!(GraniteSpec::enabled(SpecId::MERGE)); + assert!(GraniteSpec::enabled(SpecId::SHANGHAI)); + assert!(GraniteSpec::enabled(SpecId::CANCUN)); + assert!(!GraniteSpec::enabled(SpecId::LATEST)); + assert!(GraniteSpec::enabled(SpecId::BEDROCK)); + assert!(GraniteSpec::enabled(SpecId::REGOLITH)); + assert!(GraniteSpec::enabled(SpecId::CANYON)); + assert!(GraniteSpec::enabled(SpecId::ECOTONE)); + assert!(GraniteSpec::enabled(SpecId::FJORD)); + assert!(GraniteSpec::enabled(SpecId::GRANITE)); + } + + #[test] + fn test_granite_post_merge_hardforks_spec_id() { + assert!(SpecId::enabled(SpecId::GRANITE, SpecId::MERGE)); + assert!(SpecId::enabled(SpecId::GRANITE, SpecId::SHANGHAI)); + assert!(SpecId::enabled(SpecId::GRANITE, SpecId::CANCUN)); + assert!(!SpecId::enabled(SpecId::GRANITE, SpecId::LATEST)); + assert!(SpecId::enabled(SpecId::GRANITE, SpecId::BEDROCK)); + assert!(SpecId::enabled(SpecId::GRANITE, SpecId::REGOLITH)); + assert!(SpecId::enabled(SpecId::GRANITE, SpecId::CANYON)); + assert!(SpecId::enabled(SpecId::GRANITE, SpecId::ECOTONE)); + assert!(SpecId::enabled(SpecId::GRANITE, SpecId::FJORD)); + assert!(SpecId::enabled(SpecId::GRANITE, SpecId::GRANITE)); + } } diff --git a/crates/revm/src/optimism.rs b/crates/revm/src/optimism.rs index 12f3db9969..a216844559 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/revm/src/optimism.rs @@ -1,5 +1,6 @@ //! Optimism-specific constants, types, and helpers. +mod bn128; mod fast_lz; mod handler_register; mod l1block; diff --git a/crates/revm/src/optimism/bn128.rs b/crates/revm/src/optimism/bn128.rs new file mode 100644 index 0000000000..5ad8e83f95 --- /dev/null +++ b/crates/revm/src/optimism/bn128.rs @@ -0,0 +1,85 @@ +use revm_precompile::bn128; +use revm_precompile::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; + +pub(crate) mod pair { + use super::*; + + const GRANITE_MAX_INPUT_SIZE: usize = 112687; + pub(crate) const GRANITE: PrecompileWithAddress = PrecompileWithAddress( + bn128::pair::ADDRESS, + Precompile::Standard(|input, gas_limit| run_pair(input, gas_limit)), + ); + + pub(crate) fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { + if input.len() > GRANITE_MAX_INPUT_SIZE { + return Err(Error::Bn128PairLength.into()); + } + bn128::run_pair( + input, + bn128::pair::ISTANBUL_PAIR_PER_POINT, + bn128::pair::ISTANBUL_PAIR_BASE, + gas_limit, + ) + } +} + +#[cfg(test)] +mod tests { + use revm_precompile::primitives::{hex, PrecompileErrors}; + + use super::*; + + #[test] + fn test_bn128_pair() { + let input = hex::decode( + "\ + 1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\ + 3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41\ + 209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7\ + 04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678\ + 2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d\ + 120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550\ + 111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c\ + 2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411\ + 198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2\ + 1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed\ + 090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b\ + 12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + ) + .unwrap(); + let expected = + hex::decode("0000000000000000000000000000000000000000000000000000000000000001") + .unwrap(); + let outcome = pair::run_pair(&input, 260_000).unwrap(); + assert_eq!(outcome.bytes, expected); + + // invalid input length + let input = hex::decode( + "\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 111111111111111111111111111111\ + ", + ) + .unwrap(); + + let res = pair::run_pair(&input, 260_000); + assert!(matches!( + res, + Err(PrecompileErrors::Error(Error::Bn128PairLength)) + )); + + // valid input length shorter than 112687 + let input = vec![1u8; 586 * bn128::PAIR_ELEMENT_LEN]; + let res = pair::run_pair(&input, 260_000); + assert!(matches!(res, Err(PrecompileErrors::Error(Error::OutOfGas)))); + + // input length longer than 112687 + let input = vec![1u8; 587 * bn128::PAIR_ELEMENT_LEN]; + let res = pair::run_pair(&input, 260_000); + assert!(matches!( + res, + Err(PrecompileErrors::Error(Error::Bn128PairLength)) + )); + } +} diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index 348b9cf797..03202f5ba5 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -156,6 +156,13 @@ pub fn load_precompiles() -> ContextPrecompiles