snarkvm_ledger_block/transition/output/
bytes.rs1use super::*;
17
18#[allow(clippy::type_complexity)]
21fn read_record_fields<N: Network, R: Read>(
22 reader: &mut R,
23) -> IoResult<(Field<N>, Field<N>, Option<Record<N, Ciphertext<N>>>, Option<Field<N>>)> {
24 let commitment = FromBytes::read_le(&mut *reader)?;
26 let checksum = FromBytes::read_le(&mut *reader)?;
28 let record_ciphertext_exists: bool = FromBytes::read_le(&mut *reader)?;
30 let record_ciphertext: Option<Record<N, _>> = match record_ciphertext_exists {
31 true => Some(FromBytes::read_le(&mut *reader)?),
32 false => None,
33 };
34 let sender_ciphertext = match &record_ciphertext {
36 Some(record) => match record.version().is_zero() {
37 true => None,
38 false => {
39 let sender_ciphertext_version: u8 = FromBytes::read_le(&mut *reader)?;
41 if sender_ciphertext_version != 0 {
43 return Err(error(format!(
44 "Failed to decode sender ciphertext version {sender_ciphertext_version}"
45 )));
46 }
47 Some(FromBytes::read_le(&mut *reader)?)
49 }
50 },
51 None => None,
52 };
53 Ok((commitment, checksum, record_ciphertext, sender_ciphertext))
54}
55
56fn write_record_fields<N: Network, W: Write>(
58 writer: &mut W,
59 commitment: &Field<N>,
60 checksum: &Field<N>,
61 record_ciphertext: &Option<Record<N, Ciphertext<N>>>,
62 sender_ciphertext: &Option<Field<N>>,
63) -> IoResult<()> {
64 commitment.write_le(&mut *writer)?;
66 checksum.write_le(&mut *writer)?;
68 match record_ciphertext {
70 Some(record) => {
71 true.write_le(&mut *writer)?;
72 record.write_le(&mut *writer)?;
73 if !record.version().is_zero() {
75 0u8.write_le(&mut *writer)?;
77 match sender_ciphertext {
79 Some(sender) => sender.write_le(&mut *writer)?,
80 None => {
81 return Err(error("Failed to encode sender ciphertext for non-zero version record"));
82 }
83 }
84 }
85 }
86 None => false.write_le(&mut *writer)?,
87 }
88 Ok(())
89}
90
91impl<N: Network> FromBytes for Output<N> {
92 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
94 let index = Variant::read_le(&mut reader)?;
95 let literal = match index {
96 0 => {
97 let plaintext_hash: Field<N> = FromBytes::read_le(&mut reader)?;
98 let plaintext_exists: bool = FromBytes::read_le(&mut reader)?;
99 let plaintext = match plaintext_exists {
100 true => Some(FromBytes::read_le(&mut reader)?),
101 false => None,
102 };
103
104 Self::Constant(plaintext_hash, plaintext)
105 }
106 1 => {
107 let plaintext_hash: Field<N> = FromBytes::read_le(&mut reader)?;
108 let plaintext_exists: bool = FromBytes::read_le(&mut reader)?;
109 let plaintext = match plaintext_exists {
110 true => Some(FromBytes::read_le(&mut reader)?),
111 false => None,
112 };
113 Self::Public(plaintext_hash, plaintext)
114 }
115 2 => {
116 let ciphertext_hash: Field<N> = FromBytes::read_le(&mut reader)?;
117 let ciphertext_exists: bool = FromBytes::read_le(&mut reader)?;
118 let ciphertext = match ciphertext_exists {
119 true => Some(FromBytes::read_le(&mut reader)?),
120 false => None,
121 };
122 Self::Private(ciphertext_hash, ciphertext)
123 }
124 3 => {
125 let (commitment, checksum, record_ciphertext, sender_ciphertext) = read_record_fields(&mut reader)?;
126 Self::Record(commitment, checksum, record_ciphertext, sender_ciphertext)
127 }
128 4 => {
129 let commitment = FromBytes::read_le(&mut reader)?;
130 Self::ExternalRecord(commitment)
131 }
132 5 => {
133 let future_hash: Field<N> = FromBytes::read_le(&mut reader)?;
134 let future_exists: bool = FromBytes::read_le(&mut reader)?;
135 let future = match future_exists {
136 true => Some(FromBytes::read_le(&mut reader)?),
137 false => None,
138 };
139 Self::Future(future_hash, future)
140 }
141 6 => {
142 let commitment = FromBytes::read_le(&mut reader)?;
143 Self::DynamicRecord(commitment)
144 }
145 7 => {
146 let (commitment, checksum, record_ciphertext, sender_ciphertext) = read_record_fields(&mut reader)?;
147 let dynamic_id: Field<N> = FromBytes::read_le(&mut reader)?;
149 Self::RecordWithDynamicID(commitment, checksum, record_ciphertext, sender_ciphertext, dynamic_id)
150 }
151 8 => {
152 let external_hash: Field<N> = FromBytes::read_le(&mut reader)?;
154 let dynamic_id: Field<N> = FromBytes::read_le(&mut reader)?;
156 Self::ExternalRecordWithDynamicID(external_hash, dynamic_id)
158 }
159 9.. => return Err(error(format!("Failed to decode output variant {index}"))),
160 };
161 Ok(literal)
162 }
163}
164
165impl<N: Network> ToBytes for Output<N> {
166 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
168 match self {
169 Self::Constant(plaintext_hash, plaintext) => {
170 (0 as Variant).write_le(&mut writer)?;
171 plaintext_hash.write_le(&mut writer)?;
172 match plaintext {
173 Some(plaintext) => {
174 true.write_le(&mut writer)?;
175 plaintext.write_le(&mut writer)
176 }
177 None => false.write_le(&mut writer),
178 }
179 }
180 Self::Public(plaintext_hash, plaintext) => {
181 (1 as Variant).write_le(&mut writer)?;
182 plaintext_hash.write_le(&mut writer)?;
183 match plaintext {
184 Some(plaintext) => {
185 true.write_le(&mut writer)?;
186 plaintext.write_le(&mut writer)
187 }
188 None => false.write_le(&mut writer),
189 }
190 }
191 Self::Private(ciphertext_hash, ciphertext) => {
192 (2 as Variant).write_le(&mut writer)?;
193 ciphertext_hash.write_le(&mut writer)?;
194 match ciphertext {
195 Some(ciphertext) => {
196 true.write_le(&mut writer)?;
197 ciphertext.write_le(&mut writer)
198 }
199 None => false.write_le(&mut writer),
200 }
201 }
202 Self::Record(commitment, checksum, record_ciphertext, sender_ciphertext) => {
203 (3 as Variant).write_le(&mut writer)?;
204 write_record_fields(&mut writer, commitment, checksum, record_ciphertext, sender_ciphertext)
205 }
206 Self::ExternalRecord(commitment) => {
207 (4 as Variant).write_le(&mut writer)?;
208 commitment.write_le(&mut writer)
209 }
210 Self::Future(future_hash, future) => {
211 (5 as Variant).write_le(&mut writer)?;
212 future_hash.write_le(&mut writer)?;
213 match future {
214 Some(future) => {
215 true.write_le(&mut writer)?;
216 future.write_le(&mut writer)
217 }
218 None => false.write_le(&mut writer),
219 }
220 }
221 Self::DynamicRecord(commitment) => {
222 (6 as Variant).write_le(&mut writer)?;
223 commitment.write_le(&mut writer)
224 }
225 Self::RecordWithDynamicID(commitment, checksum, record_ciphertext, sender_ciphertext, dynamic_id) => {
226 (7 as Variant).write_le(&mut writer)?;
227 write_record_fields(&mut writer, commitment, checksum, record_ciphertext, sender_ciphertext)?;
228 dynamic_id.write_le(&mut writer)
230 }
231 Self::ExternalRecordWithDynamicID(external_hash, dynamic_id) => {
232 (8 as Variant).write_le(&mut writer)?;
233 external_hash.write_le(&mut writer)?;
234 dynamic_id.write_le(&mut writer)
235 }
236 }
237 }
238}
239
240#[cfg(test)]
241mod tests {
242 use super::*;
243
244 #[test]
245 fn test_bytes() {
246 for (_, expected) in crate::transition::output::test_helpers::sample_outputs() {
247 let expected_bytes = expected.to_bytes_le().unwrap();
249 assert_eq!(expected, Output::read_le(&expected_bytes[..]).unwrap());
250 }
251 }
252}