From f70243e70c0fdfd5532e15fe1d4e257e958f75ba Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 25 Jan 2023 15:31:32 +0700 Subject: [PATCH] better comments --- evm/src/bn254_arithmetic.rs | 10 +- evm/src/bn254_pairing.rs | 302 +++++++++++++++++++----------------- 2 files changed, 164 insertions(+), 148 deletions(-) diff --git a/evm/src/bn254_arithmetic.rs b/evm/src/bn254_arithmetic.rs index 72f006a1..3db48591 100644 --- a/evm/src/bn254_arithmetic.rs +++ b/evm/src/bn254_arithmetic.rs @@ -176,7 +176,7 @@ impl Fp2 { } /// Return the complex conjugate z' of z: Fp2 - /// This also happens to be the frobenius map + /// This also happens to be the frobenius map /// z -> z^p /// since p == 3 mod 4 and hence /// i^p = i^3 = -i @@ -301,9 +301,9 @@ impl Fp6 { /// x to x^(p^n) /// which sends a + bt + ct^2: Fp6 to /// a^(p^n) + b^(p^n) * t^(p^n) + c^(p^n) * t^(2p^n) - /// The Fp2 coefficients are determined by the comment in the conj method, - /// while the values of - /// t^(p^n) and t^(2p^n) + /// The Fp2 coefficients are determined by the comment in the conj method, + /// while the values of + /// t^(p^n) and t^(2p^n) /// are precomputed in the constant arrays FROB_T1 and FROB_T2 fn frob(self, n: usize) -> Fp6 { let n = n % 6; @@ -336,7 +336,7 @@ impl Fp6 { /// (x_1 * x_3) * x_5 * (x_1 * x_3)_1 /// By Galois theory, the following are in Fp2 and are complex conjugates /// x_1 * x_3 * x_5, x_0 * x_2 * x_4 - /// and therefore + /// and therefore /// phi = ||x_1 * x_3 * x_5||^2 /// and hence the inverse is given by /// ([x_1 * x_3] * x_5) * [x_1 * x_3]_1 / ||[x_1 * x_3] * x_5||^2 diff --git a/evm/src/bn254_pairing.rs b/evm/src/bn254_pairing.rs index 2df002c1..79c9b43e 100644 --- a/evm/src/bn254_pairing.rs +++ b/evm/src/bn254_pairing.rs @@ -129,158 +129,26 @@ pub fn invariance_inducing_power(f: Fp12) -> Fp12 { y.frob(3) * y_a2.frob(2) * y_a1.frob(1) * y_a0 } -/// Given an f: Fp12, this function computes -/// y^a2, y^(-a1), y^(-a0) -/// by first computing +/// We first together (so as to avoid repeated steps) compute /// y^a4, y^a2, y^a0 /// where a1 is given by /// a1 = a4 + 2a2 - a0 -/// thus what remains is inverting y^a0 and returning -/// y^a2, y^a4 * y^a2 * y^a2 * y^(-a0), y^(-a0) +/// we then invert y^a0 and return +/// y^a2, y^a1 = y^a4 * y^a2 * y^a2 * y^(-a0), y^(-a0) +/// +/// Represent a4, a2, a0 in *little endian* binary, define +/// EXPS4 = [(a4[i], a2[i], a0[i]) for i in 0..len(a4)] +/// EXPS2 = [ (a2[i], a0[i]) for i in len(a4)..len(a2)] +/// EXPS0 = [ a0[i] for i in len(a2)..len(a0)] fn get_custom_powers(f: Fp12) -> (Fp12, 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 = UNIT_FP12; let mut y2: Fp12 = UNIT_FP12; let mut y4: Fp12 = UNIT_FP12; + // proceed via standard squaring algorithm for exponentiation + + // must keep multiplying all three values: a4, a2, a0 for (a, b, c) in EXPS4 { if a != 0 { y4 = y4 * sq; @@ -293,8 +161,10 @@ fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) { } sq = sq * sq; } + // leading term of a4 is always 1 y4 = y4 * sq; + // must keep multiplying remaining two values: a2, a0 for (a, b) in EXPS2 { if a != 0 { y2 = y2 * sq; @@ -304,17 +174,23 @@ fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) { } sq = sq * sq; } + // leading term of a2 is always 1 y2 = y2 * sq; + // must keep multiplying remaining value: a0 for a in EXPS0 { if a != 0 { y0 = y0 * sq; } sq = sq * sq; } + // leading term of a0 is always 1 y0 = y0 * sq; + // invert y0 to compute y^(-a0) let y0_inv = y0.inv(); + + // return y2, y1 = y4 * y2^2 * y^(-a0), y^(-a0) (y2, y4 * y2 * y2 * y0_inv, y0_inv) } @@ -369,3 +245,143 @@ pub const TWISTED_GENERATOR: TwistedCurve = { }, } }; + +/// The folowing constants are defined above get_custom_powers + +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, +];