From 995728caa653b65b97ef2531608c3bcb247864ff Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Thu, 12 Aug 2021 15:40:39 +0800 Subject: [PATCH] primitives::sinsemilla: Use hard-coded generators in sinsemilla_s. --- src/circuit/gadget/sinsemilla/chip.rs | 1 - .../gadget/sinsemilla/chip/generator_table.rs | 45 +++---------------- .../gadget/sinsemilla/chip/hash_to_point.rs | 30 +++++-------- src/primitives/sinsemilla.rs | 10 ++--- 4 files changed, 22 insertions(+), 64 deletions(-) diff --git a/src/circuit/gadget/sinsemilla/chip.rs b/src/circuit/gadget/sinsemilla/chip.rs index a665e1f9..9264fdcc 100644 --- a/src/circuit/gadget/sinsemilla/chip.rs +++ b/src/circuit/gadget/sinsemilla/chip.rs @@ -25,7 +25,6 @@ use halo2::{ use pasta_curves::pallas; mod generator_table; -pub use generator_table::get_s_by_idx; use generator_table::GeneratorTableConfig; mod hash_to_point; diff --git a/src/circuit/gadget/sinsemilla/chip/generator_table.rs b/src/circuit/gadget/sinsemilla/chip/generator_table.rs index 0861dd1e..5c0624ac 100644 --- a/src/circuit/gadget/sinsemilla/chip/generator_table.rs +++ b/src/circuit/gadget/sinsemilla/chip/generator_table.rs @@ -1,16 +1,11 @@ -use crate::primitives::sinsemilla::{self, sinsemilla_s_generators, S_PERSONALIZATION}; +use crate::primitives::sinsemilla::{self, SINSEMILLA_S}; use halo2::{ circuit::Layouter, plonk::{ConstraintSystem, Error, Expression, TableColumn}, poly::Rotation, }; -use pasta_curves::{ - arithmetic::{CurveAffine, CurveExt, FieldExt}, - pallas, -}; - -use group::Curve; +use pasta_curves::{arithmetic::FieldExt, pallas}; /// Table containing independent generators S[0..2^k] #[derive(Eq, PartialEq, Copy, Clone, Debug)] @@ -69,10 +64,7 @@ impl GeneratorTableConfig { // Lookup expressions default to the first entry when `q_s1` // is not enabled. - let (init_x, init_y) = { - let init_p = get_s_by_idx(0).to_affine().coordinates().unwrap(); - (*init_p.x(), *init_p.y()) - }; + let (init_x, init_y) = SINSEMILLA_S[0]; let not_q_s1 = Expression::Constant(pallas::Base::one()) - q_s1.clone(); let m = q_s1.clone() * word; // The first table index is 0. @@ -87,41 +79,18 @@ impl GeneratorTableConfig { layouter.assign_table( || "generator_table", |mut table| { - // We generate the row values lazily (we only need them during keygen). - let mut rows = sinsemilla_s_generators(); - - for index in 0..(1 << sinsemilla::K) { - let mut row = None; + for (index, (x, y)) in SINSEMILLA_S.iter().enumerate() { table.assign_cell( || "table_idx", self.table_idx, index, - || { - row = rows.next(); - Ok(pallas::Base::from_u64(index as u64)) - }, - )?; - table.assign_cell( - || "table_x", - self.table_x, - index, - || row.map(|(x, _)| x).ok_or(Error::SynthesisError), - )?; - table.assign_cell( - || "table_y", - self.table_y, - index, - || row.map(|(_, y)| y).ok_or(Error::SynthesisError), + || Ok(pallas::Base::from_u64(index as u64)), )?; + table.assign_cell(|| "table_x", self.table_x, index, || Ok(*x))?; + table.assign_cell(|| "table_y", self.table_y, index, || Ok(*y))?; } Ok(()) }, ) } } - -/// Get generator S by index -pub fn get_s_by_idx(idx: u32) -> pallas::Point { - let hash = pallas::Point::hash_to_curve(S_PERSONALIZATION); - hash(&idx.to_le_bytes()) -} diff --git a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs index e36b87a1..d32d883f 100644 --- a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs +++ b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs @@ -1,13 +1,12 @@ use super::super::SinsemillaInstructions; -use super::{get_s_by_idx, CellValue, EccPoint, SinsemillaChip, Var}; -use crate::primitives::sinsemilla::{self, lebs2ip_k, INV_TWO_POW_K}; +use super::{CellValue, EccPoint, SinsemillaChip, Var}; +use crate::primitives::sinsemilla::{self, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}; use halo2::{ circuit::{Chip, Region}, plonk::Error, }; use ff::{Field, PrimeFieldBits}; -use group::Curve; use pasta_curves::{ arithmetic::{CurveAffine, FieldExt}, pallas, @@ -112,7 +111,7 @@ impl SinsemillaChip { { use crate::circuit::gadget::sinsemilla::message::MessagePiece; use crate::primitives::sinsemilla::{K, S_PERSONALIZATION}; - use group::prime::PrimeCurveAffine; + use group::{prime::PrimeCurveAffine, Curve}; use pasta_curves::arithmetic::CurveExt; let field_elems: Option> = @@ -235,22 +234,13 @@ impl SinsemillaChip { .collect() }); - // Get (x_p, y_p) for each word. We precompute this here so that we can use `batch_normalize()`. - let generators_projective: Option> = words - .clone() - .map(|words| words.iter().map(|word| get_s_by_idx(*word)).collect()); - let generators: Option> = - generators_projective.map(|generators_projective| { - let mut generators = vec![pallas::Affine::default(); generators_projective.len()]; - pallas::Point::batch_normalize(&generators_projective, &mut generators); - generators - .iter() - .map(|gen| { - let point = gen.coordinates().unwrap(); - (*point.x(), *point.y()) - }) - .collect() - }); + // Get (x_p, y_p) for each word. + let generators: Option> = words.clone().map(|words| { + words + .iter() + .map(|word| SINSEMILLA_S[*word as usize]) + .collect() + }); // Convert `words` from `Option>` to `Vec>` let words: Vec> = if let Some(words) = words { diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index a90c4fee..49c20ab8 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -1,6 +1,7 @@ //! The Sinsemilla hash function and commitment scheme. -use halo2::arithmetic::CurveExt; +use group::prime::PrimeCurveAffine; +use halo2::arithmetic::{CurveAffine, CurveExt}; use pasta_curves::pallas; use subtle::CtOption; @@ -12,6 +13,7 @@ use self::addition::IncompletePoint; mod constants; mod sinsemilla_s; pub use constants::*; +pub use sinsemilla_s::*; pub(crate) fn lebs2ip_k(bits: &[bool]) -> u32 { assert!(bits.len() == K); @@ -114,13 +116,11 @@ impl HashDomain { fn hash_to_point_inner(&self, msg: impl Iterator) -> IncompletePoint { let padded: Vec<_> = Pad::new(msg).collect(); - let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); - let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); - padded .chunks(K) .fold(IncompletePoint::from(self.Q), |acc, chunk| { - (acc + S(chunk)) + acc + let (S_x, S_y) = SINSEMILLA_S[lebs2ip_k(chunk) as usize]; + acc + pallas::Affine::from_xy(S_x, S_y).unwrap().to_curve() + acc }) }