From 2c3c3cefdc19ec73052d6b7d4d2fa53946981035 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Fri, 20 Aug 2021 17:39:55 +0800 Subject: [PATCH] Move primitives::sinsemilla::i2lebsp_k into constants::sinsemilla. --- src/constants/sinsemilla.rs | 55 +++++++++++++++++++++++++++++++ src/primitives/sinsemilla.rs | 63 ++++++++---------------------------- src/tree.rs | 4 +-- 3 files changed, 71 insertions(+), 51 deletions(-) diff --git a/src/constants/sinsemilla.rs b/src/constants/sinsemilla.rs index a1a92f25..dd7b2d7c 100644 --- a/src/constants/sinsemilla.rs +++ b/src/constants/sinsemilla.rs @@ -1,6 +1,7 @@ //! Sinsemilla generators use super::OrchardFixedBases; use crate::circuit::gadget::sinsemilla::{CommitDomains, HashDomains}; +use crate::spec::i2lebsp; use pasta_curves::{ arithmetic::{CurveAffine, FieldExt}, @@ -72,6 +73,20 @@ pub const Q_MERKLE_CRH: ([u8; 32], [u8; 32]) = ( ], ); +pub(crate) fn lebs2ip_k(bits: &[bool]) -> u32 { + assert!(bits.len() == K); + bits.iter() + .enumerate() + .fold(0u32, |acc, (i, b)| acc + if *b { 1 << i } else { 0 }) +} + +/// The sequence of K bits in little-endian order representing an integer +/// up to `2^K` - 1. +pub(crate) fn i2lebsp_k(int: usize) -> [bool; K] { + assert!(int < (1 << K)); + i2lebsp(int as u64) +} + #[derive(Clone, Debug, Eq, PartialEq)] pub enum OrchardHashDomains { NoteCommit, @@ -139,6 +154,7 @@ mod tests { arithmetic::{CurveAffine, FieldExt}, pallas, }; + use rand::{self, rngs::OsRng, Rng}; #[test] // Nodes in the Merkle tree are Pallas base field elements. @@ -146,6 +162,45 @@ mod tests { assert_eq!(super::L_ORCHARD_MERKLE, pallas::Base::NUM_BITS as usize); } + #[test] + fn lebs2ip_k_round_trip() { + let mut rng = OsRng; + { + let int = rng.gen_range(0..(1 << K)); + assert_eq!(lebs2ip_k(&i2lebsp_k(int)) as usize, int); + } + + assert_eq!(lebs2ip_k(&i2lebsp_k(0)) as usize, 0); + assert_eq!(lebs2ip_k(&i2lebsp_k((1 << K) - 1)) as usize, (1 << K) - 1); + } + + #[test] + fn i2lebsp_k_round_trip() { + { + let bitstring = (0..K).map(|_| rand::random()).collect::>(); + assert_eq!( + i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(), + bitstring + ); + } + + { + let bitstring = [false; K]; + assert_eq!( + i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(), + bitstring + ); + } + + { + let bitstring = [true; K]; + assert_eq!( + i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(), + bitstring + ); + } + } + #[test] fn q_note_commitment_m() { let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index 75189fea..f6776b92 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -1,12 +1,10 @@ //! The Sinsemilla hash function and commitment scheme. -use group::Wnaf; +use group::{Curve, Wnaf}; use halo2::arithmetic::{CurveAffine, CurveExt}; use pasta_curves::pallas; use subtle::CtOption; -use crate::spec::{extract_p_bottom, i2lebsp}; - mod addition; use self::addition::IncompletePoint; mod sinsemilla_s; @@ -42,11 +40,18 @@ pub(crate) fn lebs2ip_k(bits: &[bool]) -> u32 { .fold(0u32, |acc, (i, b)| acc + if *b { 1 << i } else { 0 }) } -/// The sequence of K bits in little-endian order representing an integer -/// up to `2^K` - 1. -pub(crate) fn i2lebsp_k(int: usize) -> [bool; K] { - assert!(int < (1 << K)); - i2lebsp(int as u64) +/// Coordinate extractor for Pallas. +/// +/// Defined in [Zcash Protocol Spec ยง 5.4.9.7: Coordinate Extractor for Pallas][concreteextractorpallas]. +/// +/// [concreteextractorpallas]: https://zips.z.cash/protocol/nu5.pdf#concreteextractorpallas +fn extract_p_bottom(point: CtOption) -> CtOption { + point.map(|p| { + p.to_affine() + .coordinates() + .map(|c| *c.x()) + .unwrap_or_else(pallas::Base::zero) + }) } /// Pads the given iterator (which MUST have length $\leq K * C$) with zero-bits to a @@ -227,9 +232,8 @@ impl CommitDomain { #[cfg(test)] mod tests { - use super::{i2lebsp_k, lebs2ip_k, Pad, K}; + use super::{Pad, K}; use pasta_curves::{arithmetic::CurveExt, pallas}; - use rand::{self, rngs::OsRng, Rng}; #[test] fn pad() { @@ -269,45 +273,6 @@ mod tests { ); } - #[test] - fn lebs2ip_k_round_trip() { - let mut rng = OsRng; - { - let int = rng.gen_range(0..(1 << K)); - assert_eq!(lebs2ip_k(&i2lebsp_k(int)) as usize, int); - } - - assert_eq!(lebs2ip_k(&i2lebsp_k(0)) as usize, 0); - assert_eq!(lebs2ip_k(&i2lebsp_k((1 << K) - 1)) as usize, (1 << K) - 1); - } - - #[test] - fn i2lebsp_k_round_trip() { - { - let bitstring = (0..K).map(|_| rand::random()).collect::>(); - assert_eq!( - i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(), - bitstring - ); - } - - { - let bitstring = [false; K]; - assert_eq!( - i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(), - bitstring - ); - } - - { - let bitstring = [true; K]; - assert_eq!( - i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(), - bitstring - ); - } - } - #[test] fn sinsemilla_s() { use super::sinsemilla_s::SINSEMILLA_S; diff --git a/src/tree.rs b/src/tree.rs index dc5b0595..d04262db 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -2,12 +2,12 @@ use crate::{ constants::{ - sinsemilla::{L_ORCHARD_MERKLE, MERKLE_CRH_PERSONALIZATION}, + sinsemilla::{i2lebsp_k, L_ORCHARD_MERKLE, MERKLE_CRH_PERSONALIZATION}, util::gen_const_array_with_default, MERKLE_DEPTH_ORCHARD, }, note::commitment::ExtractedNoteCommitment, - primitives::sinsemilla::{i2lebsp_k, HashDomain}, + primitives::sinsemilla::HashDomain, }; use incrementalmerkletree::{Altitude, Hashable}; use pasta_curves::{arithmetic::FieldExt, pallas};