add nullifier types (#568)

* add nullifier types

* Apply suggestions from code review

Co-authored-by: Deirdre Connolly <deirdre@zfnd.org>

* add zcash_deserialize impls

* Add docs

Co-authored-by: Deirdre Connolly <deirdre@zfnd.org>
This commit is contained in:
Jane Lusby 2020-07-01 17:57:32 -07:00 committed by GitHub
parent c216f5ca25
commit 00e750654a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 77 additions and 11 deletions

View File

@ -17,6 +17,7 @@ pub mod equihash_solution;
pub mod keys; pub mod keys;
pub mod note_commitment_tree; pub mod note_commitment_tree;
pub mod notes; pub mod notes;
pub mod nullifier;
pub mod proofs; pub mod proofs;
pub mod serialization; pub mod serialization;
pub mod transaction; pub mod transaction;

View File

@ -0,0 +1,4 @@
//! Nullifier set types for sproud and sapling
pub mod sapling;
pub mod sprout;

View File

@ -0,0 +1,30 @@
//! Sapling Nullifier Set types and impls
#![allow(clippy::unit_arg)]
use crate::serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize};
use serde::{Deserialize, Serialize};
use std::io;
/// A Nullifier Set for Sapling transactions
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct Nullifier([u8; 32]);
impl From<[u8; 32]> for Nullifier {
fn from(buf: [u8; 32]) -> Self {
Self(buf)
}
}
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[..])
}
}

View File

@ -0,0 +1,30 @@
//! Sprout Nullifier Set types and impls
#![allow(clippy::unit_arg)]
use crate::serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize};
use serde::{Deserialize, Serialize};
use std::io;
/// A Nullifier Set for Sprout transactions
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct Nullifier([u8; 32]);
impl From<[u8; 32]> for Nullifier {
fn from(buf: [u8; 32]) -> Self {
Self(buf)
}
}
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[..])
}
}

View File

@ -23,7 +23,7 @@ pub struct JoinSplit<P: ZkSnarkProof> {
/// A nullifier for the input notes. /// A nullifier for the input notes.
/// ///
/// XXX refine type to [T; 2] -- there are two nullifiers /// XXX refine type to [T; 2] -- there are two nullifiers
pub nullifiers: [[u8; 32]; 2], pub nullifiers: [crate::nullifier::sprout::Nullifier; 2],
/// A note commitment for this output note. /// A note commitment for this output note.
/// ///
/// XXX refine type to [T; 2] -- there are two commitments /// XXX refine type to [T; 2] -- there are two commitments

View File

@ -236,8 +236,8 @@ impl<P: ZkSnarkProof> ZcashSerialize for JoinSplit<P> {
writer.write_u64::<LittleEndian>(self.vpub_old.into())?; writer.write_u64::<LittleEndian>(self.vpub_old.into())?;
writer.write_u64::<LittleEndian>(self.vpub_new.into())?; writer.write_u64::<LittleEndian>(self.vpub_new.into())?;
writer.write_all(&self.anchor[..])?; writer.write_all(&self.anchor[..])?;
writer.write_all(&self.nullifiers[0][..])?; self.nullifiers[0].zcash_serialize(&mut writer)?;
writer.write_all(&self.nullifiers[1][..])?; self.nullifiers[1].zcash_serialize(&mut writer)?;
writer.write_all(&self.commitments[0][..])?; writer.write_all(&self.commitments[0][..])?;
writer.write_all(&self.commitments[1][..])?; writer.write_all(&self.commitments[1][..])?;
writer.write_all(&self.ephemeral_key.as_bytes()[..])?; writer.write_all(&self.ephemeral_key.as_bytes()[..])?;
@ -257,7 +257,10 @@ impl<P: ZkSnarkProof> ZcashDeserialize for JoinSplit<P> {
vpub_old: reader.read_u64::<LittleEndian>()?.try_into()?, vpub_old: reader.read_u64::<LittleEndian>()?.try_into()?,
vpub_new: reader.read_u64::<LittleEndian>()?.try_into()?, vpub_new: reader.read_u64::<LittleEndian>()?.try_into()?,
anchor: reader.read_32_bytes()?, anchor: reader.read_32_bytes()?,
nullifiers: [reader.read_32_bytes()?, reader.read_32_bytes()?], nullifiers: [
crate::nullifier::sprout::Nullifier::zcash_deserialize(&mut reader)?,
crate::nullifier::sprout::Nullifier::zcash_deserialize(&mut reader)?,
],
commitments: [reader.read_32_bytes()?, reader.read_32_bytes()?], commitments: [reader.read_32_bytes()?, reader.read_32_bytes()?],
ephemeral_key: x25519_dalek::PublicKey::from(reader.read_32_bytes()?), ephemeral_key: x25519_dalek::PublicKey::from(reader.read_32_bytes()?),
random_seed: reader.read_32_bytes()?, random_seed: reader.read_32_bytes()?,
@ -314,7 +317,7 @@ impl ZcashSerialize for Spend {
fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> { fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
writer.write_all(&self.cv[..])?; writer.write_all(&self.cv[..])?;
writer.write_all(&self.anchor.0[..])?; writer.write_all(&self.anchor.0[..])?;
writer.write_all(&self.nullifier[..])?; self.nullifier.zcash_serialize(&mut writer)?;
writer.write_all(&<[u8; 32]>::from(self.rk)[..])?; writer.write_all(&<[u8; 32]>::from(self.rk)[..])?;
self.zkproof.zcash_serialize(&mut writer)?; self.zkproof.zcash_serialize(&mut writer)?;
writer.write_all(&<[u8; 64]>::from(self.spend_auth_sig)[..])?; writer.write_all(&<[u8; 64]>::from(self.spend_auth_sig)[..])?;
@ -328,7 +331,7 @@ impl ZcashDeserialize for Spend {
Ok(Spend { Ok(Spend {
cv: reader.read_32_bytes()?, cv: reader.read_32_bytes()?,
anchor: SaplingNoteTreeRootHash(reader.read_32_bytes()?), anchor: SaplingNoteTreeRootHash(reader.read_32_bytes()?),
nullifier: reader.read_32_bytes()?, nullifier: crate::nullifier::sapling::Nullifier::zcash_deserialize(&mut reader)?,
rk: reader.read_32_bytes()?.into(), rk: reader.read_32_bytes()?.into(),
zkproof: Groth16Proof::zcash_deserialize(&mut reader)?, zkproof: Groth16Proof::zcash_deserialize(&mut reader)?,
spend_auth_sig: reader.read_64_bytes()?.into(), spend_auth_sig: reader.read_64_bytes()?.into(),

View File

@ -18,9 +18,7 @@ pub struct Spend {
/// A root of the Sapling note commitment tree at some block height in the past. /// A root of the Sapling note commitment tree at some block height in the past.
pub anchor: SaplingNoteTreeRootHash, pub anchor: SaplingNoteTreeRootHash,
/// The nullifier of the input note. /// The nullifier of the input note.
/// pub nullifier: crate::nullifier::sapling::Nullifier,
/// XXX refine to a specific type.
pub nullifier: [u8; 32],
/// The randomized public key for `spend_auth_sig`. /// The randomized public key for `spend_auth_sig`.
pub rk: redjubjub::PublicKeyBytes<SpendAuth>, pub rk: redjubjub::PublicKeyBytes<SpendAuth>,
/// The ZK spend proof. /// The ZK spend proof.

View File

@ -22,7 +22,7 @@ impl<P: ZkSnarkProof + Arbitrary + 'static> Arbitrary for JoinSplit<P> {
any::<Amount<NonNegative>>(), any::<Amount<NonNegative>>(),
any::<Amount<NonNegative>>(), any::<Amount<NonNegative>>(),
array::uniform32(any::<u8>()), array::uniform32(any::<u8>()),
array::uniform2(array::uniform32(any::<u8>())), array::uniform2(any::<crate::nullifier::sprout::Nullifier>()),
array::uniform2(array::uniform32(any::<u8>())), array::uniform2(array::uniform32(any::<u8>())),
array::uniform32(any::<u8>()), array::uniform32(any::<u8>()),
array::uniform32(any::<u8>()), array::uniform32(any::<u8>()),
@ -155,7 +155,7 @@ impl Arbitrary for Spend {
( (
array::uniform32(any::<u8>()), array::uniform32(any::<u8>()),
any::<SaplingNoteTreeRootHash>(), any::<SaplingNoteTreeRootHash>(),
array::uniform32(any::<u8>()), any::<crate::nullifier::sapling::Nullifier>(),
array::uniform32(any::<u8>()), array::uniform32(any::<u8>()),
any::<Groth16Proof>(), any::<Groth16Proof>(),
vec(any::<u8>(), 64), vec(any::<u8>(), 64),