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 }