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 let plaintext = Self::read_le_internal(&mut bytes.as_slice(), depth + 1)?;
55 members.insert(identifier, plaintext);
57 }
58 Self::Struct(members, Default::default())
60 }
61 2 => {
62 let num_elements = u32::read_le(&mut reader)?;
64 if num_elements as usize > N::MAX_ARRAY_ELEMENTS {
65 return Err(error("Failed to deserialize plaintext: Array exceeds maximum length"));
66 }
67 let mut elements = Vec::with_capacity(num_elements as usize);
69 for _ in 0..num_elements {
70 let num_bytes = u16::read_le(&mut reader)?;
72 let mut bytes = Vec::new();
74 (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
75 let plaintext = Self::read_le_internal(&mut bytes.as_slice(), depth + 1)?;
77 elements.push(plaintext);
79 }
80 Self::Array(elements, Default::default())
82 }
83 3.. => return Err(error(format!("Failed to decode plaintext variant {index}"))),
84 };
85 Ok(plaintext)
86 }
87}
88
89impl<N: Network> ToBytes for Plaintext<N> {
90 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
92 match self {
93 Self::Literal(literal, ..) => {
94 0u8.write_le(&mut writer)?;
95 literal.write_le(&mut writer)
96 }
97 Self::Struct(struct_, ..) => {
98 1u8.write_le(&mut writer)?;
99
100 u8::try_from(struct_.len()).map_err(error)?.write_le(&mut writer)?;
102
103 for (member_name, member_value) in struct_ {
105 member_name.write_le(&mut writer)?;
107
108 let bytes = member_value.to_bytes_le().map_err(|e| error(e.to_string()))?;
110 u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
112 bytes.write_le(&mut writer)?;
114 }
115 Ok(())
116 }
117 Self::Array(array, ..) => {
118 2u8.write_le(&mut writer)?;
119
120 u32::try_from(array.len()).map_err(error)?.write_le(&mut writer)?;
122
123 for element in array {
125 let bytes = element.to_bytes_le().map_err(error)?;
127 u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
129 bytes.write_le(&mut writer)?;
131 }
132 Ok(())
133 }
134 }
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141 use snarkvm_console_network::MainnetV0;
142
143 type CurrentNetwork = MainnetV0;
144
145 const ITERATIONS: u32 = 1000;
146
147 fn check_bytes(expected: Plaintext<CurrentNetwork>) -> Result<()> {
148 let expected_bytes = expected.to_bytes_le()?;
150 assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
151 Ok(())
152 }
153
154 #[test]
155 fn test_bytes() -> Result<()> {
156 let rng = &mut TestRng::default();
157
158 for _ in 0..ITERATIONS {
159 let private_key = snarkvm_console_account::PrivateKey::<CurrentNetwork>::new(rng)?;
160
161 check_bytes(Plaintext::Literal(
163 Literal::<CurrentNetwork>::Address(Address::try_from(private_key)?),
164 Default::default(),
165 ))?;
166 check_bytes(Plaintext::Literal(
168 Literal::<CurrentNetwork>::Boolean(Boolean::new(Uniform::rand(rng))),
169 Default::default(),
170 ))?;
171 check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Field(Uniform::rand(rng)), Default::default()))?;
173 check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Group(Uniform::rand(rng)), Default::default()))?;
175 check_bytes(Plaintext::Literal(
177 Literal::<CurrentNetwork>::I8(I8::new(Uniform::rand(rng))),
178 Default::default(),
179 ))?;
180 check_bytes(Plaintext::Literal(
182 Literal::<CurrentNetwork>::I16(I16::new(Uniform::rand(rng))),
183 Default::default(),
184 ))?;
185 check_bytes(Plaintext::Literal(
187 Literal::<CurrentNetwork>::I32(I32::new(Uniform::rand(rng))),
188 Default::default(),
189 ))?;
190 check_bytes(Plaintext::Literal(
192 Literal::<CurrentNetwork>::I64(I64::new(Uniform::rand(rng))),
193 Default::default(),
194 ))?;
195 check_bytes(Plaintext::Literal(
197 Literal::<CurrentNetwork>::I128(I128::new(Uniform::rand(rng))),
198 Default::default(),
199 ))?;
200 check_bytes(Plaintext::Literal(
202 Literal::<CurrentNetwork>::U8(U8::new(Uniform::rand(rng))),
203 Default::default(),
204 ))?;
205 check_bytes(Plaintext::Literal(
207 Literal::<CurrentNetwork>::U16(U16::new(Uniform::rand(rng))),
208 Default::default(),
209 ))?;
210 check_bytes(Plaintext::Literal(
212 Literal::<CurrentNetwork>::U32(U32::new(Uniform::rand(rng))),
213 Default::default(),
214 ))?;
215 check_bytes(Plaintext::Literal(
217 Literal::<CurrentNetwork>::U64(U64::new(Uniform::rand(rng))),
218 Default::default(),
219 ))?;
220 check_bytes(Plaintext::Literal(
222 Literal::<CurrentNetwork>::U128(U128::new(Uniform::rand(rng))),
223 Default::default(),
224 ))?;
225 check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Scalar(Uniform::rand(rng)), Default::default()))?;
227 check_bytes(Plaintext::Literal(
229 Literal::<CurrentNetwork>::String(StringType::rand(rng)),
230 Default::default(),
231 ))?;
232 }
233
234 let expected = Plaintext::<CurrentNetwork>::from_str(
236 "{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah, token_amount: 100u64 }",
237 )?;
238
239 let expected_bytes = expected.to_bytes_le()?;
241 assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
242
243 let expected = Plaintext::<CurrentNetwork>::from_str("[ 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8 ]")?;
245
246 let expected_bytes = expected.to_bytes_le()?;
248 assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
249
250 Ok(())
251 }
252
253 fn get_depth(plaintext: &Plaintext<CurrentNetwork>) -> usize {
255 match plaintext {
256 Plaintext::Literal(_, _) => 0,
257 Plaintext::Struct(members, _) => members.values().map(get_depth).max().unwrap_or(0) + 1,
258 Plaintext::Array(elements, _) => elements.iter().map(get_depth).max().unwrap_or(0) + 1,
259 }
260 }
261
262 #[test]
263 fn test_deeply_nested_plaintext() {
264 fn create_nested_array(depth: usize, root: impl Display) -> Vec<u8> {
266 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap();
268 result.reverse();
270 for _ in 0..depth {
272 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
274 length.reverse();
275 result.extend(length);
276 let mut num_elements = 1u32.to_bytes_le().unwrap();
278 num_elements.reverse();
279 result.extend(num_elements);
280 let mut variant = 2u8.to_bytes_le().unwrap();
282 variant.reverse();
283 result.extend(variant);
284 }
285 result.reverse();
287 result
288 }
289
290 fn create_nested_struct(depth: usize, root: impl Display) -> Vec<u8> {
292 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap();
294 result.reverse();
296 for _ in 0..depth {
298 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
300 length.reverse();
301 result.extend(length);
302 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bytes_le().unwrap();
304 member_name.reverse();
305 result.extend(member_name);
306 let mut num_members = 1u8.to_bytes_le().unwrap();
308 num_members.reverse();
309 result.extend(num_members);
310 let mut variant = 1u8.to_bytes_le().unwrap();
312 variant.reverse();
313 result.extend(variant);
314 }
315 result.reverse();
317 result
318 }
319
320 fn create_alternated_nested(depth: usize, root: impl Display) -> Vec<u8> {
322 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap();
324 result.reverse();
326 for i in 0..depth {
328 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
330 length.reverse();
331 result.extend(length);
332 if i % 2 == 0 {
334 let mut num_elements = 1u32.to_bytes_le().unwrap();
336 num_elements.reverse();
337 result.extend(num_elements);
338 let mut variant = 2u8.to_bytes_le().unwrap();
340 variant.reverse();
341 result.extend(variant);
342 } else {
343 let mut member_name =
345 Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bytes_le().unwrap();
346 member_name.reverse();
347 result.extend(member_name);
348 let mut num_members = 1u8.to_bytes_le().unwrap();
350 num_members.reverse();
351 result.extend(num_members);
352 let mut variant = 1u8.to_bytes_le().unwrap();
354 variant.reverse();
355 result.extend(variant);
356 }
357 }
358 result.reverse();
360 result
361 }
362
363 fn run_test(expected_depth: usize, input: Vec<u8>, expected_error: bool) {
365 let result = Plaintext::<CurrentNetwork>::read_le(&*input);
367 match expected_error {
369 true => {
370 assert!(result.is_err());
371 return;
372 }
373 false => assert!(result.is_ok()),
374 };
375 let candidate = result.unwrap();
377 assert_eq!(input, candidate.to_bytes_le().unwrap());
379 assert_eq!(get_depth(&candidate), expected_depth);
381 }
382
383 let mut depths = (0usize..100).collect_vec();
386 depths.extend((100..6500).step_by(100));
387
388 for i in depths.iter().copied() {
390 run_test(i, create_nested_array(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
391 run_test(i, create_nested_array(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
392 run_test(i, create_nested_array(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
393 run_test(i, create_nested_array(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
394 }
395
396 for i in depths.iter().copied() {
398 run_test(i, create_nested_struct(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
399 run_test(i, create_nested_struct(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
400 run_test(i, create_nested_struct(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
401 run_test(i, create_nested_struct(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
402 }
403
404 for i in depths.iter().copied() {
406 run_test(i, create_alternated_nested(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
407 run_test(i, create_alternated_nested(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
408 run_test(i, create_alternated_nested(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
409 run_test(i, create_alternated_nested(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
410 }
411 }
412}