snarkvm_circuit_environment/helpers/
r1cs.rs1use crate::{
17 helpers::{Constraint, Counter},
18 prelude::*,
19};
20use snarkvm_fields::PrimeField;
21
22#[cfg(feature = "save_r1cs_hashes")]
23use sha2::{Digest, Sha256};
24use std::sync::Arc;
25#[cfg(feature = "save_r1cs_hashes")]
26use std::{
27 hash::{Hash, Hasher},
28 sync::Mutex,
29};
30
31#[cfg(feature = "save_r1cs_hashes")]
32struct Sha256Hasher(Sha256);
33
34#[cfg(feature = "save_r1cs_hashes")]
35impl Hasher for Sha256Hasher {
36 fn write(&mut self, bytes: &[u8]) {
37 self.0.update(bytes);
38 }
39
40 fn finish(&self) -> u64 {
41 unimplemented!("Use Digest::finalize instead to get the full SHA-256 digest");
42 }
43}
44
45#[cfg(feature = "save_r1cs_hashes")]
46fn hash_to_sha256<T: Hash>(t: &T) -> [u8; 32] {
47 let mut hasher = Sha256Hasher(Sha256::new());
48 t.hash(&mut hasher);
49 hasher.0.finalize().into()
50}
51
52pub type Scope = String;
53
54#[cfg(feature = "save_r1cs_hashes")]
60pub static R1CS_HASHES: Mutex<Vec<[u8; 32]>> = Mutex::new(Vec::new());
61
62#[derive(Debug, Hash)]
63pub struct R1CS<F: PrimeField> {
64 constants: Vec<Variable<F>>,
65 pub(crate) public: Vec<Variable<F>>,
66 pub(crate) private: Vec<Variable<F>>,
67 pub(crate) constraints: Vec<Arc<Constraint<F>>>,
68 counter: Counter<F>,
69 pub(crate) num_variables: u64,
70 nonzeros: (u64, u64, u64),
71}
72
73impl<F: PrimeField> R1CS<F> {
74 pub(crate) fn new() -> Self {
76 Self {
77 constants: Default::default(),
78 public: vec![Variable::Public(Arc::new((0u64, F::one())))],
79 private: Default::default(),
80 constraints: Default::default(),
81 counter: Default::default(),
82 num_variables: 1u64,
83 nonzeros: (0, 0, 0),
84 }
85 }
86
87 pub(crate) fn push_scope<S: Into<String>>(&mut self, name: S) -> Result<(), String> {
89 self.counter.push(name)
90 }
91
92 pub(crate) fn pop_scope<S: Into<String>>(&mut self, name: S) -> Result<(), String> {
94 self.counter.pop(name)
95 }
96
97 pub(crate) fn new_constant(&mut self, value: F) -> Variable<F> {
99 let variable = Variable::Constant(Arc::new(value));
100 self.constants.push(variable.clone());
101 self.counter.increment_constant();
102 self.num_variables += 1;
103 variable
104 }
105
106 pub(crate) fn new_public(&mut self, value: F) -> Variable<F> {
108 let variable = Variable::Public(Arc::new((self.public.len() as u64, value)));
109 self.public.push(variable.clone());
110 self.counter.increment_public();
111 self.num_variables += 1;
112 variable
113 }
114
115 pub(crate) fn new_private(&mut self, value: F) -> Variable<F> {
117 let variable = Variable::Private(Arc::new((self.private.len() as u64, value)));
118 self.private.push(variable.clone());
119 self.counter.increment_private();
120 self.num_variables += 1;
121 variable
122 }
123
124 pub(crate) fn enforce(&mut self, constraint: Constraint<F>) {
126 let (a_nonzeros, b_nonzeros, c_nonzeros) = constraint.num_nonzeros();
127 self.nonzeros.0 += a_nonzeros;
128 self.nonzeros.1 += b_nonzeros;
129 self.nonzeros.2 += c_nonzeros;
130
131 let constraint = Arc::new(constraint);
132 self.constraints.push(Arc::clone(&constraint));
133 self.counter.add_constraint(constraint);
134 }
135
136 pub fn is_satisfied(&self) -> bool {
141 let constraints_satisfied = self.constraints.iter().all(|constraint| constraint.is_satisfied());
143 if !constraints_satisfied {
144 return false;
145 }
146
147 #[cfg(not(debug_assertions))]
149 return true;
150 #[cfg(debug_assertions)]
151 self.constraints.iter().all(|constraint| {
152 let (a, b, c) = constraint.to_terms();
153 [a, b, c].into_iter().all(|lc| {
154 lc.to_terms().iter().all(|(variable, _)| match variable {
155 Variable::Constant(_value) => false, Variable::Private(private) => {
157 let (index, value) = private.as_ref();
158 self.private.get(*index as usize).map_or_else(|| false, |v| v.value() == *value)
159 }
160 Variable::Public(public) => {
161 let (index, value) = public.as_ref();
162 self.public.get(*index as usize).map_or_else(|| false, |v| v.value() == *value)
163 }
164 })
165 })
166 })
167 }
168
169 pub(crate) fn is_satisfied_in_scope(&self) -> bool {
171 self.counter.is_satisfied_in_scope()
172 }
173
174 pub(crate) fn scope(&self) -> Scope {
176 self.counter.scope()
177 }
178
179 pub fn num_constants(&self) -> u64 {
181 self.constants.len() as u64
182 }
183
184 pub fn num_public(&self) -> u64 {
186 self.public.len() as u64
187 }
188
189 pub fn num_private(&self) -> u64 {
191 self.private.len() as u64
192 }
193
194 pub fn num_variables(&self) -> u64 {
196 self.num_variables
197 }
198
199 pub fn num_constraints(&self) -> u64 {
201 self.constraints.len() as u64
202 }
203
204 pub fn num_nonzeros(&self) -> (u64, u64, u64) {
206 self.nonzeros
207 }
208
209 pub(crate) fn num_constants_in_scope(&self) -> u64 {
211 self.counter.num_constants_in_scope()
212 }
213
214 pub(crate) fn num_public_in_scope(&self) -> u64 {
216 self.counter.num_public_in_scope()
217 }
218
219 pub(crate) fn num_private_in_scope(&self) -> u64 {
221 self.counter.num_private_in_scope()
222 }
223
224 pub(crate) fn num_constraints_in_scope(&self) -> u64 {
226 self.counter.num_constraints_in_scope()
227 }
228
229 pub(crate) fn num_nonzeros_in_scope(&self) -> (u64, u64, u64) {
231 self.counter.num_nonzeros_in_scope()
232 }
233
234 pub fn to_public_variables(&self) -> &Vec<Variable<F>> {
236 &self.public
237 }
238
239 pub fn to_private_variables(&self) -> &Vec<Variable<F>> {
241 &self.private
242 }
243
244 pub fn to_constraints(&self) -> &Vec<Arc<Constraint<F>>> {
246 &self.constraints
247 }
248
249 #[cfg(feature = "save_r1cs_hashes")]
252 pub(crate) fn save_hash(&self) {
253 let r1cs_hash = hash_to_sha256(self);
254 R1CS_HASHES.lock().unwrap().push(r1cs_hash);
255 }
256}
257
258impl<F: PrimeField> Display for R1CS<F> {
259 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
260 let mut output = String::default();
261 for constraint in self.to_constraints() {
262 output += &constraint.to_string();
263 }
264 output += "\n";
265
266 write!(f, "{output}")
267 }
268}