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 note_commitment_tree;
pub mod notes;
pub mod nullifier;
pub mod proofs;
pub mod serialization;
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.
///
/// 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.
///
/// 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_new.into())?;
writer.write_all(&self.anchor[..])?;
writer.write_all(&self.nullifiers[0][..])?;
writer.write_all(&self.nullifiers[1][..])?;
self.nullifiers[0].zcash_serialize(&mut writer)?;
self.nullifiers[1].zcash_serialize(&mut writer)?;
writer.write_all(&self.commitments[0][..])?;
writer.write_all(&self.commitments[1][..])?;
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_new: reader.read_u64::<LittleEndian>()?.try_into()?,
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()?],
ephemeral_key: x25519_dalek::PublicKey::from(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> {
writer.write_all(&self.cv[..])?;
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)[..])?;
self.zkproof.zcash_serialize(&mut writer)?;
writer.write_all(&<[u8; 64]>::from(self.spend_auth_sig)[..])?;
@ -328,7 +331,7 @@ impl ZcashDeserialize for Spend {
Ok(Spend {
cv: 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(),
zkproof: Groth16Proof::zcash_deserialize(&mut reader)?,
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.
pub anchor: SaplingNoteTreeRootHash,
/// The nullifier of the input note.
///
/// XXX refine to a specific type.
pub nullifier: [u8; 32],
pub nullifier: crate::nullifier::sapling::Nullifier,
/// The randomized public key for `spend_auth_sig`.
pub rk: redjubjub::PublicKeyBytes<SpendAuth>,
/// 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>>(),
array::uniform32(any::<u8>()),
array::uniform2(array::uniform32(any::<u8>())),
array::uniform2(any::<crate::nullifier::sprout::Nullifier>()),
array::uniform2(array::uniform32(any::<u8>())),
array::uniform32(any::<u8>()),
array::uniform32(any::<u8>()),
@ -155,7 +155,7 @@ impl Arbitrary for Spend {
(
array::uniform32(any::<u8>()),
any::<SaplingNoteTreeRootHash>(),
array::uniform32(any::<u8>()),
any::<crate::nullifier::sapling::Nullifier>(),
array::uniform32(any::<u8>()),
any::<Groth16Proof>(),
vec(any::<u8>(), 64),