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 {
35 return Err(error(format!(
36 "Failed to deserialize plaintext: Depth exceeds maximum limit: {}",
37 N::MAX_DATA_DEPTH
38 )));
39 }
40 let program_id = ProgramID::read_le(&mut reader)?;
42 let function_name = Identifier::<N>::read_le(&mut reader)?;
44 let num_arguments = u8::read_le(&mut reader)? as usize;
46 if num_arguments > N::MAX_INPUTS {
47 return Err(error("Failed to read future: too many arguments"));
48 };
49 let mut arguments = Vec::with_capacity(num_arguments);
51 for _ in 0..num_arguments {
52 let num_bytes = u16::read_le(&mut reader)?;
54 let mut bytes = Vec::new();
56 (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
57 let entry = Argument::read_le_internal(&mut bytes.as_slice(), depth)?;
59 arguments.push(entry);
61 }
62 Ok(Self::new(program_id, function_name, arguments))
64 }
65}
66
67impl<N: Network> ToBytes for Future<N> {
68 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
70 self.program_id.write_le(&mut writer)?;
72 self.function_name.write_le(&mut writer)?;
74 if self.arguments.len() > N::MAX_INPUTS {
76 return Err(error("Failed to write future: too many arguments"));
77 };
78 u8::try_from(self.arguments.len()).map_err(error)?.write_le(&mut writer)?;
79 for argument in &self.arguments {
81 let bytes = argument.to_bytes_le().map_err(error)?;
83 u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
85 bytes.write_le(&mut writer)?;
87 }
88 Ok(())
89 }
90}
91
92impl<N: Network> Argument<N> {
93 fn read_le_internal<R: Read>(mut reader: R, depth: usize) -> IoResult<Self>
94 where
95 Self: Sized,
96 {
97 let index = u8::read_le(&mut reader)?;
99 let argument = match index {
101 0 => Self::Plaintext(Plaintext::read_le(&mut reader)?),
102 1 => Self::Future(Future::read_le_internal(&mut reader, depth + 1)?),
103 2.. => 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 }
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use snarkvm_console_network::MainnetV0;
128
129 type CurrentNetwork = MainnetV0;
130
131 #[test]
132 fn test_bytes() -> Result<()> {
133 let expected =
135 Future::<CurrentNetwork>::from_str("{ program_id: credits.aleo, function_name: transfer, arguments: [] }")?;
136
137 let expected_bytes = expected.to_bytes_le()?;
139 assert_eq!(expected, Future::read_le(&expected_bytes[..])?);
140
141 Ok(())
142 }
143
144 fn get_depth<N: Network>(future: &Future<N>) -> usize {
146 future
148 .arguments
149 .iter()
150 .map(|arg| match arg {
151 Argument::Plaintext(_) => 0,
152 Argument::Future(future) => 1 + get_depth(future),
153 })
154 .sum()
155 }
156
157 #[test]
158 fn test_deeply_nested_future() {
159 fn create_nested_future(depth: usize) -> Vec<u8> {
162 let mut result = Future::<CurrentNetwork>::from_str(
164 r"{
165 program_id: foo.aleo,
166 function_name: bar,
167 arguments: []
168 }",
169 )
170 .unwrap()
171 .to_bytes_le()
172 .unwrap();
173 result.reverse();
175 for _ in 0..depth {
177 let mut variant = 1u8.to_bytes_le().unwrap();
179 variant.reverse();
180 result.extend(variant);
181 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
183 length.reverse();
184 result.extend(length);
185 let mut num_elements = 1u8.to_bytes_le().unwrap();
187 num_elements.reverse();
188 result.extend(num_elements);
189 let mut function_name = Identifier::<CurrentNetwork>::from_str("bar").unwrap().to_bytes_le().unwrap();
191 function_name.reverse();
192 result.extend(function_name);
193 let mut program_id = ProgramID::<CurrentNetwork>::from_str("foo.aleo").unwrap().to_bytes_le().unwrap();
195 program_id.reverse();
196 result.extend(program_id);
197 }
198 result.reverse();
200 result
201 }
202
203 fn run_test(expected_depth: usize, input: Vec<u8>, expected_error: bool) {
205 let result = Future::<CurrentNetwork>::read_le(&*input);
207 match expected_error {
209 true => {
210 assert!(result.is_err());
211 return;
212 }
213 false => assert!(result.is_ok()),
214 };
215 let candidate = result.unwrap();
217 assert_eq!(input, candidate.to_bytes_le().unwrap());
219 assert_eq!(get_depth(&candidate), expected_depth);
221 }
222
223 let mut depths = (0usize..100).collect_vec();
226 depths.extend((100..3900).step_by(100));
227
228 for i in depths.iter().copied() {
230 run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
231 run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
232 run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
233 run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
234 }
235 }
236}