From 2c285985c89bfbd64da295c5cb62bda28ee8cf91 Mon Sep 17 00:00:00 2001 From: Deirdre Connolly Date: Thu, 9 Jul 2020 04:20:20 -0400 Subject: [PATCH] Move nullifiers to respective note modules, pull in existing types from keys --- zebra-chain/src/keys/sprout.rs | 6 ++ zebra-chain/src/lib.rs | 1 - zebra-chain/src/notes/sapling.rs | 52 +++++++++---- zebra-chain/src/notes/sprout.rs | 74 ++++++++++++++----- zebra-chain/src/nullifier.rs | 4 - zebra-chain/src/nullifier/sapling.rs | 30 -------- zebra-chain/src/nullifier/sprout.rs | 30 -------- zebra-chain/src/transaction/joinsplit.rs | 2 +- zebra-chain/src/transaction/serialize.rs | 6 +- zebra-chain/src/transaction/shielded_data.rs | 2 +- .../src/transaction/tests/arbitrary.rs | 4 +- 11 files changed, 106 insertions(+), 105 deletions(-) delete mode 100644 zebra-chain/src/nullifier.rs delete mode 100644 zebra-chain/src/nullifier/sapling.rs delete mode 100644 zebra-chain/src/nullifier/sprout.rs diff --git a/zebra-chain/src/keys/sprout.rs b/zebra-chain/src/keys/sprout.rs index f1e1137ac..31e1c41be 100644 --- a/zebra-chain/src/keys/sprout.rs +++ b/zebra-chain/src/keys/sprout.rs @@ -169,6 +169,12 @@ impl From for ReceivingKey { #[derive(Copy, Clone, Eq, PartialEq)] pub struct PayingKey(pub [u8; 32]); +impl AsRef<[u8]> for PayingKey { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + impl fmt::Debug for PayingKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("PayingKey") diff --git a/zebra-chain/src/lib.rs b/zebra-chain/src/lib.rs index eef6fdc4a..9b7a4920c 100644 --- a/zebra-chain/src/lib.rs +++ b/zebra-chain/src/lib.rs @@ -21,7 +21,6 @@ pub mod equihash_solution; pub mod keys; pub mod note_commitment_tree; pub mod notes; -pub mod nullifier; pub mod parameters; pub mod proofs; pub mod serialization; diff --git a/zebra-chain/src/notes/sapling.rs b/zebra-chain/src/notes/sapling.rs index 50adcb8a4..f09e7ffc2 100644 --- a/zebra-chain/src/notes/sapling.rs +++ b/zebra-chain/src/notes/sapling.rs @@ -1,4 +1,5 @@ //! +#![allow(clippy::unit_arg)] #![allow(dead_code)] use std::{fmt, io}; @@ -6,27 +7,46 @@ use std::{fmt, io}; #[cfg(test)] use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*}; -use crate::serde_helpers; -use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}; - use super::*; +use crate::{ + keys::sapling::{Diversifier, TransmissionKey}, + serde_helpers, + serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize}, + types::amount::{Amount, NonNegative}, +}; -/// A _Diversifier_, an 11 byte value used to randomize the -/// recipient's final public shielded payment address to create a -/// _diversified payment address_. -/// -/// When used, this value is mapped to an affine JubJub group element. -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct Diversifier(pub [u8; 11]); +/// A Nullifier 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(mut reader: R) -> Result { + let bytes = reader.read_32_bytes()?; + + Ok(Self(bytes)) + } +} + +impl ZcashSerialize for Nullifier { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_all(&self.0[..]) + } +} + +/// A Note represents that a value is spendable by the recipient who +/// holds the spending key corresponding to a given shielded payment +/// address. pub struct Note { diversifier: Diversifier, - // TODO: refine as a type, derived from a scalar mult of the - // diversifier as a jubjub group element and the incoming view key - // scalar. - transmission_key: [u8; 32], - value: u64, + transmission_key: TransmissionKey, + value: Amount, note_commitment_randomness: NoteCommitmentRandomness, } diff --git a/zebra-chain/src/notes/sprout.rs b/zebra-chain/src/notes/sprout.rs index dff9a1d3e..41e7fe3ff 100644 --- a/zebra-chain/src/notes/sprout.rs +++ b/zebra-chain/src/notes/sprout.rs @@ -1,29 +1,70 @@ //! +#![allow(clippy::unit_arg)] #![allow(dead_code)] -use super::{memo::Memo, *}; -use crate::serde_helpers; -use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}; -use crate::types::amount::{Amount, NonNegative}; +use std::{fmt, io}; + use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; -use std::{ - fmt, - io::{self}, + +use crate::{ + keys::sprout::PayingKey, + serde_helpers, + serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize}, + types::amount::{Amount, NonNegative}, }; +use super::{memo::Memo, *}; + +/// Nullifier seed, named rho in the [spec][ps]. /// +/// [ps]: https://zips.z.cash/protocol/protocol.pdf#sproutkeycomponents +#[derive(Clone, Copy)] +struct NullifierSeed([u8; 32]); + +impl AsRef<[u8]> for NullifierSeed { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +/// 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(mut reader: R) -> Result { + let bytes = reader.read_32_bytes()?; + + Ok(Self(bytes)) + } +} + +impl ZcashSerialize for Nullifier { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_all(&self.0[..]) + } +} + +/// A Note represents that a value is spendable by the recipient who +/// holds the spending key corresponding to a given shielded payment +/// address. pub struct Note { - // TODO: refine type as a SHA-256d output derived from a spending key. - paying_key: [u8; 32], + paying_key: PayingKey, value: Amount, - // TODO: refine type as the input to the PRF that results in a nullifier. - nullifier_seed: [u8; 32], + nullifier_seed: NullifierSeed, note_commitment_randomness: NoteCommitmentRandomness, } impl Note { - pub fn note_commitment(&self) -> NoteCommitment { + pub fn commitment(&self) -> NoteCommitment { let leading_byte: u8 = 0xB0; let mut hasher = Sha256::default(); hasher.input([leading_byte]); @@ -31,14 +72,13 @@ impl Note { hasher.input(self.value.to_bytes()); hasher.input(self.nullifier_seed); hasher.input(self.note_commitment_randomness); - let hash = hasher.result().into(); - NoteCommitment { hash } + + NoteCommitment(hasher.result().into()) } } -pub struct NoteCommitment { - hash: [u8; 32], -} +/// +pub struct NoteCommitment([u8; 32]); /// The decrypted form of encrypted Sprout notes on the blockchain. pub struct NotePlaintext { diff --git a/zebra-chain/src/nullifier.rs b/zebra-chain/src/nullifier.rs deleted file mode 100644 index f8d734205..000000000 --- a/zebra-chain/src/nullifier.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! Nullifier set types for sprout and sapling - -pub mod sapling; -pub mod sprout; diff --git a/zebra-chain/src/nullifier/sapling.rs b/zebra-chain/src/nullifier/sapling.rs deleted file mode 100644 index 21845a9dc..000000000 --- a/zebra-chain/src/nullifier/sapling.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! 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(mut reader: R) -> Result { - let bytes = reader.read_32_bytes()?; - - Ok(Self(bytes)) - } -} - -impl ZcashSerialize for Nullifier { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - writer.write_all(&self.0[..]) - } -} diff --git a/zebra-chain/src/nullifier/sprout.rs b/zebra-chain/src/nullifier/sprout.rs deleted file mode 100644 index de0b3a6bf..000000000 --- a/zebra-chain/src/nullifier/sprout.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! 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(mut reader: R) -> Result { - let bytes = reader.read_32_bytes()?; - - Ok(Self(bytes)) - } -} - -impl ZcashSerialize for Nullifier { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - writer.write_all(&self.0[..]) - } -} diff --git a/zebra-chain/src/transaction/joinsplit.rs b/zebra-chain/src/transaction/joinsplit.rs index f94ed08e2..d11f447c0 100644 --- a/zebra-chain/src/transaction/joinsplit.rs +++ b/zebra-chain/src/transaction/joinsplit.rs @@ -23,7 +23,7 @@ pub struct JoinSplit { /// A nullifier for the input notes. /// /// XXX refine type to [T; 2] -- there are two nullifiers - pub nullifiers: [crate::nullifier::sprout::Nullifier; 2], + pub nullifiers: [crate::notes::sprout::Nullifier; 2], /// A note commitment for this output note. /// /// XXX refine type to [T; 2] -- there are two commitments diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index b86368f48..e933270ce 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -262,8 +262,8 @@ impl ZcashDeserialize for JoinSplit

{ vpub_new: reader.read_u64::()?.try_into()?, anchor: reader.read_32_bytes()?, nullifiers: [ - crate::nullifier::sprout::Nullifier::zcash_deserialize(&mut reader)?, - crate::nullifier::sprout::Nullifier::zcash_deserialize(&mut reader)?, + crate::notes::sprout::Nullifier::zcash_deserialize(&mut reader)?, + crate::notes::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()?), @@ -335,7 +335,7 @@ impl ZcashDeserialize for Spend { Ok(Spend { cv: reader.read_32_bytes()?, anchor: SaplingNoteTreeRootHash(reader.read_32_bytes()?), - nullifier: crate::nullifier::sapling::Nullifier::zcash_deserialize(&mut reader)?, + nullifier: crate::notes::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(), diff --git a/zebra-chain/src/transaction/shielded_data.rs b/zebra-chain/src/transaction/shielded_data.rs index 1ddf393a8..caf4c517f 100644 --- a/zebra-chain/src/transaction/shielded_data.rs +++ b/zebra-chain/src/transaction/shielded_data.rs @@ -18,7 +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. - pub nullifier: crate::nullifier::sapling::Nullifier, + pub nullifier: crate::notes::sapling::Nullifier, /// The randomized public key for `spend_auth_sig`. pub rk: redjubjub::VerificationKeyBytes, /// The ZK spend proof. diff --git a/zebra-chain/src/transaction/tests/arbitrary.rs b/zebra-chain/src/transaction/tests/arbitrary.rs index 4d5cc1859..7145b9a5a 100644 --- a/zebra-chain/src/transaction/tests/arbitrary.rs +++ b/zebra-chain/src/transaction/tests/arbitrary.rs @@ -22,7 +22,7 @@ impl Arbitrary for JoinSplit

{ any::>(), any::>(), array::uniform32(any::()), - array::uniform2(any::()), + array::uniform2(any::()), array::uniform2(array::uniform32(any::())), array::uniform32(any::()), array::uniform32(any::()), @@ -155,7 +155,7 @@ impl Arbitrary for Spend { ( array::uniform32(any::()), any::(), - any::(), + any::(), array::uniform32(any::()), any::(), vec(any::(), 64),