Skip to content

Commit 65ac816

Browse files
Update to use multi-polynomial create_gate() API
1 parent aeee55a commit 65ac816

File tree

12 files changed

+279
-280
lines changed

12 files changed

+279
-280
lines changed

src/circuit/gadget/ecc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ mod tests {
484484
// Test signed short fixed-base scalar multiplication
485485
{
486486
super::chip::mul_fixed::short::tests::test_mul_fixed_short(
487-
chip.clone(),
487+
chip,
488488
layouter.namespace(|| "signed short fixed-base scalar mul"),
489489
)?;
490490
}

src/circuit/gadget/ecc/chip/add.rs

+123-132
Original file line numberDiff line numberDiff line change
@@ -68,141 +68,131 @@ impl Config {
6868
}
6969

7070
pub(crate) fn create_gate<F: FieldExt>(&self, meta: &mut ConstraintSystem<F>) {
71-
let q_add = meta.query_selector(self.q_add, Rotation::cur());
72-
let x_p = meta.query_advice(self.x_p, Rotation::cur());
73-
let y_p = meta.query_advice(self.y_p, Rotation::cur());
74-
let x_q = meta.query_advice(self.x_qr, Rotation::cur());
75-
let y_q = meta.query_advice(self.y_qr, Rotation::cur());
76-
let x_r = meta.query_advice(self.x_qr, Rotation::next());
77-
let y_r = meta.query_advice(self.y_qr, Rotation::next());
78-
let lambda = meta.query_advice(self.lambda, Rotation::cur());
79-
80-
// α = inv0(x_q - x_p)
81-
let alpha = meta.query_advice(self.alpha, Rotation::cur());
82-
// β = inv0(x_p)
83-
let beta = meta.query_advice(self.beta, Rotation::cur());
84-
// γ = inv0(x_q)
85-
let gamma = meta.query_advice(self.gamma, Rotation::cur());
86-
// δ = inv0(y_p + y_q) if x_q = x_p, 0 otherwise
87-
let delta = meta.query_advice(self.delta, Rotation::cur());
88-
89-
// Useful composite expressions
90-
// α ⋅(x_q - x_p)
91-
let if_alpha = (x_q.clone() - x_p.clone()) * alpha;
92-
// β ⋅ x_p
93-
let if_beta = x_p.clone() * beta;
94-
// γ ⋅ x_q
95-
let if_gamma = x_q.clone() * gamma;
96-
// δ ⋅(y_p + y_q)
97-
let if_delta = (y_q.clone() + y_p.clone()) * delta;
98-
99-
// Useful constants
100-
let one = Expression::Constant(F::one());
101-
let two = Expression::Constant(F::from_u64(2));
102-
let three = Expression::Constant(F::from_u64(3));
103-
104-
// Handle cases in incomplete addition
105-
{
106-
meta.create_gate(
107-
"(x_q − x_p)⋅((x_q − x_p)⋅λ − (y_q−y_p))=0",
108-
|_| {
109-
let x_q_minus_x_p = x_q.clone() - x_p.clone(); // (x_q − x_p)
110-
111-
let y_q_minus_y_p = y_q.clone() - y_p.clone(); // (y_q − y_p)
112-
let incomplete = x_q_minus_x_p.clone() * lambda.clone() - y_q_minus_y_p; // (x_q − x_p)⋅λ − (y_q−y_p)
113-
114-
// q_add ⋅(x_q − x_p)⋅((x_q − x_p)⋅λ − (y_q−y_p))
115-
q_add.clone() * x_q_minus_x_p * incomplete
116-
},
117-
);
118-
119-
meta.create_gate("(1 - (x_q - x_p)⋅α)⋅(2y_p ⋅λ - 3x_p^2) = 0", |_| {
71+
meta.create_gate("complete addition gates", |meta| {
72+
let q_add = meta.query_selector(self.q_add, Rotation::cur());
73+
let x_p = meta.query_advice(self.x_p, Rotation::cur());
74+
let y_p = meta.query_advice(self.y_p, Rotation::cur());
75+
let x_q = meta.query_advice(self.x_qr, Rotation::cur());
76+
let y_q = meta.query_advice(self.y_qr, Rotation::cur());
77+
let x_r = meta.query_advice(self.x_qr, Rotation::next());
78+
let y_r = meta.query_advice(self.y_qr, Rotation::next());
79+
let lambda = meta.query_advice(self.lambda, Rotation::cur());
80+
81+
// α = inv0(x_q - x_p)
82+
let alpha = meta.query_advice(self.alpha, Rotation::cur());
83+
// β = inv0(x_p)
84+
let beta = meta.query_advice(self.beta, Rotation::cur());
85+
// γ = inv0(x_q)
86+
let gamma = meta.query_advice(self.gamma, Rotation::cur());
87+
// δ = inv0(y_p + y_q) if x_q = x_p, 0 otherwise
88+
let delta = meta.query_advice(self.delta, Rotation::cur());
89+
90+
// Useful composite expressions
91+
// α ⋅(x_q - x_p)
92+
let if_alpha = (x_q.clone() - x_p.clone()) * alpha;
93+
// β ⋅ x_p
94+
let if_beta = x_p.clone() * beta;
95+
// γ ⋅ x_q
96+
let if_gamma = x_q.clone() * gamma;
97+
// δ ⋅(y_p + y_q)
98+
let if_delta = (y_q.clone() + y_p.clone()) * delta;
99+
100+
// Useful constants
101+
let one = Expression::Constant(F::one());
102+
let two = Expression::Constant(F::from_u64(2));
103+
let three = Expression::Constant(F::from_u64(3));
104+
105+
// (x_q − x_p)⋅((x_q − x_p)⋅λ − (y_q−y_p)) = 0
106+
let poly1 = {
107+
let x_q_minus_x_p = x_q.clone() - x_p.clone(); // (x_q − x_p)
108+
109+
let y_q_minus_y_p = y_q.clone() - y_p.clone(); // (y_q − y_p)
110+
let incomplete = x_q_minus_x_p.clone() * lambda.clone() - y_q_minus_y_p; // (x_q − x_p)⋅λ − (y_q−y_p)
111+
112+
// q_add ⋅(x_q − x_p)⋅((x_q − x_p)⋅λ − (y_q−y_p))
113+
x_q_minus_x_p * incomplete
114+
};
115+
116+
// (1 - (x_q - x_p)⋅α)⋅(2y_p ⋅λ - 3x_p^2) = 0
117+
let poly2 = {
120118
let three_x_p_sq = three * x_p.clone() * x_p.clone(); // 3x_p^2
121-
let two_y_p = two.clone() * y_p.clone(); // 2y_p
119+
let two_y_p = two * y_p.clone(); // 2y_p
122120
let tangent_line = two_y_p * lambda.clone() - three_x_p_sq; // (2y_p ⋅λ - 3x_p^2)
123121

124122
// q_add ⋅(1 - (x_q - x_p)⋅α)⋅(2y_p ⋅λ - 3x_p^2)
125-
q_add.clone() * (one.clone() - if_alpha.clone()) * tangent_line
126-
});
127-
128-
meta.create_gate(
129-
"x_p⋅x_q⋅(x_q - x_p)⋅(λ^2 - x_p - x_q - x_r) = 0",
130-
|_| {
131-
let x_q_minus_x_p = x_q.clone() - x_p.clone(); // (x_q - x_p)
132-
let secant_line =
133-
lambda.clone() * lambda.clone() - x_p.clone() - x_q.clone() - x_r.clone(); // (λ^2 - x_p - x_q - x_r)
134-
135-
// q_add ⋅ x_p⋅x_q⋅(x_q - x_p)⋅(λ^2 - x_p - x_q - x_r)
136-
q_add.clone() * x_p.clone() * x_q.clone() * x_q_minus_x_p * secant_line
137-
},
138-
);
139-
140-
meta.create_gate(
141-
"x_p⋅x_q⋅(x_q - x_p)⋅(λ ⋅(x_p - x_r) - y_p - y_r) = 0",
142-
|_| {
143-
let x_q_minus_x_p = x_q.clone() - x_p.clone(); // (x_q - x_p)
144-
let x_p_minus_x_r = x_p.clone() - x_r.clone(); // (x_p - x_r)
145-
146-
// q_add ⋅ x_p⋅x_q⋅(x_q - x_p)⋅(λ ⋅(x_p - x_r) - y_p - y_r)
147-
q_add.clone()
148-
* x_p.clone()
149-
* x_q.clone()
150-
* x_q_minus_x_p
151-
* (lambda.clone() * x_p_minus_x_r - y_p.clone() - y_r.clone())
152-
},
153-
);
154-
155-
meta.create_gate(
156-
"x_p⋅x_q⋅(y_q + y_p)⋅(λ^2 - x_p - x_q - x_r) = 0",
157-
|_| {
158-
let y_q_plus_y_p = y_q.clone() + y_p.clone(); // (y_q + y_p)
159-
let incomplete =
160-
lambda.clone() * lambda.clone() - x_p.clone() - x_q.clone() - x_r.clone(); // (λ^2 - x_p - x_q - x_r)
161-
162-
// q_add ⋅ x_p⋅x_q⋅(y_q + y_p)⋅(λ^2 - x_p - x_q - x_r)
163-
q_add.clone() * x_p.clone() * x_q.clone() * y_q_plus_y_p * incomplete
164-
},
165-
);
166-
167-
meta.create_gate(
168-
"x_p⋅x_q⋅(y_q + y_p)⋅(λ ⋅(x_p - x_r) - y_p - y_r) = 0",
169-
|_| {
170-
let y_q_plus_y_p = y_q.clone() + y_p.clone(); // (y_q + y_p)
171-
let x_p_minus_x_r = x_p.clone() - x_r.clone(); // (x_p - x_r)
172-
173-
// q_add ⋅ x_p⋅x_q⋅(y_q + y_p)⋅(λ ⋅(x_p - x_r) - y_p - y_r)
174-
q_add.clone()
175-
* x_p.clone()
176-
* x_q.clone()
177-
* y_q_plus_y_p
178-
* (lambda.clone() * x_p_minus_x_r - y_p.clone() - y_r.clone())
179-
},
180-
);
181-
182-
meta.create_gate("(1 - x_p * β) * (x_r - x_q) = 0", |_| {
183-
q_add.clone() * (one.clone() - if_beta.clone()) * (x_r.clone() - x_q.clone())
184-
});
185-
186-
meta.create_gate("(1 - x_p * β) * (y_r - y_q) = 0", |_| {
187-
q_add.clone() * (one.clone() - if_beta) * (y_r.clone() - y_q.clone())
188-
});
189-
190-
meta.create_gate("(1 - x_q * γ) * (x_r - x_p) = 0", |_| {
191-
q_add.clone() * (one.clone() - if_gamma.clone()) * (x_r.clone() - x_p.clone())
192-
});
193-
194-
meta.create_gate("(1 - x_q * γ) * (y_r - y_p) = 0", |_| {
195-
q_add.clone() * (one.clone() - if_gamma) * (y_r.clone() - y_p.clone())
196-
});
197-
198-
meta.create_gate("((1 - (x_q - x_p) * α - (y_q + y_p) * δ)) * x_r", |_| {
199-
q_add.clone() * (one.clone() - if_alpha.clone() - if_delta.clone()) * x_r.clone()
200-
});
201-
202-
meta.create_gate("((1 - (x_q - x_p) * α - (y_q + y_p) * δ)) * y_r", |_| {
203-
q_add * (one - if_alpha - if_delta) * y_r
204-
});
205-
}
123+
(one.clone() - if_alpha.clone()) * tangent_line
124+
};
125+
126+
// x_p⋅x_q⋅(x_q - x_p)⋅(λ^2 - x_p - x_q - x_r) = 0
127+
let poly3 = {
128+
let x_q_minus_x_p = x_q.clone() - x_p.clone(); // (x_q - x_p)
129+
let secant_line =
130+
lambda.clone() * lambda.clone() - x_p.clone() - x_q.clone() - x_r.clone(); // (λ^2 - x_p - x_q - x_r)
131+
132+
// x_p⋅x_q⋅(x_q - x_p)⋅(λ^2 - x_p - x_q - x_r)
133+
x_p.clone() * x_q.clone() * x_q_minus_x_p * secant_line
134+
};
135+
136+
// x_p⋅x_q⋅(x_q - x_p)⋅(λ ⋅(x_p - x_r) - y_p - y_r) = 0
137+
let poly4 = {
138+
let x_q_minus_x_p = x_q.clone() - x_p.clone(); // (x_q - x_p)
139+
let x_p_minus_x_r = x_p.clone() - x_r.clone(); // (x_p - x_r)
140+
141+
// x_p⋅x_q⋅(x_q - x_p)⋅(λ ⋅(x_p - x_r) - y_p - y_r)
142+
x_p.clone()
143+
* x_q.clone()
144+
* x_q_minus_x_p
145+
* (lambda.clone() * x_p_minus_x_r - y_p.clone() - y_r.clone())
146+
};
147+
148+
// x_p⋅x_q⋅(y_q + y_p)⋅(λ^2 - x_p - x_q - x_r) = 0
149+
let poly5 = {
150+
let y_q_plus_y_p = y_q.clone() + y_p.clone(); // (y_q + y_p)
151+
let incomplete =
152+
lambda.clone() * lambda.clone() - x_p.clone() - x_q.clone() - x_r.clone(); // (λ^2 - x_p - x_q - x_r)
153+
154+
// x_p⋅x_q⋅(y_q + y_p)⋅(λ^2 - x_p - x_q - x_r)
155+
x_p.clone() * x_q.clone() * y_q_plus_y_p * incomplete
156+
};
157+
158+
// x_p⋅x_q⋅(y_q + y_p)⋅(λ ⋅(x_p - x_r) - y_p - y_r) = 0
159+
let poly6 = {
160+
let y_q_plus_y_p = y_q.clone() + y_p.clone(); // (y_q + y_p)
161+
let x_p_minus_x_r = x_p.clone() - x_r.clone(); // (x_p - x_r)
162+
163+
// x_p⋅x_q⋅(y_q + y_p)⋅(λ ⋅(x_p - x_r) - y_p - y_r)
164+
x_p.clone()
165+
* x_q.clone()
166+
* y_q_plus_y_p
167+
* (lambda * x_p_minus_x_r - y_p.clone() - y_r.clone())
168+
};
169+
170+
// (1 - x_p * β) * (x_r - x_q) = 0
171+
let poly7 = (one.clone() - if_beta.clone()) * (x_r.clone() - x_q);
172+
173+
// (1 - x_p * β) * (y_r - y_q) = 0
174+
let poly8 = (one.clone() - if_beta) * (y_r.clone() - y_q);
175+
176+
// (1 - x_q * γ) * (x_r - x_p) = 0
177+
let poly9 = (one.clone() - if_gamma.clone()) * (x_r.clone() - x_p);
178+
179+
// (1 - x_q * γ) * (y_r - y_p) = 0
180+
let poly10 = (one.clone() - if_gamma) * (y_r.clone() - y_p);
181+
182+
// ((1 - (x_q - x_p) * α - (y_q + y_p) * δ)) * x_r
183+
let poly11 = (one.clone() - if_alpha.clone() - if_delta.clone()) * x_r;
184+
185+
// ((1 - (x_q - x_p) * α - (y_q + y_p) * δ)) * y_r
186+
let poly12 = (one - if_alpha - if_delta) * y_r;
187+
188+
[
189+
poly1, poly2, poly3, poly4, poly5, poly6, poly7, poly8, poly9, poly10, poly11,
190+
poly12,
191+
]
192+
.iter()
193+
.map(|poly| q_add.clone() * poly.clone())
194+
.collect()
195+
});
206196
}
207197

208198
pub(super) fn assign_region<C: CurveAffine>(
@@ -406,6 +396,7 @@ pub mod tests {
406396

407397
use crate::circuit::gadget::ecc::{EccInstructions, Point};
408398

399+
#[allow(clippy::too_many_arguments)]
409400
pub fn test_add<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Eq + std::fmt::Debug>(
410401
chip: EccChip,
411402
mut layouter: impl Layouter<C::Base>,
@@ -467,7 +458,7 @@ pub mod tests {
467458
// (x, y) + ((ζ^2)x, -y)
468459
let endo_2_p_neg = (-p_val).to_curve().endo().endo();
469460
let endo_2_p_neg = Point::new(
470-
chip.clone(),
461+
chip,
471462
layouter.namespace(|| "point"),
472463
Some(endo_2_p_neg.to_affine()),
473464
)?;

src/circuit/gadget/ecc/chip/add_incomplete.rs

+24-23
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,30 @@ impl From<&EccConfig> for Config {
3838

3939
impl Config {
4040
pub(super) fn create_gate<F: FieldExt>(&self, meta: &mut ConstraintSystem<F>) {
41-
let q_add_incomplete = meta.query_selector(self.q_add_incomplete, Rotation::cur());
42-
let x_p = meta.query_advice(self.x_p, Rotation::cur());
43-
let y_p = meta.query_advice(self.y_p, Rotation::cur());
44-
let x_q = meta.query_advice(self.x_qr, Rotation::cur());
45-
let y_q = meta.query_advice(self.y_qr, Rotation::cur());
46-
let x_r = meta.query_advice(self.x_qr, Rotation::next());
47-
let y_r = meta.query_advice(self.y_qr, Rotation::next());
48-
49-
// (x_r + x_q + x_p)⋅(x_p − x_q)^2 − (y_p − y_q)^2 = 0
50-
meta.create_gate("point addition expr1", |_| {
51-
let expr1 = (x_r.clone() + x_q.clone() + x_p.clone())
52-
* (x_p.clone() - x_q.clone())
53-
* (x_p.clone() - x_q.clone())
54-
- (y_p.clone() - y_q.clone()) * (y_p.clone() - y_q.clone());
55-
56-
q_add_incomplete.clone() * expr1
57-
});
58-
59-
// (y_r + y_q)(x_p − x_q) − (y_p − y_q)(x_q − x_r) = 0
60-
meta.create_gate("point addition expr2", |_| {
61-
let expr2 = (y_r + y_q.clone()) * (x_p - x_q.clone()) - (y_p - y_q) * (x_q - x_r);
62-
63-
q_add_incomplete * expr2
41+
meta.create_gate("incomplete addition gates", |meta| {
42+
let q_add_incomplete = meta.query_selector(self.q_add_incomplete, Rotation::cur());
43+
let x_p = meta.query_advice(self.x_p, Rotation::cur());
44+
let y_p = meta.query_advice(self.y_p, Rotation::cur());
45+
let x_q = meta.query_advice(self.x_qr, Rotation::cur());
46+
let y_q = meta.query_advice(self.y_qr, Rotation::cur());
47+
let x_r = meta.query_advice(self.x_qr, Rotation::next());
48+
let y_r = meta.query_advice(self.y_qr, Rotation::next());
49+
50+
// (x_r + x_q + x_p)⋅(x_p − x_q)^2 − (y_p − y_q)^2 = 0
51+
let poly1 = {
52+
(x_r.clone() + x_q.clone() + x_p.clone())
53+
* (x_p.clone() - x_q.clone())
54+
* (x_p.clone() - x_q.clone())
55+
- (y_p.clone() - y_q.clone()) * (y_p.clone() - y_q.clone())
56+
};
57+
58+
// (y_r + y_q)(x_p − x_q) − (y_p − y_q)(x_q − x_r) = 0
59+
let poly2 = (y_r + y_q.clone()) * (x_p - x_q.clone()) - (y_p - y_q) * (x_q - x_r);
60+
61+
[poly1, poly2]
62+
.iter()
63+
.map(|poly| q_add_incomplete.clone() * poly.clone())
64+
.collect()
6465
});
6566
}
6667

src/circuit/gadget/ecc/chip/mul.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,19 @@ impl<C: CurveAffine> Config<C> {
8181

8282
/// Gate used to check final scalar is recovered.
8383
fn create_final_scalar_gate(&self, meta: &mut ConstraintSystem<C::Base>) {
84-
let q_mul_decompose_var = meta.query_selector(self.q_mul_decompose_var, Rotation::cur());
85-
let scalar = meta.query_advice(self.scalar, Rotation::cur());
86-
let z_cur = meta.query_advice(self.z_complete, Rotation::cur());
84+
meta.create_gate("Decompose scalar for variable-base mul", |meta| {
85+
let q_mul_decompose_var =
86+
meta.query_selector(self.q_mul_decompose_var, Rotation::cur());
87+
let scalar = meta.query_advice(self.scalar, Rotation::cur());
88+
let z_cur = meta.query_advice(self.z_complete, Rotation::cur());
8789

88-
meta.create_gate("Decompose scalar", |_| {
8990
// The scalar field `F_q = 2^254 + t_q`.
9091
// -((2^127)^2) = -(2^254) = t_q (mod q)
9192
let t_q = -(C::Scalar::from_u128(1u128 << 127).square());
9293
let t_q = C::Base::from_bytes(&t_q.to_bytes()).unwrap();
9394

9495
// Check that `k = scalar + t_q`
95-
q_mul_decompose_var * (scalar + Expression::Constant(t_q) - z_cur)
96+
vec![q_mul_decompose_var * (scalar + Expression::Constant(t_q) - z_cur)]
9697
});
9798
}
9899

0 commit comments

Comments
 (0)