/ console / program / src / data / plaintext / mod.rs
mod.rs
  1  // Copyright (c) 2025-2026 ACDC Network
  2  // This file is part of the alphavm library.
  3  //
  4  // Alpha Chain | Delta Chain Protocol
  5  // International Monetary Graphite.
  6  //
  7  // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com).
  8  // They built world-class ZK infrastructure. We installed the EASY button.
  9  // Their cryptography: elegant. Our modifications: bureaucracy-compatible.
 10  // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours.
 11  //
 12  // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0
 13  // All modifications and new work: CC0 1.0 Universal Public Domain Dedication.
 14  // No rights reserved. No permission required. No warranty. No refunds.
 15  //
 16  // https://creativecommons.org/publicdomain/zero/1.0/
 17  // SPDX-License-Identifier: CC0-1.0
 18  
 19  mod bytes;
 20  mod encrypt;
 21  mod equal;
 22  mod find;
 23  mod from_bits;
 24  mod from_fields;
 25  mod num_randomizers;
 26  mod parse;
 27  mod serialize;
 28  mod size_in_fields;
 29  mod to_bits;
 30  mod to_bits_raw;
 31  mod to_fields;
 32  mod to_fields_raw;
 33  
 34  use crate::{Access, Ciphertext, Identifier, Literal, PlaintextType};
 35  use alphavm_console_network::Network;
 36  use alphavm_console_types::prelude::*;
 37  
 38  use indexmap::IndexMap;
 39  use std::sync::OnceLock;
 40  
 41  #[derive(Clone)]
 42  pub enum Plaintext<N: Network> {
 43      /// A literal.
 44      Literal(Literal<N>, OnceLock<Vec<bool>>),
 45      /// A struct.
 46      Struct(IndexMap<Identifier<N>, Plaintext<N>>, OnceLock<Vec<bool>>),
 47      /// An array.
 48      Array(Vec<Plaintext<N>>, OnceLock<Vec<bool>>),
 49  }
 50  
 51  impl<N: Network> Plaintext<N> {
 52      /// Returns a new `Plaintext::Array` from `Vec<bool>`, checking that the length is correct.
 53      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      /// Returns the `Plaintext` as a `Vec<bool>`, if it is a bit array.
 62      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  
 79  impl<N: Network> From<Literal<N>> for Plaintext<N> {
 80      /// Returns a new `Plaintext` from a `Literal`.
 81      fn from(literal: Literal<N>) -> Self {
 82          Self::Literal(literal, OnceLock::new())
 83      }
 84  }
 85  
 86  impl<N: Network> From<&Literal<N>> for Plaintext<N> {
 87      /// Returns a new `Plaintext` from a `&Literal`.
 88      fn from(literal: &Literal<N>) -> Self {
 89          Self::Literal(literal.clone(), OnceLock::new())
 90      }
 91  }
 92  
 93  // A macro that derives implementations of `From` for arrays of a plaintext literals of various sizes.
 94  macro_rules! impl_plaintext_from_array {
 95      ($element:ident, $($size:literal),+) => {
 96          $(
 97              impl<N: Network> From<[$element<N>; $size]> for Plaintext<N> {
 98                  fn from(value: [$element<N>; $size]) -> Self {
 99                      Self::Array(
100                          value
101                              .into_iter()
102                              .map(|element| Plaintext::from(Literal::$element(element)))
103                              .collect(),
104                          OnceLock::new(),
105                      )
106                  }
107              }
108          )+
109      };
110  }
111  
112  // Implement for `[U8<N>, SIZE]` for sizes 1 through 256.
113  seq_macro::seq!(S in 1..=256 {
114      impl_plaintext_from_array!(U8, S);
115  });
116  
117  #[cfg(test)]
118  mod tests {
119      use super::*;
120      use alphavm_console_network::MainnetV0;
121      use alphavm_console_types::Field;
122  
123      use core::str::FromStr;
124  
125      type CurrentNetwork = MainnetV0;
126  
127      #[test]
128      fn test_plaintext() -> Result<()> {
129          let run_test = |value: Plaintext<CurrentNetwork>| {
130              assert_eq!(
131                  value.to_bits_le(),
132                  Plaintext::<CurrentNetwork>::from_bits_le(&value.to_bits_le()).unwrap().to_bits_le()
133              );
134              assert_eq!(value, Plaintext::<CurrentNetwork>::from_fields(&value.to_fields().unwrap()).unwrap());
135              assert_eq!(value, Plaintext::<CurrentNetwork>::from_str(&value.to_string()).unwrap());
136              assert!(*value.is_equal(&value));
137              assert!(*!value.is_not_equal(&value));
138          };
139  
140          let mut rng = TestRng::default();
141  
142          // Test booleans.
143          run_test(Plaintext::<CurrentNetwork>::from_str("true")?);
144          run_test(Plaintext::<CurrentNetwork>::from_str("false")?);
145  
146          // Test a random field element.
147          run_test(Plaintext::<CurrentNetwork>::Literal(
148              Literal::Field(Field::new(Uniform::rand(&mut rng))),
149              OnceLock::new(),
150          ));
151  
152          // Test a random struct with literal members.
153          run_test(Plaintext::<CurrentNetwork>::Struct(
154              IndexMap::from_iter(vec![
155                  (Identifier::from_str("a")?, Plaintext::<CurrentNetwork>::from_str("true")?),
156                  (
157                      Identifier::from_str("b")?,
158                      Plaintext::<CurrentNetwork>::Literal(
159                          Literal::Field(Field::new(Uniform::rand(&mut rng))),
160                          OnceLock::new(),
161                      ),
162                  ),
163              ]),
164              OnceLock::new(),
165          ));
166  
167          // Test a random struct with array members.
168          run_test(Plaintext::<CurrentNetwork>::Struct(
169              IndexMap::from_iter(vec![
170                  (Identifier::from_str("a")?, Plaintext::<CurrentNetwork>::from_str("true")?),
171                  (
172                      Identifier::from_str("b")?,
173                      Plaintext::<CurrentNetwork>::Array(
174                          vec![
175                              Plaintext::<CurrentNetwork>::from_str("true")?,
176                              Plaintext::<CurrentNetwork>::from_str("false")?,
177                          ],
178                          OnceLock::new(),
179                      ),
180                  ),
181              ]),
182              OnceLock::new(),
183          ));
184  
185          // Test random deeply-nested struct.
186          run_test(Plaintext::<CurrentNetwork>::Struct(
187              IndexMap::from_iter(vec![
188                  (Identifier::from_str("a")?, Plaintext::<CurrentNetwork>::from_str("true")?),
189                  (
190                      Identifier::from_str("b")?,
191                      Plaintext::<CurrentNetwork>::Struct(
192                          IndexMap::from_iter(vec![
193                              (Identifier::from_str("c")?, Plaintext::<CurrentNetwork>::from_str("true")?),
194                              (
195                                  Identifier::from_str("d")?,
196                                  Plaintext::<CurrentNetwork>::Struct(
197                                      IndexMap::from_iter(vec![
198                                          (Identifier::from_str("e")?, Plaintext::<CurrentNetwork>::from_str("true")?),
199                                          (
200                                              Identifier::from_str("f")?,
201                                              Plaintext::<CurrentNetwork>::Literal(
202                                                  Literal::Field(Field::new(Uniform::rand(&mut rng))),
203                                                  OnceLock::new(),
204                                              ),
205                                          ),
206                                      ]),
207                                      OnceLock::new(),
208                                  ),
209                              ),
210                              (
211                                  Identifier::from_str("g")?,
212                                  Plaintext::Array(
213                                      vec![
214                                          Plaintext::<CurrentNetwork>::from_str("true")?,
215                                          Plaintext::<CurrentNetwork>::from_str("false")?,
216                                      ],
217                                      OnceLock::new(),
218                                  ),
219                              ),
220                          ]),
221                          OnceLock::new(),
222                      ),
223                  ),
224                  (
225                      Identifier::from_str("h")?,
226                      Plaintext::<CurrentNetwork>::Literal(
227                          Literal::Field(Field::new(Uniform::rand(&mut rng))),
228                          OnceLock::new(),
229                      ),
230                  ),
231              ]),
232              OnceLock::new(),
233          ));
234  
235          // Test an array of literals.
236          run_test(Plaintext::<CurrentNetwork>::Array(
237              vec![
238                  Plaintext::<CurrentNetwork>::from_str("0field")?,
239                  Plaintext::<CurrentNetwork>::from_str("1field")?,
240                  Plaintext::<CurrentNetwork>::from_str("2field")?,
241                  Plaintext::<CurrentNetwork>::from_str("3field")?,
242                  Plaintext::<CurrentNetwork>::from_str("4field")?,
243              ],
244              OnceLock::new(),
245          ));
246  
247          // Test an array of structs.
248          run_test(Plaintext::<CurrentNetwork>::Array(
249              vec![
250                  Plaintext::<CurrentNetwork>::from_str("{ x: 0field, y: 1field }")?,
251                  Plaintext::<CurrentNetwork>::from_str("{ x: 2field, y: 3field }")?,
252                  Plaintext::<CurrentNetwork>::from_str("{ x: 4field, y: 5field }")?,
253                  Plaintext::<CurrentNetwork>::from_str("{ x: 6field, y: 7field }")?,
254                  Plaintext::<CurrentNetwork>::from_str("{ x: 8field, y: 9field }")?,
255              ],
256              OnceLock::new(),
257          ));
258  
259          // Test a non-uniform array.
260          run_test(Plaintext::<CurrentNetwork>::Array(
261              vec![
262                  Plaintext::<CurrentNetwork>::from_str("true")?,
263                  Plaintext::<CurrentNetwork>::from_str("1field")?,
264                  Plaintext::<CurrentNetwork>::from_str("{ x: 4field, y: 1u8 }")?,
265              ],
266              OnceLock::new(),
267          ));
268  
269          Ok(())
270      }
271  }