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::sync::OnceLock;
37
38#[derive(Clone)]
39pub enum Plaintext<N: Network> {
40 Literal(Literal<N>, OnceLock<Vec<bool>>),
42 Struct(IndexMap<Identifier<N>, Plaintext<N>>, OnceLock<Vec<bool>>),
44 Array(Vec<Plaintext<N>>, OnceLock<Vec<bool>>),
46}
47
48impl<N: Network> Plaintext<N> {
49 pub fn from_bit_array(bits: Vec<bool>, length: u32) -> Result<Self> {
51 ensure!(bits.len() == length as usize, "Expected '{length}' bits, got '{}' bits", bits.len());
52 Ok(Self::Array(
53 bits.into_iter().map(|bit| Plaintext::from(Literal::Boolean(Boolean::new(bit)))).collect(),
54 OnceLock::new(),
55 ))
56 }
57
58 pub fn as_bit_array(&self) -> Result<Vec<bool>> {
60 match self {
61 Self::Array(elements, _) => {
62 let mut bits = Vec::with_capacity(elements.len());
63 for element in elements {
64 match element {
65 Self::Literal(Literal::Boolean(bit), _) => bits.push(**bit),
66 _ => bail!("Expected a bit array, found a non-boolean element."),
67 }
68 }
69 Ok(bits)
70 }
71 _ => bail!("Expected a bit array, found a non-array plaintext."),
72 }
73 }
74}
75
76impl<N: Network> From<Literal<N>> for Plaintext<N> {
77 fn from(literal: Literal<N>) -> Self {
79 Self::Literal(literal, OnceLock::new())
80 }
81}
82
83impl<N: Network> From<&Literal<N>> for Plaintext<N> {
84 fn from(literal: &Literal<N>) -> Self {
86 Self::Literal(literal.clone(), OnceLock::new())
87 }
88}
89
90macro_rules! impl_plaintext_from_array {
92 ($element:ident, $($size:literal),+) => {
93 $(
94 impl<N: Network> From<[$element<N>; $size]> for Plaintext<N> {
95 fn from(value: [$element<N>; $size]) -> Self {
96 Self::Array(
97 value
98 .into_iter()
99 .map(|element| Plaintext::from(Literal::$element(element)))
100 .collect(),
101 OnceLock::new(),
102 )
103 }
104 }
105 )+
106 };
107}
108
109seq_macro::seq!(S in 1..=256 {
111 impl_plaintext_from_array!(U8, S);
112});
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117 use snarkvm_console_network::MainnetV0;
118 use snarkvm_console_types::Field;
119
120 use core::str::FromStr;
121
122 type CurrentNetwork = MainnetV0;
123
124 #[test]
125 fn test_plaintext() -> Result<()> {
126 let run_test = |value: Plaintext<CurrentNetwork>| {
127 assert_eq!(
128 value.to_bits_le(),
129 Plaintext::<CurrentNetwork>::from_bits_le(&value.to_bits_le()).unwrap().to_bits_le()
130 );
131 assert_eq!(value, Plaintext::<CurrentNetwork>::from_fields(&value.to_fields().unwrap()).unwrap());
132 assert_eq!(value, Plaintext::<CurrentNetwork>::from_str(&value.to_string()).unwrap());
133 assert!(*value.is_equal(&value));
134 assert!(*!value.is_not_equal(&value));
135 };
136
137 let mut rng = TestRng::default();
138
139 run_test(Plaintext::<CurrentNetwork>::from_str("true")?);
141 run_test(Plaintext::<CurrentNetwork>::from_str("false")?);
142
143 run_test(Plaintext::<CurrentNetwork>::Literal(
145 Literal::Field(Field::new(Uniform::rand(&mut rng))),
146 OnceLock::new(),
147 ));
148
149 run_test(Plaintext::<CurrentNetwork>::Struct(
151 IndexMap::from_iter(vec![
152 (Identifier::from_str("a")?, Plaintext::<CurrentNetwork>::from_str("true")?),
153 (
154 Identifier::from_str("b")?,
155 Plaintext::<CurrentNetwork>::Literal(
156 Literal::Field(Field::new(Uniform::rand(&mut rng))),
157 OnceLock::new(),
158 ),
159 ),
160 ]),
161 OnceLock::new(),
162 ));
163
164 run_test(Plaintext::<CurrentNetwork>::Struct(
166 IndexMap::from_iter(vec![
167 (Identifier::from_str("a")?, Plaintext::<CurrentNetwork>::from_str("true")?),
168 (
169 Identifier::from_str("b")?,
170 Plaintext::<CurrentNetwork>::Array(
171 vec![
172 Plaintext::<CurrentNetwork>::from_str("true")?,
173 Plaintext::<CurrentNetwork>::from_str("false")?,
174 ],
175 OnceLock::new(),
176 ),
177 ),
178 ]),
179 OnceLock::new(),
180 ));
181
182 run_test(Plaintext::<CurrentNetwork>::Struct(
184 IndexMap::from_iter(vec![
185 (Identifier::from_str("a")?, Plaintext::<CurrentNetwork>::from_str("true")?),
186 (
187 Identifier::from_str("b")?,
188 Plaintext::<CurrentNetwork>::Struct(
189 IndexMap::from_iter(vec![
190 (Identifier::from_str("c")?, Plaintext::<CurrentNetwork>::from_str("true")?),
191 (
192 Identifier::from_str("d")?,
193 Plaintext::<CurrentNetwork>::Struct(
194 IndexMap::from_iter(vec![
195 (Identifier::from_str("e")?, Plaintext::<CurrentNetwork>::from_str("true")?),
196 (
197 Identifier::from_str("f")?,
198 Plaintext::<CurrentNetwork>::Literal(
199 Literal::Field(Field::new(Uniform::rand(&mut rng))),
200 OnceLock::new(),
201 ),
202 ),
203 ]),
204 OnceLock::new(),
205 ),
206 ),
207 (
208 Identifier::from_str("g")?,
209 Plaintext::Array(
210 vec![
211 Plaintext::<CurrentNetwork>::from_str("true")?,
212 Plaintext::<CurrentNetwork>::from_str("false")?,
213 ],
214 OnceLock::new(),
215 ),
216 ),
217 ]),
218 OnceLock::new(),
219 ),
220 ),
221 (
222 Identifier::from_str("h")?,
223 Plaintext::<CurrentNetwork>::Literal(
224 Literal::Field(Field::new(Uniform::rand(&mut rng))),
225 OnceLock::new(),
226 ),
227 ),
228 ]),
229 OnceLock::new(),
230 ));
231
232 run_test(Plaintext::<CurrentNetwork>::Array(
234 vec![
235 Plaintext::<CurrentNetwork>::from_str("0field")?,
236 Plaintext::<CurrentNetwork>::from_str("1field")?,
237 Plaintext::<CurrentNetwork>::from_str("2field")?,
238 Plaintext::<CurrentNetwork>::from_str("3field")?,
239 Plaintext::<CurrentNetwork>::from_str("4field")?,
240 ],
241 OnceLock::new(),
242 ));
243
244 run_test(Plaintext::<CurrentNetwork>::Array(
246 vec![
247 Plaintext::<CurrentNetwork>::from_str("{ x: 0field, y: 1field }")?,
248 Plaintext::<CurrentNetwork>::from_str("{ x: 2field, y: 3field }")?,
249 Plaintext::<CurrentNetwork>::from_str("{ x: 4field, y: 5field }")?,
250 Plaintext::<CurrentNetwork>::from_str("{ x: 6field, y: 7field }")?,
251 Plaintext::<CurrentNetwork>::from_str("{ x: 8field, y: 9field }")?,
252 ],
253 OnceLock::new(),
254 ));
255
256 run_test(Plaintext::<CurrentNetwork>::Array(
258 vec![
259 Plaintext::<CurrentNetwork>::from_str("true")?,
260 Plaintext::<CurrentNetwork>::from_str("1field")?,
261 Plaintext::<CurrentNetwork>::from_str("{ x: 4field, y: 1u8 }")?,
262 ],
263 OnceLock::new(),
264 ));
265
266 Ok(())
267 }
268}