snarkvm_console_program/data/future/
bytes.rs1use super::*;
17
18impl<N: Network> FromBytes for Future<N> {
19 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
21 Self::read_le_internal(&mut reader, 0)
23 }
24}
25
26impl<N: Network> Future<N> {
27 fn read_le_internal<R: Read>(mut reader: R, depth: usize) -> IoResult<Self> {
29 if depth > N::MAX_DATA_DEPTH {
34 return Err(error(format!(
35 "Failed to deserialize plaintext: Depth exceeds maximum limit: {}",
36 N::MAX_DATA_DEPTH
37 )));
38 }
39 let program_id = ProgramID::read_le(&mut reader)?;
41 let function_name = Identifier::<N>::read_le(&mut reader)?;
43 let num_arguments = u8::read_le(&mut reader)? as usize;
45 if num_arguments > N::MAX_INPUTS {
46 return Err(error("Failed to read future: too many arguments"));
47 };
48 let mut arguments = Vec::with_capacity(num_arguments);
50 for _ in 0..num_arguments {
51 let num_bytes = u16::read_le(&mut reader)?;
53 let mut bytes = Vec::new();
55 (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
56 let entry = Argument::read_le_internal(&mut bytes.as_slice(), depth)?;
58 arguments.push(entry);
60 }
61 Ok(Self::new(program_id, function_name, arguments))
63 }
64}
65
66impl<N: Network> ToBytes for Future<N> {
67 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
69 self.program_id.write_le(&mut writer)?;
71 self.function_name.write_le(&mut writer)?;
73 if self.arguments.len() > N::MAX_INPUTS {
75 return Err(error("Failed to write future: too many arguments"));
76 };
77 u8::try_from(self.arguments.len()).map_err(error)?.write_le(&mut writer)?;
78 for argument in &self.arguments {
80 let bytes = argument.to_bytes_le().map_err(error)?;
82 u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
84 bytes.write_le(&mut writer)?;
86 }
87 Ok(())
88 }
89}
90
91impl<N: Network> Argument<N> {
92 fn read_le_internal<R: Read>(mut reader: R, depth: usize) -> IoResult<Self>
93 where
94 Self: Sized,
95 {
96 let index = u8::read_le(&mut reader)?;
98 let argument = match index {
100 0 => Self::Plaintext(Plaintext::read_le(&mut reader)?),
101 1 => Self::Future(Future::read_le_internal(&mut reader, depth + 1)?),
102 2 => Self::DynamicFuture(DynamicFuture::read_le(&mut reader)?),
103 3.. => return Err(error(format!("Failed to decode future argument {index}"))),
104 };
105 Ok(argument)
106 }
107}
108
109impl<N: Network> ToBytes for Argument<N> {
110 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
111 match self {
112 Self::Plaintext(plaintext) => {
113 0u8.write_le(&mut writer)?;
114 plaintext.write_le(&mut writer)
115 }
116 Self::Future(future) => {
117 1u8.write_le(&mut writer)?;
118 future.write_le(&mut writer)
119 }
120 Self::DynamicFuture(dynamic_future) => {
121 2u8.write_le(&mut writer)?;
122 dynamic_future.write_le(&mut writer)
123 }
124 }
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use snarkvm_console_network::MainnetV0;
132
133 use core::str::FromStr;
134
135 type CurrentNetwork = MainnetV0;
136
137 #[test]
138 fn test_bytes() {
139 let expected =
141 Future::<CurrentNetwork>::from_str("{ program_id: credits.aleo, function_name: transfer, arguments: [] }")
142 .unwrap();
143
144 let expected_bytes = expected.to_bytes_le().unwrap();
146 assert_eq!(expected, Future::read_le(&expected_bytes[..]).unwrap());
147 }
148
149 #[test]
150 fn test_bytes_with_plaintext_arguments() {
151 let expected = Future::<CurrentNetwork>::new(
153 ProgramID::from_str("test.aleo").unwrap(),
154 Identifier::from_str("foo").unwrap(),
155 vec![
156 Argument::Plaintext(Plaintext::from_str("100u64").unwrap()),
157 Argument::Plaintext(Plaintext::from_str("true").unwrap()),
158 ],
159 );
160
161 let expected_bytes = expected.to_bytes_le().unwrap();
163 let candidate = Future::read_le(&expected_bytes[..]).unwrap();
164 assert_eq!(expected, candidate);
165 }
166
167 #[test]
168 fn test_bytes_with_dynamic_future_argument() {
169 let inner = Future::<CurrentNetwork>::new(
171 ProgramID::from_str("inner.aleo").unwrap(),
172 Identifier::from_str("bar").unwrap(),
173 vec![Argument::Plaintext(Plaintext::from_str("42u64").unwrap())],
174 );
175
176 let dynamic_inner = DynamicFuture::from_future(&inner).unwrap();
178
179 let expected = Future::<CurrentNetwork>::new(
181 ProgramID::from_str("outer.aleo").unwrap(),
182 Identifier::from_str("baz").unwrap(),
183 vec![Argument::DynamicFuture(dynamic_inner)],
184 );
185
186 let expected_bytes = expected.to_bytes_le().unwrap();
188 let candidate = Future::read_le(&expected_bytes[..]).unwrap();
189
190 assert_eq!(expected.program_id(), candidate.program_id());
192 assert_eq!(expected.function_name(), candidate.function_name());
193 assert_eq!(expected.arguments().len(), candidate.arguments().len());
194
195 match (&expected.arguments()[0], &candidate.arguments()[0]) {
197 (Argument::DynamicFuture(e), Argument::DynamicFuture(c)) => {
198 assert_eq!(e.program_name(), c.program_name());
199 assert_eq!(e.program_network(), c.program_network());
200 assert_eq!(e.function_name(), c.function_name());
201 assert_eq!(e.checksum(), c.checksum());
202 }
203 _ => panic!("Expected DynamicFuture argument"),
204 }
205 }
206
207 #[test]
208 fn test_bytes_with_nested_future_argument() {
209 let inner = Future::<CurrentNetwork>::new(
211 ProgramID::from_str("inner.aleo").unwrap(),
212 Identifier::from_str("bar").unwrap(),
213 vec![Argument::Plaintext(Plaintext::from_str("42u64").unwrap())],
214 );
215
216 let expected = Future::<CurrentNetwork>::new(
218 ProgramID::from_str("outer.aleo").unwrap(),
219 Identifier::from_str("baz").unwrap(),
220 vec![Argument::Future(inner)],
221 );
222
223 let expected_bytes = expected.to_bytes_le().unwrap();
225 let candidate = Future::read_le(&expected_bytes[..]).unwrap();
226 assert_eq!(expected, candidate);
227 }
228
229 #[test]
230 fn test_bytes_with_mixed_arguments() {
231 let inner = Future::<CurrentNetwork>::new(
233 ProgramID::from_str("inner.aleo").unwrap(),
234 Identifier::from_str("bar").unwrap(),
235 vec![],
236 );
237
238 let dynamic_inner = DynamicFuture::from_future(&inner).unwrap();
240
241 let expected = Future::<CurrentNetwork>::new(
243 ProgramID::from_str("test.aleo").unwrap(),
244 Identifier::from_str("mixed").unwrap(),
245 vec![
246 Argument::Plaintext(Plaintext::from_str("100u64").unwrap()),
247 Argument::Future(inner),
248 Argument::DynamicFuture(dynamic_inner),
249 ],
250 );
251
252 let expected_bytes = expected.to_bytes_le().unwrap();
254 let candidate = Future::read_le(&expected_bytes[..]).unwrap();
255
256 assert_eq!(expected.program_id(), candidate.program_id());
258 assert_eq!(expected.function_name(), candidate.function_name());
259 assert_eq!(expected.arguments().len(), candidate.arguments().len());
260 }
261
262 fn get_depth<N: Network>(future: &Future<N>) -> usize {
264 future
266 .arguments
267 .iter()
268 .map(|arg| match arg {
269 Argument::Plaintext(_) => 0,
270 Argument::Future(future) => 1 + get_depth(future),
271 Argument::DynamicFuture(_) => panic!("Dynamic futures are not used in this test"),
272 })
273 .sum()
274 }
275
276 #[test]
277 fn test_deeply_nested_future() {
278 fn create_nested_future(depth: usize) -> Vec<u8> {
281 let mut result = Future::<CurrentNetwork>::from_str(
283 r"{
284 program_id: foo.aleo,
285 function_name: bar,
286 arguments: []
287 }",
288 )
289 .unwrap()
290 .to_bytes_le()
291 .unwrap();
292 result.reverse();
294 for _ in 0..depth {
296 let mut variant = 1u8.to_bytes_le().unwrap();
298 variant.reverse();
299 result.extend(variant);
300 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
302 length.reverse();
303 result.extend(length);
304 let mut num_elements = 1u8.to_bytes_le().unwrap();
306 num_elements.reverse();
307 result.extend(num_elements);
308 let mut function_name = Identifier::<CurrentNetwork>::from_str("bar").unwrap().to_bytes_le().unwrap();
310 function_name.reverse();
311 result.extend(function_name);
312 let mut program_id = ProgramID::<CurrentNetwork>::from_str("foo.aleo").unwrap().to_bytes_le().unwrap();
314 program_id.reverse();
315 result.extend(program_id);
316 }
317 result.reverse();
319 result
320 }
321
322 fn run_test(expected_depth: usize, input: Vec<u8>, expected_error: bool) {
324 let result = Future::<CurrentNetwork>::read_le(&*input);
326 match expected_error {
328 true => {
329 assert!(result.is_err());
330 return;
331 }
332 false => assert!(result.is_ok()),
333 };
334 let candidate = result.unwrap();
336 assert_eq!(input, candidate.to_bytes_le().unwrap());
338 assert_eq!(get_depth(&candidate), expected_depth);
340 }
341
342 let mut depths = (0usize..100).collect_vec();
345 depths.extend((100..3900).step_by(100));
346
347 for i in depths.iter().copied() {
349 run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
350 run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
351 run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
352 run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
353 }
354 }
355}