From 05ca1c0c8a546da537c2319bb632ccea8329cae9 Mon Sep 17 00:00:00 2001 From: Deirdre Connolly Date: Mon, 13 Apr 2020 14:45:43 -0400 Subject: [PATCH] Refine JoinSplit ephemeral keys to be x25519_dalek::PublicKey Impls PartialEq and Eq and Arbitrary on JoinSplit because PublicKey does not impl them and we can't do it directly. Resolves #313 --- zebra-chain/src/transaction/joinsplit.rs | 76 ++++++++++++++++++++++-- zebra-chain/src/transaction/serialize.rs | 4 +- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/zebra-chain/src/transaction/joinsplit.rs b/zebra-chain/src/transaction/joinsplit.rs index f399d02d..46eda637 100644 --- a/zebra-chain/src/transaction/joinsplit.rs +++ b/zebra-chain/src/transaction/joinsplit.rs @@ -16,8 +16,7 @@ use crate::{ /// A _JoinSplit Description_, as described in [protocol specification ยง7.2][ps]. /// /// [ps]: https://zips.z.cash/protocol/protocol.pdf#joinsplitencoding -#[derive(Clone, Debug, PartialEq, Eq)] -#[cfg_attr(test, derive(Arbitrary))] +#[derive(Clone, Debug)] pub struct JoinSplit { /// A value that the JoinSplit transfer removes from the transparent value /// pool. @@ -46,7 +45,7 @@ pub struct JoinSplit { /// An X25519 public key. /// /// XXX refine to an x25519-dalek type? - pub ephemeral_key: [u8; 32], + pub ephemeral_key: x25519_dalek::PublicKey, /// A 256-bit seed that must be chosen independently at random for each /// JoinSplit description. pub random_seed: [u8; 32], @@ -62,8 +61,77 @@ pub struct JoinSplit { pub enc_ciphertexts: [EncryptedCiphertext; 2], } +// Because x25519_dalek::PublicKey does not impl PartialEq +impl PartialEq for JoinSplit

{ + fn eq(&self, other: &Self) -> bool { + self.vpub_old == other.vpub_old + && self.vpub_new == other.vpub_new + && self.anchor == other.anchor + && self.nullifiers == other.nullifiers + && self.commitments == other.commitments + && self.ephemeral_key.as_bytes() == other.ephemeral_key.as_bytes() + && self.random_seed == other.random_seed + && self.vmacs == other.vmacs + && self.zkproof == other.zkproof + && self.enc_ciphertexts == other.enc_ciphertexts + } +} + +// Because x25519_dalek::PublicKey does not impl Eq +impl Eq for JoinSplit

{} + +#[cfg(test)] +impl Arbitrary for JoinSplit

{ + type Parameters = (); + + fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { + ( + any::(), + any::(), + array::uniform32(any::()), + array::uniform2(array::uniform32(any::())), + array::uniform2(array::uniform32(any::())), + array::uniform32(any::()), + array::uniform32(any::()), + array::uniform2(array::uniform32(any::())), + any::

(), + array::uniform2(any::()), + ) + .prop_map( + |( + vpub_old, + vpub_new, + anchor, + nullifiers, + commitments, + ephemeral_key_bytes, + random_seed, + vmacs, + zkproof, + enc_ciphertexts, + )| { + return Self { + vpub_old, + vpub_new, + anchor, + nullifiers, + commitments, + ephemeral_key: x25519_dalek::PublicKey::from(ephemeral_key_bytes), + random_seed, + vmacs, + zkproof, + enc_ciphertexts, + }; + }, + ) + .boxed() + } + + type Strategy = BoxedStrategy; +} + /// A bundle of JoinSplit descriptions and signature data. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct JoinSplitData { /// The first JoinSplit description, using proofs of type `P`. /// diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index b63865f3..25fcdaab 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -235,7 +235,7 @@ impl ZcashSerialize for JoinSplit

{ writer.write_all(&self.nullifiers[1][..])?; writer.write_all(&self.commitments[0][..])?; writer.write_all(&self.commitments[1][..])?; - writer.write_all(&self.ephemeral_key[..])?; + writer.write_all(&self.ephemeral_key.as_bytes()[..])?; writer.write_all(&self.random_seed[..])?; writer.write_all(&self.vmacs[0][..])?; writer.write_all(&self.vmacs[1][..])?; @@ -254,7 +254,7 @@ impl ZcashDeserialize for JoinSplit

{ anchor: reader.read_32_bytes()?, nullifiers: [reader.read_32_bytes()?, reader.read_32_bytes()?], commitments: [reader.read_32_bytes()?, reader.read_32_bytes()?], - ephemeral_key: reader.read_32_bytes()?, + ephemeral_key: x25519_dalek::PublicKey::from(reader.read_32_bytes()?), random_seed: reader.read_32_bytes()?, vmacs: [reader.read_32_bytes()?, reader.read_32_bytes()?], zkproof: P::zcash_deserialize(&mut reader)?,