zebra/zebra-chain/src/notes/sprout/nullifiers.rs

101 lines
2.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#![allow(clippy::unit_arg)]
#![allow(dead_code)]
use std::io;
use byteorder::{ByteOrder, LittleEndian};
use serde::{Deserialize, Serialize};
use crate::{
keys::sprout::SpendingKey,
serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize},
};
/// PRF^nf is used to derive a Sprout nullifer from the receiver's
/// spending key a_sk and a nullifier seed ρ, instantiated using the
/// SHA-256 compression function.
///
/// https://zips.z.cash/protocol/protocol.pdf#abstractprfs
/// https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers
fn prf_nf(a_sk: [u8; 32], rho: [u8; 32]) -> [u8; 32] {
let mut state = [0u32; 8];
let mut block = [0u8; 64];
block[0..32].copy_from_slice(&a_sk[..]);
// The first four bits i.e. the most signicant four bits of the
// first byte are used to separate distinct uses
// of SHA256Compress, ensuring that the functions are independent.
block[0] |= 0b1110_0000;
block[32..].copy_from_slice(&rho[..]);
sha2::compress256(&mut state, &block);
let mut derived_bytes = [0u8; 32];
LittleEndian::write_u32_into(&state, &mut derived_bytes);
derived_bytes
}
/// Nullifier seed, named rho in the [spec][ps].
///
/// [ps]: https://zips.z.cash/protocol/protocol.pdf#sproutkeycomponents
#[derive(Clone, Copy, Debug)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct NullifierSeed(pub(crate) [u8; 32]);
impl AsRef<[u8]> for NullifierSeed {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl From<[u8; 32]> for NullifierSeed {
fn from(bytes: [u8; 32]) -> Self {
Self(bytes)
}
}
impl From<NullifierSeed> for [u8; 32] {
fn from(rho: NullifierSeed) -> Self {
rho.0
}
}
/// A Nullifier for Sprout transactions
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct Nullifier(pub(crate) [u8; 32]);
impl From<[u8; 32]> for Nullifier {
fn from(bytes: [u8; 32]) -> Self {
Self(bytes)
}
}
impl<'a> From<(&'a SpendingKey, NullifierSeed)> for Nullifier {
fn from((a_sk, rho): (&'a SpendingKey, NullifierSeed)) -> Self {
Self(prf_nf(a_sk.into(), rho.into()))
}
}
impl From<Nullifier> for [u8; 32] {
fn from(n: Nullifier) -> Self {
n.0
}
}
impl ZcashDeserialize for Nullifier {
fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
let bytes = reader.read_32_bytes()?;
Ok(Self(bytes))
}
}
impl ZcashSerialize for Nullifier {
fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
writer.write_all(&self.0[..])
}
}