snarkvm_circuit_environment/
environment.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::{Assignment, Inject, LinearCombination, Mode, R1CS, Variable, witness_mode};
17use snarkvm_curves::AffineCurve;
18use snarkvm_fields::traits::*;
19
20use core::{fmt, hash};
21
22/// Attention: Do not use `Send + Sync` on this trait, as it is not thread-safe.
23pub trait Environment: 'static + Copy + Clone + fmt::Debug + fmt::Display + Eq + PartialEq + hash::Hash {
24    type Network: console::Network<Affine = Self::Affine, Field = Self::BaseField, Scalar = Self::ScalarField>;
25
26    type Affine: AffineCurve<
27            BaseField = Self::BaseField,
28            ScalarField = Self::ScalarField,
29            Coordinates = (Self::BaseField, Self::BaseField),
30        >;
31    type BaseField: PrimeField + SquareRootField + Copy;
32    type ScalarField: PrimeField<BigInteger = <Self::BaseField as PrimeField>::BigInteger> + Copy;
33
34    /// The coefficient `A` of the twisted Edwards curve.
35    const EDWARDS_A: Self::BaseField = <Self::Network as console::Environment>::EDWARDS_A;
36    /// The coefficient `D` of the twisted Edwards curve.
37    const EDWARDS_D: Self::BaseField = <Self::Network as console::Environment>::EDWARDS_D;
38
39    /// The coefficient `A` of the Montgomery curve.
40    const MONTGOMERY_A: Self::BaseField = <Self::Network as console::Environment>::MONTGOMERY_A;
41    /// The coefficient `B` of the Montgomery curve.
42    const MONTGOMERY_B: Self::BaseField = <Self::Network as console::Environment>::MONTGOMERY_B;
43
44    /// The maximum number of bytes allowed in a string.
45    const MAX_STRING_BYTES: u32 = <Self::Network as console::Environment>::MAX_STRING_BYTES;
46
47    /// Returns the `zero` constant.
48    fn zero() -> LinearCombination<Self::BaseField>;
49
50    /// Returns the `one` constant.
51    fn one() -> LinearCombination<Self::BaseField>;
52
53    /// Returns a new variable of the given mode and value.
54    fn new_variable(mode: Mode, value: Self::BaseField) -> Variable<Self::BaseField>;
55
56    /// Returns a new witness of the given mode and value.
57    fn new_witness<Fn: FnOnce() -> Output::Primitive, Output: Inject>(mode: Mode, value: Fn) -> Output;
58
59    /// Enters a new scope for the environment.
60    fn scope<S: Into<String>, Fn, Output>(name: S, logic: Fn) -> Output
61    where
62        Fn: FnOnce() -> Output;
63
64    /// Adds one constraint enforcing that `(A * B) == C`.
65    fn enforce<Fn, A, B, C>(constraint: Fn)
66    where
67        Fn: FnOnce() -> (A, B, C),
68        A: Into<LinearCombination<Self::BaseField>>,
69        B: Into<LinearCombination<Self::BaseField>>,
70        C: Into<LinearCombination<Self::BaseField>>;
71
72    /// Adds one constraint enforcing that the given boolean is `true`.
73    fn assert<Boolean: Into<LinearCombination<Self::BaseField>>>(boolean: Boolean) {
74        Self::enforce(|| (boolean, Self::one(), Self::one()))
75    }
76
77    /// Adds one constraint enforcing that the `A == B`.
78    fn assert_eq<A, B>(a: A, b: B)
79    where
80        A: Into<LinearCombination<Self::BaseField>>,
81        B: Into<LinearCombination<Self::BaseField>>,
82    {
83        Self::enforce(|| (a, Self::one(), b))
84    }
85
86    /// Adds one constraint enforcing that the `A != B`.
87    fn assert_neq<A, B>(a: A, b: B)
88    where
89        A: Into<LinearCombination<Self::BaseField>>,
90        B: Into<LinearCombination<Self::BaseField>>,
91    {
92        let (a, b) = (a.into(), b.into());
93        let mode = witness_mode!(a, b);
94
95        // Compute `(a - b)`.
96        let a_minus_b = a - b;
97
98        // Compute `multiplier` as `1 / (a - b)`.
99        let multiplier = match a_minus_b.value().inverse() {
100            Some(inverse) => Self::new_variable(mode, inverse).into(),
101            None => Self::zero(),
102        };
103
104        // Enforce `(a - b) * multiplier == 1`.
105        Self::enforce(|| (a_minus_b, multiplier, Self::one()));
106    }
107
108    /// Returns `true` if all constraints in the environment are satisfied.
109    fn is_satisfied() -> bool;
110
111    /// Returns `true` if all constraints in the current scope are satisfied.
112    fn is_satisfied_in_scope() -> bool;
113
114    /// Returns the number of constants in the entire environment.
115    fn num_constants() -> u64;
116
117    /// Returns the number of public variables in the entire environment.
118    fn num_public() -> u64;
119
120    /// Returns the number of private variables in the entire environment.
121    fn num_private() -> u64;
122
123    /// Returns the number of constant, public, and private variables in the entire environment.
124    fn num_variables() -> u64;
125
126    /// Returns the number of constraints in the entire environment.
127    fn num_constraints() -> u64;
128
129    /// Returns the number of nonzeros in the entire circuit.
130    fn num_nonzeros() -> (u64, u64, u64);
131
132    /// Returns a tuple containing the number of constants, public variables, private variables, constraints, and nonzeros in the entire environment.
133    fn count() -> (u64, u64, u64, u64, (u64, u64, u64)) {
134        (Self::num_constants(), Self::num_public(), Self::num_private(), Self::num_constraints(), Self::num_nonzeros())
135    }
136
137    /// Returns the number of constants for the current scope.
138    fn num_constants_in_scope() -> u64;
139
140    /// Returns the number of public variables for the current scope.
141    fn num_public_in_scope() -> u64;
142
143    /// Returns the number of private variables for the current scope.
144    fn num_private_in_scope() -> u64;
145
146    /// Returns the number of constraints for the current scope.
147    fn num_constraints_in_scope() -> u64;
148
149    /// Returns the number of nonzeros for the current scope.
150    fn num_nonzeros_in_scope() -> (u64, u64, u64);
151
152    /// Returns a tuple containing the number of constants, public variables, private variables, constraints, and nonzeros for the current scope.
153    fn count_in_scope() -> (u64, u64, u64, u64, (u64, u64, u64)) {
154        (
155            Self::num_constants_in_scope(),
156            Self::num_public_in_scope(),
157            Self::num_private_in_scope(),
158            Self::num_constraints_in_scope(),
159            Self::num_nonzeros_in_scope(),
160        )
161    }
162
163    /// Returns the variable limit for the circuit, if one exists.
164    fn get_variable_limit() -> Option<u64>;
165
166    /// Sets the variable limit for the circuit.
167    fn set_variable_limit(limit: Option<u64>);
168
169    /// Returns the constraint limit for the circuit, if one exists.
170    fn get_constraint_limit() -> Option<u64>;
171
172    /// Sets the constraint limit for the circuit.
173    fn set_constraint_limit(limit: Option<u64>);
174
175    /// Halts the program from further synthesis, evaluation, and execution in the current environment.
176    fn halt<S: Into<String>, T>(message: S) -> T {
177        <Self::Network as console::Environment>::halt(message)
178    }
179
180    /// Returns the R1CS circuit, resetting the circuit.
181    fn inject_r1cs(r1cs: R1CS<Self::BaseField>);
182
183    /// Returns the R1CS circuit, resetting the circuit.
184    fn eject_r1cs_and_reset() -> R1CS<Self::BaseField>;
185
186    /// Returns the R1CS assignment of the circuit, resetting the circuit.
187    fn eject_assignment_and_reset() -> Assignment<<Self::Network as console::Environment>::Field>;
188
189    /// Clears and initializes an empty environment.
190    fn reset();
191}