diff --git a/src/circuit/gadget/sinsemilla/merkle.rs b/src/circuit/gadget/sinsemilla/merkle.rs index d52d29dd..e9c1a57c 100644 --- a/src/circuit/gadget/sinsemilla/merkle.rs +++ b/src/circuit/gadget/sinsemilla/merkle.rs @@ -4,14 +4,12 @@ use halo2::{ }; use pasta_curves::arithmetic::CurveAffine; -use crate::{ - circuit::gadget::{ - sinsemilla::{HashDomains, SinsemillaInstructions}, - utilities::{ - cond_swap::CondSwapInstructions, transpose_option_array, UtilitiesInstructions, - }, +use crate::circuit::gadget::{ + sinsemilla::{HashDomains, SinsemillaInstructions}, + utilities::{ + cond_swap::CondSwapInstructions, gen_const_array, transpose_option_array, + UtilitiesInstructions, }, - spec::i2lebsp, }; use std::iter; @@ -27,6 +25,17 @@ pub(crate) const MERKLE_DEPTH_ORCHARD: usize = 32; /// Number of bits in a Pallas base field element. pub(crate) const L_ORCHARD_BASE: usize = 255; +/// The sequence of bits representing a u64 in little-endian order. +/// +/// # Panics +/// +/// Panics if the expected length of the sequence `NUM_BITS` exceeds +/// 64. +fn i2lebsp(int: u64) -> [bool; NUM_BITS] { + assert!(NUM_BITS <= 64); + gen_const_array(|mask: usize| (int & (1 << mask)) != 0) +} + /// Instructions to check the validity of a Merkle path of a given `PATH_LENGTH`. /// The hash function used is a Sinsemilla instance with `K`-bit words. /// The hash function can process `MAX_WORDS` words. diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index 79fe8124..11cc0590 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -165,6 +165,18 @@ pub fn decompose_word( .collect() } +/// Takes in an FnMut closure and returns a constant-length array with elements of +/// type `Output`. +pub fn gen_const_array( + mut closure: impl FnMut(usize) -> Output, +) -> [Output; LEN] { + let mut ret: [Output; LEN] = [Default::default(); LEN]; + for (bit, val) in ret.iter_mut().zip((0..LEN).map(|idx| closure(idx))) { + *bit = val; + } + ret +} + #[cfg(test)] mod tests { use super::*;