1use crate::Aleo;
17use snarkvm_circuit_algorithms::{
18 BHP256,
19 BHP512,
20 BHP768,
21 BHP1024,
22 Commit,
23 CommitUncompressed,
24 Hash,
25 HashMany,
26 HashToGroup,
27 HashToScalar,
28 HashUncompressed,
29 Keccak256,
30 Keccak384,
31 Keccak512,
32 Pedersen64,
33 Pedersen128,
34 Poseidon2,
35 Poseidon4,
36 Poseidon8,
37 Sha3_256,
38 Sha3_384,
39 Sha3_512,
40};
41use snarkvm_circuit_collections::merkle_tree::MerklePath;
42use snarkvm_circuit_types::{
43 Boolean,
44 Field,
45 Group,
46 Scalar,
47 environment::{Assignment, R1CS, TestnetCircuit, prelude::*},
48};
49
50use core::fmt;
51
52type E = TestnetCircuit;
53
54thread_local! {
55 static GENERATOR_G: Vec<Group<AleoTestnetV0>> = Vec::constant(<console::TestnetV0 as console::Network>::g_powers().to_vec());
57
58 static ENCRYPTION_DOMAIN: Field<AleoTestnetV0> = Field::constant(<console::TestnetV0 as console::Network>::encryption_domain());
60 static GRAPH_KEY_DOMAIN: Field<AleoTestnetV0> = Field::constant(<console::TestnetV0 as console::Network>::graph_key_domain());
62 static SERIAL_NUMBER_DOMAIN: Field<AleoTestnetV0> = Field::constant(<console::TestnetV0 as console::Network>::serial_number_domain());
64
65 static BHP_256: BHP256<AleoTestnetV0> = BHP256::<AleoTestnetV0>::constant(console::TESTNET_BHP_256.clone());
67 static BHP_512: BHP512<AleoTestnetV0> = BHP512::<AleoTestnetV0>::constant(console::TESTNET_BHP_512.clone());
69 static BHP_768: BHP768<AleoTestnetV0> = BHP768::<AleoTestnetV0>::constant(console::TESTNET_BHP_768.clone());
71 static BHP_1024: BHP1024<AleoTestnetV0> = BHP1024::<AleoTestnetV0>::constant(console::TESTNET_BHP_1024.clone());
73
74 static KECCAK_256: Keccak256<AleoTestnetV0> = Keccak256::<AleoTestnetV0>::new();
76 static KECCAK_384: Keccak384<AleoTestnetV0> = Keccak384::<AleoTestnetV0>::new();
78 static KECCAK_512: Keccak512<AleoTestnetV0> = Keccak512::<AleoTestnetV0>::new();
80
81 static PEDERSEN_64: Pedersen64<AleoTestnetV0> = Pedersen64::<AleoTestnetV0>::constant(console::TESTNET_PEDERSEN_64.clone());
83 static PEDERSEN_128: Pedersen128<AleoTestnetV0> = Pedersen128::<AleoTestnetV0>::constant(console::TESTNET_PEDERSEN_128.clone());
85
86 static POSEIDON_2: Poseidon2<AleoTestnetV0> = Poseidon2::<AleoTestnetV0>::constant(console::TESTNET_POSEIDON_2.clone());
88 static POSEIDON_4: Poseidon4<AleoTestnetV0> = Poseidon4::<AleoTestnetV0>::constant(console::TESTNET_POSEIDON_4.clone());
90 static POSEIDON_8: Poseidon8<AleoTestnetV0> = Poseidon8::<AleoTestnetV0>::constant(console::TESTNET_POSEIDON_8.clone());
92
93 static SHA3_256: Sha3_256<AleoTestnetV0> = Sha3_256::<AleoTestnetV0>::new();
95 static SHA3_384: Sha3_384<AleoTestnetV0> = Sha3_384::<AleoTestnetV0>::new();
97 static SHA3_512: Sha3_512<AleoTestnetV0> = Sha3_512::<AleoTestnetV0>::new();
99}
100
101#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
102pub struct AleoTestnetV0;
103
104impl Aleo for AleoTestnetV0 {
105 fn initialize_global_constants() {
107 GENERATOR_G.with(|_| ());
108 ENCRYPTION_DOMAIN.with(|_| ());
109 GRAPH_KEY_DOMAIN.with(|_| ());
110 SERIAL_NUMBER_DOMAIN.with(|_| ());
111 BHP_256.with(|_| ());
112 BHP_512.with(|_| ());
113 BHP_768.with(|_| ());
114 BHP_1024.with(|_| ());
115 KECCAK_256.with(|_| ());
116 KECCAK_384.with(|_| ());
117 KECCAK_512.with(|_| ());
118 PEDERSEN_64.with(|_| ());
119 PEDERSEN_128.with(|_| ());
120 POSEIDON_2.with(|_| ());
121 POSEIDON_4.with(|_| ());
122 POSEIDON_8.with(|_| ());
123 SHA3_256.with(|_| ());
124 SHA3_384.with(|_| ());
125 SHA3_512.with(|_| ());
126 }
127
128 fn encryption_domain() -> Field<Self> {
130 ENCRYPTION_DOMAIN.with(|domain| domain.clone())
131 }
132
133 fn graph_key_domain() -> Field<Self> {
135 GRAPH_KEY_DOMAIN.with(|domain| domain.clone())
136 }
137
138 fn serial_number_domain() -> Field<Self> {
140 SERIAL_NUMBER_DOMAIN.with(|domain| domain.clone())
141 }
142
143 #[inline]
145 fn g_scalar_multiply(scalar: &Scalar<Self>) -> Group<Self> {
146 GENERATOR_G.with(|bases| {
147 bases
148 .iter()
149 .zip_eq(&scalar.to_bits_le())
150 .fold(Group::zero(), |output, (base, bit)| Group::ternary(bit, &(&output + base), &output))
151 })
152 }
153
154 fn commit_bhp256(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
156 BHP_256.with(|bhp| bhp.commit(input, randomizer))
157 }
158
159 fn commit_bhp512(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
161 BHP_512.with(|bhp| bhp.commit(input, randomizer))
162 }
163
164 fn commit_bhp768(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
166 BHP_768.with(|bhp| bhp.commit(input, randomizer))
167 }
168
169 fn commit_bhp1024(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
171 BHP_1024.with(|bhp| bhp.commit(input, randomizer))
172 }
173
174 fn commit_ped64(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
176 PEDERSEN_64.with(|pedersen| pedersen.commit(input, randomizer))
177 }
178
179 fn commit_ped128(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
181 PEDERSEN_128.with(|pedersen| pedersen.commit(input, randomizer))
182 }
183
184 fn commit_to_group_bhp256(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
186 BHP_256.with(|bhp| bhp.commit_uncompressed(input, randomizer))
187 }
188
189 fn commit_to_group_bhp512(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
191 BHP_512.with(|bhp| bhp.commit_uncompressed(input, randomizer))
192 }
193
194 fn commit_to_group_bhp768(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
196 BHP_768.with(|bhp| bhp.commit_uncompressed(input, randomizer))
197 }
198
199 fn commit_to_group_bhp1024(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
201 BHP_1024.with(|bhp| bhp.commit_uncompressed(input, randomizer))
202 }
203
204 fn commit_to_group_ped64(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
206 PEDERSEN_64.with(|pedersen| pedersen.commit_uncompressed(input, randomizer))
207 }
208
209 fn commit_to_group_ped128(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
211 PEDERSEN_128.with(|pedersen| pedersen.commit_uncompressed(input, randomizer))
212 }
213
214 fn hash_bhp256(input: &[Boolean<Self>]) -> Field<Self> {
216 BHP_256.with(|bhp| bhp.hash(input))
217 }
218
219 fn hash_bhp512(input: &[Boolean<Self>]) -> Field<Self> {
221 BHP_512.with(|bhp| bhp.hash(input))
222 }
223
224 fn hash_bhp768(input: &[Boolean<Self>]) -> Field<Self> {
226 BHP_768.with(|bhp| bhp.hash(input))
227 }
228
229 fn hash_bhp1024(input: &[Boolean<Self>]) -> Field<Self> {
231 BHP_1024.with(|bhp| bhp.hash(input))
232 }
233
234 fn hash_keccak256(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
236 KECCAK_256.with(|keccak| keccak.hash(input))
237 }
238
239 fn hash_keccak384(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
241 KECCAK_384.with(|keccak| keccak.hash(input))
242 }
243
244 fn hash_keccak512(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
246 KECCAK_512.with(|keccak| keccak.hash(input))
247 }
248
249 fn hash_ped64(input: &[Boolean<Self>]) -> Field<Self> {
251 PEDERSEN_64.with(|pedersen| pedersen.hash(input))
252 }
253
254 fn hash_ped128(input: &[Boolean<Self>]) -> Field<Self> {
256 PEDERSEN_128.with(|pedersen| pedersen.hash(input))
257 }
258
259 fn hash_psd2(input: &[Field<Self>]) -> Field<Self> {
261 POSEIDON_2.with(|poseidon| poseidon.hash(input))
262 }
263
264 fn hash_psd4(input: &[Field<Self>]) -> Field<Self> {
266 POSEIDON_4.with(|poseidon| poseidon.hash(input))
267 }
268
269 fn hash_psd8(input: &[Field<Self>]) -> Field<Self> {
271 POSEIDON_8.with(|poseidon| poseidon.hash(input))
272 }
273
274 fn hash_sha3_256(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
276 SHA3_256.with(|sha3| sha3.hash(input))
277 }
278
279 fn hash_sha3_384(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
281 SHA3_384.with(|sha3| sha3.hash(input))
282 }
283
284 fn hash_sha3_512(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
286 SHA3_512.with(|sha3| sha3.hash(input))
287 }
288
289 fn hash_many_psd2(input: &[Field<Self>], num_outputs: u16) -> Vec<Field<Self>> {
291 POSEIDON_2.with(|poseidon| poseidon.hash_many(input, num_outputs))
292 }
293
294 fn hash_many_psd4(input: &[Field<Self>], num_outputs: u16) -> Vec<Field<Self>> {
296 POSEIDON_4.with(|poseidon| poseidon.hash_many(input, num_outputs))
297 }
298
299 fn hash_many_psd8(input: &[Field<Self>], num_outputs: u16) -> Vec<Field<Self>> {
301 POSEIDON_8.with(|poseidon| poseidon.hash_many(input, num_outputs))
302 }
303
304 fn hash_to_group_bhp256(input: &[Boolean<Self>]) -> Group<Self> {
306 BHP_256.with(|bhp| bhp.hash_uncompressed(input))
307 }
308
309 fn hash_to_group_bhp512(input: &[Boolean<Self>]) -> Group<Self> {
311 BHP_512.with(|bhp| bhp.hash_uncompressed(input))
312 }
313
314 fn hash_to_group_bhp768(input: &[Boolean<Self>]) -> Group<Self> {
316 BHP_768.with(|bhp| bhp.hash_uncompressed(input))
317 }
318
319 fn hash_to_group_bhp1024(input: &[Boolean<Self>]) -> Group<Self> {
321 BHP_1024.with(|bhp| bhp.hash_uncompressed(input))
322 }
323
324 fn hash_to_group_ped64(input: &[Boolean<Self>]) -> Group<Self> {
326 PEDERSEN_64.with(|pedersen| pedersen.hash_uncompressed(input))
327 }
328
329 fn hash_to_group_ped128(input: &[Boolean<Self>]) -> Group<Self> {
331 PEDERSEN_128.with(|pedersen| pedersen.hash_uncompressed(input))
332 }
333
334 fn hash_to_group_psd2(input: &[Field<Self>]) -> Group<Self> {
336 POSEIDON_2.with(|poseidon| poseidon.hash_to_group(input))
337 }
338
339 fn hash_to_group_psd4(input: &[Field<Self>]) -> Group<Self> {
341 POSEIDON_4.with(|poseidon| poseidon.hash_to_group(input))
342 }
343
344 fn hash_to_group_psd8(input: &[Field<Self>]) -> Group<Self> {
346 POSEIDON_8.with(|poseidon| poseidon.hash_to_group(input))
347 }
348
349 fn hash_to_scalar_psd2(input: &[Field<Self>]) -> Scalar<Self> {
351 POSEIDON_2.with(|poseidon| poseidon.hash_to_scalar(input))
352 }
353
354 fn hash_to_scalar_psd4(input: &[Field<Self>]) -> Scalar<Self> {
356 POSEIDON_4.with(|poseidon| poseidon.hash_to_scalar(input))
357 }
358
359 fn hash_to_scalar_psd8(input: &[Field<Self>]) -> Scalar<Self> {
361 POSEIDON_8.with(|poseidon| poseidon.hash_to_scalar(input))
362 }
363
364 fn verify_merkle_path_bhp<const DEPTH: u8>(
366 path: &MerklePath<Self, DEPTH>,
367 root: &Field<Self>,
368 leaf: &Vec<Boolean<Self>>,
369 ) -> Boolean<Self> {
370 BHP_1024.with(|bhp1024| BHP_512.with(|bhp512| path.verify(bhp1024, bhp512, root, leaf)))
371 }
372
373 fn verify_merkle_path_psd<const DEPTH: u8>(
375 path: &MerklePath<Self, DEPTH>,
376 root: &Field<Self>,
377 leaf: &Vec<Field<Self>>,
378 ) -> Boolean<Self> {
379 POSEIDON_4.with(|psd4| POSEIDON_2.with(|psd2| path.verify(psd4, psd2, root, leaf)))
380 }
381}
382
383impl Environment for AleoTestnetV0 {
384 type Affine = <E as Environment>::Affine;
385 type BaseField = <E as Environment>::BaseField;
386 type Network = <E as Environment>::Network;
387 type ScalarField = <E as Environment>::ScalarField;
388
389 fn zero() -> LinearCombination<Self::BaseField> {
391 E::zero()
392 }
393
394 fn one() -> LinearCombination<Self::BaseField> {
396 E::one()
397 }
398
399 fn new_variable(mode: Mode, value: Self::BaseField) -> Variable<Self::BaseField> {
401 E::new_variable(mode, value)
402 }
403
404 fn new_witness<Fn: FnOnce() -> Output::Primitive, Output: Inject>(mode: Mode, logic: Fn) -> Output {
406 E::new_witness(mode, logic)
407 }
408
409 fn scope<S: Into<String>, Fn, Output>(name: S, logic: Fn) -> Output
411 where
412 Fn: FnOnce() -> Output,
413 {
414 E::scope(name, logic)
415 }
416
417 fn enforce<Fn, A, B, C>(constraint: Fn)
419 where
420 Fn: FnOnce() -> (A, B, C),
421 A: Into<LinearCombination<Self::BaseField>>,
422 B: Into<LinearCombination<Self::BaseField>>,
423 C: Into<LinearCombination<Self::BaseField>>,
424 {
425 E::enforce(constraint)
426 }
427
428 fn is_satisfied() -> bool {
430 E::is_satisfied()
431 }
432
433 fn is_satisfied_in_scope() -> bool {
435 E::is_satisfied_in_scope()
436 }
437
438 fn num_constants() -> u64 {
440 E::num_constants()
441 }
442
443 fn num_public() -> u64 {
445 E::num_public()
446 }
447
448 fn num_private() -> u64 {
450 E::num_private()
451 }
452
453 fn num_variables() -> u64 {
455 E::num_variables()
456 }
457
458 fn num_constraints() -> u64 {
460 E::num_constraints()
461 }
462
463 fn num_nonzeros() -> (u64, u64, u64) {
465 E::num_nonzeros()
466 }
467
468 fn num_constants_in_scope() -> u64 {
470 E::num_constants_in_scope()
471 }
472
473 fn num_public_in_scope() -> u64 {
475 E::num_public_in_scope()
476 }
477
478 fn num_private_in_scope() -> u64 {
480 E::num_private_in_scope()
481 }
482
483 fn num_constraints_in_scope() -> u64 {
485 E::num_constraints_in_scope()
486 }
487
488 fn num_nonzeros_in_scope() -> (u64, u64, u64) {
490 E::num_nonzeros_in_scope()
491 }
492
493 fn get_variable_limit() -> Option<u64> {
495 E::get_variable_limit()
496 }
497
498 fn set_variable_limit(limit: Option<u64>) {
500 E::set_variable_limit(limit)
501 }
502
503 fn get_constraint_limit() -> Option<u64> {
505 E::get_constraint_limit()
506 }
507
508 fn set_constraint_limit(limit: Option<u64>) {
510 E::set_constraint_limit(limit)
511 }
512
513 fn halt<S: Into<String>, T>(message: S) -> T {
515 E::halt(message)
516 }
517
518 fn inject_r1cs(r1cs: R1CS<Self::BaseField>) {
520 E::inject_r1cs(r1cs)
521 }
522
523 fn eject_r1cs_and_reset() -> R1CS<Self::BaseField> {
525 E::eject_r1cs_and_reset()
526 }
527
528 fn eject_assignment_and_reset() -> Assignment<<Self::Network as console::Environment>::Field> {
530 E::eject_assignment_and_reset()
531 }
532
533 fn reset() {
535 E::reset()
536 }
537}
538
539impl Display for AleoTestnetV0 {
540 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
541 fmt::Display::fmt(&TestnetCircuit, f)
543 }
544}
545
546#[cfg(test)]
547mod tests {
548 use super::*;
549 use snarkvm_circuit_types::Field;
550
551 type CurrentAleo = AleoTestnetV0;
552
553 fn create_example_circuit<E: Environment>() -> Field<E> {
555 let one = snarkvm_console_types::Field::<<E as Environment>::Network>::one();
556 let two = one + one;
557
558 const EXPONENT: u64 = 64;
559
560 let mut candidate = Field::<E>::new(Mode::Public, one);
562 let mut accumulator = Field::new(Mode::Private, two);
563 for _ in 0..EXPONENT {
564 candidate += &accumulator;
565 accumulator *= Field::new(Mode::Private, two);
566 }
567
568 assert_eq!((accumulator - Field::one()).eject_value(), candidate.eject_value());
569 assert_eq!(2, E::num_public());
570 assert_eq!(2 * EXPONENT + 1, E::num_private());
571 assert_eq!(EXPONENT, E::num_constraints());
572 assert!(E::is_satisfied());
573
574 candidate
575 }
576
577 #[test]
578 fn test_print_circuit() {
579 let circuit = CurrentAleo {};
580 let _candidate = create_example_circuit::<CurrentAleo>();
581 let output = format!("{circuit}");
582 println!("{output}");
583 }
584
585 #[test]
586 fn test_circuit_scope() {
587 CurrentAleo::scope("test_circuit_scope", || {
588 assert_eq!(0, CurrentAleo::num_constants());
589 assert_eq!(1, CurrentAleo::num_public());
590 assert_eq!(0, CurrentAleo::num_private());
591 assert_eq!(0, CurrentAleo::num_constraints());
592
593 assert_eq!(0, CurrentAleo::num_constants_in_scope());
594 assert_eq!(0, CurrentAleo::num_public_in_scope());
595 assert_eq!(0, CurrentAleo::num_private_in_scope());
596 assert_eq!(0, CurrentAleo::num_constraints_in_scope());
597 })
598 }
599}