NoteCommitments, renames, ValueCommitment, strategies, stub commit()

This commit is contained in:
Deirdre Connolly 2020-07-13 18:38:49 -04:00 committed by Deirdre Connolly
parent fa053e2b0b
commit 0f46a9b6a8
4 changed files with 76 additions and 16 deletions

View File

@ -176,6 +176,7 @@ impl From<SpendingKey> for ReceivingKey {
/// Derived from a _SpendingKey_. /// Derived from a _SpendingKey_.
#[derive(Copy, Clone, Eq, PartialEq)] #[derive(Copy, Clone, Eq, PartialEq)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct PayingKey(pub [u8; 32]); pub struct PayingKey(pub [u8; 32]);
impl AsRef<[u8]> for PayingKey { impl AsRef<[u8]> for PayingKey {

View File

@ -1,5 +1,8 @@
use std::{cmp, convert::TryFrom, fmt}; use std::{cmp, convert::TryFrom, fmt};
#[cfg(test)]
use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*};
/// A 512-byte _Memo_ field associated with a note, as described in /// A 512-byte _Memo_ field associated with a note, as described in
/// [protocol specification §5.5][ps]. /// [protocol specification §5.5][ps].
/// ///
@ -48,6 +51,23 @@ impl fmt::Debug for Memo {
} }
} }
#[cfg(test)]
impl Arbitrary for Memo {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(vec(any::<u8>(), 512))
.prop_map(|v| {
let mut bytes = [0; 512];
bytes.copy_from_slice(v.as_slice());
Memo(Box::new(bytes))
})
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}
#[test] #[test]
fn memo_fmt() { fn memo_fmt() {
let memo = Memo(Box::new( let memo = Memo(Box::new(

View File

@ -1,4 +1,3 @@
//!
#![allow(clippy::unit_arg)] #![allow(clippy::unit_arg)]
#![allow(dead_code)] #![allow(dead_code)]
@ -51,14 +50,33 @@ pub struct Note {
diversifier: Diversifier, diversifier: Diversifier,
transmission_key: TransmissionKey, transmission_key: TransmissionKey,
value: Amount<NonNegative>, value: Amount<NonNegative>,
note_commitment_randomness: NoteCommitmentRandomness, rcm: NoteCommitmentRandomness,
} }
impl Note {
/// Construct a “windowed” Pedersen commitment by reusing a
/// Perderson hash constructon, and adding a randomized point on
/// the Jubjub curve.
///
/// https://zips.z.cash/protocol/protocol.pdf#concretewindowedcommit
pub fn commit(&self) -> NoteCommitment {
// Windowed Pedersen Commitment
// NoteCommitment()
unimplemented!()
}
}
///
#[derive(Clone, Copy, Debug)]
//#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct NoteCommitment(jubjub::ExtendedPoint);
/// The decrypted form of encrypted Sapling notes on the blockchain. /// The decrypted form of encrypted Sapling notes on the blockchain.
pub struct NotePlaintext { pub struct NotePlaintext {
diversifier: Diversifier, diversifier: Diversifier,
value: Amount<NonNegative>, value: Amount<NonNegative>,
note_commitment_randomness: NoteCommitmentRandomness, rcm: NoteCommitmentRandomness,
memo: memo::Memo, memo: memo::Memo,
} }
@ -190,6 +208,13 @@ impl Arbitrary for OutCiphertext {
type Strategy = BoxedStrategy<Self>; type Strategy = BoxedStrategy<Self>;
} }
/// A Homomorphic Pedersen commitment to the value of a note, used in
/// Spend and Output Descriptions.
///
/// https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit
#[derive(Clone, Copy, Debug)]
pub struct ValueCommitment(pub jubjub::ExtendedPoint);
#[cfg(test)] #[cfg(test)]
proptest! { proptest! {

View File

@ -46,8 +46,9 @@ fn prf_nf(a_sk: [u8; 32], rho: [u8; 32]) -> [u8; 32] {
/// Nullifier seed, named rho in the [spec][ps]. /// Nullifier seed, named rho in the [spec][ps].
/// ///
/// [ps]: https://zips.z.cash/protocol/protocol.pdf#sproutkeycomponents /// [ps]: https://zips.z.cash/protocol/protocol.pdf#sproutkeycomponents
#[derive(Clone, Copy)] #[derive(Clone, Copy, Debug)]
struct NullifierSeed([u8; 32]); #[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct NullifierSeed([u8; 32]);
impl AsRef<[u8]> for NullifierSeed { impl AsRef<[u8]> for NullifierSeed {
fn as_ref(&self) -> &[u8] { fn as_ref(&self) -> &[u8] {
@ -94,6 +95,7 @@ impl ZcashSerialize for Nullifier {
/// The randomness used in the Pedersen Hash for note commitment. /// The randomness used in the Pedersen Hash for note commitment.
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct NoteCommitmentRandomness(pub [u8; 32]); pub struct NoteCommitmentRandomness(pub [u8; 32]);
impl AsRef<[u8]> for NoteCommitmentRandomness { impl AsRef<[u8]> for NoteCommitmentRandomness {
@ -102,39 +104,51 @@ impl AsRef<[u8]> for NoteCommitmentRandomness {
} }
} }
///
#[derive(Clone, Copy, Debug)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct NoteCommitment([u8; 32]);
/// A Note represents that a value is spendable by the recipient who /// A Note represents that a value is spendable by the recipient who
/// holds the spending key corresponding to a given shielded payment /// holds the spending key corresponding to a given shielded payment
/// address. /// address.
///
/// https://zips.z.cash/protocol/protocol.pdf#notes
#[derive(Clone, Copy, Debug)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct Note { pub struct Note {
/// The paying key of the recipients shielded payment address
paying_key: PayingKey, paying_key: PayingKey,
/// An integer representing the value of the note in zatoshi (1 ZEC
/// = 10^8 zatoshi)
value: Amount<NonNegative>, value: Amount<NonNegative>,
nullifier_seed: NullifierSeed, /// Input to PRF^nf to derive the nullifier of the note
note_commitment_randomness: NoteCommitmentRandomness, rho: NullifierSeed,
/// A random commitment trapdoor
rcm: NoteCommitmentRandomness,
} }
impl Note { impl Note {
pub fn commitment(&self) -> NoteCommitment { pub fn commit(&self) -> NoteCommitment {
let leading_byte: u8 = 0xB0; let leading_byte: u8 = 0xB0;
let mut hasher = Sha256::default(); let mut hasher = Sha256::default();
hasher.input([leading_byte]); hasher.input([leading_byte]);
hasher.input(self.paying_key); hasher.input(self.paying_key);
hasher.input(self.value.to_bytes()); hasher.input(self.value.to_bytes());
hasher.input(self.nullifier_seed); hasher.input(self.rho);
hasher.input(self.note_commitment_randomness); hasher.input(self.rcm);
NoteCommitment(hasher.result().into()) NoteCommitment(hasher.result().into())
} }
} }
///
pub struct NoteCommitment([u8; 32]);
/// The decrypted form of encrypted Sprout notes on the blockchain. /// The decrypted form of encrypted Sprout notes on the blockchain.
#[derive(Clone, Debug)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub struct NotePlaintext { pub struct NotePlaintext {
value: Amount<NonNegative>, value: Amount<NonNegative>,
// TODO: refine type rho: NullifierSeed,
rho: [u8; 32], rcm: NoteCommitmentRandomness,
note_commitment_randomness: NoteCommitmentRandomness,
memo: Memo, memo: Memo,
} }