From fdb09bead681ec851402160d24dfe64d63660759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Wed, 8 Oct 2025 11:35:28 -0300 Subject: [PATCH 01/16] implement substrate bn and patch sp1 --- Cargo.lock | 18 +- .../src/guest_program/src/sp1/Cargo.toml | 5 +- crates/vm/Cargo.toml | 1 + crates/vm/levm/Cargo.toml | 2 + crates/vm/levm/src/precompiles.rs | 235 ++++++++++++++++++ 5 files changed, 258 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4df6096630..4b0aff14e80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1032,7 +1032,7 @@ dependencies = [ "bitflags 2.9.4", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", "regex", @@ -3779,6 +3779,7 @@ dependencies = [ "sha3", "spinoff", "strum 0.27.2", + "substrate-bn", "thiserror 2.0.17", "walkdir", ] @@ -10886,6 +10887,19 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "substrate-bn" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +dependencies = [ + "byteorder", + "crunchy", + "lazy_static", + "rand 0.8.5", + "rustc-hex", +] + [[package]] name = "subtle" version = "2.6.1" @@ -11923,7 +11937,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.3", "static_assertions", ] diff --git a/crates/l2/prover/src/guest_program/src/sp1/Cargo.toml b/crates/l2/prover/src/guest_program/src/sp1/Cargo.toml index 097c9b5ada0..67858d4ce8c 100644 --- a/crates/l2/prover/src/guest_program/src/sp1/Cargo.toml +++ b/crates/l2/prover/src/guest_program/src/sp1/Cargo.toml @@ -14,7 +14,9 @@ guest_program = { path = "../../" } ethrex-common = { path = "../../../../../../common", default-features = false } ethrex-storage = { path = "../../../../../../storage", default-features = false } ethrex-rlp = { path = "../../../../../../common/rlp" } -ethrex-vm = { path = "../../../../../../vm", default-features = false } +ethrex-vm = { path = "../../../../../../vm", default-features = false, features = [ + "substrate-bn", +] } ethrex-blockchain = { path = "../../../../../../blockchain", default-features = false } ethrex-l2-common = { path = "../../../../../common", default-features = false } @@ -28,6 +30,7 @@ p256 = { git = "https://github.com/sp1-patches/elliptic-curves", tag = "patch-p2 secp256k1 = { git = "https://github.com/sp1-patches/rust-secp256k1", tag = "patch-0.30.0-sp1-5.0.0" } ecdsa = { git = "https://github.com/sp1-patches/signatures", tag = "patch-16.9-sp1-4.1.0" } k256 = { git = "https://github.com/sp1-patches/elliptic-curves", tag = "patch-k256-13.4-sp1-5.0.0" } +substrate-bn = { git = "https://github.com/sp1-patches/bn", tag = "patch-0.6.0-sp1-5.0.0" } [patch."https://github.com/lambdaclass/bls12_381"] bls12_381 = { git = "https://github.com/lambdaclass/bls12_381-patch/", branch = "expose-fp-struct" } diff --git a/crates/vm/Cargo.toml b/crates/vm/Cargo.toml index 6a429945038..ab38a7a96af 100644 --- a/crates/vm/Cargo.toml +++ b/crates/vm/Cargo.toml @@ -32,6 +32,7 @@ path = "./lib.rs" [features] default = [] c-kzg = ["ethrex-levm/c-kzg", "ethrex-common/c-kzg"] +substrate-bn = ["ethrex-levm/substrate-bn"] debug = ["ethrex-levm/debug"] [lints.clippy] diff --git a/crates/vm/levm/Cargo.toml b/crates/vm/levm/Cargo.toml index ec81c64064c..629f3a947ae 100644 --- a/crates/vm/levm/Cargo.toml +++ b/crates/vm/levm/Cargo.toml @@ -38,6 +38,7 @@ ark-ec = "0.5.0" ark-ff = "0.5.0" strum = { version = "0.27.1", features = ["derive"] } k256 = "0.13.4" +substrate-bn = { version = "0.6.0", optional = true } [dev-dependencies] @@ -49,6 +50,7 @@ spinoff = "0.8.0" default = [] c-kzg = ["ethrex-common/c-kzg"] ethereum_foundation_tests = [] +substrate-bn = ["dep:substrate-bn"] debug = [] [lints.rust] diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index e10cbf926ef..f822fcd0f1d 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -73,6 +73,9 @@ use lambdaworks_math::elliptic_curve::short_weierstrass::curves::bls12_381::fiel use lambdaworks_math::elliptic_curve::short_weierstrass::traits::IsShortWeierstrass; use lambdaworks_math::field::fields::montgomery_backed_prime_fields::IsModulus; +#[cfg(feature = "substrate-bn")] +extern crate bn; + pub const BLAKE2F_ELEMENT_SIZE: usize = 8; pub const SIZE_PRECOMPILES_PRE_CANCUN: u64 = 9; @@ -316,6 +319,38 @@ pub fn execute_precompile( ) -> Result { type PrecompileFn = fn(&Bytes, &mut u64, Fork) -> Result; + #[cfg(feature = "substrate-bn")] + const PRECOMPILES: [Option; 512] = const { + let mut precompiles = [const { None }; 512]; + precompiles[ECRECOVER.address.0[19] as usize] = Some(ecrecover as PrecompileFn); + precompiles[IDENTITY.address.0[19] as usize] = Some(identity as PrecompileFn); + precompiles[SHA2_256.address.0[19] as usize] = Some(sha2_256 as PrecompileFn); + precompiles[RIPEMD_160.address.0[19] as usize] = Some(ripemd_160 as PrecompileFn); + precompiles[MODEXP.address.0[19] as usize] = Some(modexp as PrecompileFn); + precompiles[ECADD.address.0[19] as usize] = Some(ecadd as PrecompileFn); + precompiles[ECMUL.address.0[19] as usize] = Some(ecmul as PrecompileFn); + precompiles[ECPAIRING.address.0[19] as usize] = Some(ecpairing_substrate as PrecompileFn); + precompiles[BLAKE2F.address.0[19] as usize] = Some(blake2f as PrecompileFn); + precompiles[POINT_EVALUATION.address.0[19] as usize] = + Some(point_evaluation as PrecompileFn); + precompiles[BLS12_G1ADD.address.0[19] as usize] = Some(bls12_g1add as PrecompileFn); + precompiles[BLS12_G1MSM.address.0[19] as usize] = Some(bls12_g1msm as PrecompileFn); + precompiles[BLS12_G2ADD.address.0[19] as usize] = Some(bls12_g2add as PrecompileFn); + precompiles[BLS12_G2MSM.address.0[19] as usize] = Some(bls12_g2msm as PrecompileFn); + precompiles[BLS12_PAIRING_CHECK.address.0[19] as usize] = + Some(bls12_pairing_check as PrecompileFn); + precompiles[BLS12_MAP_FP_TO_G1.address.0[19] as usize] = + Some(bls12_map_fp_to_g1 as PrecompileFn); + precompiles[BLS12_MAP_FP2_TO_G2.address.0[19] as usize] = + Some(bls12_map_fp2_tp_g2 as PrecompileFn); + precompiles[u16::from_be_bytes([ + P256_VERIFICATION.address.0[18], + P256_VERIFICATION.address.0[19], + ]) as usize] = Some(p_256_verify as PrecompileFn); + precompiles + }; + + #[cfg(not(feature = "substrate-bn"))] const PRECOMPILES: [Option; 512] = const { let mut precompiles = [const { None }; 512]; precompiles[ECRECOVER.address.0[19] as usize] = Some(ecrecover as PrecompileFn); @@ -793,6 +828,92 @@ fn parse_first_point_coordinates(input_data: &[u8; 192]) -> Result Result<(substrate_bn::Fq, substrate_bn::Fq), VMError> { + use substrate_bn::{Fq, arith::U256}; + + let BN254_PRIME_FIELD_ORDER_SUBSTRATE: U256 = U256::from_slice(&[ + 0x30, 0x64, 0x4e, 0x72, 0xe1, 0x31, 0xa0, 0x29, 0xb8, 0x50, 0x45, 0xb6, 0x81, 0x81, 0x58, + 0x5d, 0x97, 0x81, 0x6a, 0x91, 0x68, 0x71, 0xca, 0x8d, 0x3c, 0x20, 0x8c, 0x16, 0xd8, 0x7c, + 0xfd, 0x47, + ]) + .unwrap(); + + let first_point_x = U256::from_slice(&input_data[..32]) + .map_err(|_| InternalError::msg("Failed to create BN254 element from bytes"))?; + let first_point_y = U256::from_slice(&input_data[32..64]) + .map_err(|_| InternalError::msg("Failed to create BN254 element from bytes"))?; + // Infinite is defined by (0,0). Any other zero-combination is invalid + if (first_point_x == U256::zero()) ^ (first_point_y == U256::zero()) { + return Err(PrecompileError::InvalidPoint.into()); + } + + if first_point_x > BN254_PRIME_FIELD_ORDER_SUBSTRATE + || first_point_y > BN254_PRIME_FIELD_ORDER_SUBSTRATE + { + return Err(PrecompileError::CoordinateExceedsFieldModulus.into()); + } + + let first_point_x = Fq::from_u256(first_point_x).unwrap(); + let first_point_y = Fq::from_u256(first_point_y).unwrap(); + + Ok((first_point_x, first_point_y)) +} + +#[cfg(feature = "substrate-bn")] +/// Parses second point coordinates and makes verification of invalid infinite and curve belonging. +/// +/// Slice must have len of 192. This function is only called from ecpairing which ensures that. +fn parse_second_point_coordinates_substrate( + input_data: &[u8; 192], +) -> Result<(substrate_bn::Fq2, substrate_bn::Fq2), VMError> { + let second_point_x_first_part = &input_data[96..128]; + let second_point_x_second_part = &input_data[64..96]; + + // Infinite is defined by (0,0). Any other zero-combination is invalid + if (u256_from_big_endian(second_point_x_first_part) == U256::zero()) + ^ (u256_from_big_endian(second_point_x_second_part) == U256::zero()) + { + return Err(PrecompileError::InvalidPoint.into()); + } + + let second_point_y_first_part = &input_data[160..192]; + let second_point_y_second_part = &input_data[128..160]; + + // Infinite is defined by (0,0). Any other zero-combination is invalid + if (u256_from_big_endian(second_point_y_first_part) == U256::zero()) + ^ (u256_from_big_endian(second_point_y_second_part) == U256::zero()) + { + return Err(PrecompileError::InvalidPoint.into()); + } + + // Check if the second point belongs to the curve (this happens if it's lower than the prime) + if u256_from_big_endian(second_point_x_first_part) >= ALT_BN128_PRIME + || u256_from_big_endian(second_point_x_second_part) >= ALT_BN128_PRIME + || u256_from_big_endian(second_point_y_first_part) >= ALT_BN128_PRIME + || u256_from_big_endian(second_point_y_second_part) >= ALT_BN128_PRIME + { + return Err(PrecompileError::PointNotInTheCurve.into()); + } + + use substrate_bn::{Fq, Fq2}; + + let second_point_x = Fq2::new( + Fq::from_slice(second_point_x_first_part).unwrap(), + Fq::from_slice(second_point_x_second_part).unwrap(), + ); + let second_point_y = Fq2::new( + Fq::from_slice(second_point_y_first_part).unwrap(), + Fq::from_slice(second_point_y_second_part).unwrap(), + ); + + Ok((second_point_x, second_point_y)) +} + /// Parses second point coordinates and makes verification of invalid infinite and curve belonging. /// /// Slice must have len of 192. This function is only called from ecpairing which ensures that. @@ -905,6 +1026,59 @@ fn validate_pairing( } } +#[cfg(feature = "substrate-bn")] +/// Handles pairing given a certain elements, and depending on if elements represent infinity, then +/// verifies errors on the other point returning None or returns the pairing +#[inline(always)] // called only from one place, so inlining always wont increase code size. +#[expect(clippy::type_complexity)] +fn validate_pairing_substrate( + first_point_x: substrate_bn::Fq, + first_point_y: substrate_bn::Fq, + second_point_x: substrate_bn::Fq2, + second_point_y: substrate_bn::Fq2, +) -> Result, VMError> { + use substrate_bn::{AffineG1, AffineG2, Fq2, Fr, G1, G2}; + + let first_point_is_infinity = first_point_x.is_zero() && first_point_y.is_zero(); + let second_point_is_infinity = second_point_x.is_zero() && second_point_y.is_zero(); + + match (first_point_is_infinity, second_point_is_infinity) { + (true, true) => { + // If both points are infinity, then continue to the next input + Ok(None) + } + (true, false) => { + // If the first point is infinity, then do the checks for the second + G2::from( + AffineG2::new(second_point_x, second_point_y) + .map_err(|_| PrecompileError::PointNotInSubgroup)?, + ); + Ok(None) + } + (false, true) => { + // If the second point is infinity, then do the checks for the first + G1::from( + AffineG1::new(first_point_x, first_point_y) + .map_err(|_| PrecompileError::InvalidPoint)?, + ); + Ok(None) + } + (false, false) => { + // Define the pairing points + let first_point = G1::from( + AffineG1::new(first_point_x, first_point_y) + .map_err(|_| PrecompileError::InvalidPoint)?, + ); + let second_point = G2::from( + AffineG2::new(second_point_x, second_point_y) + .map_err(|_| PrecompileError::PointNotInSubgroup)?, + ); + + Ok(Some((first_point, second_point))) + } + } +} + /// Performs a bilinear pairing on points on the elliptic curve 'alt_bn128', returns 1 on success and 0 on failure pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Result { // The input must always be a multiple of 192 (6 32-byte values) @@ -954,6 +1128,67 @@ pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu Ok(Bytes::from(result.to_vec())) } +#[cfg(feature = "substrate-bn")] +/// Performs a bilinear pairing on points on the elliptic curve 'alt_bn128', returns 1 on success and 0 on failure +pub fn ecpairing_substrate( + calldata: &Bytes, + gas_remaining: &mut u64, + _fork: Fork, +) -> Result { + // The input must always be a multiple of 192 (6 32-byte values) + if calldata.len() % 192 != 0 { + return Err(PrecompileError::ParsingInputError.into()); + } + + let inputs_amount = calldata.len() / 192; + + // Consume gas + let gas_cost = gas_cost::ecpairing(inputs_amount)?; + increase_precompile_consumed_gas(gas_cost, gas_remaining)?; + + let mut valid_pairs = Vec::new(); + + //// + + for input in calldata.chunks_exact(192) { + #[expect(unsafe_code, reason = "chunks_exact ensures the conversion is valid")] + let input: [u8; 192] = unsafe { input.try_into().unwrap_unchecked() }; + + let (first_point_x, first_point_y) = parse_first_point_coordinates_substrate(&input)?; + + let (second_point_x, second_point_y) = parse_second_point_coordinates_substrate(&input)?; + + if let Some(pair) = validate_pairing_substrate( + first_point_x, + first_point_y, + second_point_x, + second_point_y, + )? { + valid_pairs.push(pair); + } + } + + #[allow( + clippy::arithmetic_side_effects, + reason = "library will not panic on mul overflow" + )] + let pairing_result = if !valid_pairs.is_empty() { + let batch: Vec<_> = valid_pairs.into_iter().map(|(p1, p2)| (p1, p2)).collect(); + substrate_bn::pairing_batch(&batch) + } else { + substrate_bn::Gt::one() + }; + + // Generate the result from the variable mul + let success = pairing_result == substrate_bn::Gt::one(); + + //// + + let mut result = [0; 32]; + result[31] = u8::from(success); + Ok(Bytes::from(result.to_vec())) +} + /// Returns the result of Blake2 hashing algorithm given a certain parameters from the calldata. pub fn blake2f(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Result { if calldata.len() != 213 { From cd111750731a55ad1af3070d99f4fe6543986988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Wed, 8 Oct 2025 12:47:30 -0300 Subject: [PATCH 02/16] fix --- crates/vm/levm/src/precompiles.rs | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index f822fcd0f1d..f6b8eebe5b1 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -73,9 +73,6 @@ use lambdaworks_math::elliptic_curve::short_weierstrass::curves::bls12_381::fiel use lambdaworks_math::elliptic_curve::short_weierstrass::traits::IsShortWeierstrass; use lambdaworks_math::field::fields::montgomery_backed_prime_fields::IsModulus; -#[cfg(feature = "substrate-bn")] -extern crate bn; - pub const BLAKE2F_ELEMENT_SIZE: usize = 8; pub const SIZE_PRECOMPILES_PRE_CANCUN: u64 = 9; @@ -1048,31 +1045,26 @@ fn validate_pairing_substrate( Ok(None) } (true, false) => { + let affine = AffineG2::new(second_point_x, second_point_y) + .map_err(|_| PrecompileError::PointNotInSubgroup)?; // If the first point is infinity, then do the checks for the second - G2::from( - AffineG2::new(second_point_x, second_point_y) - .map_err(|_| PrecompileError::PointNotInSubgroup)?, - ); Ok(None) } (false, true) => { // If the second point is infinity, then do the checks for the first - G1::from( - AffineG1::new(first_point_x, first_point_y) - .map_err(|_| PrecompileError::InvalidPoint)?, - ); + let affine = AffineG1::new(first_point_x, first_point_y) + .map_err(|_| PrecompileError::InvalidPoint)?; Ok(None) } (false, false) => { // Define the pairing points - let first_point = G1::from( - AffineG1::new(first_point_x, first_point_y) - .map_err(|_| PrecompileError::InvalidPoint)?, - ); - let second_point = G2::from( - AffineG2::new(second_point_x, second_point_y) - .map_err(|_| PrecompileError::PointNotInSubgroup)?, - ); + let affine1 = AffineG1::new(first_point_x, first_point_y) + .map_err(|_| PrecompileError::InvalidPoint)?; + let affine2 = AffineG2::new(second_point_x, second_point_y) + .map_err(|_| PrecompileError::PointNotInSubgroup)?; + + let first_point = affine1.into(); + let second_point = affine2.into(); Ok(Some((first_point, second_point))) } From 48362c5fc6f2875e7ef986c12cae89502a7f2802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Mon, 13 Oct 2025 14:47:25 -0300 Subject: [PATCH 03/16] clean --- Cargo.lock | 7 +- crates/common/Cargo.toml | 2 +- crates/vm/Cargo.toml | 2 +- crates/vm/levm/Cargo.toml | 4 +- crates/vm/levm/src/precompiles.rs | 520 ++++++++---------------------- 5 files changed, 142 insertions(+), 393 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b0aff14e80..8e908583b4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10890,14 +10890,17 @@ dependencies = [ [[package]] name = "substrate-bn" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +source = "git+https://github.com/sp1-patches/bn?tag=patch-0.6.0-sp1-5.0.0#e0d67f219b2ad6a1887e3275b7ba09ada4b1afb6" dependencies = [ + "bytemuck", "byteorder", + "cfg-if 1.0.3", "crunchy", "lazy_static", + "num-bigint 0.4.6", "rand 0.8.5", "rustc-hex", + "sp1-lib", ] [[package]] diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index b5113a8e8e4..ceaca96d845 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -40,7 +40,7 @@ hex-literal.workspace = true [features] default = [] c-kzg = ["dep:c-kzg", "ethrex-crypto/c-kzg"] - + [lib] path = "./common.rs" diff --git a/crates/vm/Cargo.toml b/crates/vm/Cargo.toml index ab38a7a96af..c53f09bba84 100644 --- a/crates/vm/Cargo.toml +++ b/crates/vm/Cargo.toml @@ -32,7 +32,7 @@ path = "./lib.rs" [features] default = [] c-kzg = ["ethrex-levm/c-kzg", "ethrex-common/c-kzg"] -substrate-bn = ["ethrex-levm/substrate-bn"] +sp1 = ["ethrex-levm/sp1"] debug = ["ethrex-levm/debug"] [lints.clippy] diff --git a/crates/vm/levm/Cargo.toml b/crates/vm/levm/Cargo.toml index 629f3a947ae..e92496cbf5c 100644 --- a/crates/vm/levm/Cargo.toml +++ b/crates/vm/levm/Cargo.toml @@ -38,7 +38,7 @@ ark-ec = "0.5.0" ark-ff = "0.5.0" strum = { version = "0.27.1", features = ["derive"] } k256 = "0.13.4" -substrate-bn = { version = "0.6.0", optional = true } +substrate-bn = { git = "https://github.com/sp1-patches/bn", tag = "patch-0.6.0-sp1-5.0.0", optional = true } [dev-dependencies] @@ -50,8 +50,8 @@ spinoff = "0.8.0" default = [] c-kzg = ["ethrex-common/c-kzg"] ethereum_foundation_tests = [] -substrate-bn = ["dep:substrate-bn"] debug = [] +sp1 = ["dep:substrate-bn"] [lints.rust] unsafe_code = "warn" diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index f6b8eebe5b1..97c1e95a569 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -15,22 +15,17 @@ use ethrex_common::{ use ethrex_crypto::{blake2f::blake2b_f, kzg::verify_kzg_proof}; use k256::ecdsa::{RecoveryId, Signature, VerifyingKey}; use k256::elliptic_curve::Field; +use lambdaworks_math::cyclic_group::IsGroup; use lambdaworks_math::{ elliptic_curve::{ - short_weierstrass::{ - curves::{ - bls12_381::{curve::BLS12381TwistCurveFieldElement, twist::BLS12381TwistCurve}, - bn_254::{ - curve::{BN254Curve, BN254FieldElement, BN254TwistCurveFieldElement}, - field_extension::{ - BN254_PRIME_FIELD_ORDER, BN254FieldModulus, Degree2ExtensionField, - Degree12ExtensionField, - }, - pairing::BN254AtePairing, - twist::BN254TwistCurve, - }, + short_weierstrass::curves::{ + bls12_381::{curve::BLS12381TwistCurveFieldElement, twist::BLS12381TwistCurve}, + bn_254::{ + curve::BN254Curve, + field_extension::{BN254FieldModulus, Degree2ExtensionField}, + pairing::BN254AtePairing, + twist::BN254TwistCurve, }, - point::ShortWeierstrassProjectivePoint, }, traits::{IsEllipticCurve, IsPairing}, }, @@ -316,38 +311,6 @@ pub fn execute_precompile( ) -> Result { type PrecompileFn = fn(&Bytes, &mut u64, Fork) -> Result; - #[cfg(feature = "substrate-bn")] - const PRECOMPILES: [Option; 512] = const { - let mut precompiles = [const { None }; 512]; - precompiles[ECRECOVER.address.0[19] as usize] = Some(ecrecover as PrecompileFn); - precompiles[IDENTITY.address.0[19] as usize] = Some(identity as PrecompileFn); - precompiles[SHA2_256.address.0[19] as usize] = Some(sha2_256 as PrecompileFn); - precompiles[RIPEMD_160.address.0[19] as usize] = Some(ripemd_160 as PrecompileFn); - precompiles[MODEXP.address.0[19] as usize] = Some(modexp as PrecompileFn); - precompiles[ECADD.address.0[19] as usize] = Some(ecadd as PrecompileFn); - precompiles[ECMUL.address.0[19] as usize] = Some(ecmul as PrecompileFn); - precompiles[ECPAIRING.address.0[19] as usize] = Some(ecpairing_substrate as PrecompileFn); - precompiles[BLAKE2F.address.0[19] as usize] = Some(blake2f as PrecompileFn); - precompiles[POINT_EVALUATION.address.0[19] as usize] = - Some(point_evaluation as PrecompileFn); - precompiles[BLS12_G1ADD.address.0[19] as usize] = Some(bls12_g1add as PrecompileFn); - precompiles[BLS12_G1MSM.address.0[19] as usize] = Some(bls12_g1msm as PrecompileFn); - precompiles[BLS12_G2ADD.address.0[19] as usize] = Some(bls12_g2add as PrecompileFn); - precompiles[BLS12_G2MSM.address.0[19] as usize] = Some(bls12_g2msm as PrecompileFn); - precompiles[BLS12_PAIRING_CHECK.address.0[19] as usize] = - Some(bls12_pairing_check as PrecompileFn); - precompiles[BLS12_MAP_FP_TO_G1.address.0[19] as usize] = - Some(bls12_map_fp_to_g1 as PrecompileFn); - precompiles[BLS12_MAP_FP2_TO_G2.address.0[19] as usize] = - Some(bls12_map_fp2_tp_g2 as PrecompileFn); - precompiles[u16::from_be_bytes([ - P256_VERIFICATION.address.0[18], - P256_VERIFICATION.address.0[19], - ]) as usize] = Some(p_256_verify as PrecompileFn); - precompiles - }; - - #[cfg(not(feature = "substrate-bn"))] const PRECOMPILES: [Option; 512] = const { let mut precompiles = [const { None }; 512]; precompiles[ECRECOVER.address.0[19] as usize] = Some(ecrecover as PrecompileFn); @@ -797,388 +760,171 @@ const ALT_BN128_PRIME: U256 = U256([ 0x30644e72e131a029, ]); -type FirstPointCoordinates = ( - FieldElement>, - FieldElement>, -); - -/// Parses first point coordinates and makes verification of invalid infinite -#[inline] -fn parse_first_point_coordinates(input_data: &[u8; 192]) -> Result { - let first_point_x = UnsignedInteger::from_bytes_be(&input_data[..32]) - .map_err(|_| InternalError::msg("Failed to create BN254 element from bytes"))?; - let first_point_y = UnsignedInteger::from_bytes_be(&input_data[32..64]) - .map_err(|_| InternalError::msg("Failed to create BN254 element from bytes"))?; - // Infinite is defined by (0,0). Any other zero-combination is invalid - if (first_point_x == UnsignedInteger::default()) ^ (first_point_y == UnsignedInteger::default()) - { - return Err(PrecompileError::InvalidPoint.into()); - } - - if first_point_x > BN254_PRIME_FIELD_ORDER || first_point_y > BN254_PRIME_FIELD_ORDER { - return Err(PrecompileError::CoordinateExceedsFieldModulus.into()); - } - - let first_point_x = BN254FieldElement::from(&first_point_x); - let first_point_y = BN254FieldElement::from(&first_point_y); - - Ok((first_point_x, first_point_y)) -} +pub type G1 = (U256, U256); +pub type G2 = (U256, U256, U256, U256); -#[cfg(feature = "substrate-bn")] -/// Parses first point coordinates and makes verification of invalid infinite #[inline] -fn parse_first_point_coordinates_substrate( - input_data: &[u8; 192], -) -> Result<(substrate_bn::Fq, substrate_bn::Fq), VMError> { - use substrate_bn::{Fq, arith::U256}; - - let BN254_PRIME_FIELD_ORDER_SUBSTRATE: U256 = U256::from_slice(&[ - 0x30, 0x64, 0x4e, 0x72, 0xe1, 0x31, 0xa0, 0x29, 0xb8, 0x50, 0x45, 0xb6, 0x81, 0x81, 0x58, - 0x5d, 0x97, 0x81, 0x6a, 0x91, 0x68, 0x71, 0xca, 0x8d, 0x3c, 0x20, 0x8c, 0x16, 0xd8, 0x7c, - 0xfd, 0x47, - ]) - .unwrap(); - - let first_point_x = U256::from_slice(&input_data[..32]) - .map_err(|_| InternalError::msg("Failed to create BN254 element from bytes"))?; - let first_point_y = U256::from_slice(&input_data[32..64]) - .map_err(|_| InternalError::msg("Failed to create BN254 element from bytes"))?; - // Infinite is defined by (0,0). Any other zero-combination is invalid - if (first_point_x == U256::zero()) ^ (first_point_y == U256::zero()) { - return Err(PrecompileError::InvalidPoint.into()); - } - - if first_point_x > BN254_PRIME_FIELD_ORDER_SUBSTRATE - || first_point_y > BN254_PRIME_FIELD_ORDER_SUBSTRATE - { - return Err(PrecompileError::CoordinateExceedsFieldModulus.into()); - } - - let first_point_x = Fq::from_u256(first_point_x).unwrap(); - let first_point_y = Fq::from_u256(first_point_y).unwrap(); - - Ok((first_point_x, first_point_y)) -} - -#[cfg(feature = "substrate-bn")] -/// Parses second point coordinates and makes verification of invalid infinite and curve belonging. -/// -/// Slice must have len of 192. This function is only called from ecpairing which ensures that. -fn parse_second_point_coordinates_substrate( - input_data: &[u8; 192], -) -> Result<(substrate_bn::Fq2, substrate_bn::Fq2), VMError> { - let second_point_x_first_part = &input_data[96..128]; - let second_point_x_second_part = &input_data[64..96]; - - // Infinite is defined by (0,0). Any other zero-combination is invalid - if (u256_from_big_endian(second_point_x_first_part) == U256::zero()) - ^ (u256_from_big_endian(second_point_x_second_part) == U256::zero()) - { - return Err(PrecompileError::InvalidPoint.into()); - } - - let second_point_y_first_part = &input_data[160..192]; - let second_point_y_second_part = &input_data[128..160]; - - // Infinite is defined by (0,0). Any other zero-combination is invalid - if (u256_from_big_endian(second_point_y_first_part) == U256::zero()) - ^ (u256_from_big_endian(second_point_y_second_part) == U256::zero()) - { - return Err(PrecompileError::InvalidPoint.into()); - } - - // Check if the second point belongs to the curve (this happens if it's lower than the prime) - if u256_from_big_endian(second_point_x_first_part) >= ALT_BN128_PRIME - || u256_from_big_endian(second_point_x_second_part) >= ALT_BN128_PRIME - || u256_from_big_endian(second_point_y_first_part) >= ALT_BN128_PRIME - || u256_from_big_endian(second_point_y_second_part) >= ALT_BN128_PRIME - { - return Err(PrecompileError::PointNotInTheCurve.into()); - } - - use substrate_bn::{Fq, Fq2}; - - let second_point_x = Fq2::new( - Fq::from_slice(second_point_x_first_part).unwrap(), - Fq::from_slice(second_point_x_second_part).unwrap(), +fn parse_bn254_points(buf: &[u8; 192]) -> (G1, G2) { + let (g1_x, g1_y) = ( + u256_from_big_endian(&buf[..32]), + u256_from_big_endian(&buf[32..64]), ); - let second_point_y = Fq2::new( - Fq::from_slice(second_point_y_first_part).unwrap(), - Fq::from_slice(second_point_y_second_part).unwrap(), + let (g2_xy, g2_xx, g2_yy, g2_yx) = ( + u256_from_big_endian(&buf[64..96]), + u256_from_big_endian(&buf[96..128]), + u256_from_big_endian(&buf[128..160]), + u256_from_big_endian(&buf[160..]), ); - Ok((second_point_x, second_point_y)) + ((g1_x, g1_y), (g2_xx, g2_xy, g2_yx, g2_yy)) } -/// Parses second point coordinates and makes verification of invalid infinite and curve belonging. -/// -/// Slice must have len of 192. This function is only called from ecpairing which ensures that. -fn parse_second_point_coordinates( - input_data: &[u8; 192], -) -> Result< - ( - FieldElement, - FieldElement, - ), - VMError, -> { - let second_point_x_first_part = &input_data[96..128]; - let second_point_x_second_part = &input_data[64..96]; - - // Infinite is defined by (0,0). Any other zero-combination is invalid - if (u256_from_big_endian(second_point_x_first_part) == U256::zero()) - ^ (u256_from_big_endian(second_point_x_second_part) == U256::zero()) - { - return Err(PrecompileError::InvalidPoint.into()); - } - - let second_point_y_first_part = &input_data[160..192]; - let second_point_y_second_part = &input_data[128..160]; - - // Infinite is defined by (0,0). Any other zero-combination is invalid - if (u256_from_big_endian(second_point_y_first_part) == U256::zero()) - ^ (u256_from_big_endian(second_point_y_second_part) == U256::zero()) - { - return Err(PrecompileError::InvalidPoint.into()); - } +fn validate_bn254_points(g1: &G1, g2: &G2) -> Result<(), VMError> { + // check each element is in field + if g1.0 >= ALT_BN128_PRIME || g1.1 >= ALT_BN128_PRIME { + return Err(PrecompileError::CoordinateExceedsFieldModulus.into()); + } // TODO: https://eips.ethereum.org/EIPS/eip-197 maybe this check is not necessary - // Check if the second point belongs to the curve (this happens if it's lower than the prime) - if u256_from_big_endian(second_point_x_first_part) >= ALT_BN128_PRIME - || u256_from_big_endian(second_point_x_second_part) >= ALT_BN128_PRIME - || u256_from_big_endian(second_point_y_first_part) >= ALT_BN128_PRIME - || u256_from_big_endian(second_point_y_second_part) >= ALT_BN128_PRIME + if g2.0 >= ALT_BN128_PRIME + || g2.1 >= ALT_BN128_PRIME + || g2.2 >= ALT_BN128_PRIME + || g2.3 >= ALT_BN128_PRIME { - return Err(PrecompileError::PointNotInTheCurve.into()); - } - - let second_point_x_bytes = [second_point_x_first_part, second_point_x_second_part].concat(); - let second_point_y_bytes = [second_point_y_first_part, second_point_y_second_part].concat(); - - let second_point_x = BN254TwistCurveFieldElement::from_bytes_be(&second_point_x_bytes) - .map_err(|_| InternalError::msg("Failed to create BN254 element from bytes"))?; - let second_point_y = BN254TwistCurveFieldElement::from_bytes_be(&second_point_y_bytes) - .map_err(|_| InternalError::msg("Failed to create BN254 element from bytes"))?; - - Ok((second_point_x, second_point_y)) -} - -/// Handles pairing given a certain elements, and depending on if elements represent infinity, then -/// verifies errors on the other point returning None or returns the pairing -#[inline(always)] // called only from one place, so inlining always wont increase code size. -#[expect(clippy::type_complexity)] -fn validate_pairing( - first_point_x: FieldElement>, - first_point_y: FieldElement>, - second_point_x: FieldElement, - second_point_y: FieldElement, -) -> Result< - Option<( - ShortWeierstrassProjectivePoint, - ShortWeierstrassProjectivePoint, - )>, - VMError, -> { - let zero_element = BN254FieldElement::zero(); - let twcurve_zero_element = BN254TwistCurveFieldElement::zero(); - let first_point_is_infinity = - first_point_x.eq(&zero_element) && first_point_y.eq(&zero_element); - let second_point_is_infinity = - second_point_x.eq(&twcurve_zero_element) && second_point_y.eq(&twcurve_zero_element); - - match (first_point_is_infinity, second_point_is_infinity) { - (true, true) => { - // If both points are infinity, then continue to the next input - Ok(None) - } - (true, false) => { - // If the first point is infinity, then do the checks for the second - let p2 = BN254TwistCurve::create_point_from_affine(second_point_x, second_point_y) - .map_err(|_| PrecompileError::InvalidPoint)?; - - if !p2.is_in_subgroup() { - return Err(PrecompileError::PointNotInSubgroup.into()); - } - Ok(None) - } - (false, true) => { - // If the second point is infinity, then do the checks for the first - BN254Curve::create_point_from_affine(first_point_x, first_point_y) - .map_err(|_| PrecompileError::InvalidPoint)?; - Ok(None) - } - (false, false) => { - // Define the pairing points - let first_point = BN254Curve::create_point_from_affine(first_point_x, first_point_y) - .map_err(|_| PrecompileError::InvalidPoint)?; - - let second_point = - BN254TwistCurve::create_point_from_affine(second_point_x, second_point_y) - .map_err(|_| PrecompileError::InvalidPoint)?; - if !second_point.is_in_subgroup() { - return Err(PrecompileError::PointNotInSubgroup.into()); - } - Ok(Some((first_point, second_point))) - } + return Err(PrecompileError::CoordinateExceedsFieldModulus.into()); } -} - -#[cfg(feature = "substrate-bn")] -/// Handles pairing given a certain elements, and depending on if elements represent infinity, then -/// verifies errors on the other point returning None or returns the pairing -#[inline(always)] // called only from one place, so inlining always wont increase code size. -#[expect(clippy::type_complexity)] -fn validate_pairing_substrate( - first_point_x: substrate_bn::Fq, - first_point_y: substrate_bn::Fq, - second_point_x: substrate_bn::Fq2, - second_point_y: substrate_bn::Fq2, -) -> Result, VMError> { - use substrate_bn::{AffineG1, AffineG2, Fq2, Fr, G1, G2}; - - let first_point_is_infinity = first_point_x.is_zero() && first_point_y.is_zero(); - let second_point_is_infinity = second_point_x.is_zero() && second_point_y.is_zero(); - - match (first_point_is_infinity, second_point_is_infinity) { - (true, true) => { - // If both points are infinity, then continue to the next input - Ok(None) - } - (true, false) => { - let affine = AffineG2::new(second_point_x, second_point_y) - .map_err(|_| PrecompileError::PointNotInSubgroup)?; - // If the first point is infinity, then do the checks for the second - Ok(None) - } - (false, true) => { - // If the second point is infinity, then do the checks for the first - let affine = AffineG1::new(first_point_x, first_point_y) - .map_err(|_| PrecompileError::InvalidPoint)?; - Ok(None) - } - (false, false) => { - // Define the pairing points - let affine1 = AffineG1::new(first_point_x, first_point_y) - .map_err(|_| PrecompileError::InvalidPoint)?; - let affine2 = AffineG2::new(second_point_x, second_point_y) - .map_err(|_| PrecompileError::PointNotInSubgroup)?; - - let first_point = affine1.into(); - let second_point = affine2.into(); - Ok(Some((first_point, second_point))) - } - } + Ok(()) } -/// Performs a bilinear pairing on points on the elliptic curve 'alt_bn128', returns 1 on success and 0 on failure -pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Result { +fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Result { // The input must always be a multiple of 192 (6 32-byte values) if calldata.len() % 192 != 0 { return Err(PrecompileError::ParsingInputError.into()); } let inputs_amount = calldata.len() / 192; - - // Consume gas let gas_cost = gas_cost::ecpairing(inputs_amount)?; increase_precompile_consumed_gas(gas_cost, gas_remaining)?; - let mut valid_pairs = Vec::new(); - let mut mul: FieldElement = QuadraticExtensionFieldElement::one(); - + let mut batch = Vec::new(); for input in calldata.chunks_exact(192) { #[expect(unsafe_code, reason = "chunks_exact ensures the conversion is valid")] let input: [u8; 192] = unsafe { input.try_into().unwrap_unchecked() }; - - let (first_point_x, first_point_y) = parse_first_point_coordinates(&input)?; - - let (second_point_x, second_point_y) = parse_second_point_coordinates(&input)?; - - if let Some(pair) = - validate_pairing(first_point_x, first_point_y, second_point_x, second_point_y)? - { - valid_pairs.push(pair); - } + let (g1, g2) = parse_bn254_points(&input); + validate_bn254_points(&g1, &g2).inspect(|_| batch.push((g1, g2)))?; } - #[allow( - clippy::arithmetic_side_effects, - reason = "library will not panic on mul overflow" - )] - if !valid_pairs.is_empty() { - let batch: Vec<_> = valid_pairs.iter().map(|(p1, p2)| (p1, p2)).collect(); - let pairing_result = BN254AtePairing::compute_batch(&batch) - .map_err(|_| PrecompileError::BN254AtePairingError)?; - mul *= pairing_result; - } + #[allow(unreachable_code)] + let pairing_check = 'inner: { + if batch.is_empty() { + break 'inner true; + } - // Generate the result from the variable mul - let success = mul.eq(&QuadraticExtensionFieldElement::one()); - let mut result = [0; 32]; - result[31] = u8::from(success); - Ok(Bytes::from(result.to_vec())) -} + #[cfg(feature = "sp1")] + break 'inner pairing_substrate(&batch)?; -#[cfg(feature = "substrate-bn")] -/// Performs a bilinear pairing on points on the elliptic curve 'alt_bn128', returns 1 on success and 0 on failure -pub fn ecpairing_substrate( - calldata: &Bytes, - gas_remaining: &mut u64, - _fork: Fork, -) -> Result { - // The input must always be a multiple of 192 (6 32-byte values) - if calldata.len() % 192 != 0 { - return Err(PrecompileError::ParsingInputError.into()); - } + // default + break 'inner pairing_lambdaworks(&batch)?; + }; - let inputs_amount = calldata.len() / 192; + let mut result = vec![0; 31]; + result.push(u8::from(pairing_check)); + Ok(Bytes::from(result)) +} - // Consume gas - let gas_cost = gas_cost::ecpairing(inputs_amount)?; - increase_precompile_consumed_gas(gas_cost, gas_remaining)?; +#[cfg(feature = "sp1")] +pub fn pairing_substrate(batch: &[(G1, G2)]) -> Result { + use substrate_bn::{AffineG1, AffineG2, Fq, Fq2, G1 as SubstrateG1, G2 as SubstrateG2, Group}; - let mut valid_pairs = Vec::new(); + let result = if batch.is_empty() { + substrate_bn::Gt::one() + } else { + let mut valid_batch = Vec::with_capacity(batch.len()); + for (g1, g2) in batch { + let (g1_x, g1_y) = ( + Fq::from_slice(&g1.0.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + Fq::from_slice(&g1.1.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + ); + let (g2_x, g2_y) = ( + Fq2::new( + Fq::from_slice(&g2.0.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + Fq::from_slice(&g2.1.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + ), + Fq2::new( + Fq::from_slice(&g2.2.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + Fq::from_slice(&g2.3.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + ), + ); + let g1: SubstrateG1 = AffineG1::new(g1_x, g1_y) + .map_err(|_| PrecompileError::InvalidPoint)? + .into(); + let g2: SubstrateG2 = AffineG2::new(g2_x, g2_y) + .map_err(|_| PrecompileError::InvalidPoint)? + .into(); + + if g1.is_zero() || g2.is_zero() { + continue; + } + valid_batch.push((g1, g2)); + } - //// + substrate_bn::pairing_batch(&valid_batch) + }; - for input in calldata.chunks_exact(192) { - #[expect(unsafe_code, reason = "chunks_exact ensures the conversion is valid")] - let input: [u8; 192] = unsafe { input.try_into().unwrap_unchecked() }; + Ok(result == substrate_bn::Gt::one()) +} - let (first_point_x, first_point_y) = parse_first_point_coordinates_substrate(&input)?; +pub fn pairing_lambdaworks(batch: &[(G1, G2)]) -> Result { + type Fq = FieldElement>; + type Fq2 = FieldElement; + type LambdaworksG1 = BN254Curve; + type LambdaworksG2 = BN254TwistCurve; - let (second_point_x, second_point_y) = parse_second_point_coordinates_substrate(&input)?; + let result = if batch.is_empty() { + QuadraticExtensionFieldElement::one() + } else { + let mut valid_batch = Vec::with_capacity(batch.len()); + for (g1, g2) in batch { + let (g1_x, g1_y) = ( + Fq::from_bytes_be(&g1.0.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + Fq::from_bytes_be(&g1.1.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + ); + let (g2_x, g2_y) = { + let x_bytes = [g2.0.to_big_endian(), g2.1.to_big_endian()].concat(); + let y_bytes = [g2.2.to_big_endian(), g2.3.to_big_endian()].concat(); + let (x, y) = ( + Fq2::from_bytes_be(&x_bytes).map_err(|_| PrecompileError::ParsingInputError)?, + Fq2::from_bytes_be(&y_bytes).map_err(|_| PrecompileError::ParsingInputError)?, + ); + (x, y) + }; + let g1 = LambdaworksG1::create_point_from_affine(g1_x, g1_y) + .map_err(|_| PrecompileError::InvalidPoint)?; + let g2 = LambdaworksG2::create_point_from_affine(g2_x, g2_y) + .map_err(|_| PrecompileError::InvalidPoint)?; + // if !g2.is_in_subgroup() { + // return Err(PrecompileError::PointNotInSubgroup.into()); + // } - if let Some(pair) = validate_pairing_substrate( - first_point_x, - first_point_y, - second_point_x, - second_point_y, - )? { - valid_pairs.push(pair); + if g1.is_neutral_element() || g2.is_neutral_element() { + continue; + } + valid_batch.push((g1, g2)); } - } - - #[allow( - clippy::arithmetic_side_effects, - reason = "library will not panic on mul overflow" - )] - let pairing_result = if !valid_pairs.is_empty() { - let batch: Vec<_> = valid_pairs.into_iter().map(|(p1, p2)| (p1, p2)).collect(); - substrate_bn::pairing_batch(&batch) - } else { - substrate_bn::Gt::one() + let valid_batch_refs: Vec<_> = valid_batch.iter().map(|(p1, p2)| (p1, p2)).collect(); + BN254AtePairing::compute_batch(&valid_batch_refs) + .map_err(|_| PrecompileError::BN254AtePairingError)? }; - // Generate the result from the variable mul - let success = pairing_result == substrate_bn::Gt::one(); - - //// - - let mut result = [0; 32]; - result[31] = u8::from(success); - Ok(Bytes::from(result.to_vec())) + Ok(result == QuadraticExtensionFieldElement::one()) } /// Returns the result of Blake2 hashing algorithm given a certain parameters from the calldata. From f27566f298748a92dfd5d4e519463aebbbd4437d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Mon, 13 Oct 2025 14:56:41 -0300 Subject: [PATCH 04/16] nits --- .../l2/prover/src/guest_program/src/sp1/Cargo.toml | 3 +-- crates/vm/Cargo.toml | 2 +- crates/vm/levm/src/precompiles.rs | 14 +++++++++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/l2/prover/src/guest_program/src/sp1/Cargo.toml b/crates/l2/prover/src/guest_program/src/sp1/Cargo.toml index 67858d4ce8c..1ab4ee1649f 100644 --- a/crates/l2/prover/src/guest_program/src/sp1/Cargo.toml +++ b/crates/l2/prover/src/guest_program/src/sp1/Cargo.toml @@ -15,7 +15,7 @@ ethrex-common = { path = "../../../../../../common", default-features = false } ethrex-storage = { path = "../../../../../../storage", default-features = false } ethrex-rlp = { path = "../../../../../../common/rlp" } ethrex-vm = { path = "../../../../../../vm", default-features = false, features = [ - "substrate-bn", + "sp1", ] } ethrex-blockchain = { path = "../../../../../../blockchain", default-features = false } ethrex-l2-common = { path = "../../../../../common", default-features = false } @@ -30,7 +30,6 @@ p256 = { git = "https://github.com/sp1-patches/elliptic-curves", tag = "patch-p2 secp256k1 = { git = "https://github.com/sp1-patches/rust-secp256k1", tag = "patch-0.30.0-sp1-5.0.0" } ecdsa = { git = "https://github.com/sp1-patches/signatures", tag = "patch-16.9-sp1-4.1.0" } k256 = { git = "https://github.com/sp1-patches/elliptic-curves", tag = "patch-k256-13.4-sp1-5.0.0" } -substrate-bn = { git = "https://github.com/sp1-patches/bn", tag = "patch-0.6.0-sp1-5.0.0" } [patch."https://github.com/lambdaclass/bls12_381"] bls12_381 = { git = "https://github.com/lambdaclass/bls12_381-patch/", branch = "expose-fp-struct" } diff --git a/crates/vm/Cargo.toml b/crates/vm/Cargo.toml index c53f09bba84..d1dfc3ff31d 100644 --- a/crates/vm/Cargo.toml +++ b/crates/vm/Cargo.toml @@ -32,8 +32,8 @@ path = "./lib.rs" [features] default = [] c-kzg = ["ethrex-levm/c-kzg", "ethrex-common/c-kzg"] -sp1 = ["ethrex-levm/sp1"] debug = ["ethrex-levm/debug"] +sp1 = ["ethrex-levm/sp1"] [lints.clippy] unwrap_used = "deny" diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index 97c1e95a569..3b6086f2816 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -764,7 +764,7 @@ pub type G1 = (U256, U256); pub type G2 = (U256, U256, U256, U256); #[inline] -fn parse_bn254_points(buf: &[u8; 192]) -> (G1, G2) { +fn parse_bn254_coords(buf: &[u8; 192]) -> (G1, G2) { let (g1_x, g1_y) = ( u256_from_big_endian(&buf[..32]), u256_from_big_endian(&buf[32..64]), @@ -779,11 +779,12 @@ fn parse_bn254_points(buf: &[u8; 192]) -> (G1, G2) { ((g1_x, g1_y), (g2_xx, g2_xy, g2_yx, g2_yy)) } -fn validate_bn254_points(g1: &G1, g2: &G2) -> Result<(), VMError> { +#[inline] +fn validate_bn254_coords(g1: &G1, g2: &G2) -> Result<(), VMError> { // check each element is in field if g1.0 >= ALT_BN128_PRIME || g1.1 >= ALT_BN128_PRIME { return Err(PrecompileError::CoordinateExceedsFieldModulus.into()); - } // TODO: https://eips.ethereum.org/EIPS/eip-197 maybe this check is not necessary + } if g2.0 >= ALT_BN128_PRIME || g2.1 >= ALT_BN128_PRIME @@ -796,6 +797,7 @@ fn validate_bn254_points(g1: &G1, g2: &G2) -> Result<(), VMError> { Ok(()) } +#[inline] fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Result { // The input must always be a multiple of 192 (6 32-byte values) if calldata.len() % 192 != 0 { @@ -810,8 +812,8 @@ fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Result Result Result { use substrate_bn::{AffineG1, AffineG2, Fq, Fq2, G1 as SubstrateG1, G2 as SubstrateG2, Group}; @@ -880,6 +883,7 @@ pub fn pairing_substrate(batch: &[(G1, G2)]) -> Result { Ok(result == substrate_bn::Gt::one()) } +#[inline] pub fn pairing_lambdaworks(batch: &[(G1, G2)]) -> Result { type Fq = FieldElement>; type Fq2 = FieldElement; From ee05e85890f816586b44f8f159e8dc3786d45e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Mon, 13 Oct 2025 14:57:31 -0300 Subject: [PATCH 05/16] revert common/Cargo.toml --- crates/common/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index ceaca96d845..b5113a8e8e4 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -40,7 +40,7 @@ hex-literal.workspace = true [features] default = [] c-kzg = ["dep:c-kzg", "ethrex-crypto/c-kzg"] - + [lib] path = "./common.rs" From 3e8fba3b28ae223293cb86412d98684a7ab16cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Mon, 13 Oct 2025 15:06:23 -0300 Subject: [PATCH 06/16] update sp1 cargo lock --- .../src/guest_program/src/sp1/Cargo.lock | 469 ++++++++++-------- 1 file changed, 264 insertions(+), 205 deletions(-) diff --git a/crates/l2/prover/src/guest_program/src/sp1/Cargo.lock b/crates/l2/prover/src/guest_program/src/sp1/Cargo.lock index 72e1c4e41ac..ec205664d59 100644 --- a/crates/l2/prover/src/guest_program/src/sp1/Cargo.lock +++ b/crates/l2/prover/src/guest_program/src/sp1/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] @@ -66,9 +66,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -81,9 +81,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -116,9 +116,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "ark-bn254" @@ -275,9 +275,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -285,7 +285,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -422,9 +422,9 @@ checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "bytecheck" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50690fb3370fb9fe3550372746084c46f2ac8c9685c583d2be10eefd89d3d1a3" +checksum = "0caa33a2c0edca0419d15ac723dff03f1956f7978329b1e3b5fdaaaed9d3ca8b" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -434,9 +434,9 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb7846e0cb180355c2dec69e721edafa36919850f1a9f52ffba4ebc0393cb71" +checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9" dependencies = [ "proc-macro2", "quote", @@ -445,9 +445,23 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.23.2" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] [[package]] name = "byteorder" @@ -466,15 +480,15 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.12" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0b03af37dad7a14518b7691d81acb0f8222604ad3d1b02f6b4bed5188c0cd5" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" [[package]] name = "cc" -version = "1.2.36" +version = "1.2.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" dependencies = [ "find-msvc-tools", "shlex", @@ -495,14 +509,14 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-link 0.2.0", + "windows-link", ] [[package]] name = "clap" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" +checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f" dependencies = [ "clap_builder", "clap_derive", @@ -510,9 +524,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" +checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730" dependencies = [ "anstream", "anstyle", @@ -522,9 +536,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", @@ -534,9 +548,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "colorchoice" @@ -558,9 +572,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const_format" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" dependencies = [ "const_format_proc_macros", ] @@ -706,9 +720,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ "darling_core", "darling_macro", @@ -716,9 +730,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", @@ -730,9 +744,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", @@ -764,12 +778,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" +checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] @@ -1044,6 +1058,7 @@ dependencies = [ "sha2", "sha3", "strum", + "substrate-bn", "thiserror", "walkdir", ] @@ -1183,9 +1198,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" [[package]] name = "fixed-hash" @@ -1277,9 +1292,9 @@ checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -1306,14 +1321,14 @@ dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.4+wasi-0.2.4", + "wasi 0.14.7+wasi-0.2.4", ] [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "group" @@ -1363,6 +1378,12 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "heck" version = "0.5.0" @@ -1404,9 +1425,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1590,13 +1611,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.0" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.0", "serde", + "serde_core", ] [[package]] @@ -1651,9 +1673,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.78" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" dependencies = [ "once_cell", "wasm-bindgen", @@ -1725,12 +1747,15 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "libc" -version = "0.2.175" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libm" @@ -1825,9 +1850,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "miniz_oxide" @@ -1851,18 +1876,18 @@ dependencies = [ [[package]] name = "munge" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7feb0b48aa0a25f9fe0899482c6e1379ee7a11b24a53073eacdecb9adb6dc60" +checksum = "5e17401f259eba956ca16491461b6e8f72913a0a114e39736ce404410f915a0c" dependencies = [ "munge_macro", ] [[package]] name = "munge_macro" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e3795a5d2da581a8b252fec6022eee01aea10161a4d1bf237d4cbe47f7e988" +checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" dependencies = [ "proc-macro2", "quote", @@ -1871,11 +1896,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1925,9 +1950,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -2196,9 +2221,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ "toml_edit", ] @@ -2214,18 +2239,18 @@ dependencies = [ [[package]] name = "ptr_meta" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90" +checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79" dependencies = [ "ptr_meta_derive", ] [[package]] name = "ptr_meta_derive" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" +checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" dependencies = [ "proc-macro2", "quote", @@ -2234,9 +2259,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] @@ -2255,9 +2280,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rancor" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947" +checksum = "a063ea72381527c2a0561da9c80000ef822bdd7c3241b1cc1b12100e3df081ee" dependencies = [ "ptr_meta", ] @@ -2314,18 +2339,18 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", @@ -2334,9 +2359,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -2345,15 +2370,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rend" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215" +checksum = "cadadef317c2f20755a64d7fdc48f9e7178ee6b0e1f7fce33fa60f1d68a276e6" dependencies = [ "bytecheck", ] @@ -2378,14 +2403,14 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f5c3e5da784cd8c69d32cdc84673f3204536ca56e1fa01be31a74b92c932ac" +checksum = "35a640b26f007713818e9a9b65d34da1cf58538207b052916a83d80e43f3ffa4" dependencies = [ "bytecheck", "bytes", "hashbrown 0.15.5", - "indexmap 2.11.0", + "indexmap 2.11.4", "munge", "ptr_meta", "rancor", @@ -2397,9 +2422,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4270433626cffc9c4c1d3707dd681f2a2718d3d7b09ad754bec137acecda8d22" +checksum = "bd83f5f173ff41e00337d97f6572e416d022ef8a19f371817259ae960324c482" dependencies = [ "proc-macro2", "quote", @@ -2530,10 +2555,11 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -2546,11 +2572,20 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -2559,31 +2594,31 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] name = "serde_with" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" +checksum = "6093cd8c01b25262b84927e0f7151692158fab02d961e04c979d3903eba7ecc5" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.11.0", + "indexmap 2.11.4", "schemars 0.9.0", "schemars 1.0.4", - "serde", - "serde_derive", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -2591,9 +2626,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" +checksum = "a7e6c180db0816026a61afa1cff5344fb7ebded7e4d3062772179f2501481c27" dependencies = [ "darling", "proc-macro2", @@ -2671,9 +2706,9 @@ checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "sp1-lib" -version = "5.2.1" +version = "5.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1fe81b6f87134f9170cb642f948ae41e0ee1cd3785e0cb665add5b67106d1a" +checksum = "fce8ad0f153443d09d398eccb650a0b2dcbf829470e394e4bf60ec4379c7af93" dependencies = [ "bincode", "elliptic-curve", @@ -2683,9 +2718,9 @@ dependencies = [ [[package]] name = "sp1-primitives" -version = "5.2.1" +version = "5.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dddd8d022840c1c500e0d7f82e9b9cf080b7dabd469f06b394010e6a594f692b" +checksum = "0244dee3a7a0f88cf71c3edf518f4fc97794ae870a107cbe7c810ac3fbf879cb" dependencies = [ "bincode", "blake3", @@ -2753,9 +2788,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -2790,6 +2825,22 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "substrate-bn" +version = "0.6.0" +source = "git+https://github.com/sp1-patches/bn?tag=patch-0.6.0-sp1-5.0.0#e0d67f219b2ad6a1887e3275b7ba09ada4b1afb6" +dependencies = [ + "bytemuck", + "byteorder", + "cfg-if", + "crunchy", + "lazy_static", + "num-bigint 0.4.6", + "rand", + "rustc-hex", + "sp1-lib", +] + [[package]] name = "subtle" version = "2.6.1" @@ -2850,18 +2901,18 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", @@ -2879,11 +2930,12 @@ dependencies = [ [[package]] name = "time" -version = "0.3.43" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", "serde", @@ -2971,18 +3023,31 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.11" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] [[package]] name = "toml_edit" -version = "0.22.27" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" dependencies = [ - "indexmap 2.11.0", + "indexmap 2.11.4", "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ "winnow", ] @@ -3050,9 +3115,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "uint" @@ -3068,9 +3133,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "unicode-segmentation" @@ -3154,18 +3219,27 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.4+wasi-0.2.4" +version = "0.14.7+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a5f4a424faf49c3c2c344f166f0662341d470ea185e939657aaff130f0ec4a" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.101" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" dependencies = [ "cfg-if", "once_cell", @@ -3176,9 +3250,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.101" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" dependencies = [ "bumpalo", "log", @@ -3190,9 +3264,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.101" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3200,9 +3274,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.101" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", @@ -3213,9 +3287,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.101" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" dependencies = [ "unicode-ident", ] @@ -3236,27 +3310,27 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.1.3", + "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", @@ -3265,9 +3339,9 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", @@ -3276,41 +3350,26 @@ dependencies = [ [[package]] name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - -[[package]] -name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -3328,16 +3387,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -3358,19 +3417,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.1.3", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -3381,9 +3440,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -3393,9 +3452,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -3405,9 +3464,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -3417,9 +3476,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -3429,9 +3488,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -3441,9 +3500,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -3453,9 +3512,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -3465,9 +3524,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" @@ -3480,9 +3539,9 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.45.1" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" @@ -3566,9 +3625,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] From 948e09d8aa2713341a6429ad2679013bc8fd3f17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Mon, 13 Oct 2025 15:27:37 -0300 Subject: [PATCH 07/16] bot reviews --- crates/vm/levm/src/precompiles.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index c4817cd7acd..07fb6ee7324 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -797,8 +797,8 @@ fn validate_bn254_coords(g1: &G1, g2: &G2) -> Result<(), VMError> { Ok(()) } -#[inline] -fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Result { +/// Performs a bilinear pairing on points on the elliptic curve 'alt_bn128', returns 1 on success and 0 on failure +pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Result { // The input must always be a multiple of 192 (6 32-byte values) if !calldata.len().is_multiple_of(192) { return Err(PrecompileError::ParsingInputError.into()); @@ -914,9 +914,9 @@ pub fn pairing_lambdaworks(batch: &[(G1, G2)]) -> Result { .map_err(|_| PrecompileError::InvalidPoint)?; let g2 = LambdaworksG2::create_point_from_affine(g2_x, g2_y) .map_err(|_| PrecompileError::InvalidPoint)?; - // if !g2.is_in_subgroup() { - // return Err(PrecompileError::PointNotInSubgroup.into()); - // } + if !g2.is_in_subgroup() { + return Err(PrecompileError::PointNotInSubgroup.into()); + } if g1.is_neutral_element() || g2.is_neutral_element() { continue; From ee650a73d9ce89a5896d1a4b555d5028b9ffabc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Wed, 15 Oct 2025 20:05:55 -0300 Subject: [PATCH 08/16] fix pt at inf --- crates/vm/levm/src/precompiles.rs | 61 ++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index aae64ae9f0c..4c7b56f5a4a 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -16,6 +16,8 @@ use ethrex_crypto::{blake2f::blake2b_f, kzg::verify_kzg_proof}; use k256::ecdsa::{RecoveryId, Signature, VerifyingKey}; use k256::elliptic_curve::Field; use lambdaworks_math::cyclic_group::IsGroup; +use lambdaworks_math::elliptic_curve::short_weierstrass::curves::bn_254::curve::{BN254FieldElement, BN254TwistCurveFieldElement}; +use lambdaworks_math::elliptic_curve::short_weierstrass::point::ShortWeierstrassProjectivePoint; use lambdaworks_math::{ elliptic_curve::{ short_weierstrass::curves::{ @@ -780,7 +782,7 @@ fn parse_bn254_coords(buf: &[u8; 192]) -> (G1, G2) { } #[inline] -fn validate_bn254_coords(g1: &G1, g2: &G2) -> Result<(), VMError> { +fn validate_bn254_coords(g1: &G1, g2: &G2) -> Result { // check each element is in field if g1.0 >= ALT_BN128_PRIME || g1.1 >= ALT_BN128_PRIME { return Err(PrecompileError::CoordinateExceedsFieldModulus.into()); @@ -794,7 +796,7 @@ fn validate_bn254_coords(g1: &G1, g2: &G2) -> Result<(), VMError> { return Err(PrecompileError::CoordinateExceedsFieldModulus.into()); } - Ok(()) + Ok(true) } /// Performs a bilinear pairing on points on the elliptic curve 'alt_bn128', returns 1 on success and 0 on failure @@ -813,7 +815,10 @@ pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu #[expect(unsafe_code, reason = "chunks_exact ensures the conversion is valid")] let input: [u8; 192] = unsafe { input.try_into().unwrap_unchecked() }; let (g1, g2) = parse_bn254_coords(&input); - validate_bn254_coords(&g1, &g2).inspect(|_| batch.push((g1, g2)))?; + if validate_bn254_coords(&g1, &g2)? { + batch.push((g1, g2)); + } else { + } } #[allow(unreachable_code)] @@ -885,35 +890,47 @@ pub fn pairing_substrate(batch: &[(G1, G2)]) -> Result { #[inline] pub fn pairing_lambdaworks(batch: &[(G1, G2)]) -> Result { - type Fq = FieldElement>; - type Fq2 = FieldElement; + type Fq = BN254FieldElement; + type Fq2 = BN254TwistCurveFieldElement; type LambdaworksG1 = BN254Curve; type LambdaworksG2 = BN254TwistCurve; + type ProjectiveG1 = ShortWeierstrassProjectivePoint; + type ProjectiveG2 = ShortWeierstrassProjectivePoint; let result = if batch.is_empty() { QuadraticExtensionFieldElement::one() } else { let mut valid_batch = Vec::with_capacity(batch.len()); for (g1, g2) in batch { - let (g1_x, g1_y) = ( - Fq::from_bytes_be(&g1.0.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - Fq::from_bytes_be(&g1.1.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - ); - let (g2_x, g2_y) = { - let x_bytes = [g2.0.to_big_endian(), g2.1.to_big_endian()].concat(); - let y_bytes = [g2.2.to_big_endian(), g2.3.to_big_endian()].concat(); - let (x, y) = ( - Fq2::from_bytes_be(&x_bytes).map_err(|_| PrecompileError::ParsingInputError)?, - Fq2::from_bytes_be(&y_bytes).map_err(|_| PrecompileError::ParsingInputError)?, + let g1 = if g1.0.is_zero() && g1.1.is_zero() { + ProjectiveG1::neutral_element() + } else { + let (g1_x, g1_y) = ( + Fq::from_bytes_be(&g1.0.to_big_endian()) + .map_err(|_| InternalError::msg("failed to parse g1 x"))?, + Fq::from_bytes_be(&g1.1.to_big_endian()) + .map_err(|_| InternalError::msg("failed to parse g1 y"))?, ); - (x, y) + LambdaworksG1::create_point_from_affine(g1_x, g1_y) + .map_err(|_| PrecompileError::InvalidPoint)? + }; + let g2 = if g2.0.is_zero() && g2.1.is_zero() && g2.2.is_zero() && g2.3.is_zero() { + ProjectiveG2::neutral_element() + } else { + let (g2_x, g2_y) = { + let x_bytes = [g2.0.to_big_endian(), g2.1.to_big_endian()].concat(); + let y_bytes = [g2.2.to_big_endian(), g2.3.to_big_endian()].concat(); + let (x, y) = ( + Fq2::from_bytes_be(&x_bytes) + .map_err(|_| InternalError::msg("failed to parse g2 x"))?, + Fq2::from_bytes_be(&y_bytes) + .map_err(|_| InternalError::msg("failed to parse g2 y"))?, + ); + (x, y) + }; + LambdaworksG2::create_point_from_affine(g2_x, g2_y) + .map_err(|_| PrecompileError::InvalidPoint)? }; - let g1 = LambdaworksG1::create_point_from_affine(g1_x, g1_y) - .map_err(|_| PrecompileError::InvalidPoint)?; - let g2 = LambdaworksG2::create_point_from_affine(g2_x, g2_y) - .map_err(|_| PrecompileError::InvalidPoint)?; if !g2.is_in_subgroup() { return Err(PrecompileError::PointNotInSubgroup.into()); } From a42a39ab4a459fe7c34c8d50ade1e08f5bd614f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Thu, 16 Oct 2025 10:14:33 -0300 Subject: [PATCH 09/16] fix substrate pairing too --- crates/vm/levm/src/precompiles.rs | 74 ++++++++++++++++--------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index 4c7b56f5a4a..83febf60110 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -16,25 +16,19 @@ use ethrex_crypto::{blake2f::blake2b_f, kzg::verify_kzg_proof}; use k256::ecdsa::{RecoveryId, Signature, VerifyingKey}; use k256::elliptic_curve::Field; use lambdaworks_math::cyclic_group::IsGroup; -use lambdaworks_math::elliptic_curve::short_weierstrass::curves::bn_254::curve::{BN254FieldElement, BN254TwistCurveFieldElement}; +use lambdaworks_math::elliptic_curve::short_weierstrass::curves::bn_254::curve::{ + BN254FieldElement, BN254TwistCurveFieldElement, +}; use lambdaworks_math::elliptic_curve::short_weierstrass::point::ShortWeierstrassProjectivePoint; use lambdaworks_math::{ elliptic_curve::{ short_weierstrass::curves::{ bls12_381::{curve::BLS12381TwistCurveFieldElement, twist::BLS12381TwistCurve}, - bn_254::{ - curve::BN254Curve, - field_extension::{BN254FieldModulus, Degree2ExtensionField}, - pairing::BN254AtePairing, - twist::BN254TwistCurve, - }, + bn_254::{curve::BN254Curve, pairing::BN254AtePairing, twist::BN254TwistCurve}, }, traits::{IsEllipticCurve, IsPairing}, }, - field::{ - element::FieldElement, extensions::quadratic::QuadraticExtensionFieldElement, - fields::montgomery_backed_prime_fields::MontgomeryBackendPrimeField, - }, + field::extensions::quadratic::QuadraticExtensionFieldElement, traits::ByteConversion, unsigned_integer::element::UnsignedInteger, }; @@ -817,7 +811,6 @@ pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu let (g1, g2) = parse_bn254_coords(&input); if validate_bn254_coords(&g1, &g2)? { batch.push((g1, g2)); - } else { } } @@ -849,32 +842,41 @@ pub fn pairing_substrate(batch: &[(G1, G2)]) -> Result { } else { let mut valid_batch = Vec::with_capacity(batch.len()); for (g1, g2) in batch { - let (g1_x, g1_y) = ( - Fq::from_slice(&g1.0.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - Fq::from_slice(&g1.1.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - ); - let (g2_x, g2_y) = ( - Fq2::new( - Fq::from_slice(&g2.0.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - Fq::from_slice(&g2.1.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - ), - Fq2::new( - Fq::from_slice(&g2.2.to_big_endian()) + let g1: SubstrateG1 = if g1.0.is_zero() && g1.1.is_zero() { + SubstrateG1::zero() + } else { + let (g1_x, g1_y) = ( + Fq::from_slice(&g1.0.to_big_endian()) .map_err(|_| PrecompileError::ParsingInputError)?, - Fq::from_slice(&g2.3.to_big_endian()) + Fq::from_slice(&g1.1.to_big_endian()) .map_err(|_| PrecompileError::ParsingInputError)?, - ), - ); - let g1: SubstrateG1 = AffineG1::new(g1_x, g1_y) - .map_err(|_| PrecompileError::InvalidPoint)? - .into(); - let g2: SubstrateG2 = AffineG2::new(g2_x, g2_y) - .map_err(|_| PrecompileError::InvalidPoint)? - .into(); + ); + AffineG1::new(g1_x, g1_y) + .map_err(|_| PrecompileError::InvalidPoint)? + .into() + }; + let g2: SubstrateG2 = + if g2.0.is_zero() && g2.1.is_zero() && g2.2.is_zero() && g2.3.is_zero() { + SubstrateG2::zero() + } else { + let (g2_x, g2_y) = ( + Fq2::new( + Fq::from_slice(&g2.0.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + Fq::from_slice(&g2.1.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + ), + Fq2::new( + Fq::from_slice(&g2.2.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + Fq::from_slice(&g2.3.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + ), + ); + AffineG2::new(g2_x, g2_y) + .map_err(|_| PrecompileError::InvalidPoint)? + .into() + }; if g1.is_zero() || g2.is_zero() { continue; From db4affaf7d8b456136fa653f622b7843e343c148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Thu, 16 Oct 2025 12:49:36 -0300 Subject: [PATCH 10/16] add sp1 patch import comment --- crates/vm/levm/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/vm/levm/Cargo.toml b/crates/vm/levm/Cargo.toml index e92496cbf5c..cf5858aa27b 100644 --- a/crates/vm/levm/Cargo.toml +++ b/crates/vm/levm/Cargo.toml @@ -38,6 +38,7 @@ ark-ec = "0.5.0" ark-ff = "0.5.0" strum = { version = "0.27.1", features = ["derive"] } k256 = "0.13.4" +# We directly import SP1's patch because the API for the patch is different from the original subtrate-bn crate substrate-bn = { git = "https://github.com/sp1-patches/bn", tag = "patch-0.6.0-sp1-5.0.0", optional = true } From caf15fe964737a329e2ba403e8fb06c2df96ce55 Mon Sep 17 00:00:00 2001 From: ilitteri Date: Thu, 16 Oct 2025 15:59:10 -0300 Subject: [PATCH 11/16] Push temporary print --- crates/vm/levm/src/precompiles.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index 83febf60110..bcc256d1636 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -821,7 +821,10 @@ pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu } #[cfg(feature = "sp1")] - break 'inner pairing_substrate(&batch)?; + { + println!("Using substrate_bn for pairing"); + break 'inner pairing_substrate(&batch)?; + } // default break 'inner pairing_lambdaworks(&batch)?; From f8da994817bc7f7f51b557779731d5b716ca3899 Mon Sep 17 00:00:00 2001 From: ilitteri Date: Thu, 16 Oct 2025 16:00:20 -0300 Subject: [PATCH 12/16] Push temporary compilation error --- crates/vm/levm/src/precompiles.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index bcc256d1636..04ce529385f 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -822,7 +822,7 @@ pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu #[cfg(feature = "sp1")] { - println!("Using substrate_bn for pairing"); + compile_error!("TODO OK"); break 'inner pairing_substrate(&batch)?; } From cbe0ac5316fb3ccad030bcabd036079b667854ed Mon Sep 17 00:00:00 2001 From: ilitteri Date: Thu, 16 Oct 2025 16:05:32 -0300 Subject: [PATCH 13/16] revert temporary compilation error --- crates/vm/levm/src/precompiles.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index 04ce529385f..83febf60110 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -821,10 +821,7 @@ pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu } #[cfg(feature = "sp1")] - { - compile_error!("TODO OK"); - break 'inner pairing_substrate(&batch)?; - } + break 'inner pairing_substrate(&batch)?; // default break 'inner pairing_lambdaworks(&batch)?; From abb5a30cce5895355d3792c081cae0bfe69e28c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Thu, 16 Oct 2025 18:10:27 -0300 Subject: [PATCH 14/16] address some comments, impl is_zero --- crates/vm/levm/src/precompiles.rs | 85 ++++++++++++++++--------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index 83febf60110..0853c79b5ce 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -756,8 +756,20 @@ const ALT_BN128_PRIME: U256 = U256([ 0x30644e72e131a029, ]); -pub type G1 = (U256, U256); -pub type G2 = (U256, U256, U256, U256); +pub struct G1(U256, U256); +impl G1 { + /// According to EIP-197, the point at infinity (also called neutral element of G1 or zero) is encoded as (0, 0) + pub fn is_zero(&self) -> bool { + self.0.is_zero() && self.1.is_zero() + } +} +pub struct G2(U256, U256, U256, U256); +impl G2 { + /// According to EIP-197, the point at infinity (also called neutral element of G2 or zero) is encoded as (0, 0, 0, 0) + pub fn is_zero(&self) -> bool { + self.0.is_zero() && self.1.is_zero() && self.2.is_zero() && self.3.is_zero() + } +} #[inline] fn parse_bn254_coords(buf: &[u8; 192]) -> (G1, G2) { @@ -814,17 +826,10 @@ pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu } } - #[allow(unreachable_code)] - let pairing_check = 'inner: { - if batch.is_empty() { - break 'inner true; - } - - #[cfg(feature = "sp1")] - break 'inner pairing_substrate(&batch)?; - - // default - break 'inner pairing_lambdaworks(&batch)?; + let pairing_check = if batch.is_empty() { + true + } else { + pairing_check(&batch)? }; let mut result = [0; 32]; @@ -834,7 +839,7 @@ pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu #[cfg(feature = "sp1")] #[inline] -pub fn pairing_substrate(batch: &[(G1, G2)]) -> Result { +pub fn pairing_check(batch: &[(G1, G2)]) -> Result { use substrate_bn::{AffineG1, AffineG2, Fq, Fq2, G1 as SubstrateG1, G2 as SubstrateG2, Group}; let result = if batch.is_empty() { @@ -842,7 +847,7 @@ pub fn pairing_substrate(batch: &[(G1, G2)]) -> Result { } else { let mut valid_batch = Vec::with_capacity(batch.len()); for (g1, g2) in batch { - let g1: SubstrateG1 = if g1.0.is_zero() && g1.1.is_zero() { + let g1: SubstrateG1 = if g1.is_zero() { SubstrateG1::zero() } else { let (g1_x, g1_y) = ( @@ -855,28 +860,27 @@ pub fn pairing_substrate(batch: &[(G1, G2)]) -> Result { .map_err(|_| PrecompileError::InvalidPoint)? .into() }; - let g2: SubstrateG2 = - if g2.0.is_zero() && g2.1.is_zero() && g2.2.is_zero() && g2.3.is_zero() { - SubstrateG2::zero() - } else { - let (g2_x, g2_y) = ( - Fq2::new( - Fq::from_slice(&g2.0.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - Fq::from_slice(&g2.1.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - ), - Fq2::new( - Fq::from_slice(&g2.2.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - Fq::from_slice(&g2.3.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - ), - ); - AffineG2::new(g2_x, g2_y) - .map_err(|_| PrecompileError::InvalidPoint)? - .into() - }; + let g2: SubstrateG2 = if g2.is_zero() { + SubstrateG2::zero() + } else { + let (g2_x, g2_y) = ( + Fq2::new( + Fq::from_slice(&g2.0.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + Fq::from_slice(&g2.1.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + ), + Fq2::new( + Fq::from_slice(&g2.2.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + Fq::from_slice(&g2.3.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + ), + ); + AffineG2::new(g2_x, g2_y) + .map_err(|_| PrecompileError::InvalidPoint)? + .into() + }; if g1.is_zero() || g2.is_zero() { continue; @@ -890,8 +894,9 @@ pub fn pairing_substrate(batch: &[(G1, G2)]) -> Result { Ok(result == substrate_bn::Gt::one()) } +#[cfg(not(feature = "sp1"))] #[inline] -pub fn pairing_lambdaworks(batch: &[(G1, G2)]) -> Result { +pub fn pairing_check(batch: &[(G1, G2)]) -> Result { type Fq = BN254FieldElement; type Fq2 = BN254TwistCurveFieldElement; type LambdaworksG1 = BN254Curve; @@ -904,7 +909,7 @@ pub fn pairing_lambdaworks(batch: &[(G1, G2)]) -> Result { } else { let mut valid_batch = Vec::with_capacity(batch.len()); for (g1, g2) in batch { - let g1 = if g1.0.is_zero() && g1.1.is_zero() { + let g1 = if g1.is_zero() { ProjectiveG1::neutral_element() } else { let (g1_x, g1_y) = ( @@ -916,7 +921,7 @@ pub fn pairing_lambdaworks(batch: &[(G1, G2)]) -> Result { LambdaworksG1::create_point_from_affine(g1_x, g1_y) .map_err(|_| PrecompileError::InvalidPoint)? }; - let g2 = if g2.0.is_zero() && g2.1.is_zero() && g2.2.is_zero() && g2.3.is_zero() { + let g2 = if g2.is_zero() { ProjectiveG2::neutral_element() } else { let (g2_x, g2_y) = { From ae0f7277049bacc21927ce5e4999c273590f1d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Thu, 16 Oct 2025 18:20:22 -0300 Subject: [PATCH 15/16] early return --- crates/vm/levm/src/precompiles.rs | 171 +++++++++++++++--------------- 1 file changed, 85 insertions(+), 86 deletions(-) diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index 0853c79b5ce..6371874d229 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -842,54 +842,53 @@ pub fn ecpairing(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu pub fn pairing_check(batch: &[(G1, G2)]) -> Result { use substrate_bn::{AffineG1, AffineG2, Fq, Fq2, G1 as SubstrateG1, G2 as SubstrateG2, Group}; - let result = if batch.is_empty() { - substrate_bn::Gt::one() - } else { - let mut valid_batch = Vec::with_capacity(batch.len()); - for (g1, g2) in batch { - let g1: SubstrateG1 = if g1.is_zero() { - SubstrateG1::zero() - } else { - let (g1_x, g1_y) = ( - Fq::from_slice(&g1.0.to_big_endian()) + if batch.is_empty() { + return Ok(true); + } + let mut valid_batch = Vec::with_capacity(batch.len()); + for (g1, g2) in batch { + let g1: SubstrateG1 = if g1.is_zero() { + SubstrateG1::zero() + } else { + let (g1_x, g1_y) = ( + Fq::from_slice(&g1.0.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + Fq::from_slice(&g1.1.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + ); + AffineG1::new(g1_x, g1_y) + .map_err(|_| PrecompileError::InvalidPoint)? + .into() + }; + let g2: SubstrateG2 = if g2.is_zero() { + SubstrateG2::zero() + } else { + let (g2_x, g2_y) = ( + Fq2::new( + Fq::from_slice(&g2.0.to_big_endian()) .map_err(|_| PrecompileError::ParsingInputError)?, - Fq::from_slice(&g1.1.to_big_endian()) + Fq::from_slice(&g2.1.to_big_endian()) .map_err(|_| PrecompileError::ParsingInputError)?, - ); - AffineG1::new(g1_x, g1_y) - .map_err(|_| PrecompileError::InvalidPoint)? - .into() - }; - let g2: SubstrateG2 = if g2.is_zero() { - SubstrateG2::zero() - } else { - let (g2_x, g2_y) = ( - Fq2::new( - Fq::from_slice(&g2.0.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - Fq::from_slice(&g2.1.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - ), - Fq2::new( - Fq::from_slice(&g2.2.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - Fq::from_slice(&g2.3.to_big_endian()) - .map_err(|_| PrecompileError::ParsingInputError)?, - ), - ); - AffineG2::new(g2_x, g2_y) - .map_err(|_| PrecompileError::InvalidPoint)? - .into() - }; + ), + Fq2::new( + Fq::from_slice(&g2.2.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + Fq::from_slice(&g2.3.to_big_endian()) + .map_err(|_| PrecompileError::ParsingInputError)?, + ), + ); + AffineG2::new(g2_x, g2_y) + .map_err(|_| PrecompileError::InvalidPoint)? + .into() + }; - if g1.is_zero() || g2.is_zero() { - continue; - } - valid_batch.push((g1, g2)); + if g1.is_zero() || g2.is_zero() { + continue; } + valid_batch.push((g1, g2)); + } - substrate_bn::pairing_batch(&valid_batch) - }; + let result = substrate_bn::pairing_batch(&valid_batch); Ok(result == substrate_bn::Gt::one()) } @@ -904,53 +903,53 @@ pub fn pairing_check(batch: &[(G1, G2)]) -> Result { type ProjectiveG1 = ShortWeierstrassProjectivePoint; type ProjectiveG2 = ShortWeierstrassProjectivePoint; - let result = if batch.is_empty() { - QuadraticExtensionFieldElement::one() - } else { - let mut valid_batch = Vec::with_capacity(batch.len()); - for (g1, g2) in batch { - let g1 = if g1.is_zero() { - ProjectiveG1::neutral_element() - } else { - let (g1_x, g1_y) = ( - Fq::from_bytes_be(&g1.0.to_big_endian()) - .map_err(|_| InternalError::msg("failed to parse g1 x"))?, - Fq::from_bytes_be(&g1.1.to_big_endian()) - .map_err(|_| InternalError::msg("failed to parse g1 y"))?, + if batch.is_empty() { + return Ok(true); + } + + let mut valid_batch = Vec::with_capacity(batch.len()); + for (g1, g2) in batch { + let g1 = if g1.is_zero() { + ProjectiveG1::neutral_element() + } else { + let (g1_x, g1_y) = ( + Fq::from_bytes_be(&g1.0.to_big_endian()) + .map_err(|_| InternalError::msg("failed to parse g1 x"))?, + Fq::from_bytes_be(&g1.1.to_big_endian()) + .map_err(|_| InternalError::msg("failed to parse g1 y"))?, + ); + LambdaworksG1::create_point_from_affine(g1_x, g1_y) + .map_err(|_| PrecompileError::InvalidPoint)? + }; + let g2 = if g2.is_zero() { + ProjectiveG2::neutral_element() + } else { + let (g2_x, g2_y) = { + let x_bytes = [g2.0.to_big_endian(), g2.1.to_big_endian()].concat(); + let y_bytes = [g2.2.to_big_endian(), g2.3.to_big_endian()].concat(); + let (x, y) = ( + Fq2::from_bytes_be(&x_bytes) + .map_err(|_| InternalError::msg("failed to parse g2 x"))?, + Fq2::from_bytes_be(&y_bytes) + .map_err(|_| InternalError::msg("failed to parse g2 y"))?, ); - LambdaworksG1::create_point_from_affine(g1_x, g1_y) - .map_err(|_| PrecompileError::InvalidPoint)? + (x, y) }; - let g2 = if g2.is_zero() { - ProjectiveG2::neutral_element() - } else { - let (g2_x, g2_y) = { - let x_bytes = [g2.0.to_big_endian(), g2.1.to_big_endian()].concat(); - let y_bytes = [g2.2.to_big_endian(), g2.3.to_big_endian()].concat(); - let (x, y) = ( - Fq2::from_bytes_be(&x_bytes) - .map_err(|_| InternalError::msg("failed to parse g2 x"))?, - Fq2::from_bytes_be(&y_bytes) - .map_err(|_| InternalError::msg("failed to parse g2 y"))?, - ); - (x, y) - }; - LambdaworksG2::create_point_from_affine(g2_x, g2_y) - .map_err(|_| PrecompileError::InvalidPoint)? - }; - if !g2.is_in_subgroup() { - return Err(PrecompileError::PointNotInSubgroup.into()); - } + LambdaworksG2::create_point_from_affine(g2_x, g2_y) + .map_err(|_| PrecompileError::InvalidPoint)? + }; + if !g2.is_in_subgroup() { + return Err(PrecompileError::PointNotInSubgroup.into()); + } - if g1.is_neutral_element() || g2.is_neutral_element() { - continue; - } - valid_batch.push((g1, g2)); + if g1.is_neutral_element() || g2.is_neutral_element() { + continue; } - let valid_batch_refs: Vec<_> = valid_batch.iter().map(|(p1, p2)| (p1, p2)).collect(); - BN254AtePairing::compute_batch(&valid_batch_refs) - .map_err(|_| PrecompileError::BN254AtePairingError)? - }; + valid_batch.push((g1, g2)); + } + let valid_batch_refs: Vec<_> = valid_batch.iter().map(|(p1, p2)| (p1, p2)).collect(); + let result = BN254AtePairing::compute_batch(&valid_batch_refs) + .map_err(|_| PrecompileError::BN254AtePairingError)?; Ok(result == QuadraticExtensionFieldElement::one()) } From 9cad02229f506c4602e1a2408ee58e771899168b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Est=C3=A9fano=20Bargas?= Date: Thu, 16 Oct 2025 18:31:29 -0300 Subject: [PATCH 16/16] fix --- crates/vm/levm/src/precompiles.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index 6371874d229..130b71e288b 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -784,7 +784,7 @@ fn parse_bn254_coords(buf: &[u8; 192]) -> (G1, G2) { u256_from_big_endian(&buf[160..]), ); - ((g1_x, g1_y), (g2_xx, g2_xy, g2_yx, g2_yy)) + (G1(g1_x, g1_y), G2(g2_xx, g2_xy, g2_yx, g2_yy)) } #[inline]