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
use super::expression::Expr;
use crate::halo2_proofs::{arithmetic::FieldExt, plonk::Expression};
#[derive(Default)]
pub struct BaseConstraintBuilder<F> {
pub constraints: Vec<(&'static str, Expression<F>)>,
pub max_degree: usize,
pub condition: Option<Expression<F>>,
}
impl<F: FieldExt> BaseConstraintBuilder<F> {
pub(crate) fn new(max_degree: usize) -> Self {
BaseConstraintBuilder { constraints: Vec::new(), max_degree, condition: None }
}
pub(crate) fn require_zero(&mut self, name: &'static str, constraint: Expression<F>) {
self.add_constraint(name, constraint);
}
pub(crate) fn require_equal(
&mut self,
name: &'static str,
lhs: Expression<F>,
rhs: Expression<F>,
) {
self.add_constraint(name, lhs - rhs);
}
pub(crate) fn require_boolean(&mut self, name: &'static str, value: Expression<F>) {
self.add_constraint(name, value.clone() * (1.expr() - value));
}
pub(crate) fn condition<R>(
&mut self,
condition: Expression<F>,
constraint: impl FnOnce(&mut Self) -> R,
) -> R {
debug_assert!(self.condition.is_none(), "Nested condition is not supported");
self.condition = Some(condition);
let ret = constraint(self);
self.condition = None;
ret
}
pub(crate) fn add_constraint(&mut self, name: &'static str, constraint: Expression<F>) {
let constraint = match &self.condition {
Some(condition) => condition.clone() * constraint,
None => constraint,
};
self.validate_degree(constraint.degree(), name);
self.constraints.push((name, constraint));
}
pub(crate) fn validate_degree(&self, degree: usize, name: &'static str) {
if self.max_degree > 0 {
assert!(
degree <= self.max_degree,
"Expression {} degree too high: {} > {}",
name,
degree,
self.max_degree,
);
}
}
pub(crate) fn gate(&self, selector: Expression<F>) -> Vec<(&'static str, Expression<F>)> {
self.constraints
.clone()
.into_iter()
.map(|(name, constraint)| (name, selector.clone() * constraint))
.filter(|(name, constraint)| {
self.validate_degree(constraint.degree(), name);
true
})
.collect()
}
}