primitives::sinsemilla: Use hard-coded generators in sinsemilla_s.

This commit is contained in:
therealyingtong 2021-08-12 15:40:39 +08:00
parent 506b6a6dcd
commit 995728caa6
4 changed files with 22 additions and 64 deletions

View File

@ -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;

View File

@ -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())
}

View File

@ -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<Vec<pallas::Base>> =
@ -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<Vec<pallas::Point>> = words
.clone()
.map(|words| words.iter().map(|word| get_s_by_idx(*word)).collect());
let generators: Option<Vec<(pallas::Base, pallas::Base)>> =
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<Vec<(pallas::Base, pallas::Base)>> = words.clone().map(|words| {
words
.iter()
.map(|word| SINSEMILLA_S[*word as usize])
.collect()
});
// Convert `words` from `Option<Vec<u32>>` to `Vec<Option<u32>>`
let words: Vec<Option<u32>> = if let Some(words) = words {

View File

@ -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<Item = bool>) -> 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
})
}