diff --git a/zebra-chain/src/transaction/joinsplit.rs b/zebra-chain/src/transaction/joinsplit.rs index 15814366bd7..8ce679e8408 100644 --- a/zebra-chain/src/transaction/joinsplit.rs +++ b/zebra-chain/src/transaction/joinsplit.rs @@ -34,9 +34,7 @@ pub struct JoinSplit { /// JoinSplit description. pub random_seed: [u8; 32], /// A message authentication tag. - /// - /// XXX refine type to [T; 2] -- there are two macs - pub vmacs: [[u8; 32]; 2], + pub vmacs: [crate::types::MAC; 2], /// A ZK JoinSplit proof, either a /// [`Groth16Proof`](crate::proofs::Groth16Proof) or a /// [`Bctv14Proof`](crate::proofs::Bctv14Proof). diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 666375e3c92..d49e7a6fb1e 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -242,8 +242,8 @@ impl ZcashSerialize for JoinSplit

{ writer.write_all(&self.commitments[1][..])?; 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][..])?; + self.vmacs[0].zcash_serialize(&mut writer)?; + self.vmacs[1].zcash_serialize(&mut writer)?; self.zkproof.zcash_serialize(&mut writer)?; self.enc_ciphertexts[0].zcash_serialize(&mut writer)?; self.enc_ciphertexts[1].zcash_serialize(&mut writer)?; @@ -261,7 +261,10 @@ impl ZcashDeserialize for JoinSplit

{ 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()?, - vmacs: [reader.read_32_bytes()?, reader.read_32_bytes()?], + vmacs: [ + crate::types::MAC::zcash_deserialize(&mut reader)?, + crate::types::MAC::zcash_deserialize(&mut reader)?, + ], zkproof: P::zcash_deserialize(&mut reader)?, enc_ciphertexts: [ notes::sprout::EncryptedCiphertext::zcash_deserialize(&mut reader)?, diff --git a/zebra-chain/src/transaction/tests/arbitrary.rs b/zebra-chain/src/transaction/tests/arbitrary.rs index 0340389b07d..3e40dda4a3a 100644 --- a/zebra-chain/src/transaction/tests/arbitrary.rs +++ b/zebra-chain/src/transaction/tests/arbitrary.rs @@ -26,7 +26,7 @@ impl Arbitrary for JoinSplit

{ array::uniform2(array::uniform32(any::())), array::uniform32(any::()), array::uniform32(any::()), - array::uniform2(array::uniform32(any::())), + array::uniform2(any::()), any::

(), array::uniform2(any::()), ) diff --git a/zebra-chain/src/types.rs b/zebra-chain/src/types.rs index fde98a02602..81e803fb2f2 100644 --- a/zebra-chain/src/types.rs +++ b/zebra-chain/src/types.rs @@ -1,18 +1,13 @@ //! Newtype wrappers for primitive data types with semantic meaning. - -use std::{ - fmt, - io::{self, Read}, +#![allow(clippy::unit_arg)] +use crate::serialization::{ + ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize, ZcashSerialize, }; - use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use chrono::{DateTime, TimeZone, Utc}; - -#[cfg(test)] -use proptest_derive::Arbitrary; - -use crate::serialization::{ - ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize, ZcashSerialize, +use std::{ + fmt, + io::{self, Read}, }; pub mod amount; @@ -93,9 +88,30 @@ impl Arbitrary for LockTime { type Strategy = BoxedStrategy; } +/// A sequence of message authentication tags ... +/// +/// binding h_sig to each a_sk of the JoinSplit description, computed as +/// described in § 4.10 ‘Non-malleability (Sprout)’ on p. 37 +#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] +#[cfg_attr(test, derive(proptest_derive::Arbitrary))] +pub struct MAC([u8; 32]); + +impl ZcashDeserialize for MAC { + fn zcash_deserialize(mut reader: R) -> Result { + let bytes = reader.read_32_bytes()?; + + Ok(Self(bytes)) + } +} + +impl ZcashSerialize for MAC { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_all(&self.0[..]) + } +} /// An encoding of a Bitcoin script. #[derive(Clone, Eq, PartialEq, Serialize, Deserialize)] -#[cfg_attr(test, derive(Arbitrary))] +#[cfg_attr(test, derive(proptest_derive::Arbitrary))] pub struct Script(pub Vec); impl fmt::Debug for Script {