mirror of https://github.com/zcash/halo2.git
Merge pull request #84 from zcash/pasta-curves
Replace Tweedle curves with Pasta curves
This commit is contained in:
commit
7c0e56a44e
|
@ -3,9 +3,9 @@ extern crate criterion;
|
|||
|
||||
extern crate halo2;
|
||||
use crate::arithmetic::{small_multiexp, FieldExt};
|
||||
use crate::pasta::{EqAffine, Fp, Fq};
|
||||
use crate::poly::commitment::Params;
|
||||
use crate::transcript::DummyHash;
|
||||
use crate::tweedle::{EqAffine, Fp, Fq};
|
||||
use halo2::*;
|
||||
|
||||
use criterion::{black_box, Criterion};
|
||||
|
|
|
@ -3,10 +3,10 @@ extern crate criterion;
|
|||
|
||||
extern crate halo2;
|
||||
use halo2::arithmetic::FieldExt;
|
||||
use halo2::pasta::{EqAffine, Fp, Fq};
|
||||
use halo2::plonk::*;
|
||||
use halo2::poly::commitment::Params;
|
||||
use halo2::transcript::DummyHash;
|
||||
use halo2::tweedle::{EqAffine, Fp, Fq};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use halo2::{
|
||||
arithmetic::{Curve, FieldExt},
|
||||
model::ModelRecorder,
|
||||
pasta::{EqAffine, Fp, Fq},
|
||||
plonk::*,
|
||||
poly::commitment::{Blind, Params},
|
||||
transcript::DummyHash,
|
||||
tweedle::{EqAffine, Fp, Fq},
|
||||
};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
|
|
@ -468,7 +468,7 @@ pub fn lagrange_interpolate<F: FieldExt>(points: &[F], evals: &[F]) -> Vec<F> {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::tweedle::Fp;
|
||||
use crate::pasta::Fp;
|
||||
|
||||
#[test]
|
||||
fn test_lagrange_interpolate() {
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
#![deny(unsafe_code)]
|
||||
|
||||
pub mod arithmetic;
|
||||
pub mod pasta;
|
||||
pub mod plonk;
|
||||
pub mod poly;
|
||||
pub mod transcript;
|
||||
pub mod tweedle;
|
||||
|
||||
pub mod model;
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
//! This module contains implementations for the Pallas and Vesta elliptic curve
|
||||
//! groups.
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod curves;
|
||||
mod fields;
|
||||
|
||||
pub mod pallas;
|
||||
pub mod vesta;
|
||||
|
||||
pub use curves::*;
|
||||
pub use fields::*;
|
||||
|
||||
#[test]
|
||||
fn test_endo_consistency() {
|
||||
use crate::arithmetic::{Curve, FieldExt};
|
||||
|
||||
let a = pallas::Point::one();
|
||||
assert_eq!(a * pallas::Scalar::ZETA, a.endo());
|
||||
let a = vesta::Point::one();
|
||||
assert_eq!(a * vesta::Scalar::ZETA, a.endo());
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
//! This module contains implementations for the Tweedledum and Tweedledee
|
||||
//! elliptic curve groups.
|
||||
//! This module contains implementations for the Pallas and Vesta elliptic curve
|
||||
//! groups.
|
||||
|
||||
use core::cmp;
|
||||
use core::fmt::Debug;
|
|
@ -1,5 +1,5 @@
|
|||
//! This module contains implementations for the two finite fields of the
|
||||
//! Tweedledum and Tweedledee curves.
|
||||
//! This module contains implementations for the two finite fields of the Pallas
|
||||
//! and Vesta curves.
|
||||
|
||||
mod fp;
|
||||
mod fq;
|
|
@ -9,9 +9,9 @@ use crate::arithmetic::{adc, mac, sbb, FieldExt, Group};
|
|||
|
||||
/// This represents an element of $\mathbb{F}_p$ where
|
||||
///
|
||||
/// `p = 0x40000000000000000000000000000000038aa1276c3f59b9a14064e200000001`
|
||||
/// `p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001`
|
||||
///
|
||||
/// is the base field of the Tweedledum curve.
|
||||
/// is the base field of the Pallas curve.
|
||||
// The internal representation of this type is four 64-bit unsigned
|
||||
// integers in little-endian order. `Fp` values are always in
|
||||
// Montgomery form; i.e., Fp(a) = aR mod p, with R = 2^256.
|
||||
|
@ -94,11 +94,11 @@ impl ConditionallySelectable for Fp {
|
|||
}
|
||||
|
||||
/// Constant representing the modulus
|
||||
/// p = 0x40000000000000000000000000000000038aa1276c3f59b9a14064e200000001
|
||||
/// p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
const MODULUS: Fp = Fp([
|
||||
0xa14064e200000001,
|
||||
0x38aa1276c3f59b9,
|
||||
0x0,
|
||||
0x992d30ed00000001,
|
||||
0x224698fc094cf91b,
|
||||
0x0000000000000000,
|
||||
0x4000000000000000,
|
||||
]);
|
||||
|
||||
|
@ -106,9 +106,9 @@ const MODULUS: Fp = Fp([
|
|||
#[cfg(not(target_pointer_width = "64"))]
|
||||
const MODULUS_LIMBS_32: [u32; 8] = [
|
||||
0x0000_0001,
|
||||
0xa140_64e2,
|
||||
0x6c3f_59b9,
|
||||
0x038a_a127,
|
||||
0x992d_30ed,
|
||||
0x094c_f91b,
|
||||
0x2246_98fc,
|
||||
0x0000_0000,
|
||||
0x0000_0000,
|
||||
0x0000_0000,
|
||||
|
@ -164,34 +164,34 @@ impl_binops_additive!(Fp, Fp);
|
|||
impl_binops_multiplicative!(Fp, Fp);
|
||||
|
||||
/// INV = -(p^{-1} mod 2^64) mod 2^64
|
||||
const INV: u64 = 0xa14064e1ffffffff;
|
||||
const INV: u64 = 0x992d30ecffffffff;
|
||||
|
||||
/// R = 2^256 mod p
|
||||
const R: Fp = Fp([
|
||||
0x1c3ed159fffffffd,
|
||||
0xf5601c89bb41f2d3,
|
||||
0x34786d38fffffffd,
|
||||
0x992c350be41914ad,
|
||||
0xffffffffffffffff,
|
||||
0x3fffffffffffffff,
|
||||
]);
|
||||
|
||||
/// R^2 = 2^512 mod p
|
||||
const R2: Fp = Fp([
|
||||
0x280c9c4000000010,
|
||||
0x91a4409b5400af74,
|
||||
0xdd7b28e19094c659,
|
||||
0xc8ad9107ccca0e,
|
||||
0x8c78ecb30000000f,
|
||||
0xd7d30dbd8b0de0e7,
|
||||
0x7797a99bc3c95d18,
|
||||
0x096d41af7b9cb714,
|
||||
]);
|
||||
|
||||
/// R^3 = 2^768 mod p
|
||||
const R3: Fp = Fp([
|
||||
0x98fb3d144380a737,
|
||||
0xf9fdbeb55b7eb87c,
|
||||
0x63f75cb999eafa89,
|
||||
0x217cb214ebb8fc72,
|
||||
0xf185a5993a9e10f9,
|
||||
0xf6a68f3b6ac5b1d1,
|
||||
0xdf8d1014353fd42c,
|
||||
0x2ae309222d2d9910,
|
||||
]);
|
||||
|
||||
/// `GENERATOR = 5 mod p` is a generator of the `p - 1` order multiplicative subgroup, and
|
||||
/// is also a quadratic non-residue.
|
||||
/// `GENERATOR = 5 mod p` is a generator of the `p - 1` order multiplicative
|
||||
/// subgroup, or in other words a primitive root of the field.
|
||||
const GENERATOR: Fp = Fp::from_raw([
|
||||
0x0000_0000_0000_0005,
|
||||
0x0000_0000_0000_0000,
|
||||
|
@ -199,34 +199,26 @@ const GENERATOR: Fp = Fp::from_raw([
|
|||
0x0000_0000_0000_0000,
|
||||
]);
|
||||
|
||||
const S: u32 = 33;
|
||||
const S: u32 = 32;
|
||||
|
||||
/// GENERATOR^t where t * 2^s + 1 = p
|
||||
/// with t odd. In other words, this
|
||||
/// is a 2^s root of unity.
|
||||
///
|
||||
/// `GENERATOR = 5 mod p` is a generator
|
||||
/// of the p - 1 order multiplicative
|
||||
/// subgroup.
|
||||
const ROOT_OF_UNITY: Fp = Fp::from_raw([
|
||||
0x53de9f31b88837ce,
|
||||
0xff46e8f3f3ea99d6,
|
||||
0xf624f2eaaf8c2d57,
|
||||
0x2ae45117890ee2fc,
|
||||
0xbdad6fabd87ea32f,
|
||||
0xea322bf2b7bb7584,
|
||||
0x362120830561f81a,
|
||||
0x2bce74deac30ebda,
|
||||
]);
|
||||
|
||||
/// GENERATOR^{2^s} where t * 2^s + 1 = p
|
||||
/// with t odd. In other words, this
|
||||
/// is a t root of unity.
|
||||
///
|
||||
/// `GENERATOR = 5 mod p` is a generator
|
||||
/// of the p - 1 order multiplicative
|
||||
/// subgroup.
|
||||
const DELTA: Fp = Fp::from_raw([
|
||||
0x48796f6fde98a425,
|
||||
0xa99d8b67e918805e,
|
||||
0x671383de08b5fe3c,
|
||||
0x1e9372724e80300d,
|
||||
0x6a6ccd20dd7b9ba2,
|
||||
0xf5e4f3f13eee5636,
|
||||
0xbd455b7112a5049d,
|
||||
0x0a757d0f0006ab6c,
|
||||
]);
|
||||
|
||||
impl Default for Fp {
|
||||
|
@ -503,7 +495,7 @@ impl ff::Field for Fp {
|
|||
// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
|
||||
|
||||
// w = self^((t - 1) // 2)
|
||||
let w = self.pow_vartime(&[0xdb0fd66e68501938, 0xe2a849, 0x0, 0x10000000]);
|
||||
let w = self.pow_vartime(&[0x04a67c8dcc969876, 0x11234c7e, 0x0, 0x20000000]);
|
||||
|
||||
let mut v = S;
|
||||
let mut x = self * w;
|
||||
|
@ -544,8 +536,8 @@ impl ff::Field for Fp {
|
|||
/// failing if the element is zero.
|
||||
fn invert(&self) -> CtOption<Self> {
|
||||
let tmp = self.pow_vartime(&[
|
||||
0xa14064e1ffffffff,
|
||||
0x38aa1276c3f59b9,
|
||||
0x992d30ecffffffff,
|
||||
0x224698fc094cf91b,
|
||||
0x0,
|
||||
0x4000000000000000,
|
||||
]);
|
||||
|
@ -646,43 +638,43 @@ impl ff::PrimeField for Fp {
|
|||
impl FieldExt for Fp {
|
||||
const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
|
||||
const ROOT_OF_UNITY_INV: Self = Fp::from_raw([
|
||||
0x9246674078fa45bb,
|
||||
0xd822ebd60888c5ea,
|
||||
0x56d579133a11731f,
|
||||
0x1c88fa9e942120bb,
|
||||
0xf0b87c7db2ce91f6,
|
||||
0x84a0a1d8859f066f,
|
||||
0xb4ed8e647196dad1,
|
||||
0x2cd5282c53116b5c,
|
||||
]);
|
||||
const UNROLL_T_EXPONENT: [u64; 4] = [
|
||||
0x3b3a6633d1897d83,
|
||||
0x0000000000c93d5b,
|
||||
0xf000000000000000,
|
||||
0xe34ab16,
|
||||
0x955a0a417453113c,
|
||||
0x0000000022016b89,
|
||||
0xc000000000000000,
|
||||
0x3f7ed4c6,
|
||||
];
|
||||
const T_EXPONENT: [u64; 4] = [
|
||||
0xb61facdcd0a03271,
|
||||
0x0000000001c55093,
|
||||
0x094cf91b992d30ed,
|
||||
0x00000000224698fc,
|
||||
0x0000000000000000,
|
||||
0x20000000,
|
||||
0x40000000,
|
||||
];
|
||||
const DELTA: Self = DELTA;
|
||||
const UNROLL_S_EXPONENT: u64 = 0x11cb54e91;
|
||||
const UNROLL_S_EXPONENT: u64 = 0x204ace5;
|
||||
const TWO_INV: Self = Fp::from_raw([
|
||||
0xd0a0327100000001,
|
||||
0x01c55093b61facdc,
|
||||
0xcc96987680000001,
|
||||
0x11234c7e04a67c8d,
|
||||
0x0000000000000000,
|
||||
0x2000000000000000,
|
||||
]);
|
||||
const RESCUE_ALPHA: u64 = 5;
|
||||
const RESCUE_INVALPHA: [u64; 4] = [
|
||||
0x810050b4cccccccd,
|
||||
0x360880ec56991494,
|
||||
0xe0f0f3f0cccccccd,
|
||||
0x4e9ee0c9a10a60e2,
|
||||
0x3333333333333333,
|
||||
0x3333333333333333,
|
||||
];
|
||||
const ZETA: Self = Fp::from_raw([
|
||||
0x8598abb3a410c9c8,
|
||||
0x7881fb239ba41a26,
|
||||
0x9bebc9146ef83d9a,
|
||||
0x1508415ab5e97c94,
|
||||
0x1dad5ebdfdfe4ab9,
|
||||
0x1d1f8bd237ad3149,
|
||||
0x2caad5dc57aab1b0,
|
||||
0x12ccca834acdba71,
|
||||
]);
|
||||
|
||||
fn ct_is_zero(&self) -> Choice {
|
||||
|
@ -781,11 +773,36 @@ fn test_inv() {
|
|||
assert_eq!(inv, INV);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rescue() {
|
||||
// NB: TWO_INV is standing in as a "random" field element
|
||||
assert_eq!(
|
||||
Fp::TWO_INV
|
||||
.pow_vartime(&[Fp::RESCUE_ALPHA, 0, 0, 0])
|
||||
.pow_vartime(&Fp::RESCUE_INVALPHA),
|
||||
Fp::TWO_INV
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sqrt() {
|
||||
// NB: TWO_INV is standing in as a "random" field element
|
||||
let v = (Fp::TWO_INV).square().sqrt().unwrap();
|
||||
assert!(v == Fp::TWO_INV || (-v) == Fp::TWO_INV);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deterministic_sqrt() {
|
||||
// NB: TWO_INV is standing in as a "random" field element
|
||||
let v = (Fp::TWO_INV).square().deterministic_sqrt().unwrap();
|
||||
assert!(v == Fp::TWO_INV || (-v) == Fp::TWO_INV);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zeta() {
|
||||
assert_eq!(
|
||||
format!("{:?}", Fp::ZETA),
|
||||
"0x1508415ab5e97c949bebc9146ef83d9a7881fb239ba41a268598abb3a410c9c8"
|
||||
"0x12ccca834acdba712caad5dc57aab1b01d1f8bd237ad31491dad5ebdfdfe4ab9"
|
||||
);
|
||||
|
||||
let a = Fp::ZETA;
|
||||
|
@ -796,6 +813,14 @@ fn test_zeta() {
|
|||
assert!(c == Fp::one());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_root_of_unity() {
|
||||
assert_eq!(
|
||||
Fp::ROOT_OF_UNITY.pow_vartime(&[1 << Fp::S, 0, 0, 0]),
|
||||
Fp::one()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_root_of_unity() {
|
||||
assert_eq!(Fp::ROOT_OF_UNITY_INV, Fp::ROOT_OF_UNITY.invert().unwrap());
|
||||
|
@ -808,5 +833,45 @@ fn test_inv_2() {
|
|||
|
||||
#[test]
|
||||
fn test_delta() {
|
||||
assert_eq!(Fp::DELTA, Fp::from(5).pow(&[1u64 << Fp::S, 0, 0, 0]));
|
||||
assert_eq!(Fp::DELTA, GENERATOR.pow(&[1u64 << Fp::S, 0, 0, 0]));
|
||||
assert_eq!(Fp::DELTA, Fp::multiplicative_generator().pow(&[1u64 << Fp::S, 0, 0, 0]));
|
||||
}
|
||||
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
#[test]
|
||||
fn consistent_modulus_limbs() {
|
||||
for (a, &b) in MODULUS
|
||||
.0
|
||||
.iter()
|
||||
.flat_map(|&limb| {
|
||||
Some(limb as u32)
|
||||
.into_iter()
|
||||
.chain(Some((limb >> 32) as u32))
|
||||
})
|
||||
.zip(MODULUS_LIMBS_32.iter())
|
||||
{
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_u512() {
|
||||
assert_eq!(
|
||||
Fp::from_raw([
|
||||
0x3daec14d565241d9,
|
||||
0x0b7af45b6073944b,
|
||||
0xea5b8bd611a5bd4c,
|
||||
0x150160330625db3d
|
||||
]),
|
||||
Fp::from_u512([
|
||||
0xee155641297678a1,
|
||||
0xd83e156bdbfdbe65,
|
||||
0xd9ccd834c68ba0b5,
|
||||
0xf508ede312272758,
|
||||
0x038df7cbf8228e89,
|
||||
0x3505a1e4a3c74b41,
|
||||
0xbfa46f775eb82db3,
|
||||
0x26ebe27e262f471d
|
||||
])
|
||||
);
|
||||
}
|
|
@ -9,9 +9,9 @@ use crate::arithmetic::{adc, mac, sbb, FieldExt, Group};
|
|||
|
||||
/// This represents an element of $\mathbb{F}_q$ where
|
||||
///
|
||||
/// `q = 0x40000000000000000000000000000000038aa127696286c9842cafd400000001`
|
||||
/// `q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001`
|
||||
///
|
||||
/// is the base field of the Tweedledee curve.
|
||||
/// is the base field of the Vesta curve.
|
||||
// The internal representation of this type is four 64-bit unsigned
|
||||
// integers in little-endian order. `Fq` values are always in
|
||||
// Montgomery form; i.e., Fq(a) = aR mod q, with R = 2^256.
|
||||
|
@ -94,10 +94,10 @@ impl ConditionallySelectable for Fq {
|
|||
}
|
||||
|
||||
/// Constant representing the modulus
|
||||
/// q = 0x40000000000000000000000000000000038aa127696286c9842cafd400000001
|
||||
/// q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
|
||||
const MODULUS: Fq = Fq([
|
||||
0x842cafd400000001,
|
||||
0x38aa127696286c9,
|
||||
0x8c46eb2100000001,
|
||||
0x224698fc0994a8dd,
|
||||
0x0,
|
||||
0x4000000000000000,
|
||||
]);
|
||||
|
@ -106,9 +106,9 @@ const MODULUS: Fq = Fq([
|
|||
#[cfg(not(target_pointer_width = "64"))]
|
||||
const MODULUS_LIMBS_32: [u32; 8] = [
|
||||
0x0000_0001,
|
||||
0x842c_afd4,
|
||||
0x6962_86c9,
|
||||
0x038a_a127,
|
||||
0x8c46_eb21,
|
||||
0x0994_a8dd,
|
||||
0x2246_98fc,
|
||||
0x0000_0000,
|
||||
0x0000_0000,
|
||||
0x0000_0000,
|
||||
|
@ -164,34 +164,34 @@ impl_binops_additive!(Fq, Fq);
|
|||
impl_binops_multiplicative!(Fq, Fq);
|
||||
|
||||
/// INV = -(q^{-1} mod 2^64) mod 2^64
|
||||
const INV: u64 = 0x842cafd3ffffffff;
|
||||
const INV: u64 = 0x8c46eb20ffffffff;
|
||||
|
||||
/// R = 2^256 mod q
|
||||
const R: Fq = Fq([
|
||||
0x7379f083fffffffd,
|
||||
0xf5601c89c3d86ba3,
|
||||
0x5b2b3e9cfffffffd,
|
||||
0x992c350be3420567,
|
||||
0xffffffffffffffff,
|
||||
0x3fffffffffffffff,
|
||||
]);
|
||||
|
||||
/// R^2 = 2^512 mod q
|
||||
const R2: Fq = Fq([
|
||||
0x8595fa8000000010,
|
||||
0x7e16a565c6895230,
|
||||
0xf4c0e6fcb03aa0a2,
|
||||
0xc8ad9106886013,
|
||||
0xfc9678ff0000000f,
|
||||
0x67bb433d891a16e3,
|
||||
0x7fae231004ccf590,
|
||||
0x096d41af7ccfdaa9,
|
||||
]);
|
||||
|
||||
/// R^3 = 2^768 mod q
|
||||
const R3: Fq = Fq([
|
||||
0xa624f338075cdb5e,
|
||||
0x57964eacb8fe21f2,
|
||||
0xcb266d18c0413bc2,
|
||||
0xa42cdf95f959577,
|
||||
0x008b421c249dae4c,
|
||||
0xe13bda50dba41326,
|
||||
0x88fececb8e15cb63,
|
||||
0x07dd97a06e6792c8,
|
||||
]);
|
||||
|
||||
/// `GENERATOR = 5 mod q` is a generator of the `q - 1` order multiplicative subgroup, and
|
||||
/// is also a quadratic non-residue.
|
||||
/// `GENERATOR = 5 mod q` is a generator of the `q - 1` order multiplicative
|
||||
/// subgroup, or in other words a primitive root of the field.
|
||||
const GENERATOR: Fq = Fq::from_raw([
|
||||
0x0000_0000_0000_0005,
|
||||
0x0000_0000_0000_0000,
|
||||
|
@ -199,34 +199,26 @@ const GENERATOR: Fq = Fq::from_raw([
|
|||
0x0000_0000_0000_0000,
|
||||
]);
|
||||
|
||||
const S: u32 = 34;
|
||||
const S: u32 = 32;
|
||||
|
||||
/// GENERATOR^t where t * 2^s + 1 = q
|
||||
/// with t odd. In other words, this
|
||||
/// is a 2^s root of unity.
|
||||
///
|
||||
/// `GENERATOR = 5 mod q` is a generator
|
||||
/// of the q - 1 order multiplicative
|
||||
/// subgroup.
|
||||
const ROOT_OF_UNITY: Fq = Fq::from_raw([
|
||||
0x1cbd3234869d57ec,
|
||||
0xa287dd1b8084fbf,
|
||||
0xf1dbcb645a987293,
|
||||
0x113efc510dc03c0b,
|
||||
0xa70e2c1102b6d05f,
|
||||
0x9bb97ea3c106f049,
|
||||
0x9e5c4dfd492ae26e,
|
||||
0x2de6a9b8746d3f58,
|
||||
]);
|
||||
|
||||
/// GENERATOR^{2^s} where t * 2^s + 1 = q
|
||||
/// with t odd. In other words, this
|
||||
/// is a t root of unity.
|
||||
///
|
||||
/// `GENERATOR = 5 mod q` is a generator
|
||||
/// of the q - 1 order multiplicative
|
||||
/// subgroup.
|
||||
const DELTA: Fq = Fq::from_raw([
|
||||
0x83d2833d15f2bbf9,
|
||||
0x5127e2ce24a8e69c,
|
||||
0x4243423589e0a9b5,
|
||||
0x20daec44973be920,
|
||||
0x8494392472d1683c,
|
||||
0xe3ac3376541d1140,
|
||||
0x06f0a88e7f7949f8,
|
||||
0x2237d54423724166,
|
||||
]);
|
||||
|
||||
impl Default for Fq {
|
||||
|
@ -256,21 +248,6 @@ impl Fq {
|
|||
self.add(self)
|
||||
}
|
||||
|
||||
/// Converts a 512-bit little endian integer into
|
||||
/// a `Fq` by reducing by the modulus.
|
||||
pub fn from_bytes_wide(bytes: &[u8; 64]) -> Fq {
|
||||
Fq::from_u512([
|
||||
u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
|
||||
u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
|
||||
u64::from_le_bytes(bytes[16..24].try_into().unwrap()),
|
||||
u64::from_le_bytes(bytes[24..32].try_into().unwrap()),
|
||||
u64::from_le_bytes(bytes[32..40].try_into().unwrap()),
|
||||
u64::from_le_bytes(bytes[40..48].try_into().unwrap()),
|
||||
u64::from_le_bytes(bytes[48..56].try_into().unwrap()),
|
||||
u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
|
||||
])
|
||||
}
|
||||
|
||||
fn from_u512(limbs: [u64; 8]) -> Fq {
|
||||
// We reduce an arbitrary 512-bit number by decomposing it into two 256-bit digits
|
||||
// with the higher bits multiplied by 2^256. Thus, we perform two reductions
|
||||
|
@ -518,7 +495,7 @@ impl ff::Field for Fq {
|
|||
// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
|
||||
|
||||
// w = self^((t - 1) // 2)
|
||||
let w = self.pow_vartime(&[0xed2c50d9308595fa, 0x715424, 0x0, 0x8000000]);
|
||||
let w = self.pow_vartime(&[0x04ca546ec6237590, 0x11234c7e, 0x0, 0x20000000]);
|
||||
|
||||
let mut v = S;
|
||||
let mut x = self * w;
|
||||
|
@ -559,8 +536,8 @@ impl ff::Field for Fq {
|
|||
/// failing if the element is zero.
|
||||
fn invert(&self) -> CtOption<Self> {
|
||||
let tmp = self.pow_vartime(&[
|
||||
0x842cafd3ffffffff,
|
||||
0x38aa127696286c9,
|
||||
0x8c46eb20ffffffff,
|
||||
0x224698fc0994a8dd,
|
||||
0x0,
|
||||
0x4000000000000000,
|
||||
]);
|
||||
|
@ -661,43 +638,43 @@ impl ff::PrimeField for Fq {
|
|||
impl FieldExt for Fq {
|
||||
const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
|
||||
const ROOT_OF_UNITY_INV: Self = Fq::from_raw([
|
||||
0x824860d3eb30de02,
|
||||
0xad9f0afd0ea63acc,
|
||||
0xd250318c11a16fe1,
|
||||
0x12a9f5e1dd62dabc,
|
||||
0x57eecda0a84b6836,
|
||||
0x4ad38b9084b8a80c,
|
||||
0xf4c8f353124086c1,
|
||||
0x2235e1a7415bf936,
|
||||
]);
|
||||
const UNROLL_T_EXPONENT: [u64; 4] = [
|
||||
0x9b71de17e6d2d5a0,
|
||||
0x0000000000296ee0,
|
||||
0x8c00000000000000,
|
||||
0x2ecc05e,
|
||||
0xcc771cc2ac1e1664,
|
||||
0x00000000062dfe9e,
|
||||
0xc000000000000000,
|
||||
0xb89e9c7,
|
||||
];
|
||||
const T_EXPONENT: [u64; 4] = [
|
||||
0xda58a1b2610b2bf5,
|
||||
0x0000000000e2a849,
|
||||
0x0994a8dd8c46eb21,
|
||||
0x00000000224698fc,
|
||||
0x0000000000000000,
|
||||
0x10000000,
|
||||
0x40000000,
|
||||
];
|
||||
const DELTA: Self = DELTA;
|
||||
const UNROLL_S_EXPONENT: u64 = 0x344cfe85d;
|
||||
const UNROLL_S_EXPONENT: u64 = 0xd1d858e1;
|
||||
const TWO_INV: Self = Fq::from_raw([
|
||||
0xc21657ea00000001,
|
||||
0x01c55093b4b14364,
|
||||
0xc623759080000001,
|
||||
0x11234c7e04ca546e,
|
||||
0x0000000000000000,
|
||||
0x2000000000000000,
|
||||
]);
|
||||
const RESCUE_ALPHA: u64 = 5;
|
||||
const RESCUE_INVALPHA: [u64; 4] = [
|
||||
0xd023bfdccccccccd,
|
||||
0x360880ec544ed23a,
|
||||
0xd69f2280cccccccd,
|
||||
0x4e9ee0c9a143ba4a,
|
||||
0x3333333333333333,
|
||||
0x3333333333333333,
|
||||
];
|
||||
const ZETA: Self = Fq::from_raw([
|
||||
0x4394c2bd148fa4fd,
|
||||
0x69cf8de720e52ec1,
|
||||
0x87ad8b5ff9731ffe,
|
||||
0x36c66d3a1e049a58,
|
||||
0x2aa9d2e050aa0e4f,
|
||||
0x0fed467d47c033af,
|
||||
0x511db4d81cf70f5a,
|
||||
0x06819a58283e528e,
|
||||
]);
|
||||
|
||||
fn ct_is_zero(&self) -> Choice {
|
||||
|
@ -796,11 +773,36 @@ fn test_inv() {
|
|||
assert_eq!(inv, INV);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rescue() {
|
||||
// NB: TWO_INV is standing in as a "random" field element
|
||||
assert_eq!(
|
||||
Fq::TWO_INV
|
||||
.pow_vartime(&[Fq::RESCUE_ALPHA, 0, 0, 0])
|
||||
.pow_vartime(&Fq::RESCUE_INVALPHA),
|
||||
Fq::TWO_INV
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sqrt() {
|
||||
// NB: TWO_INV is standing in as a "random" field element
|
||||
let v = (Fq::TWO_INV).square().sqrt().unwrap();
|
||||
assert!(v == Fq::TWO_INV || (-v) == Fq::TWO_INV);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deterministic_sqrt() {
|
||||
// NB: TWO_INV is standing in as a "random" field element
|
||||
let v = (Fq::TWO_INV).square().deterministic_sqrt().unwrap();
|
||||
assert!(v == Fq::TWO_INV || (-v) == Fq::TWO_INV);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zeta() {
|
||||
assert_eq!(
|
||||
format!("{:?}", Fq::ZETA),
|
||||
"0x36c66d3a1e049a5887ad8b5ff9731ffe69cf8de720e52ec14394c2bd148fa4fd"
|
||||
"0x06819a58283e528e511db4d81cf70f5a0fed467d47c033af2aa9d2e050aa0e4f"
|
||||
);
|
||||
let a = Fq::ZETA;
|
||||
assert!(a != Fq::one());
|
||||
|
@ -810,6 +812,14 @@ fn test_zeta() {
|
|||
assert!(c == Fq::one());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_root_of_unity() {
|
||||
assert_eq!(
|
||||
Fq::ROOT_OF_UNITY.pow_vartime(&[1 << Fq::S, 0, 0, 0]),
|
||||
Fq::one()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_root_of_unity() {
|
||||
assert_eq!(Fq::ROOT_OF_UNITY_INV, Fq::ROOT_OF_UNITY.invert().unwrap());
|
||||
|
@ -822,5 +832,45 @@ fn test_inv_2() {
|
|||
|
||||
#[test]
|
||||
fn test_delta() {
|
||||
assert_eq!(Fq::DELTA, Fq::from(5).pow(&[1u64 << Fq::S, 0, 0, 0]));
|
||||
assert_eq!(Fq::DELTA, GENERATOR.pow(&[1u64 << Fq::S, 0, 0, 0]));
|
||||
assert_eq!(Fq::DELTA, Fq::multiplicative_generator().pow(&[1u64 << Fq::S, 0, 0, 0]));
|
||||
}
|
||||
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
#[test]
|
||||
fn consistent_modulus_limbs() {
|
||||
for (a, &b) in MODULUS
|
||||
.0
|
||||
.iter()
|
||||
.flat_map(|&limb| {
|
||||
Some(limb as u32)
|
||||
.into_iter()
|
||||
.chain(Some((limb >> 32) as u32))
|
||||
})
|
||||
.zip(MODULUS_LIMBS_32.iter())
|
||||
{
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_u512() {
|
||||
assert_eq!(
|
||||
Fq::from_raw([
|
||||
0xe22bd0d1b22cc43e,
|
||||
0x6b84e5b52490a7c8,
|
||||
0x264262941ac9e229,
|
||||
0x27dcfdf361ce4254
|
||||
]),
|
||||
Fq::from_u512([
|
||||
0x64a80cce0b5a2369,
|
||||
0x84f2ef0501bc783c,
|
||||
0x696e5e63c86bbbde,
|
||||
0x924072f52dc6cc62,
|
||||
0x8288a507c8d61128,
|
||||
0x3b2efb1ef697e3fe,
|
||||
0x75a4998d06855f27,
|
||||
0x52ea589e69712cc0
|
||||
])
|
||||
);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
//! The Pallas elliptic curve group.
|
||||
|
||||
/// A Pallas point in the projective coordinate space.
|
||||
pub type Point = super::Ep;
|
||||
|
||||
/// A Pallas point in the affine coordinate space (or the point at infinity).
|
||||
pub type Affine = super::EpAffine;
|
||||
|
||||
/// The base field of the Pallas group.
|
||||
pub type Base = super::Fp;
|
||||
|
||||
/// The scalar field of the Pallas group.
|
||||
pub type Scalar = super::Fq;
|
|
@ -0,0 +1,13 @@
|
|||
//! The Vesta elliptic curve group.
|
||||
|
||||
/// A Vesta point in the projective coordinate space.
|
||||
pub type Point = super::Eq;
|
||||
|
||||
/// A Vesta point in the affine coordinate space (or the point at infinity).
|
||||
pub type Affine = super::EqAffine;
|
||||
|
||||
/// The base field of the Vesta group.
|
||||
pub type Base = super::Fq;
|
||||
|
||||
/// The scalar field of the Vesta group.
|
||||
pub type Scalar = super::Fp;
|
|
@ -119,9 +119,9 @@ type ChallengeX<F> = ChallengeScalar<F, X>;
|
|||
#[test]
|
||||
fn test_proving() {
|
||||
use crate::arithmetic::{Curve, FieldExt};
|
||||
use crate::pasta::{EqAffine, Fp, Fq};
|
||||
use crate::poly::commitment::{Blind, Params};
|
||||
use crate::transcript::DummyHash;
|
||||
use crate::tweedle::{EqAffine, Fp, Fq};
|
||||
use circuit::{Advice, Column, Fixed};
|
||||
use std::marker::PhantomData;
|
||||
const K: u32 = 5;
|
||||
|
|
|
@ -103,7 +103,6 @@ impl<C: CurveAffine> Params<C> {
|
|||
|
||||
let h = {
|
||||
let mut hasher = H::init(C::Base::zero());
|
||||
hasher.absorb(-C::Base::one());
|
||||
let x = hasher.squeeze().to_bytes();
|
||||
let p = C::from_bytes(&x);
|
||||
p.unwrap()
|
||||
|
@ -226,8 +225,8 @@ impl<F: FieldExt> MulAssign<F> for Blind<F> {
|
|||
fn test_commit_lagrange() {
|
||||
const K: u32 = 6;
|
||||
|
||||
use crate::pasta::{EpAffine, Fp, Fq};
|
||||
use crate::transcript::DummyHash;
|
||||
use crate::tweedle::{EpAffine, Fp, Fq};
|
||||
let params = Params::<EpAffine>::new::<DummyHash<Fp>>(K);
|
||||
let domain = super::EvaluationDomain::new(1, K);
|
||||
|
||||
|
@ -255,8 +254,8 @@ fn test_opening_proof() {
|
|||
EvaluationDomain,
|
||||
};
|
||||
use crate::arithmetic::{eval_polynomial, Curve, FieldExt};
|
||||
use crate::pasta::{EpAffine, Fp, Fq};
|
||||
use crate::transcript::{ChallengeScalar, DummyHash, Transcript};
|
||||
use crate::tweedle::{EpAffine, Fp, Fq};
|
||||
|
||||
let params = Params::<EpAffine>::new::<DummyHash<Fp>>(K);
|
||||
let domain = EvaluationDomain::new(1, K);
|
||||
|
|
|
@ -217,7 +217,7 @@ where
|
|||
mod tests {
|
||||
use super::{construct_intermediate_sets, Query};
|
||||
use crate::arithmetic::FieldExt;
|
||||
use crate::tweedle::Fp;
|
||||
use crate::pasta::Fp;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct MyQuery<F> {
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
//! This module contains implementations for the Tweedledum and Tweedledee
|
||||
//! elliptic curve groups.
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod curves;
|
||||
mod fields;
|
||||
|
||||
pub mod dee;
|
||||
pub mod dum;
|
||||
|
||||
pub use curves::*;
|
||||
pub use fields::*;
|
|
@ -1,13 +0,0 @@
|
|||
//! The Tweedledee elliptic curve group.
|
||||
|
||||
/// A Tweedledee point in the projective coordinate space.
|
||||
pub type Point = super::Eq;
|
||||
|
||||
/// A Tweedledee point in the affine coordinate space (or the point at infinity).
|
||||
pub type Affine = super::EqAffine;
|
||||
|
||||
/// The base field of the Tweedledee group.
|
||||
pub type Base = super::Fq;
|
||||
|
||||
/// The scalar field of the Tweedledee group.
|
||||
pub type Scalar = super::Fp;
|
|
@ -1,13 +0,0 @@
|
|||
//! The Tweedledum elliptic curve group.
|
||||
|
||||
/// A Tweedledum point in the projective coordinate space.
|
||||
pub type Point = super::Ep;
|
||||
|
||||
/// A Tweedledum point in the affine coordinate space (or the point at infinity).
|
||||
pub type Affine = super::EpAffine;
|
||||
|
||||
/// The base field of the Tweedledum group.
|
||||
pub type Base = super::Fp;
|
||||
|
||||
/// The scalar field of the Tweedledum group.
|
||||
pub type Scalar = super::Fq;
|
Loading…
Reference in New Issue