From 1ac3541505357bef2531ad44d6d331b3e53d8aaa Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Sat, 5 Jun 2021 00:51:01 +0800 Subject: [PATCH] Add spec::i2lebsp and constants::MERKLE_DEPTH_ORCHARD --- src/primitives/sinsemilla.rs | 5 ++-- src/spec.rs | 58 +++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index 0922f17c..a2d6bc34 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -4,8 +4,7 @@ use halo2::arithmetic::CurveExt; use pasta_curves::pallas; use subtle::CtOption; -use crate::constants::util::gen_const_array; -use crate::spec::extract_p_bottom; +use crate::spec::{extract_p_bottom, i2lebsp}; mod addition; use self::addition::IncompletePoint; @@ -25,7 +24,7 @@ pub(crate) fn lebs2ip_k(bits: &[bool]) -> u32 { /// up to `2^K` - 1. pub fn i2lebsp_k(int: usize) -> [bool; K] { assert!(int < (1 << K)); - gen_const_array(|mask: usize| (int & (1 << mask)) != 0) + i2lebsp(int as u64) } /// Pads the given iterator (which MUST have length $\leq K * C$) with zero-bits to a diff --git a/src/spec.rs b/src/spec.rs index 34f8a5dd..44e19c48 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -11,7 +11,7 @@ use pasta_curves::pallas; use subtle::{ConditionallySelectable, CtOption}; use crate::{ - constants::L_ORCHARD_BASE, + constants::{util::gen_const_array, L_ORCHARD_BASE}, primitives::{poseidon, sinsemilla}, }; @@ -252,11 +252,26 @@ pub fn lebs2ip(bits: &[bool; L]) -> u64 { .fold(0u64, |acc, (i, b)| acc + if *b { 1 << i } else { 0 }) } +/// The sequence of bits representing a u64 in little-endian order. +/// +/// # Panics +/// +/// Panics if the expected length of the sequence `NUM_BITS` exceeds +/// 64. +pub fn i2lebsp(int: u64) -> [bool; NUM_BITS] { + assert!(NUM_BITS <= 64); + gen_const_array(|mask: usize| (int & (1 << mask)) != 0) +} + #[cfg(test)] mod tests { + use super::{i2lebsp, lebs2ip}; + use group::Group; use halo2::arithmetic::CurveExt; use pasta_curves::pallas; + use rand::{rngs::OsRng, RngCore}; + use std::convert::TryInto; #[test] fn diversify_hash_substitution() { @@ -264,4 +279,45 @@ mod tests { pallas::Point::hash_to_curve("z.cash:Orchard-gd")(&[]).is_identity() )); } + + #[test] + fn lebs2ip_round_trip() { + let mut rng = OsRng; + { + let int = rng.next_u64(); + assert_eq!(lebs2ip::<64>(&i2lebsp(int)), int); + } + + assert_eq!(lebs2ip::<64>(&i2lebsp(0)), 0); + assert_eq!( + lebs2ip::<64>(&i2lebsp(0xFFFFFFFFFFFFFFFF)), + 0xFFFFFFFFFFFFFFFF + ); + } + + #[test] + fn i2lebsp_round_trip() { + { + let bitstring = (0..64).map(|_| rand::random()).collect::>(); + assert_eq!( + i2lebsp::<64>(lebs2ip::<64>(&bitstring.clone().try_into().unwrap())).to_vec(), + bitstring + ); + } + + { + let bitstring = [false; 64]; + assert_eq!(i2lebsp(lebs2ip(&bitstring)), bitstring); + } + + { + let bitstring = [true; 64]; + assert_eq!(i2lebsp(lebs2ip(&bitstring)), bitstring); + } + + { + let bitstring = []; + assert_eq!(i2lebsp(lebs2ip(&bitstring)), bitstring); + } + } }