Add and use OutCiphertext

Instead of [u64; 10].
This commit is contained in:
Deirdre Connolly 2020-01-27 23:25:17 -05:00 committed by Deirdre Connolly
parent 289f8ec9ca
commit a93e2db44b
2 changed files with 67 additions and 28 deletions

View File

@ -2,7 +2,7 @@
//! transaction types, so that all of the serialization logic is in one place.
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::io::{self, Read};
use std::io;
use crate::proofs::ZkSnarkProof;
use crate::serialization::{
@ -177,21 +177,8 @@ impl ZcashSerialize for OutputDescription {
writer.write_all(&self.cv[..])?;
writer.write_all(&self.cmu[..])?;
writer.write_all(&self.ephemeral_key[..])?;
// assert_eq!(self.enc_ciphertext.len(), 580);
self.enc_ciphertext.zcash_serialize(&mut writer)?;
// XXX remove this assertion when types are refined
assert_eq!(self.out_ciphertext.len(), 80);
// XXX very ugly, this happens because we used a [u64; 10] instead of
// [u8; 80] to get trait impls and it will disappear when we refine to
// a note ciphertext type
writer.write_all(
&{
use byteorder::ByteOrder;
let mut bytes = [0u8; 80];
LittleEndian::write_u64_into(&self.out_ciphertext[..], &mut bytes);
bytes
}[..],
)?;
self.out_ciphertext.zcash_serialize(&mut writer)?;
self.zkproof.zcash_serialize(&mut writer)?;
Ok(())
}
@ -204,15 +191,7 @@ impl ZcashDeserialize for OutputDescription {
cmu: reader.read_32_bytes()?,
ephemeral_key: reader.read_32_bytes()?,
enc_ciphertext: shielded_data::EncryptedCiphertext::zcash_deserialize(&mut reader)?,
out_ciphertext: {
// XXX this is horrible, see above, will be removed with type refinement
use byteorder::ByteOrder;
let mut bytes = [0u8; 80];
reader.read_exact(&mut bytes[..])?;
let mut u64s = [0u64; 10];
LittleEndian::read_u64_into(&bytes, &mut u64s[..]);
u64s
},
out_ciphertext: shielded_data::OutCiphertext::zcash_deserialize(&mut reader)?,
zkproof: Groth16Proof::zcash_deserialize(&mut reader)?,
})
}

View File

@ -91,10 +91,7 @@ pub struct OutputDescription {
/// A ciphertext component for the encrypted output note.
pub enc_ciphertext: EncryptedCiphertext,
/// A ciphertext component for the encrypted output note.
///
/// XXX refine to a specific type.
/// XXX this is a [u64; 10] rather than a [u8; 80] to get trait impls
pub out_ciphertext: [u64; 10],
pub out_ciphertext: OutCiphertext,
/// The ZK output proof.
pub zkproof: Groth16Proof,
}
@ -267,3 +264,66 @@ impl Arbitrary for EncryptedCiphertext {
type Strategy = BoxedStrategy<Self>;
}
/// A ciphertext component for encrypted output notes.
pub struct OutCiphertext(pub [u8; 80]);
impl fmt::Debug for OutCiphertext {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("OutCiphertext")
.field(&hex::encode(&self.0[..]))
.finish()
}
}
// These impls all only exist because of array length restrictions.
impl Copy for OutCiphertext {}
impl Clone for OutCiphertext {
fn clone(&self) -> Self {
let mut bytes = [0; 80];
bytes[..].copy_from_slice(&self.0[..]);
Self(bytes)
}
}
impl PartialEq for OutCiphertext {
fn eq(&self, other: &Self) -> bool {
self.0[..] == other.0[..]
}
}
impl Eq for OutCiphertext {}
impl ZcashSerialize for OutCiphertext {
fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), SerializationError> {
writer.write_all(&self.0[..])?;
Ok(())
}
}
impl ZcashDeserialize for OutCiphertext {
fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
let mut bytes = [0; 80];
reader.read_exact(&mut bytes[..])?;
Ok(Self(bytes))
}
}
#[cfg(test)]
impl Arbitrary for OutCiphertext {
type Parameters = ();
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(vec(any::<u8>(), 80))
.prop_map(|v| {
let mut bytes = [0; 80];
bytes.copy_from_slice(v.as_slice());
return Self(bytes);
})
.boxed()
}
type Strategy = BoxedStrategy<Self>;
}