diff --git a/benches/arithmetic.rs b/benches/arithmetic.rs index 5939c262..400725bf 100644 --- a/benches/arithmetic.rs +++ b/benches/arithmetic.rs @@ -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}; diff --git a/benches/plonk.rs b/benches/plonk.rs index 13334160..70a4f4e6 100644 --- a/benches/plonk.rs +++ b/benches/plonk.rs @@ -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; diff --git a/examples/performance_model.rs b/examples/performance_model.rs index 796dbc10..cd38cd01 100644 --- a/examples/performance_model.rs +++ b/examples/performance_model.rs @@ -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; diff --git a/src/arithmetic.rs b/src/arithmetic.rs index f5e7ed84..dcb4189f 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -468,7 +468,7 @@ pub fn lagrange_interpolate(points: &[F], evals: &[F]) -> Vec { } #[cfg(test)] -use crate::tweedle::Fp; +use crate::pasta::Fp; #[test] fn test_lagrange_interpolate() { diff --git a/src/lib.rs b/src/lib.rs index 2676e3e4..36287ac4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/pasta.rs b/src/pasta.rs new file mode 100644 index 00000000..c851450e --- /dev/null +++ b/src/pasta.rs @@ -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()); +} diff --git a/src/tweedle/curves.rs b/src/pasta/curves.rs similarity index 99% rename from src/tweedle/curves.rs rename to src/pasta/curves.rs index cfc7df67..8d5ad8ab 100644 --- a/src/tweedle/curves.rs +++ b/src/pasta/curves.rs @@ -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; diff --git a/src/tweedle/fields.rs b/src/pasta/fields.rs similarity index 91% rename from src/tweedle/fields.rs rename to src/pasta/fields.rs index e9f4972f..5b0647d4 100644 --- a/src/tweedle/fields.rs +++ b/src/pasta/fields.rs @@ -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; diff --git a/src/tweedle/fields/fp.rs b/src/pasta/fields/fp.rs similarity index 86% rename from src/tweedle/fields/fp.rs rename to src/pasta/fields/fp.rs index 2b969a31..47cc64e9 100644 --- a/src/tweedle/fields/fp.rs +++ b/src/pasta/fields/fp.rs @@ -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 { 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 + ]) + ); } diff --git a/src/tweedle/fields/fq.rs b/src/pasta/fields/fq.rs similarity index 86% rename from src/tweedle/fields/fq.rs rename to src/pasta/fields/fq.rs index 7462922a..0c36f9dd 100644 --- a/src/tweedle/fields/fq.rs +++ b/src/pasta/fields/fq.rs @@ -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 { 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 + ]) + ); } diff --git a/src/tweedle/macros.rs b/src/pasta/macros.rs similarity index 100% rename from src/tweedle/macros.rs rename to src/pasta/macros.rs diff --git a/src/pasta/pallas.rs b/src/pasta/pallas.rs new file mode 100644 index 00000000..78b2f649 --- /dev/null +++ b/src/pasta/pallas.rs @@ -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; diff --git a/src/pasta/vesta.rs b/src/pasta/vesta.rs new file mode 100644 index 00000000..c20d9b67 --- /dev/null +++ b/src/pasta/vesta.rs @@ -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; diff --git a/src/plonk.rs b/src/plonk.rs index a5fbae05..16e61372 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -119,9 +119,9 @@ type ChallengeX = ChallengeScalar; #[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; diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index 69ae7b02..6729ac53 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -103,7 +103,6 @@ impl Params { 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 MulAssign for Blind { 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::::new::>(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::::new::>(K); let domain = EvaluationDomain::new(1, K); diff --git a/src/poly/multiopen.rs b/src/poly/multiopen.rs index bcae0e6d..0d4cc935 100644 --- a/src/poly/multiopen.rs +++ b/src/poly/multiopen.rs @@ -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 { diff --git a/src/tweedle.rs b/src/tweedle.rs deleted file mode 100644 index 417071e4..00000000 --- a/src/tweedle.rs +++ /dev/null @@ -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::*; diff --git a/src/tweedle/dee.rs b/src/tweedle/dee.rs deleted file mode 100644 index a900ada1..00000000 --- a/src/tweedle/dee.rs +++ /dev/null @@ -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; diff --git a/src/tweedle/dum.rs b/src/tweedle/dum.rs deleted file mode 100644 index 9f9b1b28..00000000 --- a/src/tweedle/dum.rs +++ /dev/null @@ -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;