1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use crate::constraint::Constraint;
use crate::field::Field;
use crate::wire_values::WireValues;
use crate::witness_generator::WitnessGenerator;
pub struct Gadget<F: Field> {
pub constraints: Vec<Constraint<F>>,
pub witness_generators: Vec<WitnessGenerator<F>>,
}
impl<F: Field> Gadget<F> {
pub fn size(&self) -> usize {
self.constraints.len()
}
pub fn execute(&self, wire_values: &mut WireValues<F>) -> bool {
let mut pending_generators: Vec<&WitnessGenerator<F>> = self.witness_generators.iter().collect();
loop {
let mut made_progress = false;
pending_generators.retain(|generator| {
if wire_values.contains_all(generator.inputs()) {
generator.generate(wire_values);
made_progress = true;
false
} else {
true
}
});
if !made_progress {
break;
}
}
assert_eq!(pending_generators.len(), 0, "Some generators never received inputs");
self.constraints.iter().all(|constraint| constraint.evaluate(wire_values))
}
}
#[cfg(test)]
mod tests {
use crate::expression::Expression;
use crate::gadget_builder::GadgetBuilder;
use crate::test_util::F257;
use crate::wire_values::WireValues;
#[test]
fn constraint_not_satisfied() {
let mut builder = GadgetBuilder::<F257>::new();
let (x, y) = (builder.wire(), builder.wire());
builder.assert_equal(&Expression::from(x), &Expression::from(y));
let gadget = builder.build();
let mut values = values!(x => 42u8.into(), y => 43u8.into());
let constraints_satisfied = gadget.execute(&mut values);
assert!(!constraints_satisfied);
}
#[test]
#[should_panic]
fn missing_generator() {
let mut builder = GadgetBuilder::<F257>::new();
let (x, y, z) = (builder.wire(), builder.wire(), builder.wire());
builder.assert_product(&Expression::from(x), &Expression::from(y), &Expression::from(z));
let gadget = builder.build();
let mut values = values!(x => 2u8.into(), y => 3u8.into());
gadget.execute(&mut values);
}
#[test]
#[should_panic]
fn missing_input() {
let mut builder = GadgetBuilder::<F257>::new();
let x = builder.wire();
builder.inverse(&Expression::from(x));
let gadget = builder.build();
let mut values = WireValues::new();
gadget.execute(&mut values);
}
}