Merge pull request #56 from zcash/more-poseidon-const-generics

Use const generics for poseidon::ConstantLength
This commit is contained in:
ebfull 2021-03-30 09:53:05 -06:00 committed by GitHub
commit 58a6aa3849
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 19 deletions

View File

@ -1,3 +1,4 @@
use std::array;
use std::iter;
use std::marker::PhantomData;
@ -250,15 +251,15 @@ pub trait Domain<F: FieldExt, S: Spec<F, T, RATE>, const T: usize, const RATE: u
///
/// Domain specified in section 4.2 of https://eprint.iacr.org/2019/458.pdf
#[derive(Clone, Copy, Debug)]
pub struct ConstantLength(pub usize);
pub struct ConstantLength<const L: usize>;
impl<F: FieldExt, S: Spec<F, T, RATE>, const T: usize, const RATE: usize> Domain<F, S, T, RATE>
for ConstantLength
impl<F: FieldExt, S: Spec<F, T, RATE>, const T: usize, const RATE: usize, const L: usize>
Domain<F, S, T, RATE> for ConstantLength<L>
{
fn initial_capacity_element(&self) -> F {
// Capacity value is $length \cdot 2^64 + (o-1)$ where o is the output length.
// We hard-code an output length of 1.
F::from_u128((self.0 as u128) << 64)
F::from_u128((L as u128) << 64)
}
fn pad_and_add(&self) -> Box<dyn Fn(&mut State<F, T>, &SpongeState<F, RATE>)> {
@ -309,21 +310,14 @@ impl<
}
}
impl<F: FieldExt, S: Spec<F, T, RATE>, const T: usize, const RATE: usize>
Hash<F, S, ConstantLength, T, RATE>
impl<F: FieldExt, S: Spec<F, T, RATE>, const T: usize, const RATE: usize, const L: usize>
Hash<F, S, ConstantLength<L>, T, RATE>
{
/// Hashes the given input.
///
/// # Panics
///
/// Panics if the message length is not the correct length.
pub fn hash(mut self, message: impl Iterator<Item = F>) -> F {
let mut length = 0;
for (i, value) in message.enumerate() {
length = i + 1;
pub fn hash(mut self, message: [F; L]) -> F {
for value in array::IntoIter::new(message) {
self.duplex.absorb(value);
}
assert_eq!(length, self.domain.0);
self.duplex.squeeze()
}
}
@ -341,8 +335,8 @@ mod tests {
let (round_constants, mds, _) = OrchardNullifier.constants();
let hasher = Hash::init(OrchardNullifier, ConstantLength(2));
let result = hasher.hash(message.iter().cloned());
let hasher = Hash::init(OrchardNullifier, ConstantLength);
let result = hasher.hash(message);
// The result should be equivalent to just directly applying the permutation and
// taking the first state element as the output.

View File

@ -104,8 +104,7 @@ pub(crate) fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> [u8; 64] {
///
/// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs
pub(crate) fn prf_nf(nk: pallas::Base, rho: pallas::Base) -> pallas::Base {
poseidon::Hash::init(poseidon::OrchardNullifier, poseidon::ConstantLength(2))
.hash(iter::empty().chain(Some(nk)).chain(Some(rho)))
poseidon::Hash::init(poseidon::OrchardNullifier, poseidon::ConstantLength).hash([nk, rho])
}
/// Defined in [Zcash Protocol Spec § 5.4.5.5: Orchard Key Agreement][concreteorchardkeyagreement].