diff --git a/src/precompile/bn128.rs b/src/precompile/bn128.rs index 2be19e7..4e7dd1c 100644 --- a/src/precompile/bn128.rs +++ b/src/precompile/bn128.rs @@ -19,7 +19,7 @@ pub mod pair { const BN128_PAIRING_PRECOMPILE_INDEX: u64 = 8; /// The BN128 pairing precompile address. - const BN128_PAIRING_PRECOMPILE_ADDRESS: Address = + pub const BN128_PAIRING_PRECOMPILE_ADDRESS: Address = u64_to_address(BN128_PAIRING_PRECOMPILE_INDEX); /// The number of pairing inputs per pairing operation. If the inputs provided to the precompile @@ -48,4 +48,10 @@ pub mod pair { } run_pair(input, ISTANBUL_PAIR_PER_POINT, ISTANBUL_PAIR_BASE, gas_limit) } + + /// The BN128 PAIRING precompile with address. + pub const FEYNMAN: PrecompileWithAddress = + PrecompileWithAddress(BN128_PAIRING_PRECOMPILE_ADDRESS, |input, gas_limit| { + run_pair(input, ISTANBUL_PAIR_PER_POINT, ISTANBUL_PAIR_BASE, gas_limit) + }); } diff --git a/src/precompile/mod.rs b/src/precompile/mod.rs index 9b7bad0..607a713 100644 --- a/src/precompile/mod.rs +++ b/src/precompile/mod.rs @@ -29,7 +29,8 @@ impl ScrollPrecompileProvider { let precompiles = match spec { ScrollSpecId::SHANGHAI => pre_bernoulli(), ScrollSpecId::BERNOULLI | ScrollSpecId::CURIE | ScrollSpecId::DARWIN => bernoulli(), - ScrollSpecId::EUCLID | ScrollSpecId::FEYNMAN => euclid(), + ScrollSpecId::EUCLID => euclid(), + ScrollSpecId::FEYNMAN => feynman(), }; Self { precompile_provider: EthPrecompiles { precompiles, spec: SpecId::default() }, spec } } @@ -91,6 +92,16 @@ pub(crate) fn euclid() -> &'static Precompiles { }) } +/// Returns precompiles for Feynman spec. +pub(crate) fn feynman() -> &'static Precompiles { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = euclid().clone(); + precompiles.extend([bn128::pair::FEYNMAN]); + Box::new(precompiles) + }) +} + impl PrecompileProvider for ScrollPrecompileProvider where CTX: ContextTr>, @@ -134,3 +145,30 @@ impl Default for ScrollPrecompileProvider { Self::new_with_spec(ScrollSpecId::default()) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::precompile::bn128::pair::BN128_PAIRING_PRECOMPILE_ADDRESS; + use revm::primitives::hex; + + #[test] + fn test_bn128_large_input() { + // test case copied from geth + let input = hex::decode("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d").unwrap(); + + let expected = + hex::decode("0000000000000000000000000000000000000000000000000000000000000001") + .unwrap(); + + // Euclid version should reject this input + let f = euclid().get(&BN128_PAIRING_PRECOMPILE_ADDRESS).expect("precompile exists"); + let outcome = f(&input, u64::MAX); + assert!(outcome.is_err()); + + // Feynman version should accept this input + let f = feynman().get(&BN128_PAIRING_PRECOMPILE_ADDRESS).expect("precompile exists"); + let outcome = f(&input, u64::MAX).expect("call succeeds"); + assert_eq!(outcome.bytes, expected); + } +}