inv as method

This commit is contained in:
Dmitry Vagner 2023-01-23 14:59:08 +07:00
parent 7b52438173
commit ec4cddb7c9
6 changed files with 82 additions and 69 deletions

View File

@ -147,7 +147,7 @@ impl Div for Fp2 {
fn div(self, rhs: Self) -> Self::Output {
let norm = rhs.re * rhs.re + rhs.im * rhs.im;
let inv = mul_fp_fp2(norm, conj_fp2(rhs));
let inv = scalar_mul_fp2(norm, conj_fp2(rhs));
self * inv
}
}
@ -162,7 +162,7 @@ pub const UNIT_FP2: Fp2 = Fp2 {
im: ZERO_FP,
};
pub fn mul_fp_fp2(x: Fp, a: Fp2) -> Fp2 {
pub fn scalar_mul_fp2(x: Fp, a: Fp2) -> Fp2 {
Fp2 {
re: x * a.re,
im: x * a.im,
@ -199,9 +199,9 @@ fn i9(a: Fp2) -> Fp2 {
// Fp6 has basis 1, t, t^2 over Fp2
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Fp6 {
t0: Fp2,
t1: Fp2,
t2: Fp2,
pub t0: Fp2,
pub t1: Fp2,
pub t2: Fp2,
}
impl Add for Fp6 {
@ -273,7 +273,7 @@ impl Div for Fp6 {
let prod_135 = (prod_13 * frob_fp6(5, rhs)).t0;
let prod_odds_over_phi = normalize_fp2(prod_135);
let prod_24 = frob_fp6(1, prod_13);
let inv = mul_fp2_fp6(prod_odds_over_phi, prod_24);
let inv = scalar_mul_fp6(prod_odds_over_phi, prod_24);
self * inv
}
}
@ -290,7 +290,7 @@ pub const UNIT_FP6: Fp6 = Fp6 {
t2: ZERO_FP2,
};
fn mul_fp2_fp6(x: Fp2, f: Fp6) -> Fp6 {
fn scalar_mul_fp6(x: Fp2, f: Fp6) -> Fp6 {
Fp6 {
t0: x * f.t0,
t1: x * f.t1,
@ -312,8 +312,8 @@ fn sh(c: Fp6) -> Fp6 {
/// It thus has basis 1, z over Fp6
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Fp12 {
z0: Fp6,
z1: Fp6,
pub z0: Fp6,
pub z1: Fp6,
}
impl Mul for Fp12 {
@ -351,8 +351,8 @@ impl Div for Fp12 {
let prod_odds = (prod_1379 * frob_fp6(4, prod_17)).t0;
let prod_odds_over_phi = normalize_fp2(prod_odds);
let prod_evens_except_six = frob_fp6(1, prod_1379);
let prod_penultimate = mul_fp2_fp6(prod_odds_over_phi, prod_evens_except_six);
let inv = mul_fp6_fp12(prod_penultimate, conj_fp12(rhs));
let prod_penultimate = scalar_mul_fp6(prod_odds_over_phi, prod_evens_except_six);
let inv = scalar_mul_fp12(prod_penultimate, conj_fp12(rhs));
self * inv
}
}
@ -369,15 +369,17 @@ fn conj_fp12(f: Fp12) -> Fp12 {
}
}
fn mul_fp6_fp12(c: Fp6, f: Fp12) -> Fp12 {
fn scalar_mul_fp12(c: Fp6, f: Fp12) -> Fp12 {
Fp12 {
z0: c * f.z0,
z1: c * f.z1,
}
}
pub fn inv_fp12(f: Fp12) -> Fp12 {
UNIT_FP12 / f
impl Fp12 {
pub fn inv(self) -> Fp12 {
UNIT_FP12 / self
}
}
/// The nth frobenius endomorphism of a finite field F of order p^q is given by sending x: F to x^(p^n)
@ -422,7 +424,7 @@ pub fn frob_fp12(n: usize, f: Fp12) -> Fp12 {
let n = n % 12;
Fp12 {
z0: frob_fp6(n, f.z0),
z1: mul_fp2_fp6(FROB_Z[n], frob_fp6(n, f.z1)),
z1: scalar_mul_fp6(FROB_Z[n], frob_fp6(n, f.z1)),
}
}
@ -819,14 +821,14 @@ pub fn gen_fp() -> Fp {
Fp { val: x256 }
}
fn gen_fp2() -> Fp2 {
pub fn gen_fp2() -> Fp2 {
Fp2 {
re: gen_fp(),
im: gen_fp(),
}
}
fn gen_fp6() -> Fp6 {
pub fn gen_fp6() -> Fp6 {
Fp6 {
t0: gen_fp2(),
t1: gen_fp2(),
@ -840,26 +842,3 @@ pub fn gen_fp12() -> Fp12 {
z1: gen_fp6(),
}
}
pub fn gen_fp12_sparse() -> Fp12 {
sparse_embed(gen_fp(), gen_fp2(), gen_fp2())
}
pub fn sparse_embed(g000: Fp, g01: Fp2, g11: Fp2) -> Fp12 {
let g0 = Fp6 {
t0: Fp2 {
re: g000,
im: ZERO_FP,
},
t1: g01,
t2: ZERO_FP2,
};
let g1 = Fp6 {
t0: ZERO_FP2,
t1: g11,
t2: ZERO_FP2,
};
Fp12 { z0: g0, z1: g1 }
}

View File

@ -3,7 +3,7 @@ use std::ops::Add;
use ethereum_types::U256;
use crate::bn254_arithmetic::{
frob_fp12, inv_fp12, mul_fp_fp2, sparse_embed, Fp, Fp12, Fp2, UNIT_FP12,
frob_fp12, scalar_mul_fp2, Fp, Fp6, Fp12, Fp2, UNIT_FP12, ZERO_FP, ZERO_FP2, gen_fp, gen_fp2
};
// The curve consists of pairs (x, y): (Fp, Fp) | y^2 = x^3 + 2
@ -40,13 +40,10 @@ pub struct TwistedCurve {
y: Fp2,
}
// The tate pairing takes point each from the curve and its twist and outputs an Fp12
// The tate pairing takes a point each from the curve and its twist and outputs an Fp12 element
pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 {
let miller_output = miller_loop(p, q);
let post_mul_1 = frob_fp12(6, miller_output) / miller_output;
let post_mul_2 = frob_fp12(2, post_mul_1) * post_mul_1;
let power_output = power(post_mul_2);
frob_fp12(3, post_mul_2) * power_output
invariance_inducing_power(miller_output)
}
pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 {
@ -80,13 +77,36 @@ pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 {
acc
}
pub fn gen_fp12_sparse() -> Fp12 {
sparse_embed(gen_fp(), gen_fp2(), gen_fp2())
}
pub fn sparse_embed(g000: Fp, g01: Fp2, g11: Fp2) -> Fp12 {
let g0 = Fp6 {
t0: Fp2 {
re: g000,
im: ZERO_FP,
},
t1: g01,
t2: ZERO_FP2,
};
let g1 = Fp6 {
t0: ZERO_FP2,
t1: g11,
t2: ZERO_FP2,
};
Fp12 { z0: g0, z1: g1 }
}
pub fn tangent(p: Curve, q: TwistedCurve) -> Fp12 {
let cx = -Fp::new(3) * p.x * p.x;
let cy = Fp::new(2) * p.y;
sparse_embed(
p.y * p.y - Fp::new(9),
mul_fp_fp2(cx, q.x),
mul_fp_fp2(cy, q.y),
scalar_mul_fp2(cx, q.x),
scalar_mul_fp2(cy, q.y),
)
}
@ -95,12 +115,34 @@ pub fn cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12 {
let cy = p1.x - p2.x;
sparse_embed(
p1.y * p2.x - p2.y * p1.x,
mul_fp_fp2(cx, q.x),
mul_fp_fp2(cy, q.y),
scalar_mul_fp2(cx, q.x),
scalar_mul_fp2(cy, q.y),
)
}
pub fn power(f: Fp12) -> Fp12 {
/// The output T of the miller loop is not an invariant,
/// but one gets an invariant by raising T to the power
/// (p^12 - 1)/N = (p^6 - 1)(p^2 + 1)(p^4 - p^2 + 1)/N
/// where N is the cyclic group order of the curve.
/// To achieve this, we first exponentiate T by p^6 - 1 via
/// T = T_6 / T
/// and then exponentiate the result by p^2 + 1 via
/// T = T_2 * T
/// We then note that (p^4 - p^2 + 1)/N can be rewritten as
/// (p^4 - p^2 + 1)/N = p^3 + (a2)p^2 - (a1)p - a0
/// where 0 < a0, a1, a2 < p. Then the final power is given by
/// T = T_3 * (T^a2)_2 * (T^-a1)_1 * (T^-a0)
pub fn invariance_inducing_power(f: Fp12) -> Fp12 {
let mut t = frob_fp12(6, f) / f;
t = frob_fp12(2, t) * t;
let (t_a2, t_a1, t_a0) = get_powers(t);
frob_fp12(3, t) * frob_fp12(2, t_a2) * frob_fp12(1, t_a1) * t_a0
}
/// Given an f: Fp12, this function computes the triple
/// T^a2, T^(-a1), T^(-a0)
///
fn get_powers(f: Fp12) -> (Fp12, Fp12, Fp12) {
const EXPS4: [(usize, usize, usize); 64] = [
(1, 1, 0),
(1, 1, 1),
@ -277,16 +319,7 @@ pub fn power(f: Fp12) -> Fp12 {
}
y0 = y0 * sq;
y0 = inv_fp12(y0);
y4 = y4 * y2;
y4 = y4 * y2;
y4 = y4 * y0;
y4 = frob_fp12(1, y4);
y2 = frob_fp12(2, y2);
y4 * y2 * y0
(y2, y4 * y2 * y2 * y0, y0.inv())
}
// The curve is cyclic with generator (1, 2)

View File

@ -8,7 +8,7 @@
/// acc = frob_fp12(2, out)
/// out = mul_fp12(out, acc)
///
/// pow = power(out)
/// pow = invariance_inducing_power(out)
/// out = frob_fp12(3, out)
/// out = mul_fp12(out, pow)
///

View File

@ -1,4 +1,4 @@
/// def power(acc):
/// def invariance_inducing_power(acc):
/// power_init()
/// power_loop_4()
/// power_loop_2()

View File

@ -4,7 +4,8 @@ use std::ops::Range;
use anyhow::Result;
use ethereum_types::U256;
use crate::bn254_arithmetic::{frob_fp12, gen_fp12, gen_fp12_sparse, inv_fp12, Fp12};
use crate::bn254_arithmetic::{frob_fp12, gen_fp12, Fp12};
use crate::bn254_pairing::{gen_fp12_sparse};
use crate::cpu::kernel::aggregator::KERNEL;
use crate::cpu::kernel::interpreter::Interpreter;
use crate::memory::segments::Segment;
@ -158,7 +159,7 @@ fn test_inv_fp12() -> Result<()> {
};
let interpreter: Interpreter = run_setup_interpreter(setup).unwrap();
let output: Vec<U256> = extract_kernel_output(inv..inv + 12, interpreter);
let expected: Vec<U256> = fp12_on_stack(inv_fp12(f));
let expected: Vec<U256> = fp12_on_stack(f.inv());
assert_eq!(output, expected);
@ -166,7 +167,7 @@ fn test_inv_fp12() -> Result<()> {
}
// #[test]
// fn test_power() -> Result<()> {
// fn test_invariance_inducing_power() -> Result<()> {
// let ptr = U256::from(300);
// let out = U256::from(400);
@ -182,7 +183,7 @@ fn test_inv_fp12() -> Result<()> {
// ]);
// let output: Vec<U256> = run_setup_interpreter("test_pow", stack);
// let expected: Vec<U256> = fp12_on_stack(power(f));
// let expected: Vec<U256> = fp12_on_stack(invariance_inducing_power(f));
// assert_eq!(output, expected);

View File

@ -5,7 +5,7 @@ use anyhow::{bail, Error};
use ethereum_types::{BigEndianHash, H256, U256};
use plonky2::field::types::Field;
use crate::bn254_arithmetic::{inv_fp12, Fp12};
use crate::bn254_arithmetic::Fp12;
use crate::generation::prover_input::EvmField::{
Bn254Base, Bn254Scalar, Secp256k1Base, Secp256k1Scalar,
};
@ -200,7 +200,7 @@ impl EvmField {
fn field_extension_inverse(&self, n: usize, f: [U256; 12]) -> U256 {
let f: Fp12 = unsafe { transmute(f) };
let f_inv: [U256; 12] = unsafe { transmute(inv_fp12(f)) };
let f_inv: [U256; 12] = unsafe { transmute(f.inv()) };
f_inv[n]
}
}