zebra_chain/sapling/note/
ciphertexts.rs

1//! Encrypted parts of Sapling notes.
2
3use std::{fmt, io};
4
5use serde_big_array::BigArray;
6
7use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize};
8
9/// A ciphertext component for encrypted output notes.
10///
11/// Corresponds to the Sapling 'encCiphertext's
12#[derive(Deserialize, Serialize)]
13pub struct EncryptedNote(#[serde(with = "BigArray")] pub(crate) [u8; 580]);
14
15impl From<[u8; 580]> for EncryptedNote {
16    fn from(byte_array: [u8; 580]) -> Self {
17        Self(byte_array)
18    }
19}
20
21impl fmt::Debug for EncryptedNote {
22    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23        f.debug_tuple("EncryptedNote")
24            .field(&hex::encode(&self.0[..]))
25            .finish()
26    }
27}
28
29// These impls all only exist because of array length restrictions.
30
31impl Copy for EncryptedNote {}
32
33impl Clone for EncryptedNote {
34    fn clone(&self) -> Self {
35        *self
36    }
37}
38
39impl PartialEq for EncryptedNote {
40    fn eq(&self, other: &Self) -> bool {
41        self.0[..] == other.0[..]
42    }
43}
44
45impl Eq for EncryptedNote {}
46
47impl ZcashSerialize for EncryptedNote {
48    fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
49        writer.write_all(&self.0[..])?;
50        Ok(())
51    }
52}
53
54impl ZcashDeserialize for EncryptedNote {
55    fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
56        let mut bytes = [0; 580];
57        reader.read_exact(&mut bytes[..])?;
58        Ok(Self(bytes))
59    }
60}
61
62/// A ciphertext component for encrypted output notes.
63///
64/// Corresponds to Sapling's 'outCiphertext'
65#[derive(Deserialize, Serialize)]
66pub struct WrappedNoteKey(#[serde(with = "BigArray")] pub(crate) [u8; 80]);
67
68impl From<[u8; 80]> for WrappedNoteKey {
69    fn from(byte_array: [u8; 80]) -> Self {
70        Self(byte_array)
71    }
72}
73
74impl fmt::Debug for WrappedNoteKey {
75    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76        f.debug_tuple("WrappedNoteKey")
77            .field(&hex::encode(&self.0[..]))
78            .finish()
79    }
80}
81
82// These impls all only exist because of array length restrictions.
83
84impl Copy for WrappedNoteKey {}
85
86impl Clone for WrappedNoteKey {
87    fn clone(&self) -> Self {
88        *self
89    }
90}
91
92impl PartialEq for WrappedNoteKey {
93    fn eq(&self, other: &Self) -> bool {
94        self.0[..] == other.0[..]
95    }
96}
97
98impl Eq for WrappedNoteKey {}
99
100impl ZcashSerialize for WrappedNoteKey {
101    fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
102        writer.write_all(&self.0[..])?;
103        Ok(())
104    }
105}
106
107impl ZcashDeserialize for WrappedNoteKey {
108    fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
109        let mut bytes = [0; 80];
110        reader.read_exact(&mut bytes[..])?;
111        Ok(Self(bytes))
112    }
113}
114
115#[cfg(test)]
116use proptest::prelude::*;
117#[cfg(test)]
118proptest! {
119
120    #[test]
121    fn encrypted_ciphertext_roundtrip(ec in any::<EncryptedNote>()) {
122        let _init_guard = zebra_test::init();
123
124        let mut data = Vec::new();
125
126        ec.zcash_serialize(&mut data).expect("EncryptedNote should serialize");
127
128        let ec2 = EncryptedNote::zcash_deserialize(&data[..]).expect("randomized EncryptedNote should deserialize");
129
130        prop_assert_eq![ec, ec2];
131    }
132
133    #[test]
134    fn out_ciphertext_roundtrip(oc in any::<WrappedNoteKey>()) {
135        let _init_guard = zebra_test::init();
136
137        let mut data = Vec::new();
138
139        oc.zcash_serialize(&mut data).expect("WrappedNoteKey should serialize");
140
141        let oc2 = WrappedNoteKey::zcash_deserialize(&data[..]).expect("randomized WrappedNoteKey should deserialize");
142
143        prop_assert_eq![oc, oc2];
144    }
145}