Skip to content

Commit 2fc6a9a

Browse files
committed
remove clones and fix clippy
1 parent e28777f commit 2fc6a9a

File tree

5 files changed

+112
-73
lines changed

5 files changed

+112
-73
lines changed

crates/provers/gkr/src/circuit.rs

Lines changed: 98 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -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

2424
impl 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)]
4835
pub 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

5240
impl 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-
6860
pub struct CircuitEvaluation<F> {
6961
/// Evaluations on per-layer basis.
7062
pub layers: Vec<Vec<F>>,
@@ -81,9 +73,30 @@ impl<F: Copy> CircuitEvaluation<F> {
8173
pub 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)]
88101
pub 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

99111
impl 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
}

crates/provers/gkr/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ pub fn circuit_to_bytes(circuit: &Circuit) -> Vec<u8> {
2020
// For each layer append the number of gates, the type and the input indeces of each gate.
2121
for layer in circuit.layers() {
2222
bytes.extend_from_slice(&(layer.len() as u32).to_le_bytes());
23-
for gate in &layer.layer {
23+
for gate in &layer.gates {
2424
let gate_type = match gate.gate_type {
2525
crate::circuit::GateType::Add => 0u8,
2626
crate::circuit::GateType::Mul => 1u8,
2727
};
2828
bytes.push(gate_type);
29-
bytes.extend_from_slice(&(gate.inputs[0] as u32).to_le_bytes());
30-
bytes.extend_from_slice(&(gate.inputs[1] as u32).to_le_bytes());
29+
bytes.extend_from_slice(&(gate.inputs_idx[0] as u32).to_le_bytes());
30+
bytes.extend_from_slice(&(gate.inputs_idx[1] as u32).to_le_bytes());
3131
}
3232
}
3333
bytes
@@ -47,7 +47,7 @@ where
4747
{
4848
b.iter()
4949
.zip(c.iter())
50-
.map(|(b_val, c_val)| b_val.clone() + t.clone() * (c_val.clone() - b_val.clone()))
50+
.map(|(b_val, c_val)| b_val + t * (c_val - b_val))
5151
.collect()
5252
}
5353

crates/provers/gkr/src/prover.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,15 @@ impl Prover {
117117
{
118118
let mut domain_points_x = Vec::new();
119119
let mut evaluation_values_y = Vec::new();
120+
let w_next_poly = DenseMultilinearPolynomial::new(w_next_evals);
120121
for i in 0..3 {
121122
let eval_point_x = FieldElement::from(i as u64);
122-
domain_points_x.push(eval_point_x.clone());
123-
124123
let line_at_eval_point = crate::line(b, c, &eval_point_x);
125-
let w_next_poly = DenseMultilinearPolynomial::new(w_next_evals.clone());
126124
let q_at_eval_point = w_next_poly
127125
.evaluate(line_at_eval_point)
128126
.map_err(|_| ProverError::MultilinearPolynomialEvaluationError)?;
129127

128+
domain_points_x.push(eval_point_x);
130129
evaluation_values_y.push(q_at_eval_point);
131130
}
132131
let poly_q = Polynomial::interpolate(&domain_points_x, &evaluation_values_y)
@@ -182,7 +181,7 @@ impl Prover {
182181
let gkr_poly_terms =
183182
Prover::build_gkr_polynomial(circuit, &r_i, w_next_evals, layer_idx)?;
184183

185-
let sumcheck_proof = gkr_sumcheck_prove(gkr_poly_terms.clone(), &mut transcript)?;
184+
let sumcheck_proof = gkr_sumcheck_prove(gkr_poly_terms, &mut transcript)?;
186185

187186
let sumcheck_challenges = &sumcheck_proof.challenges;
188187

@@ -205,14 +204,15 @@ impl Prover {
205204

206205
let layer_proof = LayerProof {
207206
sumcheck_proof,
208-
poly_q: poly_q.clone(),
207+
poly_q,
209208
};
210209
layer_proofs.push(layer_proof);
211210
}
212211

212+
let output_values = evaluation.layers[0].clone();
213213
let proof = GKRProof {
214214
input_values: input.to_vec(),
215-
output_values: evaluation.layers[0].clone(),
215+
output_values,
216216
layer_proofs,
217217
};
218218

crates/provers/gkr/src/sumcheck.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ where
9090
let r_j = transcript.sample_field_element();
9191

9292
challenges.push(r_j.clone());
93-
current_challenge = Some(r_j.clone());
93+
current_challenge = Some(r_j);
9494
}
9595

9696
let sumcheck_proof = GKRSumcheckProof {
@@ -144,7 +144,7 @@ where
144144

145145
let g_j_0 = g_j.evaluate::<F>(&FieldElement::zero());
146146
let g_j_1 = g_j.evaluate::<F>(&FieldElement::one());
147-
let sum_evals = g_j_0.clone() + g_j_1.clone();
147+
let sum_evals = &g_j_0 + &g_j_1;
148148

149149
// We need to manually track the expected sum
150150
let expected_sum = if j == 0 {

crates/provers/gkr/src/verifier.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ impl Verifier {
3535
// Append the circuit data to the transcript.
3636
transcript.append_bytes(&crate::circuit_to_bytes(circuit));
3737
// Append public inputs x.
38-
for x in proof.input_values.clone() {
38+
for x in &proof.input_values {
3939
transcript.append_bytes(&x.to_bytes_be());
4040
}
4141
// Append public outputs y (first layer of evaluation).
42-
for y in proof.output_values.clone() {
42+
for y in &proof.output_values {
4343
transcript.append_bytes(&y.to_bytes_be());
4444
}
4545

0 commit comments

Comments
 (0)