From 9977ae03bdd14896de0cf81802d9163c919454e3 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 18 Jan 2023 14:41:09 +0700 Subject: [PATCH] new inverse --- evm/src/bn254_arithmetic.rs | 149 +++++++++++++++++++---------- evm/src/bn254_curve_pairing.rs | 70 ++++++++++---- evm/src/cpu/kernel/tests/bn254.rs | 26 ++--- evm/src/generation/prover_input.rs | 17 ++-- evm/src/lib.rs | 1 + 5 files changed, 172 insertions(+), 91 deletions(-) diff --git a/evm/src/bn254_arithmetic.rs b/evm/src/bn254_arithmetic.rs index 40aa0ff8..a174278e 100644 --- a/evm/src/bn254_arithmetic.rs +++ b/evm/src/bn254_arithmetic.rs @@ -1,6 +1,7 @@ use std::ops::{Add, Div, Mul, Neg, Sub}; use ethereum_types::U256; +use itertools::Itertools; use rand::{thread_rng, Rng}; pub const BN_BASE: U256 = U256([ @@ -10,7 +11,7 @@ pub const BN_BASE: U256 = U256([ 0x30644e72e131a029, ]); -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq)] pub struct Fp { val: U256, } @@ -59,8 +60,8 @@ impl Div for Fp { type Output = Self; fn div(self, rhs: Self) -> Self::Output { - let inv = exp_fp(self, BN_BASE - 2); - rhs * inv + let inv = exp_fp(rhs, BN_BASE - 2); + self * inv } } @@ -79,7 +80,7 @@ fn exp_fp(x: Fp, e: U256) -> Fp { product } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq)] pub struct Fp2 { re: Fp, im: Fp, @@ -133,12 +134,12 @@ impl Div for Fp2 { type Output = Self; fn div(self, rhs: Self) -> Self::Output { - let norm = self.re * self.re + self.im * self.im; + let norm = rhs.re * rhs.re + rhs.im * rhs.im; let inv = Fp2 { - re: self.re / norm, - im: -self.im / norm, + re: rhs.re / norm, + im: -rhs.im / norm, }; - rhs * inv + self * inv } } @@ -154,6 +155,14 @@ fn conj_fp2(a: Fp2) -> Fp2 { } } +fn normalize_fp2(a: Fp2) -> Fp2 { + let norm = a.re * a.re + a.im * a.im; + Fp2 { + re: a.re / norm, + im: a.im / norm, + } +} + fn i9(a: Fp2) -> Fp2 { let nine = Fp { val: U256::from(9) }; Fp2 { @@ -162,7 +171,7 @@ fn i9(a: Fp2) -> Fp2 { } } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq)] pub struct Fp6 { t0: Fp2, t1: Fp2, @@ -217,23 +226,17 @@ impl Mul for Fp6 { } } -// impl Div for Fp6 { -// type Output = Self; +impl Div for Fp6 { + type Output = Self; -// fn div(self, rhs: Self) -> Self::Output { -// let b = frob_fp6(1, self) * frob_fp6(3, self); -// let e = (b * frob_fp6(5, self)).t0; -// let n = (e * conj_fp2(e)).re; -// let d = e / embed_fp2(n); -// let f = frob_fp6(1, b); -// let inv = Fp6 { -// t0: d * f.t0, -// t1: d * f.t1, -// t2: d * f.t2, -// }; -// rhs * inv -// } -// } + fn div(self, rhs: Self) -> Self::Output { + let b = frob_fp6(1, rhs) * frob_fp6(3, rhs); + let e = normalize_fp2((b * frob_fp6(5, rhs)).t0); + let f = frob_fp6(1, b); + let inv = mul_fp2_fp6(e, f); + self * inv + } +} // pub fn inv_fp6(c: Fp6) -> Fp6 { // let b = mul_fp6(frob_fp6(1, c), frob_fp6(3, c)); @@ -245,6 +248,12 @@ impl Mul for Fp6 { // [mul_fp2(d, f0), mul_fp2(d, f1), mul_fp2(d, f2)] // } +pub const FP6_ZERO: Fp6 = Fp6 { + t0: FP2_ZERO, + t1: FP2_ZERO, + t2: FP2_ZERO, +}; + fn mul_fp2_fp6(x: Fp2, f: Fp6) -> Fp6 { Fp6 { t0: x * f.t0, @@ -261,7 +270,7 @@ fn sh(c: Fp6) -> Fp6 { } } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq)] pub struct Fp12 { z0: Fp6, z1: Fp6, @@ -281,6 +290,49 @@ impl Mul for Fp12 { } } +impl Div for Fp12 { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + let a = (frob_fp12(1, rhs) * frob_fp12(7, rhs)).z0; + let b = a * frob_fp6(2, a); + let c = normalize_fp2((b * frob_fp6(4, a)).t0); + let g = frob_fp6(1, b); + let e = mul_fp2_fp6(c, g); + let inv = Fp12 { + z0: e * rhs.z0, + z1: -e * rhs.z1, + }; + self * inv + } +} + +// pub fn inv_fp12(f: Fp12) -> Fp12 { + // let a = (frob_fp12(1, self) * frob_fp12(7, self))[0]; + // let b = a * frob_fp6(2, a); + // let c = (b * frob_fp6(4, a))[0]; + // let d = c / norm(c); + // let [g0, g1, g2] = frob_fp6(1, b); + // let e = [d * g0, d * g1, d * g2]; + // [e * self.z0, - e * self.z1] +// } + +pub const UNIT_FP12: Fp12 = Fp12 { + z0: Fp6 { + t0: Fp2 { + re: Fp {val: U256::one()}, + im: FP_ZERO + }, + t1: FP2_ZERO, + t2: FP2_ZERO, + }, + z1: FP6_ZERO, +}; + +pub fn inv_fp12(f: Fp12) -> Fp12 { + UNIT_FP12 / f +} + fn sparse_embed(g000: Fp, g01: Fp2, g11: Fp2) -> Fp12 { let g0 = Fp6 { t0: Fp2 { @@ -300,19 +352,6 @@ fn sparse_embed(g000: Fp, g01: Fp2, g11: Fp2) -> Fp12 { Fp12 { z0: g0, z1: g1 } } -// pub fn inv_fp12(f: Fp12) -> Fp12 { -// let [f0, f1] = f; -// let a = mul_fp12(frob_fp12(1, f), frob_fp12(7, f))[0]; -// let b = mul_fp6(a, frob_fp6(2, a)); -// let c = mul_fp6(b, frob_fp6(4, a))[0]; -// let n = mul_fp2(c, conj_fp2(c))[0]; -// let i = inv_fp(n); -// let d = mul_fp2(embed_fp2(i), c); -// let [g0, g1, g2] = frob_fp6(1, b); -// let e = [mul_fp2(d, g0), mul_fp2(d, g1), mul_fp2(d, g2)]; -// [mul_fp6(e, f0), neg_fp6(mul_fp6(e, f1))] -// } - pub fn fp12_to_array(f: Fp12) -> [U256; 12] { [ f.z0.t0.re.val, @@ -334,15 +373,29 @@ pub fn fp12_to_vec(f: Fp12) -> Vec { fp12_to_array(f).into_iter().collect() } -// pub fn vec_to_fp12(xs: Vec) -> Fp12 { -// xs.into_iter() -// .tuples::<(U256, U256)>() -// .map(|(v1, v2)| [v1, v2]) -// .tuples() -// .map(|(a1, a2, a3, a4, a5, a6)| [[a1, a2, a3], [a4, a5, a6]]) -// .next() -// .unwrap() -// } +pub fn vec_to_fp12(xs: Vec) -> Fp12 { + xs.into_iter() + .tuples::<(U256, U256)>() + .map(|(v1, v2)| Fp2 { + re: Fp { val: v1 }, + im: Fp { val: v2 }, + }) + .tuples() + .map(|(a1, a2, a3, a4, a5, a6)| Fp12 { + z0: Fp6 { + t0: a1, + t1: a2, + t2: a3, + }, + z1: Fp6 { + t0: a4, + t1: a5, + t2: a6, + }, + }) + .next() + .unwrap() +} fn gen_fp() -> Fp { let mut rng = thread_rng(); diff --git a/evm/src/bn254_curve_pairing.rs b/evm/src/bn254_curve_pairing.rs index dba6c5dd..a6a44677 100644 --- a/evm/src/bn254_curve_pairing.rs +++ b/evm/src/bn254_curve_pairing.rs @@ -1,26 +1,54 @@ -// pub type Curve = [Fp; 2]; -// pub type TwistedCurve = [Fp2; 2]; +use ethereum_types::U256; -// pub fn curve_generator() -> Curve { -// [U256::one(), U256::from(2)] -// } +use crate::bn254_arithmetic::{Fp, Fp12}; -// pub fn twisted_curve_generator() -> TwistedCurve { -// [ -// [ -// U256::from_str("0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed") -// .unwrap(), -// U256::from_str("0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2") -// .unwrap(), -// ], -// [ -// U256::from_str("0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa") -// .unwrap(), -// U256::from_str("0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b") -// .unwrap(), -// ], -// ] -// } +pub type Curve = [Fp; 2]; +pub type TwistedCurve = [[Fp; 2]; 2]; + +pub fn curve_generator() -> Curve { + [Fp { val: U256::one() }, Fp { val: U256::from(2) }] +} + +pub fn twisted_curve_generator() -> TwistedCurve { + [ + [ + Fp { + val: U256([ + 0x46debd5cd992f6ed, + 0x674322d4f75edadd, + 0x426a00665e5c4479, + 0x1800deef121f1e76, + ]), + }, + Fp { + val: U256([ + 0x97e485b7aef312c2, + 0xf1aa493335a9e712, + 0x7260bfb731fb5d25, + 0x198e9393920d483a, + ]), + }, + ], + [ + Fp { + val: U256([ + 0x4ce6cc0166fa7daa, + 0xe3d1e7690c43d37b, + 0x4aab71808dcb408f, + 0x12c85ea5db8c6deb, + ]), + }, + Fp { + val: U256([ + 0x55acdadcd122975b, + 0xbc4b313370b38ef3, + 0xec9e99ad690c3395, + 0x90689d0585ff075, + ]), + }, + ], + ] +} pub fn power(f: Fp12) -> Fp12 { const EXPS4: [(usize, usize, usize); 64] = [ diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index f1e9f354..235ebcec 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -1,4 +1,4 @@ -// use std::str::FromStr; +use std::str::FromStr; use anyhow::Result; use ethereum_types::U256; @@ -92,22 +92,22 @@ fn test_frob_fp12() -> Result<()> { Ok(()) } -// #[test] -// fn test_inv_fp12() -> Result<()> { -// let ptr = U256::from(200); -// let inv = U256::from(300); +#[test] +fn test_inv_fp12() -> Result<()> { + let ptr = U256::from(200); + let inv = U256::from(300); -// let f: Fp12 = gen_fp12(); -// let mut stack = vec![ptr]; -// stack.extend(fp12_to_vec(f)); -// stack.extend(vec![ptr, inv, U256::from_str("0xdeadbeef").unwrap()]); + let f: Fp12 = gen_fp12(); + let mut stack = vec![ptr]; + stack.extend(fp12_to_vec(f)); + stack.extend(vec![ptr, inv, U256::from_str("0xdeadbeef").unwrap()]); -// let output: Vec = get_output("test_inv_fp12", stack); + let output: Vec = get_output("test_inv_fp12", stack); -// assert_eq!(output, vec![]); + assert_eq!(output, vec![]); -// Ok(()) -// } + Ok(()) +} // #[test] // fn test_power() -> Result<()> { diff --git a/evm/src/generation/prover_input.rs b/evm/src/generation/prover_input.rs index 373304e7..9f305e41 100644 --- a/evm/src/generation/prover_input.rs +++ b/evm/src/generation/prover_input.rs @@ -4,7 +4,7 @@ use anyhow::{bail, Error}; use ethereum_types::{BigEndianHash, H256, U256}; use plonky2::field::types::Field; -// use crate::bn254_arithmetic::{fp12_to_array, inv_fp12, vec_to_fp12}; +use crate::bn254_arithmetic::{fp12_to_array, inv_fp12, vec_to_fp12}; use crate::generation::prover_input::EvmField::{ Bn254Base, Bn254Scalar, Secp256k1Base, Secp256k1Scalar, }; @@ -75,8 +75,7 @@ impl GenerationState { "component_11" => 11, _ => panic!("out of bounds"), }; - // field.inverse_fp12(n, xs) - todo!() + field.inverse_fp12(n, xs) } /// MPT data. @@ -197,12 +196,12 @@ impl EvmField { modexp(x, q, n) } - // fn inverse_fp12(&self, n: usize, xs: Vec) -> U256 { - // let offset = 12 - n; - // let vec: Vec = xs[offset..].to_vec(); - // let f = fp12_to_array(inv_fp12(vec_to_fp12(vec))); - // f[n] - // } + fn inverse_fp12(&self, n: usize, xs: Vec) -> U256 { + let offset = 12 - n; + let vec: Vec = xs[offset..].to_vec(); + let f = fp12_to_array(inv_fp12(vec_to_fp12(vec))); + f[n] + } } fn modexp(x: U256, e: U256, n: U256) -> U256 { diff --git a/evm/src/lib.rs b/evm/src/lib.rs index 226a8b77..689e6c57 100644 --- a/evm/src/lib.rs +++ b/evm/src/lib.rs @@ -9,6 +9,7 @@ pub mod all_stark; pub mod arithmetic; pub mod bn254_arithmetic; +// pub mod bn254_curve_pairing; pub mod config; pub mod constraint_consumer; pub mod cpu;