From 10a9aa5844598baeb33e422c8bf933346376769e Mon Sep 17 00:00:00 2001 From: Deirdre Connolly Date: Tue, 28 Jul 2020 02:31:07 -0400 Subject: [PATCH] Add prf_nf and use in From impl to derive Sapling Nullifier --- zebra-chain/src/notes/sapling/nullifiers.rs | 33 ++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/zebra-chain/src/notes/sapling/nullifiers.rs b/zebra-chain/src/notes/sapling/nullifiers.rs index 0e466c03..2c275246 100644 --- a/zebra-chain/src/notes/sapling/nullifiers.rs +++ b/zebra-chain/src/notes/sapling/nullifiers.rs @@ -3,7 +3,30 @@ use std::io; -use crate::serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize}; +use crate::{ + commitments::sapling::{mixing_pedersen_hash, NoteCommitment}, + keys::sapling::NullifierDerivingKey, + serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize}, + treestate::note_commitment_tree::Position, +}; + +/// Invokes Blake2s-256 as PRF^nfSapling to derive the nullifier for a +/// Sapling note. +/// +/// PRF^nfSapling(ρ*) := BLAKE2s-256("Zcash_nf", nk* || ρ*) +/// +/// https://zips.z.cash/protocol/protocol.pdf#concreteprfs +fn prf_nf(nk: [u8; 32], rho: [u8; 32]) -> [u8; 32] { + let hash = blake2s_simd::Params::new() + .hash_length(32) + .personal(b"Zcash_nf") + .to_state() + .update(&nk[..]) + .update(&rho[..]) + .finalize(); + + *hash.as_array() +} /// A Nullifier for Sapling transactions #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] @@ -16,6 +39,14 @@ impl From<[u8; 32]> for Nullifier { } } +impl From<(NoteCommitment, Position, NullifierDerivingKey)> for Nullifier { + fn from((cm, pos, nk): (NoteCommitment, Position, NullifierDerivingKey)) -> Self { + let rho = jubjub::AffinePoint::from(mixing_pedersen_hash(cm.0.into(), pos.0.into())); + + Nullifier(prf_nf(nk.into(), rho.to_bytes())) + } +} + impl ZcashDeserialize for Nullifier { fn zcash_deserialize(mut reader: R) -> Result { let bytes = reader.read_32_bytes()?;