snarkvm_console_program/data/plaintext/
bytes.rs1use super::*;
17
18impl<N: Network> FromBytes for Plaintext<N> {
19 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
21 Self::read_le_internal(&mut reader, 0)
22 }
23}
24
25impl<N: Network> Plaintext<N> {
26 fn read_le_internal<R: Read>(mut reader: R, depth: usize) -> IoResult<Self> {
28 if depth > N::MAX_DATA_DEPTH {
30 return Err(error(format!(
31 "Failed to deserialize plaintext: Depth exceeds maximum limit: {}",
32 N::MAX_DATA_DEPTH
33 )));
34 }
35 let index = u8::read_le(&mut reader)?;
37 let plaintext = match index {
39 0 => Self::Literal(Literal::read_le(&mut reader)?, Default::default()),
40 1 => {
41 let num_members = u8::read_le(&mut reader)?;
43 let mut members = IndexMap::with_capacity(num_members as usize);
45 for _ in 0..num_members {
46 let identifier = Identifier::<N>::read_le(&mut reader)?;
48 let num_bytes = u16::read_le(&mut reader)?;
50 let mut bytes = Vec::new();
52 (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
53 if bytes.len() != num_bytes as usize {
55 return Err(error("Failed to deserialize plaintext: struct member is truncated"));
56 }
57 let mut slice = bytes.as_slice();
59 let plaintext = Self::read_le_internal(&mut slice, depth + 1)?;
60 if !slice.is_empty() {
63 return Err(error("Failed to deserialize plaintext: struct member has trailing bytes"));
64 }
65 members.insert(identifier, plaintext);
67 }
68 Self::Struct(members, Default::default())
70 }
71 2 => {
72 let num_elements = u32::read_le(&mut reader)?;
74 if num_elements as usize > N::LATEST_MAX_ARRAY_ELEMENTS() {
75 return Err(error("Failed to deserialize plaintext: Array exceeds maximum length"));
76 }
77 let mut elements = Vec::with_capacity(num_elements as usize);
79 for _ in 0..num_elements {
80 let num_bytes = u16::read_le(&mut reader)?;
82 let mut bytes = Vec::new();
84 (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
85 if bytes.len() != num_bytes as usize {
87 return Err(error("Failed to deserialize plaintext: array element is truncated"));
88 }
89 let mut slice = bytes.as_slice();
91 let plaintext = Self::read_le_internal(&mut slice, depth + 1)?;
92 if !slice.is_empty() {
95 return Err(error("Failed to deserialize plaintext: array element has trailing bytes"));
96 }
97 elements.push(plaintext);
99 }
100 Self::Array(elements, Default::default())
102 }
103 3.. => return Err(error(format!("Failed to decode plaintext variant {index}"))),
104 };
105 Ok(plaintext)
106 }
107}
108
109impl<N: Network> ToBytes for Plaintext<N> {
110 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
112 match self {
113 Self::Literal(literal, ..) => {
114 0u8.write_le(&mut writer)?;
115 literal.write_le(&mut writer)
116 }
117 Self::Struct(struct_, ..) => {
118 1u8.write_le(&mut writer)?;
119
120 u8::try_from(struct_.len()).map_err(error)?.write_le(&mut writer)?;
122
123 for (member_name, member_value) in struct_ {
125 member_name.write_le(&mut writer)?;
127
128 let bytes = member_value.to_bytes_le().map_err(|e| error(e.to_string()))?;
130 u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
132 bytes.write_le(&mut writer)?;
134 }
135 Ok(())
136 }
137 Self::Array(array, ..) => {
138 2u8.write_le(&mut writer)?;
139
140 u32::try_from(array.len()).map_err(error)?.write_le(&mut writer)?;
142
143 for element in array {
145 let bytes = element.to_bytes_le().map_err(error)?;
147 u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
149 bytes.write_le(&mut writer)?;
151 }
152 Ok(())
153 }
154 }
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use snarkvm_console_network::MainnetV0;
162
163 type CurrentNetwork = MainnetV0;
164
165 const ITERATIONS: u32 = 1000;
166
167 fn check_bytes(expected: Plaintext<CurrentNetwork>) -> Result<()> {
168 let expected_bytes = expected.to_bytes_le()?;
170 assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
171 Ok(())
172 }
173
174 #[test]
175 fn test_bytes() -> Result<()> {
176 let rng = &mut TestRng::default();
177
178 for _ in 0..ITERATIONS {
179 let private_key = snarkvm_console_account::PrivateKey::<CurrentNetwork>::new(rng)?;
180
181 check_bytes(Plaintext::Literal(
183 Literal::<CurrentNetwork>::Address(Address::try_from(private_key)?),
184 Default::default(),
185 ))?;
186 check_bytes(Plaintext::Literal(
188 Literal::<CurrentNetwork>::Boolean(Boolean::new(Uniform::rand(rng))),
189 Default::default(),
190 ))?;
191 check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Field(Uniform::rand(rng)), Default::default()))?;
193 check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Group(Uniform::rand(rng)), Default::default()))?;
195 check_bytes(Plaintext::Literal(
197 Literal::<CurrentNetwork>::I8(I8::new(Uniform::rand(rng))),
198 Default::default(),
199 ))?;
200 check_bytes(Plaintext::Literal(
202 Literal::<CurrentNetwork>::I16(I16::new(Uniform::rand(rng))),
203 Default::default(),
204 ))?;
205 check_bytes(Plaintext::Literal(
207 Literal::<CurrentNetwork>::I32(I32::new(Uniform::rand(rng))),
208 Default::default(),
209 ))?;
210 check_bytes(Plaintext::Literal(
212 Literal::<CurrentNetwork>::I64(I64::new(Uniform::rand(rng))),
213 Default::default(),
214 ))?;
215 check_bytes(Plaintext::Literal(
217 Literal::<CurrentNetwork>::I128(I128::new(Uniform::rand(rng))),
218 Default::default(),
219 ))?;
220 check_bytes(Plaintext::Literal(
222 Literal::<CurrentNetwork>::U8(U8::new(Uniform::rand(rng))),
223 Default::default(),
224 ))?;
225 check_bytes(Plaintext::Literal(
227 Literal::<CurrentNetwork>::U16(U16::new(Uniform::rand(rng))),
228 Default::default(),
229 ))?;
230 check_bytes(Plaintext::Literal(
232 Literal::<CurrentNetwork>::U32(U32::new(Uniform::rand(rng))),
233 Default::default(),
234 ))?;
235 check_bytes(Plaintext::Literal(
237 Literal::<CurrentNetwork>::U64(U64::new(Uniform::rand(rng))),
238 Default::default(),
239 ))?;
240 check_bytes(Plaintext::Literal(
242 Literal::<CurrentNetwork>::U128(U128::new(Uniform::rand(rng))),
243 Default::default(),
244 ))?;
245 check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Scalar(Uniform::rand(rng)), Default::default()))?;
247 check_bytes(Plaintext::Literal(
249 Literal::<CurrentNetwork>::String(StringType::rand(rng)),
250 Default::default(),
251 ))?;
252 }
253
254 let expected = Plaintext::<CurrentNetwork>::from_str(
256 "{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah, token_amount: 100u64 }",
257 )?;
258
259 let expected_bytes = expected.to_bytes_le()?;
261 assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
262
263 let expected = Plaintext::<CurrentNetwork>::from_str("[ 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8 ]")?;
265
266 let expected_bytes = expected.to_bytes_le()?;
268 assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
269
270 Ok(())
271 }
272
273 fn get_depth(plaintext: &Plaintext<CurrentNetwork>) -> usize {
275 match plaintext {
276 Plaintext::Literal(_, _) => 0,
277 Plaintext::Struct(members, _) => members.values().map(get_depth).max().unwrap_or(0) + 1,
278 Plaintext::Array(elements, _) => elements.iter().map(get_depth).max().unwrap_or(0) + 1,
279 }
280 }
281
282 #[test]
283 fn test_deeply_nested_plaintext() {
284 fn create_nested_array(depth: usize, root: impl Display) -> Vec<u8> {
286 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap();
288 result.reverse();
290 for _ in 0..depth {
292 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
294 length.reverse();
295 result.extend(length);
296 let mut num_elements = 1u32.to_bytes_le().unwrap();
298 num_elements.reverse();
299 result.extend(num_elements);
300 let mut variant = 2u8.to_bytes_le().unwrap();
302 variant.reverse();
303 result.extend(variant);
304 }
305 result.reverse();
307 result
308 }
309
310 fn create_nested_struct(depth: usize, root: impl Display) -> Vec<u8> {
312 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap();
314 result.reverse();
316 for _ in 0..depth {
318 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
320 length.reverse();
321 result.extend(length);
322 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bytes_le().unwrap();
324 member_name.reverse();
325 result.extend(member_name);
326 let mut num_members = 1u8.to_bytes_le().unwrap();
328 num_members.reverse();
329 result.extend(num_members);
330 let mut variant = 1u8.to_bytes_le().unwrap();
332 variant.reverse();
333 result.extend(variant);
334 }
335 result.reverse();
337 result
338 }
339
340 fn create_alternated_nested(depth: usize, root: impl Display) -> Vec<u8> {
342 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap();
344 result.reverse();
346 for i in 0..depth {
348 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
350 length.reverse();
351 result.extend(length);
352 if i % 2 == 0 {
354 let mut num_elements = 1u32.to_bytes_le().unwrap();
356 num_elements.reverse();
357 result.extend(num_elements);
358 let mut variant = 2u8.to_bytes_le().unwrap();
360 variant.reverse();
361 result.extend(variant);
362 } else {
363 let mut member_name =
365 Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bytes_le().unwrap();
366 member_name.reverse();
367 result.extend(member_name);
368 let mut num_members = 1u8.to_bytes_le().unwrap();
370 num_members.reverse();
371 result.extend(num_members);
372 let mut variant = 1u8.to_bytes_le().unwrap();
374 variant.reverse();
375 result.extend(variant);
376 }
377 }
378 result.reverse();
380 result
381 }
382
383 fn run_test(expected_depth: usize, input: Vec<u8>, expected_error: bool) {
385 let result = Plaintext::<CurrentNetwork>::read_le(&*input);
387 match expected_error {
389 true => {
390 assert!(result.is_err());
391 return;
392 }
393 false => assert!(result.is_ok()),
394 };
395 let candidate = result.unwrap();
397 assert_eq!(input, candidate.to_bytes_le().unwrap());
399 assert_eq!(get_depth(&candidate), expected_depth);
401 }
402
403 let mut depths = (0usize..100).collect_vec();
406 depths.extend((100..6500).step_by(100));
407
408 for i in depths.iter().copied() {
410 run_test(i, create_nested_array(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
411 run_test(i, create_nested_array(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
412 run_test(i, create_nested_array(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
413 run_test(i, create_nested_array(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
414 }
415
416 for i in depths.iter().copied() {
418 run_test(i, create_nested_struct(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
419 run_test(i, create_nested_struct(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
420 run_test(i, create_nested_struct(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
421 run_test(i, create_nested_struct(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
422 }
423
424 for i in depths.iter().copied() {
426 run_test(i, create_alternated_nested(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
427 run_test(i, create_alternated_nested(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
428 run_test(i, create_alternated_nested(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
429 run_test(i, create_alternated_nested(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
430 }
431 }
432
433 fn struct_with_padded_member(padding: usize) -> Result<Vec<u8>> {
436 let member = Plaintext::<CurrentNetwork>::Literal(Literal::U8(U8::new(7)), Default::default());
437 let member_bytes = member.to_bytes_le()?;
438
439 let mut bytes = Vec::new();
440 1u8.write_le(&mut bytes)?;
441 1u8.write_le(&mut bytes)?;
442 Identifier::<CurrentNetwork>::from_str("a")?.write_le(&mut bytes)?;
443 u16::try_from(member_bytes.len() + padding)?.write_le(&mut bytes)?;
444 bytes.extend_from_slice(&member_bytes);
445 bytes.extend(std::iter::repeat_n(0u8, padding));
446 Ok(bytes)
447 }
448
449 fn array_with_padded_element(padding: usize) -> Result<Vec<u8>> {
452 let element = Plaintext::<CurrentNetwork>::Literal(Literal::U8(U8::new(7)), Default::default());
453 let element_bytes = element.to_bytes_le()?;
454
455 let mut bytes = Vec::new();
456 2u8.write_le(&mut bytes)?;
457 1u32.write_le(&mut bytes)?;
458 u16::try_from(element_bytes.len() + padding)?.write_le(&mut bytes)?;
459 bytes.extend_from_slice(&element_bytes);
460 bytes.extend(std::iter::repeat_n(0u8, padding));
461 Ok(bytes)
462 }
463
464 #[test]
465 fn test_struct_member_rejects_trailing_bytes() -> Result<()> {
466 let exact = struct_with_padded_member(0)?;
468 let plaintext = Plaintext::<CurrentNetwork>::read_le(&exact[..])?;
469 assert_eq!(exact, plaintext.to_bytes_le()?, "the unpadded encoding must round trip");
470
471 for padding in [1, 8, 32] {
475 let padded = struct_with_padded_member(padding)?;
476 assert_ne!(padded, exact);
477 assert!(
478 Plaintext::<CurrentNetwork>::read_le(&padded[..]).is_err(),
479 "a struct member declaring {padding} bytes more than it uses must be rejected"
480 );
481 }
482 Ok(())
483 }
484
485 #[test]
486 fn test_array_element_rejects_trailing_bytes() -> Result<()> {
487 let exact = array_with_padded_element(0)?;
488 let plaintext = Plaintext::<CurrentNetwork>::read_le(&exact[..])?;
489 assert_eq!(exact, plaintext.to_bytes_le()?, "the unpadded encoding must round trip");
490
491 for padding in [1, 8, 32] {
492 let padded = array_with_padded_element(padding)?;
493 assert_ne!(padded, exact);
494 assert!(
495 Plaintext::<CurrentNetwork>::read_le(&padded[..]).is_err(),
496 "an array element declaring {padding} bytes more than it uses must be rejected"
497 );
498 }
499 Ok(())
500 }
501}