snarkvm_console_program/data/plaintext/
bytes.rs

1// Copyright 2024-2025 Aleo Network Foundation
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 Plaintext<N> {
19    /// Reads the plaintext from a buffer.
20    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    /// Reads the plaintext from a buffer, while tracking the depth of the data.
27    fn read_le_internal<R: Read>(mut reader: R, depth: usize) -> IoResult<Self> {
28        // Ensure that the depth is within the maximum limit.
29        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        // Read the index.
36        let index = u8::read_le(&mut reader)?;
37        // Read the plaintext.
38        let plaintext = match index {
39            0 => Self::Literal(Literal::read_le(&mut reader)?, Default::default()),
40            1 => {
41                // Read the number of members in the struct.
42                let num_members = u8::read_le(&mut reader)?;
43                // Read the members.
44                let mut members = IndexMap::with_capacity(num_members as usize);
45                for _ in 0..num_members {
46                    // Read the identifier.
47                    let identifier = Identifier::<N>::read_le(&mut reader)?;
48                    // Read the plaintext value (in 2 steps to prevent infinite recursion).
49                    let num_bytes = u16::read_le(&mut reader)?;
50                    // Read the plaintext bytes.
51                    let mut bytes = Vec::new();
52                    (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
53                    // Recover the plaintext value.
54                    let plaintext = Self::read_le_internal(&mut bytes.as_slice(), depth + 1)?;
55                    // Add the member.
56                    members.insert(identifier, plaintext);
57                }
58                // Return the struct.
59                Self::Struct(members, Default::default())
60            }
61            2 => {
62                // Read the length of the array.
63                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                // Read the elements.
68                let mut elements = Vec::with_capacity(num_elements as usize);
69                for _ in 0..num_elements {
70                    // Read the plaintext value (in 2 steps to prevent infinite recursion).
71                    let num_bytes = u16::read_le(&mut reader)?;
72                    // Read the plaintext bytes.
73                    let mut bytes = Vec::new();
74                    (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
75                    // Recover the plaintext value.
76                    let plaintext = Self::read_le_internal(&mut bytes.as_slice(), depth + 1)?;
77                    // Add the element.
78                    elements.push(plaintext);
79                }
80                // Return the array.
81                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    /// Writes the plaintext to a buffer.
91    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                // Write the number of members in the struct.
101                u8::try_from(struct_.len()).map_err(error)?.write_le(&mut writer)?;
102
103                // Write each member.
104                for (member_name, member_value) in struct_ {
105                    // Write the member name.
106                    member_name.write_le(&mut writer)?;
107
108                    // Write the member value (performed in 2 steps to prevent infinite recursion).
109                    let bytes = member_value.to_bytes_le().map_err(|e| error(e.to_string()))?;
110                    // Write the number of bytes.
111                    u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
112                    // Write the bytes.
113                    bytes.write_le(&mut writer)?;
114                }
115                Ok(())
116            }
117            Self::Array(array, ..) => {
118                2u8.write_le(&mut writer)?;
119
120                // Write the length of the array.
121                u32::try_from(array.len()).map_err(error)?.write_le(&mut writer)?;
122
123                // Write each element.
124                for element in array {
125                    // Write the element (performed in 2 steps to prevent infinite recursion).
126                    let bytes = element.to_bytes_le().map_err(error)?;
127                    // Write the number of bytes.
128                    u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
129                    // Write the bytes.
130                    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        // Check the byte representation.
149        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            // Address
162            check_bytes(Plaintext::Literal(
163                Literal::<CurrentNetwork>::Address(Address::try_from(private_key)?),
164                Default::default(),
165            ))?;
166            // Boolean
167            check_bytes(Plaintext::Literal(
168                Literal::<CurrentNetwork>::Boolean(Boolean::new(Uniform::rand(rng))),
169                Default::default(),
170            ))?;
171            // Field
172            check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Field(Uniform::rand(rng)), Default::default()))?;
173            // Group
174            check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Group(Uniform::rand(rng)), Default::default()))?;
175            // I8
176            check_bytes(Plaintext::Literal(
177                Literal::<CurrentNetwork>::I8(I8::new(Uniform::rand(rng))),
178                Default::default(),
179            ))?;
180            // I16
181            check_bytes(Plaintext::Literal(
182                Literal::<CurrentNetwork>::I16(I16::new(Uniform::rand(rng))),
183                Default::default(),
184            ))?;
185            // I32
186            check_bytes(Plaintext::Literal(
187                Literal::<CurrentNetwork>::I32(I32::new(Uniform::rand(rng))),
188                Default::default(),
189            ))?;
190            // I64
191            check_bytes(Plaintext::Literal(
192                Literal::<CurrentNetwork>::I64(I64::new(Uniform::rand(rng))),
193                Default::default(),
194            ))?;
195            // I128
196            check_bytes(Plaintext::Literal(
197                Literal::<CurrentNetwork>::I128(I128::new(Uniform::rand(rng))),
198                Default::default(),
199            ))?;
200            // U8
201            check_bytes(Plaintext::Literal(
202                Literal::<CurrentNetwork>::U8(U8::new(Uniform::rand(rng))),
203                Default::default(),
204            ))?;
205            // U16
206            check_bytes(Plaintext::Literal(
207                Literal::<CurrentNetwork>::U16(U16::new(Uniform::rand(rng))),
208                Default::default(),
209            ))?;
210            // U32
211            check_bytes(Plaintext::Literal(
212                Literal::<CurrentNetwork>::U32(U32::new(Uniform::rand(rng))),
213                Default::default(),
214            ))?;
215            // U64
216            check_bytes(Plaintext::Literal(
217                Literal::<CurrentNetwork>::U64(U64::new(Uniform::rand(rng))),
218                Default::default(),
219            ))?;
220            // U128
221            check_bytes(Plaintext::Literal(
222                Literal::<CurrentNetwork>::U128(U128::new(Uniform::rand(rng))),
223                Default::default(),
224            ))?;
225            // Scalar
226            check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Scalar(Uniform::rand(rng)), Default::default()))?;
227            // String
228            check_bytes(Plaintext::Literal(
229                Literal::<CurrentNetwork>::String(StringType::rand(rng)),
230                Default::default(),
231            ))?;
232        }
233
234        // Check the struct manually.
235        let expected = Plaintext::<CurrentNetwork>::from_str(
236            "{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah, token_amount: 100u64 }",
237        )?;
238
239        // Check the byte representation.
240        let expected_bytes = expected.to_bytes_le()?;
241        assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
242
243        // Check the array manually.
244        let expected = Plaintext::<CurrentNetwork>::from_str("[ 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8 ]")?;
245
246        // Check the byte representation.
247        let expected_bytes = expected.to_bytes_le()?;
248        assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
249
250        Ok(())
251    }
252}