snarkvm_console_program/data/plaintext/
mod.rs1mod bytes;
17mod encrypt;
18mod equal;
19mod find;
20mod from_bits;
21mod from_fields;
22mod num_randomizers;
23mod parse;
24mod serialize;
25mod size_in_fields;
26mod to_bits;
27mod to_bits_raw;
28mod to_fields;
29mod to_fields_raw;
30
31use crate::{Access, Ciphertext, Identifier, Literal, PlaintextType};
32use snarkvm_console_network::Network;
33use snarkvm_console_types::prelude::*;
34
35use indexmap::IndexMap;
36use std::{
37 hash::{Hash, Hasher},
38 sync::OnceLock,
39};
40
41#[derive(Clone)]
42pub enum Plaintext<N: Network> {
43 Literal(Literal<N>, OnceLock<Vec<bool>>),
45 Struct(IndexMap<Identifier<N>, Plaintext<N>>, OnceLock<Vec<bool>>),
47 Array(Vec<Plaintext<N>>, OnceLock<Vec<bool>>),
49}
50
51impl<N: Network> Plaintext<N> {
52 pub fn from_bit_array(bits: Vec<bool>, length: u32) -> Result<Self> {
54 ensure!(bits.len() == length as usize, "Expected '{length}' bits, got '{}' bits", bits.len());
55 Ok(Self::Array(
56 bits.into_iter().map(|bit| Plaintext::from(Literal::Boolean(Boolean::new(bit)))).collect(),
57 OnceLock::new(),
58 ))
59 }
60
61 pub fn as_bit_array(&self) -> Result<Vec<bool>> {
63 match self {
64 Self::Array(elements, _) => {
65 let mut bits = Vec::with_capacity(elements.len());
66 for element in elements {
67 match element {
68 Self::Literal(Literal::Boolean(bit), _) => bits.push(**bit),
69 _ => bail!("Expected a bit array, found a non-boolean element."),
70 }
71 }
72 Ok(bits)
73 }
74 _ => bail!("Expected a bit array, found a non-array plaintext."),
75 }
76 }
77
78 pub fn as_byte_array(&self) -> Result<Vec<u8>> {
80 match self {
81 Self::Array(elements, _) => {
82 let mut bytes = Vec::with_capacity(elements.len());
83 for element in elements {
84 match element {
85 Self::Literal(Literal::U8(byte), _) => bytes.push(**byte),
86 _ => bail!("Expected a u8 array, found a non-u8 element."),
87 }
88 }
89 Ok(bytes)
90 }
91 _ => bail!("Expected a u8 array, found a non-array plaintext."),
92 }
93 }
94
95 pub fn as_field_array(&self) -> Result<Vec<Field<N>>> {
97 match self {
98 Self::Array(elements, _) => {
99 let mut fields = Vec::with_capacity(elements.len());
100 for element in elements {
101 match element {
102 Self::Literal(Literal::Field(field), _) => fields.push(*field),
103 _ => bail!("Expected an array of fields, found a non-field element."),
104 }
105 }
106 Ok(fields)
107 }
108 _ => bail!("Expected an array of fields, found a non-array plaintext."),
109 }
110 }
111}
112
113impl<N: Network> From<Literal<N>> for Plaintext<N> {
114 fn from(literal: Literal<N>) -> Self {
116 Self::Literal(literal, OnceLock::new())
117 }
118}
119
120impl<N: Network> From<&Literal<N>> for Plaintext<N> {
121 fn from(literal: &Literal<N>) -> Self {
123 Self::Literal(literal.clone(), OnceLock::new())
124 }
125}
126
127impl<N: Network> Hash for Plaintext<N> {
128 fn hash<H: Hasher>(&self, state: &mut H) {
129 match self {
130 Self::Literal(literal, _bits) => {
131 literal.hash(state);
132 }
133 Self::Struct(fields, _bits) => {
134 for (name, value) in fields {
135 name.hash(state);
136 value.hash(state);
137 }
138 }
139 Self::Array(array, _bits) => {
140 array.hash(state);
141 }
142 }
143 }
144}
145
146macro_rules! impl_plaintext_from_array {
148 ($element:ident, $($size:literal),+) => {
149 $(
150 impl<N: Network> From<[$element<N>; $size]> for Plaintext<N> {
151 fn from(value: [$element<N>; $size]) -> Self {
152 Self::Array(
153 value
154 .into_iter()
155 .map(|element| Plaintext::from(Literal::$element(element)))
156 .collect(),
157 OnceLock::new(),
158 )
159 }
160 }
161 )+
162 };
163}
164
165seq_macro::seq!(S in 1..=256 {
167 impl_plaintext_from_array!(U8, S);
168});
169
170#[cfg(test)]
171mod tests {
172 use super::*;
173 use snarkvm_console_network::MainnetV0;
174 use snarkvm_console_types::Field;
175
176 use core::str::FromStr;
177
178 type CurrentNetwork = MainnetV0;
179
180 #[test]
181 fn test_plaintext() -> Result<()> {
182 let run_test = |value: Plaintext<CurrentNetwork>| {
183 assert_eq!(
184 value.to_bits_le(),
185 Plaintext::<CurrentNetwork>::from_bits_le(&value.to_bits_le()).unwrap().to_bits_le()
186 );
187 assert_eq!(value, Plaintext::<CurrentNetwork>::from_fields(&value.to_fields().unwrap()).unwrap());
188 assert_eq!(value, Plaintext::<CurrentNetwork>::from_str(&value.to_string()).unwrap());
189 assert!(*value.is_equal(&value));
190 assert!(*!value.is_not_equal(&value));
191 };
192
193 let mut rng = TestRng::default();
194
195 run_test(Plaintext::<CurrentNetwork>::from_str("true")?);
197 run_test(Plaintext::<CurrentNetwork>::from_str("false")?);
198
199 run_test(Plaintext::<CurrentNetwork>::Literal(
201 Literal::Field(Field::new(Uniform::rand(&mut rng))),
202 OnceLock::new(),
203 ));
204
205 run_test(Plaintext::<CurrentNetwork>::Struct(
207 IndexMap::from_iter(vec![
208 (Identifier::from_str("a")?, Plaintext::<CurrentNetwork>::from_str("true")?),
209 (
210 Identifier::from_str("b")?,
211 Plaintext::<CurrentNetwork>::Literal(
212 Literal::Field(Field::new(Uniform::rand(&mut rng))),
213 OnceLock::new(),
214 ),
215 ),
216 ]),
217 OnceLock::new(),
218 ));
219
220 run_test(Plaintext::<CurrentNetwork>::Struct(
222 IndexMap::from_iter(vec![
223 (Identifier::from_str("a")?, Plaintext::<CurrentNetwork>::from_str("true")?),
224 (
225 Identifier::from_str("b")?,
226 Plaintext::<CurrentNetwork>::Array(
227 vec![
228 Plaintext::<CurrentNetwork>::from_str("true")?,
229 Plaintext::<CurrentNetwork>::from_str("false")?,
230 ],
231 OnceLock::new(),
232 ),
233 ),
234 ]),
235 OnceLock::new(),
236 ));
237
238 run_test(Plaintext::<CurrentNetwork>::Struct(
240 IndexMap::from_iter(vec![
241 (Identifier::from_str("a")?, Plaintext::<CurrentNetwork>::from_str("true")?),
242 (
243 Identifier::from_str("b")?,
244 Plaintext::<CurrentNetwork>::Struct(
245 IndexMap::from_iter(vec![
246 (Identifier::from_str("c")?, Plaintext::<CurrentNetwork>::from_str("true")?),
247 (
248 Identifier::from_str("d")?,
249 Plaintext::<CurrentNetwork>::Struct(
250 IndexMap::from_iter(vec![
251 (Identifier::from_str("e")?, Plaintext::<CurrentNetwork>::from_str("true")?),
252 (
253 Identifier::from_str("f")?,
254 Plaintext::<CurrentNetwork>::Literal(
255 Literal::Field(Field::new(Uniform::rand(&mut rng))),
256 OnceLock::new(),
257 ),
258 ),
259 ]),
260 OnceLock::new(),
261 ),
262 ),
263 (
264 Identifier::from_str("g")?,
265 Plaintext::Array(
266 vec![
267 Plaintext::<CurrentNetwork>::from_str("true")?,
268 Plaintext::<CurrentNetwork>::from_str("false")?,
269 ],
270 OnceLock::new(),
271 ),
272 ),
273 ]),
274 OnceLock::new(),
275 ),
276 ),
277 (
278 Identifier::from_str("h")?,
279 Plaintext::<CurrentNetwork>::Literal(
280 Literal::Field(Field::new(Uniform::rand(&mut rng))),
281 OnceLock::new(),
282 ),
283 ),
284 ]),
285 OnceLock::new(),
286 ));
287
288 run_test(Plaintext::<CurrentNetwork>::Array(
290 vec![
291 Plaintext::<CurrentNetwork>::from_str("0field")?,
292 Plaintext::<CurrentNetwork>::from_str("1field")?,
293 Plaintext::<CurrentNetwork>::from_str("2field")?,
294 Plaintext::<CurrentNetwork>::from_str("3field")?,
295 Plaintext::<CurrentNetwork>::from_str("4field")?,
296 ],
297 OnceLock::new(),
298 ));
299
300 run_test(Plaintext::<CurrentNetwork>::Array(
302 vec![
303 Plaintext::<CurrentNetwork>::from_str("{ x: 0field, y: 1field }")?,
304 Plaintext::<CurrentNetwork>::from_str("{ x: 2field, y: 3field }")?,
305 Plaintext::<CurrentNetwork>::from_str("{ x: 4field, y: 5field }")?,
306 Plaintext::<CurrentNetwork>::from_str("{ x: 6field, y: 7field }")?,
307 Plaintext::<CurrentNetwork>::from_str("{ x: 8field, y: 9field }")?,
308 ],
309 OnceLock::new(),
310 ));
311
312 run_test(Plaintext::<CurrentNetwork>::Array(
314 vec![
315 Plaintext::<CurrentNetwork>::from_str("true")?,
316 Plaintext::<CurrentNetwork>::from_str("1field")?,
317 Plaintext::<CurrentNetwork>::from_str("{ x: 4field, y: 1u8 }")?,
318 ],
319 OnceLock::new(),
320 ));
321
322 Ok(())
323 }
324}