Nullifier derivation

This commit is contained in:
Jack Grigg 2021-03-16 14:27:08 +13:00
parent 1a37ca492d
commit 0f6eb9ca6c
5 changed files with 62 additions and 10 deletions

View File

@ -14,8 +14,8 @@ use crate::{
address::Address,
primitives::redpallas::{self, SpendAuth},
spec::{
commit_ivk, diversify_hash, extract_p, ka_orchard, prf_expand, prf_expand_vec, to_base,
to_scalar,
commit_ivk, diversify_hash, extract_p, ka_orchard, prf_expand, prf_expand_vec, prf_nf,
to_base, to_scalar,
},
};
@ -102,6 +102,12 @@ impl From<&SpendingKey> for NullifierDerivingKey {
}
}
impl NullifierDerivingKey {
pub(crate) fn prf_nf(&self, rho: pallas::Base) -> pallas::Base {
prf_nf(self.0, rho)
}
}
/// The randomness for $\mathsf{Commit}^\mathsf{ivk}$.
///
/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
@ -142,6 +148,10 @@ impl From<&SpendingKey> for FullViewingKey {
}
impl FullViewingKey {
pub(crate) fn nk(&self) -> &NullifierDerivingKey {
&self.nk
}
/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
///
/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents

View File

@ -11,6 +11,9 @@ use crate::{
mod commitment;
pub use self::commitment::NoteCommitment;
mod nullifier;
pub use self::nullifier::Nullifier;
/// The ZIP 212 seed randomness for a note.
#[derive(Debug)]
struct RandomSeed([u8; 32]);
@ -69,15 +72,11 @@ impl Note {
}
/// Derives the nullifier for this note.
pub fn nullifier(&self, _: &FullViewingKey) -> Nullifier {
todo!()
pub fn nullifier(&self, fvk: &FullViewingKey) -> Nullifier {
Nullifier::derive(self.rho.0, self.rseed.psi(), self.commitment(), fvk.nk())
}
}
/// An encrypted note.
#[derive(Debug)]
pub struct EncryptedNote;
/// A unique nullifier for a note.
#[derive(Debug)]
pub struct Nullifier(pallas::Base);

View File

@ -23,7 +23,7 @@ impl From<&RandomSeed> for NoteCommitTrapdoor {
/// A commitment to a note.
#[derive(Debug)]
pub struct NoteCommitment(pallas::Point);
pub struct NoteCommitment(pub(super) pallas::Point);
impl NoteCommitment {
/// $NoteCommit^Orchard$.

30
src/note/nullifier.rs Normal file
View File

@ -0,0 +1,30 @@
use halo2::arithmetic::CurveExt;
use pasta_curves::pallas;
use super::NoteCommitment;
use crate::{
keys::NullifierDerivingKey,
spec::{extract_p, mod_r_p},
};
/// A unique nullifier for a note.
#[derive(Debug)]
pub struct Nullifier(pub(super) pallas::Base);
impl Nullifier {
/// $DeriveNullifier$.
///
/// Defined in [Zcash Protocol Spec § 4.16: Note Commitments and Nullifiers][commitmentsandnullifiers].
///
/// [commitmentsandnullifiers]: https://zips.z.cash/protocol/nu5.pdf#commitmentsandnullifiers
pub(super) fn derive(
rho: pallas::Base,
psi: pallas::Base,
cm: NoteCommitment,
nk: &NullifierDerivingKey,
) -> Self {
let k = pallas::Point::hash_to_curve("z.cash:Orchard")(b"K");
Nullifier(extract_p(&(k * mod_r_p(nk.prf_nf(rho) + psi) + cm.0)))
}
}

View File

@ -8,7 +8,10 @@ use group::{Curve, Group};
use halo2::arithmetic::{CurveAffine, CurveExt, FieldExt};
use pasta_curves::pallas;
use crate::{constants::L_ORCHARD_BASE, primitives::sinsemilla};
use crate::{
constants::L_ORCHARD_BASE,
primitives::{poseidon, sinsemilla},
};
const PRF_EXPAND_PERSONALIZATION: &[u8; 16] = b"Zcash_ExpandSeed";
@ -94,6 +97,16 @@ pub(crate) fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> [u8; 64] {
*h.finalize().as_array()
}
/// $PRF^\mathsf{nfOrchard}(nk, \rho) := Poseidon(nk, \rho)$
///
/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs].
///
/// [concreteprfs]: https://zips.z.cash/protocol/orchard.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)))
}
/// Defined in [Zcash Protocol Spec § 5.4.5.5: Orchard Key Agreement][concreteorchardkeyagreement].
///
/// [concreteorchardkeyagreement]: https://zips.z.cash/protocol/nu5.pdf#concreteorchardkeyagreement