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 COMMITMENT_DOMAIN: Field<AleoTestnetV0> = Field::constant(<console::TestnetV0 as console::Network>::commitment_domain());
60 static ENCRYPTION_DOMAIN: Field<AleoTestnetV0> = Field::constant(<console::TestnetV0 as console::Network>::encryption_domain());
62 static GRAPH_KEY_DOMAIN: Field<AleoTestnetV0> = Field::constant(<console::TestnetV0 as console::Network>::graph_key_domain());
64 static SERIAL_NUMBER_DOMAIN: Field<AleoTestnetV0> = Field::constant(<console::TestnetV0 as console::Network>::serial_number_domain());
66
67 static BHP_256: BHP256<AleoTestnetV0> = BHP256::<AleoTestnetV0>::constant(console::TESTNET_BHP_256.clone());
69 static BHP_512: BHP512<AleoTestnetV0> = BHP512::<AleoTestnetV0>::constant(console::TESTNET_BHP_512.clone());
71 static BHP_768: BHP768<AleoTestnetV0> = BHP768::<AleoTestnetV0>::constant(console::TESTNET_BHP_768.clone());
73 static BHP_1024: BHP1024<AleoTestnetV0> = BHP1024::<AleoTestnetV0>::constant(console::TESTNET_BHP_1024.clone());
75
76 static KECCAK_256: Keccak256<AleoTestnetV0> = Keccak256::<AleoTestnetV0>::new();
78 static KECCAK_384: Keccak384<AleoTestnetV0> = Keccak384::<AleoTestnetV0>::new();
80 static KECCAK_512: Keccak512<AleoTestnetV0> = Keccak512::<AleoTestnetV0>::new();
82
83 static PEDERSEN_64: Pedersen64<AleoTestnetV0> = Pedersen64::<AleoTestnetV0>::constant(console::TESTNET_PEDERSEN_64.clone());
85 static PEDERSEN_128: Pedersen128<AleoTestnetV0> = Pedersen128::<AleoTestnetV0>::constant(console::TESTNET_PEDERSEN_128.clone());
87
88 static POSEIDON_2: Poseidon2<AleoTestnetV0> = Poseidon2::<AleoTestnetV0>::constant(console::TESTNET_POSEIDON_2.clone());
90 static POSEIDON_4: Poseidon4<AleoTestnetV0> = Poseidon4::<AleoTestnetV0>::constant(console::TESTNET_POSEIDON_4.clone());
92 static POSEIDON_8: Poseidon8<AleoTestnetV0> = Poseidon8::<AleoTestnetV0>::constant(console::TESTNET_POSEIDON_8.clone());
94
95 static SHA3_256: Sha3_256<AleoTestnetV0> = Sha3_256::<AleoTestnetV0>::new();
97 static SHA3_384: Sha3_384<AleoTestnetV0> = Sha3_384::<AleoTestnetV0>::new();
99 static SHA3_512: Sha3_512<AleoTestnetV0> = Sha3_512::<AleoTestnetV0>::new();
101}
102
103#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
104pub struct AleoTestnetV0;
105
106impl Aleo for AleoTestnetV0 {
107 fn initialize_global_constants() {
109 GENERATOR_G.with(|_| ());
110 COMMITMENT_DOMAIN.with(|_| ());
111 ENCRYPTION_DOMAIN.with(|_| ());
112 GRAPH_KEY_DOMAIN.with(|_| ());
113 SERIAL_NUMBER_DOMAIN.with(|_| ());
114 BHP_256.with(|_| ());
115 BHP_512.with(|_| ());
116 BHP_768.with(|_| ());
117 BHP_1024.with(|_| ());
118 KECCAK_256.with(|_| ());
119 KECCAK_384.with(|_| ());
120 KECCAK_512.with(|_| ());
121 PEDERSEN_64.with(|_| ());
122 PEDERSEN_128.with(|_| ());
123 POSEIDON_2.with(|_| ());
124 POSEIDON_4.with(|_| ());
125 POSEIDON_8.with(|_| ());
126 SHA3_256.with(|_| ());
127 SHA3_384.with(|_| ());
128 SHA3_512.with(|_| ());
129 }
130
131 fn commitment_domain() -> Field<Self> {
133 COMMITMENT_DOMAIN.with(|domain| domain.clone())
134 }
135
136 fn encryption_domain() -> Field<Self> {
138 ENCRYPTION_DOMAIN.with(|domain| domain.clone())
139 }
140
141 fn graph_key_domain() -> Field<Self> {
143 GRAPH_KEY_DOMAIN.with(|domain| domain.clone())
144 }
145
146 fn serial_number_domain() -> Field<Self> {
148 SERIAL_NUMBER_DOMAIN.with(|domain| domain.clone())
149 }
150
151 #[inline]
153 fn g_scalar_multiply(scalar: &Scalar<Self>) -> Group<Self> {
154 GENERATOR_G.with(|bases| {
155 bases
156 .iter()
157 .zip_eq(&scalar.to_bits_le())
158 .fold(Group::zero(), |output, (base, bit)| Group::ternary(bit, &(&output + base), &output))
159 })
160 }
161
162 fn commit_bhp256(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
164 BHP_256.with(|bhp| bhp.commit(input, randomizer))
165 }
166
167 fn commit_bhp512(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
169 BHP_512.with(|bhp| bhp.commit(input, randomizer))
170 }
171
172 fn commit_bhp768(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
174 BHP_768.with(|bhp| bhp.commit(input, randomizer))
175 }
176
177 fn commit_bhp1024(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
179 BHP_1024.with(|bhp| bhp.commit(input, randomizer))
180 }
181
182 fn commit_ped64(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
184 PEDERSEN_64.with(|pedersen| pedersen.commit(input, randomizer))
185 }
186
187 fn commit_ped128(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
189 PEDERSEN_128.with(|pedersen| pedersen.commit(input, randomizer))
190 }
191
192 fn commit_to_group_bhp256(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
194 BHP_256.with(|bhp| bhp.commit_uncompressed(input, randomizer))
195 }
196
197 fn commit_to_group_bhp512(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
199 BHP_512.with(|bhp| bhp.commit_uncompressed(input, randomizer))
200 }
201
202 fn commit_to_group_bhp768(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
204 BHP_768.with(|bhp| bhp.commit_uncompressed(input, randomizer))
205 }
206
207 fn commit_to_group_bhp1024(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
209 BHP_1024.with(|bhp| bhp.commit_uncompressed(input, randomizer))
210 }
211
212 fn commit_to_group_ped64(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
214 PEDERSEN_64.with(|pedersen| pedersen.commit_uncompressed(input, randomizer))
215 }
216
217 fn commit_to_group_ped128(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Group<Self> {
219 PEDERSEN_128.with(|pedersen| pedersen.commit_uncompressed(input, randomizer))
220 }
221
222 fn hash_bhp256(input: &[Boolean<Self>]) -> Field<Self> {
224 BHP_256.with(|bhp| bhp.hash(input))
225 }
226
227 fn hash_bhp512(input: &[Boolean<Self>]) -> Field<Self> {
229 BHP_512.with(|bhp| bhp.hash(input))
230 }
231
232 fn hash_bhp768(input: &[Boolean<Self>]) -> Field<Self> {
234 BHP_768.with(|bhp| bhp.hash(input))
235 }
236
237 fn hash_bhp1024(input: &[Boolean<Self>]) -> Field<Self> {
239 BHP_1024.with(|bhp| bhp.hash(input))
240 }
241
242 fn hash_keccak256(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
244 KECCAK_256.with(|keccak| keccak.hash(input))
245 }
246
247 fn hash_keccak384(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
249 KECCAK_384.with(|keccak| keccak.hash(input))
250 }
251
252 fn hash_keccak512(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
254 KECCAK_512.with(|keccak| keccak.hash(input))
255 }
256
257 fn hash_ped64(input: &[Boolean<Self>]) -> Field<Self> {
259 PEDERSEN_64.with(|pedersen| pedersen.hash(input))
260 }
261
262 fn hash_ped128(input: &[Boolean<Self>]) -> Field<Self> {
264 PEDERSEN_128.with(|pedersen| pedersen.hash(input))
265 }
266
267 fn hash_psd2(input: &[Field<Self>]) -> Field<Self> {
269 POSEIDON_2.with(|poseidon| poseidon.hash(input))
270 }
271
272 fn hash_psd4(input: &[Field<Self>]) -> Field<Self> {
274 POSEIDON_4.with(|poseidon| poseidon.hash(input))
275 }
276
277 fn hash_psd8(input: &[Field<Self>]) -> Field<Self> {
279 POSEIDON_8.with(|poseidon| poseidon.hash(input))
280 }
281
282 fn hash_sha3_256(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
284 SHA3_256.with(|sha3| sha3.hash(input))
285 }
286
287 fn hash_sha3_384(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
289 SHA3_384.with(|sha3| sha3.hash(input))
290 }
291
292 fn hash_sha3_512(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
294 SHA3_512.with(|sha3| sha3.hash(input))
295 }
296
297 fn hash_many_psd2(input: &[Field<Self>], num_outputs: u16) -> Vec<Field<Self>> {
299 POSEIDON_2.with(|poseidon| poseidon.hash_many(input, num_outputs))
300 }
301
302 fn hash_many_psd4(input: &[Field<Self>], num_outputs: u16) -> Vec<Field<Self>> {
304 POSEIDON_4.with(|poseidon| poseidon.hash_many(input, num_outputs))
305 }
306
307 fn hash_many_psd8(input: &[Field<Self>], num_outputs: u16) -> Vec<Field<Self>> {
309 POSEIDON_8.with(|poseidon| poseidon.hash_many(input, num_outputs))
310 }
311
312 fn hash_to_group_bhp256(input: &[Boolean<Self>]) -> Group<Self> {
314 BHP_256.with(|bhp| bhp.hash_uncompressed(input))
315 }
316
317 fn hash_to_group_bhp512(input: &[Boolean<Self>]) -> Group<Self> {
319 BHP_512.with(|bhp| bhp.hash_uncompressed(input))
320 }
321
322 fn hash_to_group_bhp768(input: &[Boolean<Self>]) -> Group<Self> {
324 BHP_768.with(|bhp| bhp.hash_uncompressed(input))
325 }
326
327 fn hash_to_group_bhp1024(input: &[Boolean<Self>]) -> Group<Self> {
329 BHP_1024.with(|bhp| bhp.hash_uncompressed(input))
330 }
331
332 fn hash_to_group_ped64(input: &[Boolean<Self>]) -> Group<Self> {
334 PEDERSEN_64.with(|pedersen| pedersen.hash_uncompressed(input))
335 }
336
337 fn hash_to_group_ped128(input: &[Boolean<Self>]) -> Group<Self> {
339 PEDERSEN_128.with(|pedersen| pedersen.hash_uncompressed(input))
340 }
341
342 fn hash_to_group_psd2(input: &[Field<Self>]) -> Group<Self> {
344 POSEIDON_2.with(|poseidon| poseidon.hash_to_group(input))
345 }
346
347 fn hash_to_group_psd4(input: &[Field<Self>]) -> Group<Self> {
349 POSEIDON_4.with(|poseidon| poseidon.hash_to_group(input))
350 }
351
352 fn hash_to_group_psd8(input: &[Field<Self>]) -> Group<Self> {
354 POSEIDON_8.with(|poseidon| poseidon.hash_to_group(input))
355 }
356
357 fn hash_to_scalar_psd2(input: &[Field<Self>]) -> Scalar<Self> {
359 POSEIDON_2.with(|poseidon| poseidon.hash_to_scalar(input))
360 }
361
362 fn hash_to_scalar_psd4(input: &[Field<Self>]) -> Scalar<Self> {
364 POSEIDON_4.with(|poseidon| poseidon.hash_to_scalar(input))
365 }
366
367 fn hash_to_scalar_psd8(input: &[Field<Self>]) -> Scalar<Self> {
369 POSEIDON_8.with(|poseidon| poseidon.hash_to_scalar(input))
370 }
371
372 fn verify_merkle_path_bhp<const DEPTH: u8>(
374 path: &MerklePath<Self, DEPTH>,
375 root: &Field<Self>,
376 leaf: &Vec<Boolean<Self>>,
377 ) -> Boolean<Self> {
378 BHP_1024.with(|bhp1024| BHP_512.with(|bhp512| path.verify(bhp1024, bhp512, root, leaf)))
379 }
380
381 fn verify_merkle_path_psd<const DEPTH: u8>(
383 path: &MerklePath<Self, DEPTH>,
384 root: &Field<Self>,
385 leaf: &Vec<Field<Self>>,
386 ) -> Boolean<Self> {
387 POSEIDON_4.with(|psd4| POSEIDON_2.with(|psd2| path.verify(psd4, psd2, root, leaf)))
388 }
389}
390
391impl Environment for AleoTestnetV0 {
392 type Affine = <E as Environment>::Affine;
393 type BaseField = <E as Environment>::BaseField;
394 type Network = <E as Environment>::Network;
395 type ScalarField = <E as Environment>::ScalarField;
396
397 fn zero() -> LinearCombination<Self::BaseField> {
399 E::zero()
400 }
401
402 fn one() -> LinearCombination<Self::BaseField> {
404 E::one()
405 }
406
407 fn new_variable(mode: Mode, value: Self::BaseField) -> Variable<Self::BaseField> {
409 E::new_variable(mode, value)
410 }
411
412 fn new_witness<Fn: FnOnce() -> Output::Primitive, Output: Inject>(mode: Mode, logic: Fn) -> Output {
414 E::new_witness(mode, logic)
415 }
416
417 fn scope<S: Into<String>, Fn, Output>(name: S, logic: Fn) -> Output
419 where
420 Fn: FnOnce() -> Output,
421 {
422 E::scope(name, logic)
423 }
424
425 fn enforce<Fn, A, B, C>(constraint: Fn)
427 where
428 Fn: FnOnce() -> (A, B, C),
429 A: Into<LinearCombination<Self::BaseField>>,
430 B: Into<LinearCombination<Self::BaseField>>,
431 C: Into<LinearCombination<Self::BaseField>>,
432 {
433 E::enforce(constraint)
434 }
435
436 fn is_satisfied() -> bool {
438 E::is_satisfied()
439 }
440
441 fn is_satisfied_in_scope() -> bool {
443 E::is_satisfied_in_scope()
444 }
445
446 fn num_constants() -> u64 {
448 E::num_constants()
449 }
450
451 fn num_public() -> u64 {
453 E::num_public()
454 }
455
456 fn num_private() -> u64 {
458 E::num_private()
459 }
460
461 fn num_variables() -> u64 {
463 E::num_variables()
464 }
465
466 fn num_constraints() -> u64 {
468 E::num_constraints()
469 }
470
471 fn num_nonzeros() -> (u64, u64, u64) {
473 E::num_nonzeros()
474 }
475
476 fn num_constants_in_scope() -> u64 {
478 E::num_constants_in_scope()
479 }
480
481 fn num_public_in_scope() -> u64 {
483 E::num_public_in_scope()
484 }
485
486 fn num_private_in_scope() -> u64 {
488 E::num_private_in_scope()
489 }
490
491 fn num_constraints_in_scope() -> u64 {
493 E::num_constraints_in_scope()
494 }
495
496 fn num_nonzeros_in_scope() -> (u64, u64, u64) {
498 E::num_nonzeros_in_scope()
499 }
500
501 fn get_variable_limit() -> Option<u64> {
503 E::get_variable_limit()
504 }
505
506 fn set_variable_limit(limit: Option<u64>) {
508 E::set_variable_limit(limit)
509 }
510
511 fn get_constraint_limit() -> Option<u64> {
513 E::get_constraint_limit()
514 }
515
516 fn set_constraint_limit(limit: Option<u64>) {
518 E::set_constraint_limit(limit)
519 }
520
521 fn halt<S: Into<String>, T>(message: S) -> T {
523 E::halt(message)
524 }
525
526 fn inject_r1cs(r1cs: R1CS<Self::BaseField>) {
528 E::inject_r1cs(r1cs)
529 }
530
531 fn eject_r1cs_and_reset() -> R1CS<Self::BaseField> {
533 E::eject_r1cs_and_reset()
534 }
535
536 fn eject_assignment_and_reset() -> Assignment<<Self::Network as console::Environment>::Field> {
538 E::eject_assignment_and_reset()
539 }
540
541 fn reset() {
543 E::reset()
544 }
545}
546
547impl Display for AleoTestnetV0 {
548 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
549 fmt::Display::fmt(&TestnetCircuit, f)
551 }
552}
553
554#[cfg(test)]
555mod tests {
556 use super::*;
557 use snarkvm_circuit_types::Field;
558
559 type CurrentAleo = AleoTestnetV0;
560
561 fn create_example_circuit<E: Environment>() -> Field<E> {
563 let one = snarkvm_console_types::Field::<<E as Environment>::Network>::one();
564 let two = one + one;
565
566 const EXPONENT: u64 = 64;
567
568 let mut candidate = Field::<E>::new(Mode::Public, one);
570 let mut accumulator = Field::new(Mode::Private, two);
571 for _ in 0..EXPONENT {
572 candidate += &accumulator;
573 accumulator *= Field::new(Mode::Private, two);
574 }
575
576 assert_eq!((accumulator - Field::one()).eject_value(), candidate.eject_value());
577 assert_eq!(2, E::num_public());
578 assert_eq!(2 * EXPONENT + 1, E::num_private());
579 assert_eq!(EXPONENT, E::num_constraints());
580 assert!(E::is_satisfied());
581
582 candidate
583 }
584
585 #[test]
586 fn test_print_circuit() {
587 let circuit = CurrentAleo {};
588 let _candidate = create_example_circuit::<CurrentAleo>();
589 let output = format!("{circuit}");
590 println!("{output}");
591 }
592
593 #[test]
594 fn test_circuit_scope() {
595 CurrentAleo::scope("test_circuit_scope", || {
596 assert_eq!(0, CurrentAleo::num_constants());
597 assert_eq!(1, CurrentAleo::num_public());
598 assert_eq!(0, CurrentAleo::num_private());
599 assert_eq!(0, CurrentAleo::num_constraints());
600
601 assert_eq!(0, CurrentAleo::num_constants_in_scope());
602 assert_eq!(0, CurrentAleo::num_public_in_scope());
603 assert_eq!(0, CurrentAleo::num_private_in_scope());
604 assert_eq!(0, CurrentAleo::num_constraints_in_scope());
605 })
606 }
607}