snarkvm_circuit_network/
testnet_v0.rs

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