@@ -18,53 +18,45 @@ pub struct Gate {
1818 pub gate_type : GateType ,
1919
2020 /// Two inputs, indexes into the previous layer gates outputs.
21- pub inputs : [ usize ; 2 ] ,
21+ pub inputs_idx : [ usize ; 2 ] ,
2222}
2323
2424impl Gate {
25- pub fn new ( gate_type : GateType , inputs : [ usize ; 2 ] ) -> Self {
26- Self { gate_type, inputs }
25+ pub fn new ( gate_type : GateType , inputs_idx : [ usize ; 2 ] ) -> Self {
26+ Self {
27+ gate_type,
28+ inputs_idx,
29+ }
2730 }
2831}
2932
30- /// Circuit layer structure
31- ///
32- /// Output: o o <- circuit.layers[0]
33- /// / \ / \
34- /// o o o o <- circuit.layers[1]
35- /// ...
36- /// o o o o <- circuit.ayers[layer.len() - 1]
37- /// / \ / \ / \ / \
38- /// Input: o o o o o o o o
39-
40- ///
41- /// - The top nodes are the circuit outputs (layers[0]).
42- /// - The bottom nodes are the circuit inputs, they don't belong to the vector `layers`.
43- /// - Each layer contains gates; edges represent wiring between layers.
44- /// - The circuit is evaluated from inputs upward, but layers are stored from output to input.
45-
4633/// A layer of gates in the circuit.
4734#[ derive( Clone ) ]
4835pub struct CircuitLayer {
49- pub layer : Vec < Gate > ,
36+ pub gates : Vec < Gate > ,
37+ pub num_of_vars : usize , // log2 of number of gates in this layer
5038}
5139
5240impl CircuitLayer {
53- pub fn new ( layer : Vec < Gate > ) -> Self {
54- Self { layer }
41+ pub fn new ( gates : Vec < Gate > ) -> Self {
42+ let num_of_vars = if gates. is_empty ( ) {
43+ 0
44+ } else {
45+ gates. len ( ) . next_power_of_two ( ) . trailing_zeros ( ) as usize
46+ } ;
47+ Self { gates, num_of_vars }
5548 }
5649
5750 pub fn len ( & self ) -> usize {
58- self . layer . len ( )
51+ self . gates . len ( )
5952 }
6053
6154 pub fn is_empty ( & self ) -> bool {
62- self . layer . is_empty ( )
55+ self . gates . is_empty ( )
6356 }
6457}
6558
6659/// An evaluation of a `Circuit` on some input.
67-
6860pub struct CircuitEvaluation < F > {
6961 /// Evaluations on per-layer basis.
7062 pub layers : Vec < Vec < F > > ,
@@ -81,9 +73,30 @@ impl<F: Copy> CircuitEvaluation<F> {
8173pub enum CircuitError {
8274 InputsNotPowerOfTwo ,
8375 LayerNotPowerOfTwo ( usize ) , // index of the layer that is not a power of two
76+ GateInputsError ( usize ) , // index of the layer with invalid gate inputs
77+ EmptyCircuitError ,
8478}
8579
8680/// The circuit in layered form.
81+ ///
82+ /// ## Circuit Structure
83+ ///
84+ /// Circuits are organized in layers, with each layer containing gates that operate on outputs from the previous layer:
85+ ///
86+ /// ```text
87+ /// Output: o o <- circuit.layers[0]
88+ /// / \ / \
89+ /// o o o o <- circuit.layers[1]
90+ /// ...
91+ /// o o o o <- circuit.layers[layer.len() - 1]
92+ /// / \ / \ / \ / \
93+ /// Input: o o o o o o o o
94+ /// ```
95+ ///
96+ /// - The top nodes are the circuit outputs (layers[0]).
97+ /// - The bottom nodes are the circuit inputs, they don't belong to the vector `layers`.
98+ /// - Each layer contains gates; edges represent wiring between layers.
99+ /// - The circuit is evaluated from inputs upward, but layers are stored from output to input.
87100#[ derive( Clone ) ]
88101pub struct Circuit {
89102 /// First layer being the output layer, last layer being
@@ -92,63 +105,89 @@ pub struct Circuit {
92105
93106 /// Number of inputs
94107 num_inputs : usize ,
95- layer_num_vars : Vec < usize > , // log2 of number of gates per layer
96- input_num_vars : usize , // log2 of number of inputs
108+ input_num_vars : usize , // log2 of number of inputs
97109}
98110
99111impl Circuit {
100112 pub fn new ( layers : Vec < CircuitLayer > , num_inputs : usize ) -> Result < Self , CircuitError > {
113+ if layers. is_empty ( ) {
114+ return Err ( CircuitError :: EmptyCircuitError ) ;
115+ }
116+
101117 if !num_inputs. is_power_of_two ( ) {
102118 return Err ( CircuitError :: InputsNotPowerOfTwo ) ;
103119 }
120+
104121 let input_num_vars = num_inputs. trailing_zeros ( ) as usize ;
105- let mut layer_num_vars = Vec :: with_capacity ( layers. len ( ) ) ;
122+
123+ // Validate that each layer has power-of-two gates
106124 for ( i, layer) in layers. iter ( ) . enumerate ( ) {
107125 if !layer. len ( ) . is_power_of_two ( ) {
108126 return Err ( CircuitError :: LayerNotPowerOfTwo ( i) ) ;
109127 }
110- layer_num_vars. push ( layer. len ( ) . trailing_zeros ( ) as usize ) ;
111128 }
129+
130+ // Validate that gate inputs in each layer don't exceed the next layer number of gates
131+ for ( i, layer_pair) in layers. windows ( 2 ) . enumerate ( ) {
132+ let current_layer = & layer_pair[ 0 ] ;
133+ let next_layer = & layer_pair[ 1 ] ;
134+ let next_layer_gates = next_layer. len ( ) ;
135+
136+ for gate in & current_layer. gates {
137+ let [ a, b] = gate. inputs_idx ;
138+ if a >= next_layer_gates || b >= next_layer_gates {
139+ return Err ( CircuitError :: GateInputsError ( i) ) ;
140+ }
141+ }
142+ }
143+
144+ // Validate that the last layer gate inputs don't exceed the number of inputs
145+ if let Some ( last_layer) = layers. last ( ) {
146+ for gate in & last_layer. gates {
147+ let [ a, b] = gate. inputs_idx ;
148+ if a >= num_inputs || b >= num_inputs {
149+ return Err ( CircuitError :: GateInputsError ( layers. len ( ) - 1 ) ) ;
150+ }
151+ }
152+ }
153+
112154 Ok ( Self {
113155 layers,
114156 num_inputs,
115- layer_num_vars,
116157 input_num_vars,
117158 } )
118159 }
119160
120161 pub fn num_vars_at ( & self , layer : usize ) -> Option < usize > {
121- let num_gates = if let Some ( layer) = self . layers . get ( layer) {
122- layer. len ( )
162+ if let Some ( layer) = self . layers . get ( layer) {
163+ Some ( layer. num_of_vars )
123164 } else if layer == self . layers . len ( ) {
124- self . num_inputs
165+ Some ( self . input_num_vars )
125166 } else {
126- return None ;
127- } ;
128-
129- Some ( ( num_gates as u64 ) . trailing_zeros ( ) as usize )
167+ None
168+ }
130169 }
131170
132171 /// Evaluate a `Circuit` on a given input.
133172 pub fn evaluate < F > ( & self , input : & [ FieldElement < F > ] ) -> CircuitEvaluation < FieldElement < F > >
134173 where
135174 F : IsField ,
136175 {
137- let mut layers = vec ! [ ] ;
176+ let mut layers = Vec :: with_capacity ( self . layers . len ( ) + 1 ) ;
138177 let mut current_input = input. to_vec ( ) ;
139178
140179 layers. push ( current_input. clone ( ) ) ;
141180
142181 for layer in self . layers . iter ( ) . rev ( ) {
143182 let temp_layer: Vec < _ > = layer
144- . layer
183+ . gates
145184 . iter ( )
146- . map ( |e | match e . gate_type {
185+ . map ( |gate | match gate . gate_type {
147186 GateType :: Add => {
148- current_input[ e . inputs [ 0 ] ] . clone ( ) + current_input[ e . inputs [ 1 ] ] . clone ( )
187+ & current_input[ gate . inputs_idx [ 0 ] ] + & current_input[ gate . inputs_idx [ 1 ] ]
149188 }
150189 GateType :: Mul => {
151- current_input[ e . inputs [ 0 ] ] . clone ( ) * current_input[ e . inputs [ 1 ] ] . clone ( )
190+ & current_input[ gate . inputs_idx [ 0 ] ] * & current_input[ gate . inputs_idx [ 1 ] ]
152191 }
153192 } )
154193 . collect ( ) ;
@@ -163,22 +202,22 @@ impl Circuit {
163202
164203 /// The $\text{add}_i(a, b, c)$ polynomial value at layer $i$.
165204 pub fn add_i ( & self , i : usize , a : usize , b : usize , c : usize ) -> bool {
166- let gate = & self . layers [ i] . layer [ a] ;
167- gate. gate_type == GateType :: Add && gate. inputs [ 0 ] == b && gate. inputs [ 1 ] == c
205+ let gate = & self . layers [ i] . gates [ a] ;
206+ gate. gate_type == GateType :: Add && gate. inputs_idx [ 0 ] == b && gate. inputs_idx [ 1 ] == c
168207 }
169208
170209 /// The $\text{mul}_i(a, b, c)$ polynomial value at layer $i$.
171210 pub fn mul_i ( & self , i : usize , a : usize , b : usize , c : usize ) -> bool {
172- let gate = & self . layers [ i] . layer [ a] ;
173- gate. gate_type == GateType :: Mul && gate. inputs [ 0 ] == b && gate. inputs [ 1 ] == c
211+ let gate = & self . layers [ i] . gates [ a] ;
212+ gate. gate_type == GateType :: Mul && gate. inputs_idx [ 0 ] == b && gate. inputs_idx [ 1 ] == c
174213 }
175214
176215 pub fn layers ( & self ) -> & [ CircuitLayer ] {
177216 & self . layers
178217 }
179218
180219 pub fn num_outputs ( & self ) -> usize {
181- self . layers [ 0 ] . layer . len ( )
220+ self . layers [ 0 ] . gates . len ( )
182221 }
183222
184223 pub fn num_inputs ( & self ) -> usize {
@@ -193,18 +232,18 @@ impl Circuit {
193232 where
194233 F :: BaseType : Send + Sync + Copy ,
195234 {
196- let num_vars_current = self . layer_num_vars [ i] ;
197- let num_vars_next = if let Some ( n ) = self . layer_num_vars . get ( i + 1 ) {
198- * n
235+ let num_vars_current = self . layers [ i] . num_of_vars ;
236+ let num_vars_next = if let Some ( layer ) = self . layers . get ( i + 1 ) {
237+ layer . num_of_vars
199238 } else {
200239 self . input_num_vars
201240 } ;
202241 let total_vars = num_vars_current + 2 * num_vars_next;
203242 let mut add_i_evals = vec ! [ FieldElement :: zero( ) ; 1 << total_vars] ;
204- for ( a, gate) in self . layers [ i] . layer . iter ( ) . enumerate ( ) {
243+ for ( a, gate) in self . layers [ i] . gates . iter ( ) . enumerate ( ) {
205244 if gate. gate_type == GateType :: Add {
206- let b = gate. inputs [ 0 ] ;
207- let c = gate. inputs [ 1 ] ;
245+ let b = gate. inputs_idx [ 0 ] ;
246+ let c = gate. inputs_idx [ 1 ] ;
208247 let idx = ( a << ( 2 * num_vars_next) ) | ( b << num_vars_next) | c;
209248 add_i_evals[ idx] = FieldElement :: one ( ) ;
210249 }
@@ -224,18 +263,18 @@ impl Circuit {
224263 where
225264 F :: BaseType : Send + Sync + Copy ,
226265 {
227- let num_vars_current = self . layer_num_vars [ i] ;
228- let num_vars_next = if let Some ( n ) = self . layer_num_vars . get ( i + 1 ) {
229- * n
266+ let num_vars_current = self . layers [ i] . num_of_vars ;
267+ let num_vars_next = if let Some ( layer ) = self . layers . get ( i + 1 ) {
268+ layer . num_of_vars
230269 } else {
231270 self . input_num_vars
232271 } ;
233272 let total_vars = num_vars_current + 2 * num_vars_next;
234273 let mut mul_i_evals = vec ! [ FieldElement :: zero( ) ; 1 << total_vars] ;
235- for ( a, gate) in self . layers [ i] . layer . iter ( ) . enumerate ( ) {
274+ for ( a, gate) in self . layers [ i] . gates . iter ( ) . enumerate ( ) {
236275 if gate. gate_type == GateType :: Mul {
237- let b = gate. inputs [ 0 ] ;
238- let c = gate. inputs [ 1 ] ;
276+ let b = gate. inputs_idx [ 0 ] ;
277+ let c = gate. inputs_idx [ 1 ] ;
239278 let idx = ( a << ( 2 * num_vars_next) ) | ( b << num_vars_next) | c;
240279 mul_i_evals[ idx] = FieldElement :: one ( ) ;
241280 }
0 commit comments