mod.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the deltavm 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 16 use std::cell::OnceCell; 17 18 #[cfg(test)] 19 use deltavm_circuit_types::environment::assert_scope; 20 21 mod encrypt; 22 mod equal; 23 mod find; 24 mod from_bits; 25 mod from_fields; 26 mod num_randomizers; 27 mod size_in_fields; 28 mod to_bits; 29 mod to_bits_raw; 30 mod to_fields; 31 mod to_fields_raw; 32 33 use crate::{Access, Ciphertext, Identifier, Literal, Visibility}; 34 use deltavm_circuit_network::Alpha; 35 use deltavm_circuit_types::{Address, Boolean, Field, Scalar, U8, U16, U32, environment::prelude::*}; 36 use console::PlaintextType; 37 38 #[derive(Clone)] 39 pub enum Plaintext<A: Alpha> { 40 /// A plaintext literal. 41 Literal(Literal<A>, OnceCell<Vec<Boolean<A>>>), 42 /// A plaintext struct. 43 Struct(IndexMap<Identifier<A>, Plaintext<A>>, OnceCell<Vec<Boolean<A>>>), 44 /// A plaintext array. 45 Array(Vec<Plaintext<A>>, OnceCell<Vec<Boolean<A>>>), 46 } 47 48 impl<A: Alpha> Plaintext<A> { 49 /// Returns a new `Plaintext::Array` from `Vec<Boolean<A>>`, checking that the length is correct. 50 pub fn from_bit_array(bits: Vec<Boolean<A>>, length: u32) -> Result<Self> { 51 ensure!(bits.len() == length as usize, "Expected '{length}' bits, got '{}' bits", bits.len()); 52 Ok(Self::Array(bits.into_iter().map(|bit| Plaintext::from(Literal::Boolean(bit))).collect(), OnceCell::new())) 53 } 54 55 /// Returns the `Plaintext` as a `Vec<Boolean<A>>`, if it is a bit array. 56 pub fn as_bit_array(&self) -> Result<Vec<Boolean<A>>> { 57 match self { 58 Self::Array(elements, _) => { 59 let mut bits = Vec::with_capacity(elements.len()); 60 for element in elements { 61 match element { 62 Self::Literal(Literal::Boolean(bit), _) => bits.push(bit.clone()), 63 _ => bail!("Expected a bit array, found a non-boolean element."), 64 } 65 } 66 Ok(bits) 67 } 68 _ => bail!("Expected a bit array, found a non-array plaintext."), 69 } 70 } 71 } 72 73 impl<A: Alpha> Inject for Plaintext<A> { 74 type Primitive = console::Plaintext<A::Network>; 75 76 /// Initializes a new plaintext circuit from a primitive. 77 fn new(mode: Mode, plaintext: Self::Primitive) -> Self { 78 match plaintext { 79 Self::Primitive::Literal(literal, _) => Self::Literal(Literal::new(mode, literal), Default::default()), 80 Self::Primitive::Struct(struct_, _) => Self::Struct(Inject::new(mode, struct_), Default::default()), 81 Self::Primitive::Array(array, _) => Self::Array(Inject::new(mode, array), Default::default()), 82 } 83 } 84 } 85 86 impl<A: Alpha> Eject for Plaintext<A> { 87 type Primitive = console::Plaintext<A::Network>; 88 89 /// Ejects the mode of the plaintext value. 90 fn eject_mode(&self) -> Mode { 91 match self { 92 Self::Literal(literal, _) => literal.eject_mode(), 93 Self::Struct(struct_, _) => struct_ 94 .iter() 95 .map(|(identifier, value)| (identifier, value).eject_mode()) 96 .collect::<Vec<_>>() 97 .eject_mode(), 98 Self::Array(array, _) => array.iter().map(Eject::eject_mode).collect::<Vec<_>>().eject_mode(), 99 } 100 } 101 102 /// Ejects the plaintext value. 103 fn eject_value(&self) -> Self::Primitive { 104 match self { 105 Self::Literal(literal, _) => console::Plaintext::Literal(literal.eject_value(), Default::default()), 106 Self::Struct(struct_, _) => { 107 console::Plaintext::Struct(struct_.iter().map(|pair| pair.eject_value()).collect(), Default::default()) 108 } 109 Self::Array(array, _) => { 110 console::Plaintext::Array(array.iter().map(Eject::eject_value).collect(), Default::default()) 111 } 112 } 113 } 114 } 115 116 impl<A: Alpha> From<Literal<A>> for Plaintext<A> { 117 /// Returns a new `Plaintext` from a `Literal`. 118 fn from(literal: Literal<A>) -> Self { 119 Self::Literal(literal, OnceCell::new()) 120 } 121 } 122 123 impl<A: Alpha> From<&Literal<A>> for Plaintext<A> { 124 /// Returns a new `Plaintext` from a `Literal`. 125 fn from(literal: &Literal<A>) -> Self { 126 Self::Literal((*literal).clone(), OnceCell::new()) 127 } 128 } 129 130 // A macro that derives implementations of `From` for arrays of a plaintext literals of various sizes. 131 macro_rules! impl_plaintext_from_array { 132 ($element:ident, $($size:literal),+) => { 133 $( 134 impl<A: Alpha> From<[$element<A>; $size]> for Plaintext<A> { 135 fn from(value: [$element<A>; $size]) -> Self { 136 Self::Array( 137 value 138 .into_iter() 139 .map(|element| Plaintext::from(Literal::$element(element))) 140 .collect(), 141 OnceCell::new(), 142 ) 143 } 144 } 145 )+ 146 }; 147 } 148 149 // Implement for `[U8<N>, SIZE]` for sizes 1 through 32. 150 impl_plaintext_from_array!( 151 U8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 152 31, 32 153 ); 154 155 #[cfg(test)] 156 mod tests { 157 use super::*; 158 use crate::Circuit; 159 use deltavm_utilities::{TestRng, Uniform}; 160 161 use anyhow::Result; 162 163 #[test] 164 fn test_plaintext() -> Result<()> { 165 let run_test = |value: Plaintext<Circuit>| { 166 assert_eq!( 167 value.to_bits_le().eject(), 168 Plaintext::<Circuit>::from_bits_le(&value.to_bits_le()).to_bits_le().eject() 169 ); 170 assert_eq!(value.eject(), Plaintext::<Circuit>::from_fields(&value.to_fields()).eject()); 171 assert!(value.is_equal(&value).eject_value()); 172 assert!(!value.is_not_equal(&value).eject_value()); 173 }; 174 175 let mut rng = TestRng::default(); 176 177 // Test booleans. 178 run_test(Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new())); 179 run_test(Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, false)), OnceCell::new())); 180 181 // Test a random field element. 182 run_test(Plaintext::<Circuit>::Literal( 183 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 184 OnceCell::new(), 185 )); 186 187 // Test a random struct with literal members. 188 run_test(Plaintext::<Circuit>::Struct( 189 IndexMap::from_iter(vec![ 190 ( 191 Identifier::new(Mode::Private, "a".try_into()?), 192 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()), 193 ), 194 ( 195 Identifier::new(Mode::Private, "b".try_into()?), 196 Plaintext::<Circuit>::Literal( 197 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 198 OnceCell::new(), 199 ), 200 ), 201 ]), 202 OnceCell::new(), 203 )); 204 205 // Test a random struct with array members. 206 run_test(Plaintext::<Circuit>::Struct( 207 IndexMap::from_iter(vec![ 208 ( 209 Identifier::new(Mode::Private, "a".try_into()?), 210 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()), 211 ), 212 ( 213 Identifier::new(Mode::Private, "b".try_into()?), 214 Plaintext::<Circuit>::Array( 215 vec![ 216 Plaintext::<Circuit>::Literal( 217 Literal::Boolean(Boolean::new(Mode::Private, true)), 218 OnceCell::new(), 219 ), 220 Plaintext::<Circuit>::Literal( 221 Literal::Boolean(Boolean::new(Mode::Private, false)), 222 OnceCell::new(), 223 ), 224 ], 225 OnceCell::new(), 226 ), 227 ), 228 ]), 229 OnceCell::new(), 230 )); 231 232 // Test random deeply-nested struct. 233 run_test(Plaintext::<Circuit>::Struct( 234 IndexMap::from_iter(vec![ 235 ( 236 Identifier::new(Mode::Private, "a".try_into()?), 237 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()), 238 ), 239 ( 240 Identifier::new(Mode::Private, "b".try_into()?), 241 Plaintext::<Circuit>::Struct( 242 IndexMap::from_iter(vec![ 243 ( 244 Identifier::new(Mode::Private, "c".try_into()?), 245 Plaintext::<Circuit>::Literal( 246 Literal::Boolean(Boolean::new(Mode::Private, true)), 247 OnceCell::new(), 248 ), 249 ), 250 ( 251 Identifier::new(Mode::Private, "d".try_into()?), 252 Plaintext::<Circuit>::Struct( 253 IndexMap::from_iter(vec![ 254 ( 255 Identifier::new(Mode::Private, "e".try_into()?), 256 Plaintext::<Circuit>::Literal( 257 Literal::Boolean(Boolean::new(Mode::Private, true)), 258 OnceCell::new(), 259 ), 260 ), 261 ( 262 Identifier::new(Mode::Private, "f".try_into()?), 263 Plaintext::<Circuit>::Literal( 264 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 265 OnceCell::new(), 266 ), 267 ), 268 ]), 269 OnceCell::new(), 270 ), 271 ), 272 ( 273 Identifier::new(Mode::Private, "g".try_into()?), 274 Plaintext::<Circuit>::Array( 275 vec![ 276 Plaintext::<Circuit>::Literal( 277 Literal::Boolean(Boolean::new(Mode::Private, true)), 278 OnceCell::new(), 279 ), 280 Plaintext::<Circuit>::Literal( 281 Literal::Boolean(Boolean::new(Mode::Private, false)), 282 OnceCell::new(), 283 ), 284 ], 285 OnceCell::new(), 286 ), 287 ), 288 ]), 289 OnceCell::new(), 290 ), 291 ), 292 ( 293 Identifier::new(Mode::Private, "h".try_into()?), 294 Plaintext::<Circuit>::Literal( 295 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 296 OnceCell::new(), 297 ), 298 ), 299 ]), 300 OnceCell::new(), 301 )); 302 303 // Test an array of literals. 304 run_test(Plaintext::<Circuit>::Array( 305 vec![ 306 Plaintext::<Circuit>::Literal( 307 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 308 OnceCell::new(), 309 ), 310 Plaintext::<Circuit>::Literal( 311 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 312 OnceCell::new(), 313 ), 314 Plaintext::<Circuit>::Literal( 315 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 316 OnceCell::new(), 317 ), 318 Plaintext::<Circuit>::Literal( 319 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 320 OnceCell::new(), 321 ), 322 Plaintext::<Circuit>::Literal( 323 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 324 OnceCell::new(), 325 ), 326 ], 327 OnceCell::new(), 328 )); 329 330 // Test an array of structs. 331 run_test(Plaintext::<Circuit>::Array( 332 vec![ 333 Plaintext::<Circuit>::Struct( 334 IndexMap::from_iter(vec![ 335 ( 336 Identifier::new(Mode::Private, "x".try_into()?), 337 Plaintext::<Circuit>::Literal( 338 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 339 OnceCell::new(), 340 ), 341 ), 342 ( 343 Identifier::new(Mode::Private, "y".try_into()?), 344 Plaintext::<Circuit>::Literal( 345 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 346 OnceCell::new(), 347 ), 348 ), 349 ]), 350 OnceCell::new(), 351 ), 352 Plaintext::<Circuit>::Struct( 353 IndexMap::from_iter(vec![ 354 ( 355 Identifier::new(Mode::Private, "x".try_into()?), 356 Plaintext::<Circuit>::Literal( 357 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 358 OnceCell::new(), 359 ), 360 ), 361 ( 362 Identifier::new(Mode::Private, "y".try_into()?), 363 Plaintext::<Circuit>::Literal( 364 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 365 OnceCell::new(), 366 ), 367 ), 368 ]), 369 OnceCell::new(), 370 ), 371 Plaintext::<Circuit>::Struct( 372 IndexMap::from_iter(vec![ 373 ( 374 Identifier::new(Mode::Private, "x".try_into()?), 375 Plaintext::<Circuit>::Literal( 376 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 377 OnceCell::new(), 378 ), 379 ), 380 ( 381 Identifier::new(Mode::Private, "y".try_into()?), 382 Plaintext::<Circuit>::Literal( 383 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 384 OnceCell::new(), 385 ), 386 ), 387 ]), 388 OnceCell::new(), 389 ), 390 ], 391 OnceCell::new(), 392 )); 393 394 // Test a non-uniform array. 395 run_test(Plaintext::<Circuit>::Array( 396 vec![ 397 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()), 398 Plaintext::<Circuit>::Literal( 399 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 400 OnceCell::new(), 401 ), 402 Plaintext::<Circuit>::Struct( 403 IndexMap::from_iter(vec![ 404 ( 405 Identifier::new(Mode::Private, "x".try_into()?), 406 Plaintext::<Circuit>::Literal( 407 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 408 OnceCell::new(), 409 ), 410 ), 411 ( 412 Identifier::new(Mode::Private, "y".try_into()?), 413 Plaintext::<Circuit>::Literal( 414 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))), 415 OnceCell::new(), 416 ), 417 ), 418 ]), 419 OnceCell::new(), 420 ), 421 ], 422 OnceCell::new(), 423 )); 424 425 Ok(()) 426 } 427 }