mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 23:03:08 +00:00
inv as method
This commit is contained in:
parent
7b52438173
commit
ec4cddb7c9
@ -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 }
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
///
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/// def power(acc):
|
||||
/// def invariance_inducing_power(acc):
|
||||
/// power_init()
|
||||
/// power_loop_4()
|
||||
/// power_loop_2()
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user