snarkvm_console_program/data/future/
bytes.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use super::*;
17
18impl<N: Network> FromBytes for Future<N> {
19    /// Reads in a future from a buffer.
20    fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
21        // Read the future.
22        Self::read_le_internal(&mut reader, 0)
23    }
24}
25
26impl<N: Network> Future<N> {
27    /// Reads in a future from a buffer, while tracking the depth of the data.
28    fn read_le_internal<R: Read>(mut reader: R, depth: usize) -> IoResult<Self> {
29        // Ensure that the depth is within the maximum limit.
30        // Note: `N::MAX_DATA_DEPTH` is an upper bound on the number of nested futures.
31        //  The true maximum is defined by `Transaction::<N>::MAX_TRANSITIONS`, however, that object is not accessible in this crate.
32        //  In practice, `MAX_DATA_DEPTH` is 32, while `MAX_TRANSITIONS` is 31.
33        //  TODO: @d0cd, should we use a more precise bound?
34        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        // Read the program ID.
41        let program_id = ProgramID::read_le(&mut reader)?;
42        // Read the function name.
43        let function_name = Identifier::<N>::read_le(&mut reader)?;
44        // Read the number of arguments to the future.
45        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        // Read the arguments.
50        let mut arguments = Vec::with_capacity(num_arguments);
51        for _ in 0..num_arguments {
52            // Read the argument (in 2 steps to prevent infinite recursion).
53            let num_bytes = u16::read_le(&mut reader)?;
54            // Read the argument bytes.
55            let mut bytes = Vec::new();
56            (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
57            // Recover the argument.
58            let entry = Argument::read_le_internal(&mut bytes.as_slice(), depth)?;
59            // Add the argument.
60            arguments.push(entry);
61        }
62        // Return the future.
63        Ok(Self::new(program_id, function_name, arguments))
64    }
65}
66
67impl<N: Network> ToBytes for Future<N> {
68    /// Writes a future to a buffer.
69    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
70        // Write the program ID.
71        self.program_id.write_le(&mut writer)?;
72        // Write the function name.
73        self.function_name.write_le(&mut writer)?;
74        // Write the number of arguments.
75        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        // Write each argument.
80        for argument in &self.arguments {
81            // Write the argument (performed in 2 steps to prevent infinite recursion).
82            let bytes = argument.to_bytes_le().map_err(error)?;
83            // Write the number of bytes.
84            u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
85            // Write the bytes.
86            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        // Read the index.
98        let index = u8::read_le(&mut reader)?;
99        // Read the argument.
100        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        // Check the future manually.
134        let expected =
135            Future::<CurrentNetwork>::from_str("{ program_id: credits.aleo, function_name: transfer, arguments: [] }")?;
136
137        // Check the byte representation.
138        let expected_bytes = expected.to_bytes_le()?;
139        assert_eq!(expected, Future::read_le(&expected_bytes[..])?);
140
141        Ok(())
142    }
143
144    // A helper function to get the depth of a future.
145    fn get_depth<N: Network>(future: &Future<N>) -> usize {
146        // Count the number of nested futures.
147        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        // Creates a nested `Future`.
160        // This method is iterative to avoid stack overflows.
161        fn create_nested_future(depth: usize) -> Vec<u8> {
162            // Start from the innermost value.
163            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            // Reverse the bytes.
174            result.reverse();
175            // Build up the structure in reverse.
176            for _ in 0..depth {
177                // Write the variant of the argument in reverse.
178                let mut variant = 1u8.to_bytes_le().unwrap();
179                variant.reverse();
180                result.extend(variant);
181                // Write the size of the object in bytes in reverse.
182                let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
183                length.reverse();
184                result.extend(length);
185                // Write the number of arguments in reverse.
186                let mut num_elements = 1u8.to_bytes_le().unwrap();
187                num_elements.reverse();
188                result.extend(num_elements);
189                // Write the function name in reverse.
190                let mut function_name = Identifier::<CurrentNetwork>::from_str("bar").unwrap().to_bytes_le().unwrap();
191                function_name.reverse();
192                result.extend(function_name);
193                // Write the program ID in reverse.
194                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            // Reverse the result to get the correct order.
199            result.reverse();
200            result
201        }
202
203        // A helper function to run the test.
204        fn run_test(expected_depth: usize, input: Vec<u8>, expected_error: bool) {
205            // Parse the input string.
206            let result = Future::<CurrentNetwork>::read_le(&*input);
207            // // Check if the result is an error.
208            match expected_error {
209                true => {
210                    assert!(result.is_err());
211                    return;
212                }
213                false => assert!(result.is_ok()),
214            };
215            // Unwrap the result.
216            let candidate = result.unwrap();
217            // Check if the candidate is equal to the input, with whitespace removed.
218            assert_eq!(input, candidate.to_bytes_le().unwrap());
219            // Check if the candidate is equal to the expected depth.
220            assert_eq!(get_depth(&candidate), expected_depth);
221        }
222
223        // Initialize a sequence of depths to check.
224        // Note: It is not possible to create a `Future` of depth 4000 in this test as it's size would exceed `u16::MAX`.
225        let mut depths = (0usize..100).collect_vec();
226        depths.extend((100..3900).step_by(100));
227
228        // Test deeply nested arrays with different literal types.
229        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}