diff --git a/evm/src/bn254_arithmetic.rs b/evm/src/bn254_arithmetic.rs index d7e3ca3e..f6c192b7 100644 --- a/evm/src/bn254_arithmetic.rs +++ b/evm/src/bn254_arithmetic.rs @@ -1,8 +1,6 @@ -use std::ops::{Add, Div, Mul, Sub}; -use std::str::FromStr; +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([ @@ -12,737 +10,554 @@ pub const BN_BASE: U256 = U256([ 0x30644e72e131a029, ]); -// pub struct Fp { -// val: U256, -// } - -pub type Fp = U256; -pub type Fp2 = [U256; 2]; -pub type Fp6 = [Fp2; 3]; -pub type Fp12 = [Fp6; 2]; - -pub fn fp12_to_vec(f: Fp12) -> Vec { - f.into_iter().flatten().flatten().collect() +#[derive(Debug, Copy, Clone)] +pub struct Fp { + val: U256, } -pub fn fp12_to_array(f: Fp12) -> [U256; 12] { - let [[[f0, f1], [f2, f3], [f4, f5]], [[f6, f7], [f8, f9], [f10, f11]]] = f; - [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11] +impl Add for Fp { + type Output = Self; + + fn add(self, other: Self) -> Self { + Fp { + val: (self.val + other.val) % BN_BASE, + } + } } -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() +impl Neg for Fp { + type Output = Self; + + fn neg(self) -> Self::Output { + Fp { + val: (BN_BASE - self.val) % BN_BASE, + } + } } -pub type Curve = [Fp; 2]; -pub type TwistedCurve = [Fp2; 2]; +impl Sub for Fp { + type Output = Self; -pub fn curve_generator() -> Curve { - [U256::one(), U256::from(2)] + fn sub(self, other: Self) -> Self { + Fp { + val: (BN_BASE + self.val - other.val) % BN_BASE, + } + } } -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(), - ], - ] +impl Mul for Fp { + type Output = Self; + + fn mul(self, other: Self) -> Self { + Fp { + val: U256::try_from((self.val).full_mul(other.val) % BN_BASE).unwrap(), + } + } } -const FP_ZERO: Fp = U256::zero(); +impl Div for Fp { + type Output = Self; -fn embed_fp2(x: Fp) -> Fp2 { - [x, FP_ZERO] + fn div(self, rhs: Self) -> Self::Output { + let inv = exp_fp(self, BN_BASE - 2); + rhs * inv + } } -fn embed_fp2_fp6(a: Fp2) -> Fp6 { - [a, embed_fp2(FP_ZERO), embed_fp2(FP_ZERO)] -} - -fn embed_fp6(x: Fp) -> Fp6 { - embed_fp2_fp6(embed_fp2(x)) -} - -fn embed_fp12(x: Fp) -> Fp12 { - [embed_fp6(x), embed_fp6(FP_ZERO)] -} - -fn gen_fp() -> Fp { - let mut rng = thread_rng(); - let x64 = rng.gen::(); - U256([x64, x64, x64, x64]) % BN_BASE -} - -fn gen_fp2() -> Fp2 { - [gen_fp(), gen_fp()] -} - -fn gen_fp6() -> Fp6 { - [gen_fp2(), gen_fp2(), gen_fp2()] -} - -pub fn gen_fp12() -> Fp12 { - [gen_fp6(), gen_fp6()] -} - -pub fn gen_fp12_sparse() -> Fp12 { - sparse_embed(gen_fp(), [gen_fp(), gen_fp()], [gen_fp(), gen_fp()]) -} - -fn add_fp(x: Fp, y: Fp) -> Fp { - (x + y) % BN_BASE -} - -fn add3_fp(x: Fp, y: Fp, z: Fp) -> Fp { - (x + y + z) % BN_BASE -} - -fn mul_fp(x: Fp, y: Fp) -> Fp { - U256::try_from(x.full_mul(y) % BN_BASE).unwrap() -} - -fn sub_fp(x: Fp, y: Fp) -> Fp { - (BN_BASE + x - y) % BN_BASE -} - -fn neg_fp(x: Fp) -> Fp { - (BN_BASE - x) % BN_BASE -} +const FP_ZERO: Fp = Fp { val: U256::zero() }; fn exp_fp(x: Fp, e: U256) -> Fp { let mut current = x; - let mut product = U256::one(); + let mut product = Fp { val: U256::one() }; for j in 0..256 { if e.bit(j) { - product = U256::try_from(product.full_mul(current) % BN_BASE).unwrap(); + product = product * current; } - current = U256::try_from(current.full_mul(current) % BN_BASE).unwrap(); + current = current * current; } product } -fn inv_fp(x: Fp) -> Fp { - exp_fp(x, BN_BASE - 2) +#[derive(Debug, Copy, Clone)] +pub struct Fp2 { + re: Fp, + im: Fp, } -fn div_fp(x: Fp, y: Fp) -> Fp { - mul_fp(x, inv_fp(y)) +impl Add for Fp2 { + type Output = Self; + + fn add(self, other: Self) -> Self { + Fp2 { + re: self.re + other.re, + im: self.im + other.im, + } + } +} + +impl Neg for Fp2 { + type Output = Self; + + fn neg(self) -> Self::Output { + Fp2 { + re: -self.re, + im: -self.im, + } + } +} + +impl Sub for Fp2 { + type Output = Self; + + fn sub(self, other: Self) -> Self { + Fp2 { + re: self.re - other.re, + im: self.im - other.im, + } + } +} + +impl Mul for Fp2 { + type Output = Self; + + fn mul(self, other: Self) -> Self { + Fp2 { + re: self.re * other.re - self.im * other.im, + im: self.re * other.im + self.im * other.re, + } + } +} + +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 inv = Fp2 { + re: self.re / norm, + im: -self.im / norm, + }; + rhs * inv + } +} + +const FP2_ZERO: Fp2 = Fp2 { + re: FP_ZERO, + im: FP_ZERO, +}; + +fn flatten_fp2(a: Fp2) -> [U256; 2] { + [a.re.val, a.im.val] +} + +fn embed_fp2(x: Fp) -> Fp2 { + Fp2 { re: x, im: FP_ZERO } } fn conj_fp2(a: Fp2) -> Fp2 { - let [a, a_] = a; - [a, neg_fp(a_)] -} - -fn add_fp2(a: Fp2, b: Fp2) -> Fp2 { - let [a, a_] = a; - let [b, b_] = b; - [add_fp(a, b), add_fp(a_, b_)] -} - -fn add3_fp2(a: Fp2, b: Fp2, c: Fp2) -> Fp2 { - let [a, a_] = a; - let [b, b_] = b; - let [c, c_] = c; - [add3_fp(a, b, c), add3_fp(a_, b_, c_)] -} - -fn sub_fp2(a: Fp2, b: Fp2) -> Fp2 { - let [a, a_] = a; - let [b, b_] = b; - [sub_fp(a, b), sub_fp(a_, b_)] -} - -fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 { - let [a, a_] = a; - let [b, b_] = b; - [ - sub_fp(mul_fp(a, b), mul_fp(a_, b_)), - add_fp(mul_fp(a, b_), mul_fp(a_, b)), - ] + Fp2 { + re: a.re, + im: -a.im, + } } fn i9(a: Fp2) -> Fp2 { - let [a, a_] = a; - let nine = U256::from(9); - [sub_fp(mul_fp(nine, a), a_), add_fp(a, mul_fp(nine, a_))] + let nine = Fp { val: U256::from(9) }; + Fp2 { + re: nine * a.re - a.im, + im: a.re + nine * a.im, + } } -fn add_fp6(c: Fp6, d: Fp6) -> Fp6 { - let [c0, c1, c2] = c; - let [d0, d1, d2] = d; - - let e0 = add_fp2(c0, d0); - let e1 = add_fp2(c1, d1); - let e2 = add_fp2(c2, d2); - [e0, e1, e2] +#[derive(Debug, Copy, Clone)] +pub struct Fp6 { + t0: Fp2, + t1: Fp2, + t2: Fp2, } -fn sub_fp6(c: Fp6, d: Fp6) -> Fp6 { - let [c0, c1, c2] = c; - let [d0, d1, d2] = d; +impl Add for Fp6 { + type Output = Self; - let e0 = sub_fp2(c0, d0); - let e1 = sub_fp2(c1, d1); - let e2 = sub_fp2(c2, d2); - [e0, e1, e2] + fn add(self, other: Self) -> Self { + Fp6 { + t0: self.t0 + other.t0, + t1: self.t1 + other.t1, + t2: self.t2 + other.t2, + } + } } -fn neg_fp6(a: Fp6) -> Fp6 { - sub_fp6(embed_fp6(FP_ZERO), a) +impl Neg for Fp6 { + type Output = Self; + + fn neg(self) -> Self::Output { + Fp6 { + t0: -self.t0, + t1: -self.t1, + t2: -self.t2, + } + } } -fn mul_fp6(c: Fp6, d: Fp6) -> Fp6 { - let [c0, c1, c2] = c; - let [d0, d1, d2] = d; +impl Sub for Fp6 { + type Output = Self; - let c0d0 = mul_fp2(c0, d0); - let c0d1 = mul_fp2(c0, d1); - let c0d2 = mul_fp2(c0, d2); - let c1d0 = mul_fp2(c1, d0); - let c1d1 = mul_fp2(c1, d1); - let c1d2 = mul_fp2(c1, d2); - let c2d0 = mul_fp2(c2, d0); - let c2d1 = mul_fp2(c2, d1); - let c2d2 = mul_fp2(c2, d2); - let cd12 = add_fp2(c1d2, c2d1); + fn sub(self, other: Self) -> Self { + Fp6 { + t0: self.t0 - other.t0, + t1: self.t1 - other.t1, + t2: self.t2 - other.t2, + } + } +} - [ - add_fp2(c0d0, i9(cd12)), - add3_fp2(c0d1, c1d0, i9(c2d2)), - add3_fp2(c0d2, c1d1, c2d0), - ] +impl Mul for Fp6 { + type Output = Self; + + fn mul(self, other: Self) -> Self { + Fp6 { + t0: self.t0 * other.t0 + i9(self.t1 * other.t2 + self.t2 * other.t1), + t1: self.t0 * other.t1 + self.t1 * other.t0 + i9(self.t2 * other.t2), + t2: self.t0 * other.t2 + self.t1 * other.t1 + self.t2 * other.t0, + } + } } fn sh(c: Fp6) -> Fp6 { - let [c0, c1, c2] = c; - [i9(c2), c0, c1] + Fp6 { + t0: i9(c.t2), + t1: c.t0, + t2: c.t1, + } } -fn sparse_embed(g0: Fp, g1: Fp2, g2: Fp2) -> Fp12 { +// 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 +// } +// } + +// pub fn inv_fp6(c: Fp6) -> Fp6 { +// let b = mul_fp6(frob_fp6(1, c), frob_fp6(3, c)); +// let e = mul_fp6(b, frob_fp6(5, c))[0]; +// let n = mul_fp2(e, conj_fp2(e))[0]; +// let i = inv_fp(n); +// let d = mul_fp2(embed_fp2(i), e); +// let [f0, f1, f2] = frob_fp6(1, b); +// [mul_fp2(d, f0), mul_fp2(d, f1), mul_fp2(d, f2)] +// } + +#[derive(Debug, Copy, Clone)] +pub struct Fp12 { + z0: Fp6, + z1: Fp6, +} + +impl Mul for Fp12 { + type Output = Self; + + fn mul(self, other: Self) -> Self { + let h0 = self.z0 * other.z0; + let h1 = self.z1 * other.z1; + let h01 = (self.z0 + self.z1) * (other.z0 + other.z1); + Fp12 { + z0: h0 + sh(h1), + z1: h01 - (h0 + h1), + } + } +} + +fn sparse_embed(g000: Fp, g01: Fp2, g11: Fp2) -> Fp12 { + let g00 = Fp2 { + re: g000, + im: FP_ZERO, + }; + + let g0 = Fp6 { + t0: g00, + t1: g01, + t2: FP2_ZERO, + }; + + let g1 = Fp6 { + t0: FP2_ZERO, + t1: g11, + t2: FP2_ZERO, + }; + + 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] { [ - [embed_fp2(g0), g1, embed_fp2(FP_ZERO)], - [embed_fp2(FP_ZERO), g2, embed_fp2(FP_ZERO)], + f.z0.t0.re.val, + f.z0.t0.im.val, + f.z0.t1.re.val, + f.z0.t1.im.val, + f.z0.t2.re.val, + f.z0.t2.im.val, + f.z1.t0.re.val, + f.z1.t0.im.val, + f.z1.t1.re.val, + f.z1.t1.im.val, + f.z1.t2.re.val, + f.z1.t2.im.val, ] } -pub fn mul_fp12(f: Fp12, g: Fp12) -> Fp12 { - let [f0, f1] = f; - let [g0, g1] = g; - - let h0 = mul_fp6(f0, g0); - let h1 = mul_fp6(f1, g1); - let h01 = mul_fp6(add_fp6(f0, f1), add_fp6(g0, g1)); - [add_fp6(h0, sh(h1)), sub_fp6(h01, add_fp6(h0, h1))] +pub fn fp12_to_vec(f: Fp12) -> Vec { + fp12_to_array(f).into_iter().collect() } -fn frob_fp6(n: usize, c: Fp6) -> Fp6 { - let [c0, c1, c2] = c; - let _c0 = conj_fp2(c0); - let _c1 = conj_fp2(c1); - let _c2 = conj_fp2(c2); +// 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() +// } - let n = n % 6; - let frob_t1 = frob_t1(n); - let frob_t2 = frob_t2(n); +// fn embed_fp2(x: Fp) -> Fp2 { +// [x, FP_ZERO] +// } - if n % 2 != 0 { - [_c0, mul_fp2(frob_t1, _c1), mul_fp2(frob_t2, _c2)] - } else { - [c0, mul_fp2(frob_t1, c1), mul_fp2(frob_t2, c2)] +// fn embed_fp2_fp6(a: Fp2) -> Fp6 { +// [a, embed_fp2(FP_ZERO), embed_fp2(FP_ZERO)] +// } + +// fn embed_fp6(x: Fp) -> Fp6 { +// embed_fp2_fp6(embed_fp2(x)) +// } + +// fn embed_fp12(x: Fp) -> Fp12 { +// [embed_fp6(x), embed_fp6(FP_ZERO)] +// } + +fn gen_fp() -> Fp { + let mut rng = thread_rng(); + let x64 = rng.gen::(); + let x256 = U256([x64, x64, x64, x64]) % BN_BASE; + Fp { val: x256 } +} + +fn gen_fp2() -> Fp2 { + Fp2 { + re: gen_fp(), + im: gen_fp(), } } -pub fn frob_fp12(n: usize, f: Fp12) -> Fp12 { - let [f0, f1] = f; - let scale = embed_fp2_fp6(frob_z(n)); - - [frob_fp6(n, f0), mul_fp6(scale, frob_fp6(n, f1))] -} - -fn frob_t1(n: usize) -> Fp2 { - match n { - 0 => [ - U256::from_str("0x1").unwrap(), - U256::from_str("0x0").unwrap(), - ], - 1 => [ - U256::from_str("0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d") - .unwrap(), - U256::from_str("0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2") - .unwrap(), - ], - 2 => [ - U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48") - .unwrap(), - U256::from_str("0x0").unwrap(), - ], - 3 => [ - U256::from_str("0x856e078b755ef0abaff1c77959f25ac805ffd3d5d6942d37b746ee87bdcfb6d") - .unwrap(), - U256::from_str("0x4f1de41b3d1766fa9f30e6dec26094f0fdf31bf98ff2631380cab2baaa586de") - .unwrap(), - ], - 4 => [ - U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe").unwrap(), - U256::from_str("0x0").unwrap(), - ], - 5 => [ - U256::from_str("0x28be74d4bb943f51699582b87809d9caf71614d4b0b71f3a62e913ee1dada9e4") - .unwrap(), - U256::from_str("0x14a88ae0cb747b99c2b86abcbe01477a54f40eb4c3f6068dedae0bcec9c7aac7") - .unwrap(), - ], - _ => panic!(), +fn gen_fp6() -> Fp6 { + Fp6 { + t0: gen_fp2(), + t1: gen_fp2(), + t2: gen_fp2(), } } -fn frob_t2(n: usize) -> Fp2 { - match n { - 0 => [ - U256::from_str("0x1").unwrap(), - U256::from_str("0x0").unwrap(), - ], - 1 => [ - U256::from_str("0x5b54f5e64eea80180f3c0b75a181e84d33365f7be94ec72848a1f55921ea762") - .unwrap(), - U256::from_str("0x2c145edbe7fd8aee9f3a80b03b0b1c923685d2ea1bdec763c13b4711cd2b8126") - .unwrap(), - ], - 2 => [ - U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe").unwrap(), - U256::from_str("0x0").unwrap(), - ], - 3 => [ - U256::from_str("0xbc58c6611c08dab19bee0f7b5b2444ee633094575b06bcb0e1a92bc3ccbf066") - .unwrap(), - U256::from_str("0x23d5e999e1910a12feb0f6ef0cd21d04a44a9e08737f96e55fe3ed9d730c239f") - .unwrap(), - ], - 4 => [ - U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48") - .unwrap(), - U256::from_str("0x0").unwrap(), - ], - 5 => [ - U256::from_str("0x1ee972ae6a826a7d1d9da40771b6f589de1afb54342c724fa97bda050992657f") - .unwrap(), - U256::from_str("0x10de546ff8d4ab51d2b513cdbb25772454326430418536d15721e37e70c255c9") - .unwrap(), - ], - _ => panic!(), +pub fn gen_fp12() -> Fp12 { + Fp12 { + z0: gen_fp6(), + z1: gen_fp6(), } } -fn frob_z(n: usize) -> Fp2 { - match n { - 0 => [ - U256::from_str("0x1").unwrap(), - U256::from_str("0x0").unwrap(), - ], - 1 => [ - U256::from_str("0x1284b71c2865a7dfe8b99fdd76e68b605c521e08292f2176d60b35dadcc9e470") - .unwrap(), - U256::from_str("0x246996f3b4fae7e6a6327cfe12150b8e747992778eeec7e5ca5cf05f80f362ac") - .unwrap(), - ], - 2 => [ - U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd49") - .unwrap(), - U256::from_str("0x0").unwrap(), - ], - 3 => [ - U256::from_str("0x19dc81cfcc82e4bbefe9608cd0acaa90894cb38dbe55d24ae86f7d391ed4a67f") - .unwrap(), - U256::from_str("0xabf8b60be77d7306cbeee33576139d7f03a5e397d439ec7694aa2bf4c0c101") - .unwrap(), - ], - 4 => [ - U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48") - .unwrap(), - U256::from_str("0x0").unwrap(), - ], - 5 => [ - U256::from_str("0x757cab3a41d3cdc072fc0af59c61f302cfa95859526b0d41264475e420ac20f") - .unwrap(), - U256::from_str("0xca6b035381e35b618e9b79ba4e2606ca20b7dfd71573c93e85845e34c4a5b9c") - .unwrap(), - ], - 6 => [ - U256::from_str("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46") - .unwrap(), - U256::from_str("0x0").unwrap(), - ], - 7 => [ - U256::from_str("0x1ddf9756b8cbf849cf96a5d90a9accfd3b2f4c893f42a9166615563bfbb318d7") - .unwrap(), - U256::from_str("0xbfab77f2c36b843121dc8b86f6c4ccf2307d819d98302a771c39bb757899a9b") - .unwrap(), - ], - 8 => [ - U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe").unwrap(), - U256::from_str("0x0").unwrap(), - ], - 9 => [ - U256::from_str("0x1687cca314aebb6dc866e529b0d4adcd0e34b703aa1bf84253b10eddb9a856c8") - .unwrap(), - U256::from_str("0x2fb855bcd54a22b6b18456d34c0b44c0187dc4add09d90a0c58be1eae3bc3c46") - .unwrap(), - ], - 10 => [ - U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177ffffff").unwrap(), - U256::from_str("0x0").unwrap(), - ], - 11 => [ - U256::from_str("0x290c83bf3d14634db120850727bb392d6a86d50bd34b19b929bc44b896723b38") - .unwrap(), - U256::from_str("0x23bd9e3da9136a739f668e1adc9ef7f0f575ec93f71a8df953c846338c32a1ab") - .unwrap(), - ], - _ => panic!(), - } +pub fn gen_fp12_sparse() -> Fp12 { + sparse_embed(gen_fp(), gen_fp2(), gen_fp2()) } -pub fn inv_fp2(a: Fp2) -> Fp2 { - let [a0, a1] = a; - let norm = inv_fp(mul_fp(a0, a0) + mul_fp(a1, a1)); - [mul_fp(norm, a0), neg_fp(mul_fp(norm, a1))] -} +// fn frob_fp6(n: usize, c: Fp6) -> Fp6 { +// let [c0, c1, c2] = c; +// let _c0 = conj_fp2(c0); +// let _c1 = conj_fp2(c1); +// let _c2 = conj_fp2(c2); -pub fn inv_fp6(c: Fp6) -> Fp6 { - let b = mul_fp6(frob_fp6(1, c), frob_fp6(3, c)); - let e = mul_fp6(b, frob_fp6(5, c))[0]; - let n = mul_fp2(e, conj_fp2(e))[0]; - let i = inv_fp(n); - let d = mul_fp2(embed_fp2(i), e); - let [f0, f1, f2] = frob_fp6(1, b); - [mul_fp2(d, f0), mul_fp2(d, f1), mul_fp2(d, f2)] -} +// let n = n % 6; +// let frob_t1 = frob_t1(n); +// let frob_t2 = frob_t2(n); -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))] -} +// if n % 2 != 0 { +// [_c0, mul_fp2(frob_t1, _c1), mul_fp2(frob_t2, _c2)] +// } else { +// [c0, mul_fp2(frob_t1, c1), mul_fp2(frob_t2, c2)] +// } +// } -pub fn power(f: Fp12) -> Fp12 { - const EXPS4: [(usize, usize, usize); 64] = [ - (1, 1, 0), - (1, 1, 1), - (1, 1, 1), - (0, 0, 0), - (0, 0, 1), - (1, 0, 1), - (0, 1, 0), - (1, 0, 1), - (1, 1, 0), - (1, 0, 1), - (0, 1, 0), - (1, 1, 0), - (1, 1, 0), - (1, 1, 0), - (0, 1, 0), - (0, 1, 0), - (0, 0, 1), - (1, 0, 1), - (1, 1, 0), - (0, 1, 0), - (1, 1, 0), - (1, 1, 0), - (1, 1, 0), - (0, 0, 1), - (0, 0, 1), - (1, 0, 1), - (1, 0, 1), - (1, 1, 0), - (1, 0, 0), - (1, 1, 0), - (0, 1, 0), - (1, 1, 0), - (1, 0, 0), - (0, 1, 0), - (0, 0, 0), - (1, 0, 0), - (1, 0, 0), - (1, 0, 1), - (0, 0, 1), - (0, 1, 1), - (0, 0, 1), - (0, 1, 1), - (0, 1, 1), - (0, 0, 0), - (1, 1, 1), - (1, 0, 1), - (1, 0, 1), - (0, 1, 1), - (1, 0, 1), - (0, 1, 1), - (0, 1, 1), - (1, 1, 0), - (1, 1, 0), - (1, 1, 0), - (1, 0, 0), - (0, 0, 1), - (1, 0, 0), - (0, 0, 1), - (1, 0, 1), - (1, 1, 0), - (1, 1, 1), - (0, 1, 1), - (0, 1, 0), - (1, 1, 1), - ]; +// pub fn frob_fp12(n: usize, f: Fp12) -> Fp12 { +// let [f0, f1] = f; +// let scale = embed_fp2_fp6(frob_z(n)); - const EXPS2: [(usize, usize); 62] = [ - (1, 0), - (1, 1), - (0, 0), - (1, 0), - (1, 0), - (1, 1), - (1, 0), - (1, 1), - (1, 0), - (0, 1), - (0, 1), - (1, 1), - (1, 1), - (0, 0), - (1, 1), - (0, 0), - (0, 0), - (0, 1), - (0, 1), - (1, 1), - (1, 1), - (1, 1), - (0, 1), - (1, 1), - (0, 0), - (1, 1), - (1, 0), - (1, 1), - (0, 0), - (1, 1), - (1, 1), - (1, 0), - (0, 0), - (0, 1), - (0, 0), - (1, 1), - (0, 1), - (0, 0), - (1, 0), - (0, 1), - (0, 1), - (1, 0), - (0, 1), - (0, 0), - (0, 0), - (0, 0), - (0, 1), - (1, 0), - (1, 1), - (0, 1), - (1, 1), - (1, 0), - (0, 1), - (0, 0), - (1, 0), - (0, 1), - (1, 0), - (1, 1), - (1, 0), - (1, 1), - (0, 1), - (1, 1), - ]; +// [frob_fp6(n, f0), mul_fp6(scale, frob_fp6(n, f1))] +// } - const EXPS0: [usize; 65] = [ - 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, - 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, - 0, 0, 1, 1, 0, - ]; +// fn frob_t1(n: usize) -> Fp2 { +// match n { +// 0 => [ +// U256::from_str("0x1").unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 1 => [ +// U256::from_str("0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d") +// .unwrap(), +// U256::from_str("0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2") +// .unwrap(), +// ], +// 2 => [ +// U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48") +// .unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 3 => [ +// U256::from_str("0x856e078b755ef0abaff1c77959f25ac805ffd3d5d6942d37b746ee87bdcfb6d") +// .unwrap(), +// U256::from_str("0x4f1de41b3d1766fa9f30e6dec26094f0fdf31bf98ff2631380cab2baaa586de") +// .unwrap(), +// ], +// 4 => [ +// U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe").unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 5 => [ +// U256::from_str("0x28be74d4bb943f51699582b87809d9caf71614d4b0b71f3a62e913ee1dada9e4") +// .unwrap(), +// U256::from_str("0x14a88ae0cb747b99c2b86abcbe01477a54f40eb4c3f6068dedae0bcec9c7aac7") +// .unwrap(), +// ], +// _ => panic!(), +// } +// } - let mut sq: Fp12 = f; - let mut y0: Fp12 = embed_fp12(U256::one()); - let mut y2: Fp12 = embed_fp12(U256::one()); - let mut y4: Fp12 = embed_fp12(U256::one()); +// fn frob_t2(n: usize) -> Fp2 { +// match n { +// 0 => [ +// U256::from_str("0x1").unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 1 => [ +// U256::from_str("0x5b54f5e64eea80180f3c0b75a181e84d33365f7be94ec72848a1f55921ea762") +// .unwrap(), +// U256::from_str("0x2c145edbe7fd8aee9f3a80b03b0b1c923685d2ea1bdec763c13b4711cd2b8126") +// .unwrap(), +// ], +// 2 => [ +// U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe").unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 3 => [ +// U256::from_str("0xbc58c6611c08dab19bee0f7b5b2444ee633094575b06bcb0e1a92bc3ccbf066") +// .unwrap(), +// U256::from_str("0x23d5e999e1910a12feb0f6ef0cd21d04a44a9e08737f96e55fe3ed9d730c239f") +// .unwrap(), +// ], +// 4 => [ +// U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48") +// .unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 5 => [ +// U256::from_str("0x1ee972ae6a826a7d1d9da40771b6f589de1afb54342c724fa97bda050992657f") +// .unwrap(), +// U256::from_str("0x10de546ff8d4ab51d2b513cdbb25772454326430418536d15721e37e70c255c9") +// .unwrap(), +// ], +// _ => panic!(), +// } +// } - for (a, b, c) in EXPS4 { - if a != 0 { - y4 = mul_fp12(y4, sq); - } - if b != 0 { - y2 = mul_fp12(y2, sq); - } - if c != 0 { - y0 = mul_fp12(y0, sq); - } - sq = mul_fp12(sq, sq); - } - y4 = mul_fp12(y4, sq); - - for (a, b) in EXPS2 { - if a != 0 { - y2 = mul_fp12(y2, sq); - } - if b != 0 { - y0 = mul_fp12(y0, sq); - } - sq = mul_fp12(sq, sq); - } - y2 = mul_fp12(y2, sq); - - for a in EXPS0 { - if a != 0 { - y0 = mul_fp12(y0, sq); - } - sq = mul_fp12(sq, sq); - } - y0 = mul_fp12(y0, sq); - - y0 = inv_fp12(y0); - - y4 = mul_fp12(y4, y2); - y4 = mul_fp12(y4, y2); - y4 = mul_fp12(y4, y0); - - y4 = frob_fp12(1, y4); - y2 = frob_fp12(2, y2); - - mul_fp12(mul_fp12(y4, y2), y0) -} - -pub fn tangent(p: Curve, q: TwistedCurve) -> Fp12 { - let [px, py] = p; - let [qx, qy] = q; - - let cx = neg_fp(mul_fp(U256::from(3), mul_fp(px, px))); - let cy = mul_fp(U256::from(2), py); - - sparse_embed( - sub_fp(mul_fp(py, py), U256::from(9)), - mul_fp2(embed_fp2(cx), qx), - mul_fp2(embed_fp2(cy), qy), - ) -} - -pub fn cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12 { - let [p1x, p1y] = p1; - let [p2x, p2y] = p2; - let [qx, qy] = q; - - let cx = sub_fp(p2y, p1y); - let cy = sub_fp(p1x, p2x); - - sparse_embed( - sub_fp(mul_fp(p1y, p2x), mul_fp(p2y, p1x)), - mul_fp2(embed_fp2(cx), qx), - mul_fp2(embed_fp2(cy), qy), - ) -} - -fn tangent_slope(p: Curve) -> Fp { - let [px, py] = p; - let num = mul_fp(mul_fp(px, px), U256::from(3)); - let denom = mul_fp(py, U256::from(2)); - div_fp(num, denom) -} - -fn cord_slope(p: Curve, q: Curve) -> Fp { - let [px, py] = p; - let [qx, qy] = q; - let num = sub_fp(qy, py); - let denom = sub_fp(qx, px); - div_fp(num, denom) -} - -fn third_point(m: Fp, p: Curve, q: Curve) -> Curve { - let [px, py] = p; - let [qx, _] = q; - let ox = sub_fp(mul_fp(m, m), add_fp(px, qx)); - let oy = sub_fp(mul_fp(m, sub_fp(px, ox)), py); - [ox, oy] -} - -fn curve_add(p: Curve, q: Curve) -> Curve { - if p == q { - curve_double(p) - } else { - third_point(cord_slope(p, q), p, q) - } -} - -fn curve_double(p: Curve) -> Curve { - third_point(tangent_slope(p), p, p) -} - -pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 { - const EXP: [usize; 253] = [ - 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, - 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, - 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, - 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, - 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, - 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, - 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, - 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - - let mut o = p; - let mut acc = embed_fp12(U256::one()); - let mut line; - - for i in EXP { - acc = mul_fp12(acc, acc); - line = tangent(o, q); - acc = mul_fp12(line, acc); - o = curve_double(o); - if i != 0 { - line = cord(p, o, q); - acc = mul_fp12(line, acc); - o = curve_add(p, o); - } - } - acc -} - -pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 { - let mut out = miller_loop(p, q); - - let inv = inv_fp12(out); - out = frob_fp12(6, out); - out = mul_fp12(out, inv); - - let acc = frob_fp12(2, out); - out = mul_fp12(out, acc); - - let pow = power(out); - out = frob_fp12(3, out); - mul_fp12(out, pow) -} +// fn frob_z(n: usize) -> Fp2 { +// match n { +// 0 => [ +// U256::from_str("0x1").unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 1 => [ +// U256::from_str("0x1284b71c2865a7dfe8b99fdd76e68b605c521e08292f2176d60b35dadcc9e470") +// .unwrap(), +// U256::from_str("0x246996f3b4fae7e6a6327cfe12150b8e747992778eeec7e5ca5cf05f80f362ac") +// .unwrap(), +// ], +// 2 => [ +// U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd49") +// .unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 3 => [ +// U256::from_str("0x19dc81cfcc82e4bbefe9608cd0acaa90894cb38dbe55d24ae86f7d391ed4a67f") +// .unwrap(), +// U256::from_str("0xabf8b60be77d7306cbeee33576139d7f03a5e397d439ec7694aa2bf4c0c101") +// .unwrap(), +// ], +// 4 => [ +// U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48") +// .unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 5 => [ +// U256::from_str("0x757cab3a41d3cdc072fc0af59c61f302cfa95859526b0d41264475e420ac20f") +// .unwrap(), +// U256::from_str("0xca6b035381e35b618e9b79ba4e2606ca20b7dfd71573c93e85845e34c4a5b9c") +// .unwrap(), +// ], +// 6 => [ +// U256::from_str("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46") +// .unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 7 => [ +// U256::from_str("0x1ddf9756b8cbf849cf96a5d90a9accfd3b2f4c893f42a9166615563bfbb318d7") +// .unwrap(), +// U256::from_str("0xbfab77f2c36b843121dc8b86f6c4ccf2307d819d98302a771c39bb757899a9b") +// .unwrap(), +// ], +// 8 => [ +// U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe").unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 9 => [ +// U256::from_str("0x1687cca314aebb6dc866e529b0d4adcd0e34b703aa1bf84253b10eddb9a856c8") +// .unwrap(), +// U256::from_str("0x2fb855bcd54a22b6b18456d34c0b44c0187dc4add09d90a0c58be1eae3bc3c46") +// .unwrap(), +// ], +// 10 => [ +// U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177ffffff").unwrap(), +// U256::from_str("0x0").unwrap(), +// ], +// 11 => [ +// U256::from_str("0x290c83bf3d14634db120850727bb392d6a86d50bd34b19b929bc44b896723b38") +// .unwrap(), +// U256::from_str("0x23bd9e3da9136a739f668e1adc9ef7f0f575ec93f71a8df953c846338c32a1ab") +// .unwrap(), +// ], +// _ => panic!(), +// } +// } diff --git a/evm/src/bn254_curve_pairing.rs b/evm/src/bn254_curve_pairing.rs index e69de29b..dba6c5dd 100644 --- a/evm/src/bn254_curve_pairing.rs +++ b/evm/src/bn254_curve_pairing.rs @@ -0,0 +1,322 @@ +// pub type Curve = [Fp; 2]; +// pub type TwistedCurve = [Fp2; 2]; + +// pub fn curve_generator() -> Curve { +// [U256::one(), U256::from(2)] +// } + +// 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 fn power(f: Fp12) -> Fp12 { + const EXPS4: [(usize, usize, usize); 64] = [ + (1, 1, 0), + (1, 1, 1), + (1, 1, 1), + (0, 0, 0), + (0, 0, 1), + (1, 0, 1), + (0, 1, 0), + (1, 0, 1), + (1, 1, 0), + (1, 0, 1), + (0, 1, 0), + (1, 1, 0), + (1, 1, 0), + (1, 1, 0), + (0, 1, 0), + (0, 1, 0), + (0, 0, 1), + (1, 0, 1), + (1, 1, 0), + (0, 1, 0), + (1, 1, 0), + (1, 1, 0), + (1, 1, 0), + (0, 0, 1), + (0, 0, 1), + (1, 0, 1), + (1, 0, 1), + (1, 1, 0), + (1, 0, 0), + (1, 1, 0), + (0, 1, 0), + (1, 1, 0), + (1, 0, 0), + (0, 1, 0), + (0, 0, 0), + (1, 0, 0), + (1, 0, 0), + (1, 0, 1), + (0, 0, 1), + (0, 1, 1), + (0, 0, 1), + (0, 1, 1), + (0, 1, 1), + (0, 0, 0), + (1, 1, 1), + (1, 0, 1), + (1, 0, 1), + (0, 1, 1), + (1, 0, 1), + (0, 1, 1), + (0, 1, 1), + (1, 1, 0), + (1, 1, 0), + (1, 1, 0), + (1, 0, 0), + (0, 0, 1), + (1, 0, 0), + (0, 0, 1), + (1, 0, 1), + (1, 1, 0), + (1, 1, 1), + (0, 1, 1), + (0, 1, 0), + (1, 1, 1), + ]; + + const EXPS2: [(usize, usize); 62] = [ + (1, 0), + (1, 1), + (0, 0), + (1, 0), + (1, 0), + (1, 1), + (1, 0), + (1, 1), + (1, 0), + (0, 1), + (0, 1), + (1, 1), + (1, 1), + (0, 0), + (1, 1), + (0, 0), + (0, 0), + (0, 1), + (0, 1), + (1, 1), + (1, 1), + (1, 1), + (0, 1), + (1, 1), + (0, 0), + (1, 1), + (1, 0), + (1, 1), + (0, 0), + (1, 1), + (1, 1), + (1, 0), + (0, 0), + (0, 1), + (0, 0), + (1, 1), + (0, 1), + (0, 0), + (1, 0), + (0, 1), + (0, 1), + (1, 0), + (0, 1), + (0, 0), + (0, 0), + (0, 0), + (0, 1), + (1, 0), + (1, 1), + (0, 1), + (1, 1), + (1, 0), + (0, 1), + (0, 0), + (1, 0), + (0, 1), + (1, 0), + (1, 1), + (1, 0), + (1, 1), + (0, 1), + (1, 1), + ]; + + const EXPS0: [usize; 65] = [ + 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 1, 1, 0, + ]; + + let mut sq: Fp12 = f; + let mut y0: Fp12 = embed_fp12(U256::one()); + let mut y2: Fp12 = embed_fp12(U256::one()); + let mut y4: Fp12 = embed_fp12(U256::one()); + + for (a, b, c) in EXPS4 { + if a != 0 { + y4 = mul_fp12(y4, sq); + } + if b != 0 { + y2 = mul_fp12(y2, sq); + } + if c != 0 { + y0 = mul_fp12(y0, sq); + } + sq = mul_fp12(sq, sq); + } + y4 = mul_fp12(y4, sq); + + for (a, b) in EXPS2 { + if a != 0 { + y2 = mul_fp12(y2, sq); + } + if b != 0 { + y0 = mul_fp12(y0, sq); + } + sq = mul_fp12(sq, sq); + } + y2 = mul_fp12(y2, sq); + + for a in EXPS0 { + if a != 0 { + y0 = mul_fp12(y0, sq); + } + sq = mul_fp12(sq, sq); + } + y0 = mul_fp12(y0, sq); + + y0 = inv_fp12(y0); + + y4 = mul_fp12(y4, y2); + y4 = mul_fp12(y4, y2); + y4 = mul_fp12(y4, y0); + + y4 = frob_fp12(1, y4); + y2 = frob_fp12(2, y2); + + mul_fp12(mul_fp12(y4, y2), y0) +} + +pub fn tangent(p: Curve, q: TwistedCurve) -> Fp12 { + let [px, py] = p; + let [qx, qy] = q; + + let cx = neg_fp(mul_fp(U256::from(3), mul_fp(px, px))); + let cy = mul_fp(U256::from(2), py); + + sparse_embed( + sub_fp(mul_fp(py, py), U256::from(9)), + mul_fp2(embed_fp2(cx), qx), + mul_fp2(embed_fp2(cy), qy), + ) +} + +pub fn cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12 { + let [p1x, p1y] = p1; + let [p2x, p2y] = p2; + let [qx, qy] = q; + + let cx = sub_fp(p2y, p1y); + let cy = sub_fp(p1x, p2x); + + sparse_embed( + sub_fp(mul_fp(p1y, p2x), mul_fp(p2y, p1x)), + mul_fp2(embed_fp2(cx), qx), + mul_fp2(embed_fp2(cy), qy), + ) +} + +fn tangent_slope(p: Curve) -> Fp { + let [px, py] = p; + let num = mul_fp(mul_fp(px, px), U256::from(3)); + let denom = mul_fp(py, U256::from(2)); + div_fp(num, denom) +} + +fn cord_slope(p: Curve, q: Curve) -> Fp { + let [px, py] = p; + let [qx, qy] = q; + let num = sub_fp(qy, py); + let denom = sub_fp(qx, px); + div_fp(num, denom) +} + +fn third_point(m: Fp, p: Curve, q: Curve) -> Curve { + let [px, py] = p; + let [qx, _] = q; + let ox = sub_fp(mul_fp(m, m), add_fp(px, qx)); + let oy = sub_fp(mul_fp(m, sub_fp(px, ox)), py); + [ox, oy] +} + +fn curve_add(p: Curve, q: Curve) -> Curve { + if p == q { + curve_double(p) + } else { + third_point(cord_slope(p, q), p, q) + } +} + +fn curve_double(p: Curve) -> Curve { + third_point(tangent_slope(p), p, p) +} + +pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 { + const EXP: [usize; 253] = [ + 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, + 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, + 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, + 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + + let mut o = p; + let mut acc = embed_fp12(U256::one()); + let mut line; + + for i in EXP { + acc = mul_fp12(acc, acc); + line = tangent(o, q); + acc = mul_fp12(line, acc); + o = curve_double(o); + if i != 0 { + line = cord(p, o, q); + acc = mul_fp12(line, acc); + o = curve_add(p, o); + } + } + acc +} + +pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 { + let mut out = miller_loop(p, q); + + let inv = inv_fp12(out); + out = frob_fp12(6, out); + out = mul_fp12(out, inv); + + let acc = frob_fp12(2, out); + out = mul_fp12(out, acc); + + let pow = power(out); + out = frob_fp12(3, out); + mul_fp12(out, pow) +} diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 04b81675..be65142a 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -1,12 +1,9 @@ -use std::str::FromStr; +// use std::str::FromStr; use anyhow::Result; use ethereum_types::U256; -use crate::bn254_arithmetic::{ - curve_generator, fp12_to_vec, frob_fp12, gen_fp12, gen_fp12_sparse, miller_loop, mul_fp12, - power, tate, twisted_curve_generator, Curve, Fp12, TwistedCurve, -}; +use crate::bn254_arithmetic::{fp12_to_vec, gen_fp12, gen_fp12_sparse, Fp12}; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::run_interpreter; @@ -57,9 +54,9 @@ fn test_mul_fp12() -> Result<()> { let out_sparse: Vec = get_output("test_mul_fp12", sparse); let out_square: Vec = get_output("test_mul_fp12", square); - let exp_normal: Vec = fp12_to_vec(mul_fp12(f, g)); - let exp_sparse: Vec = fp12_to_vec(mul_fp12(f, h)); - let exp_square: Vec = fp12_to_vec(mul_fp12(f, f)); + let exp_normal: Vec = fp12_to_vec(f * g); + let exp_sparse: Vec = fp12_to_vec(f * h); + let exp_square: Vec = fp12_to_vec(f * f); assert_eq!(out_normal, exp_normal); assert_eq!(out_sparse, exp_sparse); @@ -68,118 +65,118 @@ fn test_mul_fp12() -> Result<()> { Ok(()) } -#[test] -fn test_frob_fp12() -> Result<()> { - let ptr = U256::from(100); +// #[test] +// fn test_frob_fp12() -> Result<()> { +// let ptr = U256::from(100); - let f: Fp12 = gen_fp12(); +// let f: Fp12 = gen_fp12(); - let mut stack = vec![ptr]; - stack.extend(fp12_to_vec(f)); - stack.extend(vec![ptr]); +// let mut stack = vec![ptr]; +// stack.extend(fp12_to_vec(f)); +// stack.extend(vec![ptr]); - let out_frob1: Vec = get_output("test_frob_fp12_1", stack.clone()); - let out_frob2: Vec = get_output("test_frob_fp12_2", stack.clone()); - let out_frob3: Vec = get_output("test_frob_fp12_3", stack.clone()); - let out_frob6: Vec = get_output("test_frob_fp12_6", stack); +// let out_frob1: Vec = get_output("test_frob_fp12_1", stack.clone()); +// let out_frob2: Vec = get_output("test_frob_fp12_2", stack.clone()); +// let out_frob3: Vec = get_output("test_frob_fp12_3", stack.clone()); +// let out_frob6: Vec = get_output("test_frob_fp12_6", stack); - let exp_frob1: Vec = fp12_to_vec(frob_fp12(1, f)); - let exp_frob2: Vec = fp12_to_vec(frob_fp12(2, f)); - let exp_frob3: Vec = fp12_to_vec(frob_fp12(3, f)); - let exp_frob6: Vec = fp12_to_vec(frob_fp12(6, f)); +// let exp_frob1: Vec = fp12_to_vec(frob_fp12(1, f)); +// let exp_frob2: Vec = fp12_to_vec(frob_fp12(2, f)); +// let exp_frob3: Vec = fp12_to_vec(frob_fp12(3, f)); +// let exp_frob6: Vec = fp12_to_vec(frob_fp12(6, f)); - assert_eq!(out_frob1, exp_frob1); - assert_eq!(out_frob2, exp_frob2); - assert_eq!(out_frob3, exp_frob3); - assert_eq!(out_frob6, exp_frob6); +// assert_eq!(out_frob1, exp_frob1); +// assert_eq!(out_frob2, exp_frob2); +// assert_eq!(out_frob3, exp_frob3); +// assert_eq!(out_frob6, exp_frob6); - Ok(()) -} +// 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<()> { - let ptr = U256::from(300); - let out = U256::from(400); +// #[test] +// fn test_power() -> Result<()> { +// let ptr = U256::from(300); +// let out = U256::from(400); - let f: Fp12 = gen_fp12(); +// let f: Fp12 = gen_fp12(); - let mut stack = vec![ptr]; - stack.extend(fp12_to_vec(f)); - stack.extend(vec![ - ptr, - out, - get_address_from_label("return_fp12_on_stack"), - out, - ]); +// let mut stack = vec![ptr]; +// stack.extend(fp12_to_vec(f)); +// stack.extend(vec![ +// ptr, +// out, +// get_address_from_label("return_fp12_on_stack"), +// out, +// ]); - let output: Vec = get_output("test_pow", stack); - let expected: Vec = fp12_to_vec(power(f)); +// let output: Vec = get_output("test_pow", stack); +// let expected: Vec = fp12_to_vec(power(f)); - assert_eq!(output, expected); +// assert_eq!(output, expected); - Ok(()) -} +// Ok(()) +// } -fn make_tate_stack(p: Curve, q: TwistedCurve) -> Vec { - let ptr = U256::from(300); - let out = U256::from(400); +// fn make_tate_stack(p: Curve, q: TwistedCurve) -> Vec { +// let ptr = U256::from(300); +// let out = U256::from(400); - let p_: Vec = p.into_iter().collect(); - let q_: Vec = q.into_iter().flatten().collect(); +// let p_: Vec = p.into_iter().collect(); +// let q_: Vec = q.into_iter().flatten().collect(); - let mut stack = vec![ptr]; - stack.extend(p_); - stack.extend(q_); - stack.extend(vec![ - ptr, - out, - get_address_from_label("return_fp12_on_stack"), - out, - ]); - stack -} +// let mut stack = vec![ptr]; +// stack.extend(p_); +// stack.extend(q_); +// stack.extend(vec![ +// ptr, +// out, +// get_address_from_label("return_fp12_on_stack"), +// out, +// ]); +// stack +// } -#[test] -fn test_miller() -> Result<()> { - let p: Curve = curve_generator(); - let q: TwistedCurve = twisted_curve_generator(); +// #[test] +// fn test_miller() -> Result<()> { +// let p: Curve = curve_generator(); +// let q: TwistedCurve = twisted_curve_generator(); - let stack = make_tate_stack(p, q); - let output = get_output("test_miller", stack); - let expected = fp12_to_vec(miller_loop(p, q)); +// let stack = make_tate_stack(p, q); +// let output = get_output("test_miller", stack); +// let expected = fp12_to_vec(miller_loop(p, q)); - assert_eq!(output, expected); +// assert_eq!(output, expected); - Ok(()) -} +// Ok(()) +// } -#[test] -fn test_tate() -> Result<()> { - let p: Curve = curve_generator(); - let q: TwistedCurve = twisted_curve_generator(); +// #[test] +// fn test_tate() -> Result<()> { +// let p: Curve = curve_generator(); +// let q: TwistedCurve = twisted_curve_generator(); - let stack = make_tate_stack(p, q); - let output = get_output("test_tate", stack); - let expected = fp12_to_vec(tate(p, q)); +// let stack = make_tate_stack(p, q); +// let output = get_output("test_tate", stack); +// let expected = fp12_to_vec(tate(p, q)); - assert_eq!(output, expected); +// assert_eq!(output, expected); - Ok(()) -} +// Ok(()) +// } diff --git a/evm/src/generation/prover_input.rs b/evm/src/generation/prover_input.rs index 37363715..8ccb2407 100644 --- a/evm/src/generation/prover_input.rs +++ b/evm/src/generation/prover_input.rs @@ -3,7 +3,7 @@ use std::str::FromStr; 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, }; @@ -74,7 +74,8 @@ impl GenerationState { "component_11" => 11, _ => panic!("out of bounds"), }; - field.inverse_fp12(n, xs) + // field.inverse_fp12(n, xs) + todo!() } /// MPT data. @@ -195,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 {