snarkvm_circuit_network/
testnet_v0.rs

1// Copyright 2024 Aleo Network Foundation
2// This file is part of the snarkVM 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
16use 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    /// The group bases for the Aleo signature and encryption schemes.
56    static GENERATOR_G: Vec<Group<AleoTestnetV0>> = Vec::constant(<console::TestnetV0 as console::Network>::g_powers().to_vec());
57
58    /// The encryption domain as a constant field element.
59    static ENCRYPTION_DOMAIN: Field<AleoTestnetV0> = Field::constant(<console::TestnetV0 as console::Network>::encryption_domain());
60    /// The graph key domain as a constant field element.
61    static GRAPH_KEY_DOMAIN: Field<AleoTestnetV0> = Field::constant(<console::TestnetV0 as console::Network>::graph_key_domain());
62    /// The serial number domain as a constant field element.
63    static SERIAL_NUMBER_DOMAIN: Field<AleoTestnetV0> = Field::constant(<console::TestnetV0 as console::Network>::serial_number_domain());
64
65    /// The BHP hash function, which can take an input of up to 256 bits.
66    static BHP_256: BHP256<AleoTestnetV0> = BHP256::<AleoTestnetV0>::constant(console::TESTNET_BHP_256.clone());
67    /// The BHP hash function, which can take an input of up to 512 bits.
68    static BHP_512: BHP512<AleoTestnetV0> = BHP512::<AleoTestnetV0>::constant(console::TESTNET_BHP_512.clone());
69    /// The BHP hash function, which can take an input of up to 768 bits.
70    static BHP_768: BHP768<AleoTestnetV0> = BHP768::<AleoTestnetV0>::constant(console::TESTNET_BHP_768.clone());
71    /// The BHP hash function, which can take an input of up to 1024 bits.
72    static BHP_1024: BHP1024<AleoTestnetV0> = BHP1024::<AleoTestnetV0>::constant(console::TESTNET_BHP_1024.clone());
73
74    /// The Keccak hash function, which outputs 256 bits.
75    static KECCAK_256: Keccak256<AleoTestnetV0> = Keccak256::<AleoTestnetV0>::new();
76    /// The Keccak hash function, which outputs 384 bits.
77    static KECCAK_384: Keccak384<AleoTestnetV0> = Keccak384::<AleoTestnetV0>::new();
78    /// The Keccak hash function, which outputs 512 bits.
79    static KECCAK_512: Keccak512<AleoTestnetV0> = Keccak512::<AleoTestnetV0>::new();
80
81    /// The Pedersen hash function, which can take an input of up to 64 bits.
82    static PEDERSEN_64: Pedersen64<AleoTestnetV0> = Pedersen64::<AleoTestnetV0>::constant(console::TESTNET_PEDERSEN_64.clone());
83    /// The Pedersen hash function, which can take an input of up to 128 bits.
84    static PEDERSEN_128: Pedersen128<AleoTestnetV0> = Pedersen128::<AleoTestnetV0>::constant(console::TESTNET_PEDERSEN_128.clone());
85
86    /// The Poseidon hash function, using a rate of 2.
87    static POSEIDON_2: Poseidon2<AleoTestnetV0> = Poseidon2::<AleoTestnetV0>::constant(console::TESTNET_POSEIDON_2.clone());
88    /// The Poseidon hash function, using a rate of 4.
89    static POSEIDON_4: Poseidon4<AleoTestnetV0> = Poseidon4::<AleoTestnetV0>::constant(console::TESTNET_POSEIDON_4.clone());
90    /// The Poseidon hash function, using a rate of 8.
91    static POSEIDON_8: Poseidon8<AleoTestnetV0> = Poseidon8::<AleoTestnetV0>::constant(console::TESTNET_POSEIDON_8.clone());
92
93    /// The SHA-3 hash function, which outputs 256 bits.
94    static SHA3_256: Sha3_256<AleoTestnetV0> = Sha3_256::<AleoTestnetV0>::new();
95    /// The SHA-3 hash function, which outputs 384 bits.
96    static SHA3_384: Sha3_384<AleoTestnetV0> = Sha3_384::<AleoTestnetV0>::new();
97    /// The SHA-3 hash function, which outputs 512 bits.
98    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    /// Initializes the global constants for the Aleo environment.
106    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    /// Returns the encryption domain as a constant field element.
129    fn encryption_domain() -> Field<Self> {
130        ENCRYPTION_DOMAIN.with(|domain| domain.clone())
131    }
132
133    /// Returns the graph key domain as a constant field element.
134    fn graph_key_domain() -> Field<Self> {
135        GRAPH_KEY_DOMAIN.with(|domain| domain.clone())
136    }
137
138    /// Returns the serial number domain as a constant field element.
139    fn serial_number_domain() -> Field<Self> {
140        SERIAL_NUMBER_DOMAIN.with(|domain| domain.clone())
141    }
142
143    /// Returns the scalar multiplication on the generator `G`.
144    #[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    /// Returns a BHP commitment with an input hasher of 256-bits.
155    fn commit_bhp256(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
156        BHP_256.with(|bhp| bhp.commit(input, randomizer))
157    }
158
159    /// Returns a BHP commitment with an input hasher of 512-bits.
160    fn commit_bhp512(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
161        BHP_512.with(|bhp| bhp.commit(input, randomizer))
162    }
163
164    /// Returns a BHP commitment with an input hasher of 768-bits.
165    fn commit_bhp768(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
166        BHP_768.with(|bhp| bhp.commit(input, randomizer))
167    }
168
169    /// Returns a BHP commitment with an input hasher of 1024-bits.
170    fn commit_bhp1024(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
171        BHP_1024.with(|bhp| bhp.commit(input, randomizer))
172    }
173
174    /// Returns a Pedersen commitment for the given (up to) 64-bit input and randomizer.
175    fn commit_ped64(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
176        PEDERSEN_64.with(|pedersen| pedersen.commit(input, randomizer))
177    }
178
179    /// Returns a Pedersen commitment for the given (up to) 128-bit input and randomizer.
180    fn commit_ped128(input: &[Boolean<Self>], randomizer: &Scalar<Self>) -> Field<Self> {
181        PEDERSEN_128.with(|pedersen| pedersen.commit(input, randomizer))
182    }
183
184    /// Returns a BHP commitment with an input hasher of 256-bits.
185    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    /// Returns a BHP commitment with an input hasher of 512-bits.
190    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    /// Returns a BHP commitment with an input hasher of 768-bits.
195    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    /// Returns a BHP commitment with an input hasher of 1024-bits.
200    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    /// Returns a Pedersen commitment for the given (up to) 64-bit input and randomizer.
205    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    /// Returns a Pedersen commitment for the given (up to) 128-bit input and randomizer.
210    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    /// Returns the BHP hash with an input hasher of 256-bits.
215    fn hash_bhp256(input: &[Boolean<Self>]) -> Field<Self> {
216        BHP_256.with(|bhp| bhp.hash(input))
217    }
218
219    /// Returns the BHP hash with an input hasher of 512-bits.
220    fn hash_bhp512(input: &[Boolean<Self>]) -> Field<Self> {
221        BHP_512.with(|bhp| bhp.hash(input))
222    }
223
224    /// Returns the BHP hash with an input hasher of 768-bits.
225    fn hash_bhp768(input: &[Boolean<Self>]) -> Field<Self> {
226        BHP_768.with(|bhp| bhp.hash(input))
227    }
228
229    /// Returns the BHP hash with an input hasher of 1024-bits.
230    fn hash_bhp1024(input: &[Boolean<Self>]) -> Field<Self> {
231        BHP_1024.with(|bhp| bhp.hash(input))
232    }
233
234    /// Returns the Keccak hash with a 256-bit output.
235    fn hash_keccak256(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
236        KECCAK_256.with(|keccak| keccak.hash(input))
237    }
238
239    /// Returns the Keccak hash with a 384-bit output.
240    fn hash_keccak384(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
241        KECCAK_384.with(|keccak| keccak.hash(input))
242    }
243
244    /// Returns the Keccak hash with a 512-bit output.
245    fn hash_keccak512(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
246        KECCAK_512.with(|keccak| keccak.hash(input))
247    }
248
249    /// Returns the Pedersen hash for a given (up to) 64-bit input.
250    fn hash_ped64(input: &[Boolean<Self>]) -> Field<Self> {
251        PEDERSEN_64.with(|pedersen| pedersen.hash(input))
252    }
253
254    /// Returns the Pedersen hash for a given (up to) 128-bit input.
255    fn hash_ped128(input: &[Boolean<Self>]) -> Field<Self> {
256        PEDERSEN_128.with(|pedersen| pedersen.hash(input))
257    }
258
259    /// Returns the Poseidon hash with an input rate of 2.
260    fn hash_psd2(input: &[Field<Self>]) -> Field<Self> {
261        POSEIDON_2.with(|poseidon| poseidon.hash(input))
262    }
263
264    /// Returns the Poseidon hash with an input rate of 4.
265    fn hash_psd4(input: &[Field<Self>]) -> Field<Self> {
266        POSEIDON_4.with(|poseidon| poseidon.hash(input))
267    }
268
269    /// Returns the Poseidon hash with an input rate of 8.
270    fn hash_psd8(input: &[Field<Self>]) -> Field<Self> {
271        POSEIDON_8.with(|poseidon| poseidon.hash(input))
272    }
273
274    /// Returns the SHA-3 hash with a 256-bit output.
275    fn hash_sha3_256(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
276        SHA3_256.with(|sha3| sha3.hash(input))
277    }
278
279    /// Returns the SHA-3 hash with a 384-bit output.
280    fn hash_sha3_384(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
281        SHA3_384.with(|sha3| sha3.hash(input))
282    }
283
284    /// Returns the SHA-3 hash with a 512-bit output.
285    fn hash_sha3_512(input: &[Boolean<Self>]) -> Vec<Boolean<Self>> {
286        SHA3_512.with(|sha3| sha3.hash(input))
287    }
288
289    /// Returns the extended Poseidon hash with an input rate of 2.
290    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    /// Returns the extended Poseidon hash with an input rate of 4.
295    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    /// Returns the extended Poseidon hash with an input rate of 8.
300    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    /// Returns the BHP hash with an input hasher of 256-bits.
305    fn hash_to_group_bhp256(input: &[Boolean<Self>]) -> Group<Self> {
306        BHP_256.with(|bhp| bhp.hash_uncompressed(input))
307    }
308
309    /// Returns the BHP hash with an input hasher of 512-bits.
310    fn hash_to_group_bhp512(input: &[Boolean<Self>]) -> Group<Self> {
311        BHP_512.with(|bhp| bhp.hash_uncompressed(input))
312    }
313
314    /// Returns the BHP hash with an input hasher of 768-bits.
315    fn hash_to_group_bhp768(input: &[Boolean<Self>]) -> Group<Self> {
316        BHP_768.with(|bhp| bhp.hash_uncompressed(input))
317    }
318
319    /// Returns the BHP hash with an input hasher of 1024-bits.
320    fn hash_to_group_bhp1024(input: &[Boolean<Self>]) -> Group<Self> {
321        BHP_1024.with(|bhp| bhp.hash_uncompressed(input))
322    }
323
324    /// Returns the Pedersen hash for a given (up to) 64-bit input.
325    fn hash_to_group_ped64(input: &[Boolean<Self>]) -> Group<Self> {
326        PEDERSEN_64.with(|pedersen| pedersen.hash_uncompressed(input))
327    }
328
329    /// Returns the Pedersen hash for a given (up to) 128-bit input.
330    fn hash_to_group_ped128(input: &[Boolean<Self>]) -> Group<Self> {
331        PEDERSEN_128.with(|pedersen| pedersen.hash_uncompressed(input))
332    }
333
334    /// Returns the Poseidon hash with an input rate of 2 on the affine curve.
335    fn hash_to_group_psd2(input: &[Field<Self>]) -> Group<Self> {
336        POSEIDON_2.with(|poseidon| poseidon.hash_to_group(input))
337    }
338
339    /// Returns the Poseidon hash with an input rate of 4 on the affine curve.
340    fn hash_to_group_psd4(input: &[Field<Self>]) -> Group<Self> {
341        POSEIDON_4.with(|poseidon| poseidon.hash_to_group(input))
342    }
343
344    /// Returns the Poseidon hash with an input rate of 8 on the affine curve.
345    fn hash_to_group_psd8(input: &[Field<Self>]) -> Group<Self> {
346        POSEIDON_8.with(|poseidon| poseidon.hash_to_group(input))
347    }
348
349    /// Returns the Poseidon hash with an input rate of 2 on the scalar field.
350    fn hash_to_scalar_psd2(input: &[Field<Self>]) -> Scalar<Self> {
351        POSEIDON_2.with(|poseidon| poseidon.hash_to_scalar(input))
352    }
353
354    /// Returns the Poseidon hash with an input rate of 4 on the scalar field.
355    fn hash_to_scalar_psd4(input: &[Field<Self>]) -> Scalar<Self> {
356        POSEIDON_4.with(|poseidon| poseidon.hash_to_scalar(input))
357    }
358
359    /// Returns the Poseidon hash with an input rate of 8 on the scalar field.
360    fn hash_to_scalar_psd8(input: &[Field<Self>]) -> Scalar<Self> {
361        POSEIDON_8.with(|poseidon| poseidon.hash_to_scalar(input))
362    }
363
364    /// Returns `true` if the given Merkle path is valid for the given root and leaf.
365    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    /// Returns `true` if the given Merkle path is valid for the given root and leaf.
374    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    /// Returns the `zero` constant.
390    fn zero() -> LinearCombination<Self::BaseField> {
391        E::zero()
392    }
393
394    /// Returns the `one` constant.
395    fn one() -> LinearCombination<Self::BaseField> {
396        E::one()
397    }
398
399    /// Returns a new variable of the given mode and value.
400    fn new_variable(mode: Mode, value: Self::BaseField) -> Variable<Self::BaseField> {
401        E::new_variable(mode, value)
402    }
403
404    /// Returns a new witness of the given mode and value.
405    fn new_witness<Fn: FnOnce() -> Output::Primitive, Output: Inject>(mode: Mode, logic: Fn) -> Output {
406        E::new_witness(mode, logic)
407    }
408
409    /// Enters a new scope for the environment.
410    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    /// Adds one constraint enforcing that `(A * B) == C`.
418    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    /// Returns `true` if all constraints in the environment are satisfied.
429    fn is_satisfied() -> bool {
430        E::is_satisfied()
431    }
432
433    /// Returns `true` if all constraints in the current scope are satisfied.
434    fn is_satisfied_in_scope() -> bool {
435        E::is_satisfied_in_scope()
436    }
437
438    /// Returns the number of constants in the entire circuit.
439    fn num_constants() -> u64 {
440        E::num_constants()
441    }
442
443    /// Returns the number of public variables in the entire circuit.
444    fn num_public() -> u64 {
445        E::num_public()
446    }
447
448    /// Returns the number of private variables in the entire circuit.
449    fn num_private() -> u64 {
450        E::num_private()
451    }
452
453    /// Returns the number of constant, public, and private variables in the entire circuit.
454    fn num_variables() -> u64 {
455        E::num_variables()
456    }
457
458    /// Returns the number of constraints in the entire circuit.
459    fn num_constraints() -> u64 {
460        E::num_constraints()
461    }
462
463    /// Returns the number of nonzeros in the entire circuit.
464    fn num_nonzeros() -> (u64, u64, u64) {
465        E::num_nonzeros()
466    }
467
468    /// Returns the number of constants for the current scope.
469    fn num_constants_in_scope() -> u64 {
470        E::num_constants_in_scope()
471    }
472
473    /// Returns the number of public variables for the current scope.
474    fn num_public_in_scope() -> u64 {
475        E::num_public_in_scope()
476    }
477
478    /// Returns the number of private variables for the current scope.
479    fn num_private_in_scope() -> u64 {
480        E::num_private_in_scope()
481    }
482
483    /// Returns the number of constraints for the current scope.
484    fn num_constraints_in_scope() -> u64 {
485        E::num_constraints_in_scope()
486    }
487
488    /// Returns the number of nonzeros for the current scope.
489    fn num_nonzeros_in_scope() -> (u64, u64, u64) {
490        E::num_nonzeros_in_scope()
491    }
492
493    /// Returns the variable limit for the circuit, if one exists.
494    fn get_variable_limit() -> Option<u64> {
495        E::get_variable_limit()
496    }
497
498    /// Sets the variable limit for the circuit.
499    fn set_variable_limit(limit: Option<u64>) {
500        E::set_variable_limit(limit)
501    }
502
503    /// Returns the constraint limit for the circuit, if one exists.
504    fn get_constraint_limit() -> Option<u64> {
505        E::get_constraint_limit()
506    }
507
508    /// Sets the constraint limit for the circuit.
509    fn set_constraint_limit(limit: Option<u64>) {
510        E::set_constraint_limit(limit)
511    }
512
513    /// Halts the program from further synthesis, evaluation, and execution in the current environment.
514    fn halt<S: Into<String>, T>(message: S) -> T {
515        E::halt(message)
516    }
517
518    /// Returns the R1CS circuit, resetting the circuit.
519    fn inject_r1cs(r1cs: R1CS<Self::BaseField>) {
520        E::inject_r1cs(r1cs)
521    }
522
523    /// Returns the R1CS circuit, resetting the circuit.
524    fn eject_r1cs_and_reset() -> R1CS<Self::BaseField> {
525        E::eject_r1cs_and_reset()
526    }
527
528    /// Returns the R1CS assignment of the circuit, resetting the circuit.
529    fn eject_assignment_and_reset() -> Assignment<<Self::Network as console::Environment>::Field> {
530        E::eject_assignment_and_reset()
531    }
532
533    /// Clears the circuit and initializes an empty environment.
534    fn reset() {
535        E::reset()
536    }
537}
538
539impl Display for AleoTestnetV0 {
540    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
541        // TODO (howardwu): Find a better way to print the circuit.
542        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    /// Compute 2^EXPONENT - 1, in a purposefully constraint-inefficient manner for testing.
554    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        // Compute 2^EXPONENT - 1, in a purposefully constraint-inefficient manner for testing.
561        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}