diff --git a/src/arithmetic/curves.rs b/src/arithmetic/curves.rs index 97a9527..3cffdbd 100644 --- a/src/arithmetic/curves.rs +++ b/src/arithmetic/curves.rs @@ -2,7 +2,7 @@ //! write code that generalizes over a pair of groups. use core::cmp; -use core::ops::{Add, Sub}; +use core::ops::{Add, Mul, Sub}; use group::prime::{PrimeCurve, PrimeCurveAffine}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; @@ -14,7 +14,7 @@ use std::io::{self, Read, Write}; /// curve group in a "projective" form, where that arithmetic is usually more /// efficient. pub trait CurveExt: - PrimeCurve + PrimeCurve::AffineExt> + group::Group::ScalarExt> + Default + PartialEq @@ -28,6 +28,13 @@ pub trait CurveExt: type ScalarExt: FieldExt; /// The base field over which this elliptic curve is constructed. type Base: FieldExt; + /// The affine version of the curve + type AffineExt: CurveAffine::ScalarExt> + + Mul + + for<'r> Mul; + + /// CURVE_ID used for hash-to-curve. + const CURVE_ID: &'static str; /// Apply the curve endomorphism by multiplying the x-coordinate /// by an element of multiplicative order 3. @@ -75,8 +82,10 @@ pub trait CurveExt: /// This trait is the affine counterpart to `Curve` and is used for /// serialization, storage in memory, and inspection of $x$ and $y$ coordinates. pub trait CurveAffine: - PrimeCurveAffine::ScalarExt> - + Default + PrimeCurveAffine< + Scalar = ::ScalarExt, + Curve = ::CurveExt, + > + Default + Add::Curve> + Sub::Curve> + ConditionallySelectable @@ -87,13 +96,8 @@ pub trait CurveAffine: type ScalarExt: FieldExt; /// The base field over which this elliptic curve is constructed. type Base: FieldExt; - - /// Personalization of BLAKE2b hasher used to generate the uniform - /// random string. - const BLAKE2B_PERSONALIZATION: &'static [u8; 16]; - - /// CURVE_ID used for hash-to-curve. - const CURVE_ID: &'static str; + /// The projective form of the curve + type CurveExt: CurveExt::ScalarExt>; /// Gets the $(x, y)$ coordinates of this point. fn get_xy(&self) -> CtOption<(Self::Base, Self::Base)>; diff --git a/src/pasta/curves.rs b/src/pasta/curves.rs index 552944e..006d693 100644 --- a/src/pasta/curves.rs +++ b/src/pasta/curves.rs @@ -17,7 +17,7 @@ use super::{Fp, Fq}; use crate::arithmetic::{CurveAffine, CurveExt, FieldExt, Group}; macro_rules! new_curve_impl { - (($($privacy:tt)*), $name:ident, $name_affine:ident, $iso:ident, $base:ident, $scalar:ident, $blake2b_personalization:literal, + (($($privacy:tt)*), $name:ident, $name_affine:ident, $iso:ident, $base:ident, $scalar:ident, $curve_id:literal, $a_raw:expr, $b_raw:expr, $curve_type:ident) => { /// Represents a point in the projective coordinate space. #[derive(Copy, Clone, Debug)] @@ -90,8 +90,11 @@ macro_rules! new_curve_impl { impl CurveExt for $name { type ScalarExt = $scalar; type Base = $base; + type AffineExt = $name_affine; - impl_projective_curve_ext!($name, $name_affine, $iso, $base, $curve_type); + const CURVE_ID: &'static str = $curve_id; + + impl_projective_curve_ext!($name, $iso, $base, $curve_type); fn a() -> Self::Base { $name::curve_constant_a() @@ -612,9 +615,7 @@ macro_rules! new_curve_impl { impl CurveAffine for $name_affine { type ScalarExt = $scalar; type Base = $base; - - const BLAKE2B_PERSONALIZATION: &'static [u8; 16] = $blake2b_personalization; - const CURVE_ID: &'static str = $curve_id; + type CurveExt = $name; fn is_on_curve(&self) -> Choice { // y^2 - x^3 - ax ?= b @@ -833,13 +834,13 @@ macro_rules! impl_projective_curve_specific { } macro_rules! impl_projective_curve_ext { - ($name:ident, $name_affine:ident, $iso:ident, $base:ident, special_a0_b5) => { + ($name:ident, $iso:ident, $base:ident, special_a0_b5) => { fn hash_to_curve<'a>(domain_prefix: &'a str) -> Box Self + 'a> { use super::hashtocurve; Box::new(move |message| { let mut us = [Field::zero(); 2]; - hashtocurve::hash_to_field($name_affine::CURVE_ID, domain_prefix, message, &mut us); + hashtocurve::hash_to_field($name::CURVE_ID, domain_prefix, message, &mut us); let q0 = hashtocurve::map_to_curve_simple_swu::<$base, $name, $iso>( &us[0], $name::THETA, @@ -866,7 +867,7 @@ macro_rules! impl_projective_curve_ext { } } }; - ($name:ident, $name_affine:ident, $iso:ident, $base:ident, general) => { + ($name:ident, $iso:ident, $base:ident, general) => { /// Unimplemented: hashing to this curve is not supported fn hash_to_curve<'a>(_domain_prefix: &'a str) -> Box Self + 'a> { unimplemented!() @@ -909,7 +910,6 @@ new_curve_impl!( IsoEp, Fp, Fq, - b"halo2_____pallas", "pallas", [0, 0, 0, 0], [5, 0, 0, 0], @@ -922,7 +922,6 @@ new_curve_impl!( IsoEq, Fq, Fp, - b"halo2______vesta", "vesta", [0, 0, 0, 0], [5, 0, 0, 0], @@ -935,7 +934,6 @@ new_curve_impl!( Ep, Fp, Fq, - b"halo2_iso_pallas", "iso-pallas", [ 0x92bb4b0b657a014b, @@ -953,7 +951,6 @@ new_curve_impl!( Eq, Fq, Fp, - b"halo2__iso_vesta", "iso-vesta", [ 0xc515ad7242eaa6b1, diff --git a/src/plonk.rs b/src/plonk.rs index 95719c4..0a7e1a6 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -946,28 +946,28 @@ fn test_proving() { ], }, fixed_commitments: [ - (0x3710f15f98bf0a7421343fdf390b9519506c67431a5c78678fbcc4db815c8547, 0x0a3c77f30ab2a2741b21cd45326c87dc7f7050b1a5e8c181a534b9c84a09cb02), - (0x115235d6bd2467772db857d66e7f44837cd38bb6ac0c7b412c2997dd47cbbc3c, 0x0f339c20c40e10bed476699e2ddb88256092447582b250f329b0cbf6c3f66f17), - (0x2a9ba245dcce53752e1de999b45c975472bb33b58aed8bcebdfcd185627895f0, 0x1252bf596b7acd19625f68845749f6672b99e71238cfabe91ca545103168d0f0), - (0x2a9ba245dcce53752e1de999b45c975472bb33b58aed8bcebdfcd185627895f0, 0x1252bf596b7acd19625f68845749f6672b99e71238cfabe91ca545103168d0f0), - (0x241d6d9c2060ce821d4b05ff2f9566c3947541f3d14a9aabcdb96c19158e8bc7, 0x39582cc6bdb1a4a88e89c050ad6db0ade34f45ec5791b07de6e694e9627ca66a), - (0x1ee805e20232ba31eeae1fa345bd88ac7df81dc43ffb3967a218ea4defc9d17d, 0x2838c83c064d44e87e5c8d05a234ad24d2d4a502a370acb514b430f516c0f0bf), - (0x37ead9904c760201ec4734ef398f0bdb5fe5a5e6e9db19c85e6b5483bdeb0a0b, 0x1dc08c38ed713b14f7a21a891a83b52160a3ffb0dccfbd70db7c7eb235dd193e), - (0x2dc3d20553691216c988ecbb596c4bda329f27d50bd8a7c2fb0d84b423da3cb4, 0x025b40e800020458e15e3a57268562e6c08c6971d71262bd67c72437cfc60b4c), + (0x046711bb0579a337420e33de9d54438e7c3a9cc47b6728b873d1fd0214d7eb58, 0x2416b30fadfacd828cf76891a2a5f0fe90d7ae0e5a8df947e98660ffbebf72e4), + (0x241db4dcb35d3977d45a57a9c5053e8f2c2310fa98738feb48430254034e42bc, 0x3e9545f6b9aa955ce50450eb1b37fb69d5891bca9b5193e6e8288675abded312), + (0x15a0f4deb421ccdfb7cebd60fe7055d406e8f24e9bf37d304327b2adb53e2f7a, 0x1811c4a5f95dc72b15e780bb76d5d0e91dc315c0726a361712bdcb7afd11dc6c), + (0x15a0f4deb421ccdfb7cebd60fe7055d406e8f24e9bf37d304327b2adb53e2f7a, 0x1811c4a5f95dc72b15e780bb76d5d0e91dc315c0726a361712bdcb7afd11dc6c), + (0x2c1e1e702ea5a876188a2e2d1f7fcbee31e5fba48ccd1d7d8dc000393da5b6cb, 0x302338ba3f31351e080311442a59fc9fd9cc30700ce33f4775741d6888df63ea), + (0x3e6b7c66782b06e0e7cd5bd7930b0204dee22b44a25d7c405909d4ca4eb604a7, 0x19b69444de257eb1dd99020a8c615fdc6bed7308ea63b1d4b3c0430f15e71568), + (0x05dfc2fbe7800a57610e7b61e4cd7e96f96026cc192a92750e50e9c35c2d262d, 0x3b2c6101d9a2bbf8982f84e2bd818952ea1d53c5a815c7a4d900cc27f67da390), + (0x318668190ba5ac1d3a1f93b13dd611e4dd3d68b1ea2ae1fe15b99bfc0858cc94, 0x18edacbf7ad8d4b3e43d9cab81c696cb3671ac3a9007610a5c949d85f9790841), ], permutations: [ VerifyingKey { commitments: [ - (0x289f468bca3471a3d240169ec65047d0c4bb5e1135e81822523c74b596139fed, 0x1a585c821c71fb49c883859f1389bcae45f17593ddb5f9fee1781b27129e1b06), - (0x096ef96a7725c636e7ca645dfe539694cf2a988da1ca50a468320f419d008054, 0x1ac0b48a254f8e2311081f81aa4a8ff39e37e40aa4c003325f1ac1219d231818), - (0x254c9f0088599aba37607cfd1700c653ef3ec21bfd60b98c3d725678540bc4df, 0x134d9818929589052f3cd80d50140b851db26231b2b784a6b2528a64805598dc), + (0x02d8dce08483e705f124b2e3db76a8065bfd8d893a1de76fd4ba586acb8e2cd0, 0x1456b7e28d96b5f90f885d21fde2ed00d1774cdebc358a95383b95302a87e09d), + (0x1d8a9751a63cbdf4c87787424b9c4a347483d5138943470dd1a73e1d1fd336b1, 0x2b1f6a54bff445799b6abf5bb0ed734d1cabdb46b4966556e753097ed87cef1b), + (0x1592b59a2a90b155420abde2bcf6fb822d80a11e1b44306dc07fc45025f214e5, 0x3802666ef284d7db51cbd2f9be20014e19f0f6a22e1a4d3a0db124b7bdd7fa1b), ], }, VerifyingKey { commitments: [ - (0x289f468bca3471a3d240169ec65047d0c4bb5e1135e81822523c74b596139fed, 0x1a585c821c71fb49c883859f1389bcae45f17593ddb5f9fee1781b27129e1b06), - (0x096ef96a7725c636e7ca645dfe539694cf2a988da1ca50a468320f419d008054, 0x1ac0b48a254f8e2311081f81aa4a8ff39e37e40aa4c003325f1ac1219d231818), - (0x254c9f0088599aba37607cfd1700c653ef3ec21bfd60b98c3d725678540bc4df, 0x134d9818929589052f3cd80d50140b851db26231b2b784a6b2528a64805598dc), + (0x02d8dce08483e705f124b2e3db76a8065bfd8d893a1de76fd4ba586acb8e2cd0, 0x1456b7e28d96b5f90f885d21fde2ed00d1774cdebc358a95383b95302a87e09d), + (0x1d8a9751a63cbdf4c87787424b9c4a347483d5138943470dd1a73e1d1fd336b1, 0x2b1f6a54bff445799b6abf5bb0ed734d1cabdb46b4966556e753097ed87cef1b), + (0x1592b59a2a90b155420abde2bcf6fb822d80a11e1b44306dc07fc45025f214e5, 0x3802666ef284d7db51cbd2f9be20014e19f0f6a22e1a4d3a0db124b7bdd7fa1b), ], }, ], diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index 7ed1ac3..a4b8ef1 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -3,13 +3,13 @@ //! //! [halo]: https://eprint.iacr.org/2019/1021 -use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; - use super::{Coeff, LagrangeCoeff, Polynomial}; -use crate::arithmetic::{best_fft, best_multiexp, parallelize, CurveAffine, FieldExt, Group}; +use crate::arithmetic::{ + best_fft, best_multiexp, parallelize, CurveAffine, CurveExt, FieldExt, Group, +}; use ff::{Field, PrimeField}; -use group::{prime::PrimeCurveAffine, Curve}; +use group::{prime::PrimeCurveAffine, Curve, Group as _}; use std::ops::{Add, AddAssign, Mul, MulAssign}; mod msm; @@ -36,10 +36,7 @@ pub struct Params { impl Params { /// Initializes parameters for the curve, given a random oracle to draw /// points from. - pub fn new(k: u32) -> Self - where - ::Curve: Group, - { + pub fn new(k: u32) -> Self { // This is usually a limitation on the curve, but we also want 32-bit // architectures to be supported. assert!(k < 32); @@ -48,51 +45,41 @@ impl Params { let n: u64 = 1 << k; - let try_and_increment = |hasher: &Blake2bState| { - let mut trial = 0u64; - loop { - let mut hasher = hasher.clone(); - hasher.update(&(trial.to_le_bytes())[..]); - let mut repr = C::Repr::default(); - repr.as_mut().copy_from_slice(hasher.finalize().as_bytes()); - let p = C::from_bytes(&repr); - if bool::from(p.is_some()) { - break p.unwrap(); - } - trial += 1; - } - }; - - let g = { + let g_projective = { let mut g = Vec::with_capacity(n as usize); - g.resize(n as usize, C::identity()); + g.resize(n as usize, C::Curve::identity()); parallelize(&mut g, move |g, start| { - let mut hasher = Blake2bParams::new() - .hash_length(32) - .personal(C::BLAKE2B_PERSONALIZATION) - .to_state(); - hasher.update(b"G vector"); + let hasher = C::CurveExt::hash_to_curve("Halo2-Parameters"); for (i, g) in g.iter_mut().enumerate() { - let i = (i + start) as u64; - let mut hasher = hasher.clone(); - hasher.update(&(i.to_le_bytes())[..]); + let i = (i + start) as u32; - *g = try_and_increment(&hasher); + let mut message = [0u8; 5]; + message[1..5].copy_from_slice(&i.to_le_bytes()); + + *g = hasher(&message); } }); g }; + let g = { + let mut g = vec![C::identity(); n as usize]; + parallelize(&mut g, |g, starts| { + C::Curve::batch_normalize(&g_projective[starts..(starts + g.len())], g); + }); + g + }; + // Let's evaluate all of the Lagrange basis polynomials // using an inverse FFT. let mut alpha_inv = <::Curve as Group>::Scalar::ROOT_OF_UNITY_INV; for _ in k..C::Scalar::S { alpha_inv = alpha_inv.square(); } - let mut g_lagrange_projective = g.iter().map(|g| g.to_curve()).collect::>(); + let mut g_lagrange_projective = g_projective; best_fft(&mut g_lagrange_projective, alpha_inv, k); let minv = C::Scalar::TWO_INV.pow_vartime(&[k as u64, 0, 0, 0]); parallelize(&mut g_lagrange_projective, |g, _| { @@ -113,25 +100,9 @@ impl Params { g_lagrange }; - let h = { - let mut hasher = Blake2bParams::new() - .hash_length(32) - .personal(C::BLAKE2B_PERSONALIZATION) - .to_state(); - hasher.update(b"H"); - - try_and_increment(&hasher) - }; - - let u = { - let mut hasher = Blake2bParams::new() - .hash_length(32) - .personal(C::BLAKE2B_PERSONALIZATION) - .to_state(); - hasher.update(b"U"); - - try_and_increment(&hasher) - }; + let hasher = C::CurveExt::hash_to_curve("Halo2-Parameters"); + let h = hasher(&[1]).to_affine(); + let u = hasher(&[2]).to_affine(); Params { k, diff --git a/src/transcript.rs b/src/transcript.rs index c3da9a9..2931e7f 100644 --- a/src/transcript.rs +++ b/src/transcript.rs @@ -59,7 +59,7 @@ impl Blake2bRead { Blake2bRead { state: Blake2bParams::new() .hash_length(64) - .personal(C::BLAKE2B_PERSONALIZATION) + .personal(b"Halo2-Transcript") .to_state(), reader, _marker: PhantomData, @@ -136,7 +136,7 @@ impl Blake2bWrite { Blake2bWrite { state: Blake2bParams::new() .hash_length(64) - .personal(C::BLAKE2B_PERSONALIZATION) + .personal(b"Halo2-Transcript") .to_state(), writer, _marker: PhantomData,