snarkvm_circuit_environment/helpers/
counter.rs1use crate::*;
17use snarkvm_fields::PrimeField;
18
19use std::{mem, sync::Arc};
20
21#[derive(Debug, Default, Hash)]
22pub(crate) struct Counter<F: PrimeField> {
23 scope: Scope,
24 constraints: Vec<Arc<Constraint<F>>>,
25 constants: u64,
26 public: u64,
27 private: u64,
28 nonzeros: (u64, u64, u64),
29 parents: Vec<(Scope, Vec<Arc<Constraint<F>>>, u64, u64, u64, (u64, u64, u64))>,
30}
31
32impl<F: PrimeField> Counter<F> {
33 pub(crate) fn push<S: Into<String>>(&mut self, name: S) -> Result<(), String> {
35 let name = name.into();
36 match name.contains('.') {
37 true => Err("Scope names cannot contain periods (\".\")".to_string()),
38 false => {
39 let scope = match self.scope.is_empty() {
41 true => name,
42 false => format!("{}.{}", self.scope, name),
43 };
44
45 self.parents.push((
47 self.scope.clone(),
48 mem::take(&mut self.constraints),
49 self.constants,
50 self.public,
51 self.private,
52 self.nonzeros,
53 ));
54
55 self.scope = scope;
57 self.constants = 0;
58 self.public = 0;
59 self.private = 0;
60 self.nonzeros = (0, 0, 0);
61
62 Ok(())
63 }
64 }
65 }
66
67 pub(crate) fn pop<S: Into<String>>(&mut self, name: S) -> Result<(), String> {
69 let (_previous_scope, current_scope) = match self.scope.rsplit_once('.') {
71 Some((previous_scope, current_scope)) => (previous_scope, current_scope),
72 None => ("", self.scope.as_str()),
73 };
74
75 match current_scope == name.into() {
77 true => {
78 if let Some((scope, constraints, constants, public, private, nonzeros)) = self.parents.pop() {
79 self.scope = scope;
80 self.constraints = constraints;
81 self.constants = constants;
82 self.public = public;
83 self.private = private;
84 self.nonzeros = nonzeros;
85 }
86 }
87 false => {
88 return Err("Mismatching scope. Scopes must return in the reverse order they are created".to_string());
89 }
90 }
91
92 Ok(())
93 }
94
95 pub(crate) fn add_constraint(&mut self, constraint: Arc<Constraint<F>>) {
97 let (a_nonzeros, b_nonzeros, c_nonzeros) = constraint.num_nonzeros();
98 self.nonzeros.0 += a_nonzeros;
99 self.nonzeros.1 += b_nonzeros;
100 self.nonzeros.2 += c_nonzeros;
101
102 self.constraints.push(constraint);
103 }
104
105 pub(crate) fn is_satisfied_in_scope(&self) -> bool {
107 self.constraints.iter().all(|constraint| constraint.is_satisfied())
108 }
109
110 pub(crate) fn scope(&self) -> Scope {
112 self.scope.clone()
113 }
114
115 pub(crate) fn increment_constant(&mut self) {
117 self.constants += 1;
118 }
119
120 pub(crate) fn increment_public(&mut self) {
122 self.public += 1;
123 }
124
125 pub(crate) fn increment_private(&mut self) {
127 self.private += 1;
128 }
129
130 pub(crate) fn num_constants_in_scope(&self) -> u64 {
132 self.constants
133 }
134
135 pub(crate) fn num_public_in_scope(&self) -> u64 {
137 self.public
138 }
139
140 pub(crate) fn num_private_in_scope(&self) -> u64 {
142 self.private
143 }
144
145 pub(crate) fn num_constraints_in_scope(&self) -> u64 {
147 self.constraints.len() as u64
148 }
149
150 pub(crate) fn num_nonzeros_in_scope(&self) -> (u64, u64, u64) {
152 self.nonzeros
153 }
154}