|
| 1 | +use openvm_algebra_guest::IntMod; |
| 2 | +use openvm_ecc_guest::AffinePoint; |
| 3 | +#[allow(unused_imports)] |
| 4 | +use openvm_pairing_guest::{ |
| 5 | + bn254::{Bn254, Bn254G1Affine, Fp, Fp2}, |
| 6 | + pairing::PairingCheck, |
| 7 | +}; |
| 8 | + |
| 9 | +openvm_algebra_guest::moduli_macros::moduli_init! { |
| 10 | + "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47", // Bn254Fp Coordinate field |
| 11 | + "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001", // Bn254 Scalar |
| 12 | +} |
| 13 | + |
| 14 | +openvm_ecc_guest::sw_macros::sw_init! { |
| 15 | + Bn254G1Affine |
| 16 | +} |
| 17 | + |
| 18 | +openvm_algebra_guest::complex_macros::complex_init! { |
| 19 | + Bn254Fp2 { mod_idx = 0 }, |
| 20 | +} |
| 21 | + |
| 22 | +const PAIR_ELEMENT_LEN: usize = 32 * (2 + 4); // 1 G1Affine (2 Fp), 1 G2Affine (4 Fp) |
| 23 | + |
| 24 | +pub fn main() { |
| 25 | + // copied from https://github.com/bluealloy/revm/blob/9e39df5dbc5fdc98779c644629b28b8bee75794a/crates/precompile/src/bn128.rs#L395 |
| 26 | + let input = hex::decode( |
| 27 | + "\ |
| 28 | + 1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\ |
| 29 | + 3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41\ |
| 30 | + 209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7\ |
| 31 | + 04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678\ |
| 32 | + 2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d\ |
| 33 | + 120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550\ |
| 34 | + 111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c\ |
| 35 | + 2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411\ |
| 36 | + 198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2\ |
| 37 | + 1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed\ |
| 38 | + 090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b\ |
| 39 | + 12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", |
| 40 | + ) |
| 41 | + .unwrap(); |
| 42 | + |
| 43 | + let elements = input.len() / PAIR_ELEMENT_LEN; |
| 44 | + |
| 45 | + let mut p = Vec::with_capacity(elements); |
| 46 | + let mut q = Vec::with_capacity(elements); |
| 47 | + |
| 48 | + // read points |
| 49 | + for idx in 0..elements { |
| 50 | + // At each idx, there is (G1, G2) which is 6 Fp points |
| 51 | + let read_fq_at = |n: usize| { |
| 52 | + debug_assert!(n < PAIR_ELEMENT_LEN / 32); |
| 53 | + let start = idx * PAIR_ELEMENT_LEN + n * 32; |
| 54 | + // SAFETY: We're reading `6 * 32 == PAIR_ELEMENT_LEN` bytes from `input[idx..]` |
| 55 | + // per iteration. This is guaranteed to be in-bounds. |
| 56 | + let slice = unsafe { input.get_unchecked(start..start + 32) }; |
| 57 | + Fp::from_be_bytes(&slice[..32]) |
| 58 | + }; |
| 59 | + // https://eips.ethereum.org/EIPS/eip-197, Fp2 is encoded as (a, b) where a * i + b |
| 60 | + let g1_x = read_fq_at(0); |
| 61 | + let g1_y = read_fq_at(1); |
| 62 | + let g2_x_c1 = read_fq_at(2); |
| 63 | + let g2_x_c0 = read_fq_at(3); |
| 64 | + let g2_y_c1 = read_fq_at(4); |
| 65 | + let g2_y_c0 = read_fq_at(5); |
| 66 | + |
| 67 | + let g1 = AffinePoint::new(g1_x, g1_y); |
| 68 | + let g2_x = Fp2::new(g2_x_c0, g2_x_c1); |
| 69 | + let g2_y = Fp2::new(g2_y_c0, g2_y_c1); |
| 70 | + let g2 = AffinePoint::new(g2_x, g2_y); |
| 71 | + |
| 72 | + p.push(g1); |
| 73 | + q.push(g2); |
| 74 | + } |
| 75 | + let success = Bn254::pairing_check(&p, &q).is_ok(); |
| 76 | + assert!(success); |
| 77 | +} |
0 commit comments