mul::complete.rs: Constrain negation of (x_p, y_p) in double-and-add.

Co-authored-by: Jack Grigg <jack@electriccoin.co>
This commit is contained in:
therealyingtong 2021-07-03 00:26:41 +08:00
parent e75c176181
commit 6ffd867e23
1 changed files with 31 additions and 76 deletions

View File

@ -49,15 +49,28 @@ impl Config {
"Decompose scalar for complete bits of variable-base mul", "Decompose scalar for complete bits of variable-base mul",
|meta| { |meta| {
let q_mul_decompose_var = meta.query_selector(self.q_mul_decompose_var); let q_mul_decompose_var = meta.query_selector(self.q_mul_decompose_var);
let z_cur = meta.query_advice(self.z_complete, Rotation::cur()); // z_{i + 1}
let z_prev = meta.query_advice(self.z_complete, Rotation::prev()); let z_prev = meta.query_advice(self.z_complete, Rotation::prev());
// z_i
let z_next = meta.query_advice(self.z_complete, Rotation::next());
// k_{i} = z_{i} - 2⋅z_{i+1} // k_{i} = z_{i} - 2⋅z_{i+1}
let k = z_cur - Expression::Constant(pallas::Base::from_u64(2)) * z_prev; let k = z_next - Expression::Constant(pallas::Base::from_u64(2)) * z_prev;
let k_minus_one = k.clone() - Expression::Constant(pallas::Base::one());
// (k_i) ⋅ (k_i - 1) = 0 // (k_i) ⋅ (k_i - 1) = 0
let bool_check = k.clone() * (k + Expression::Constant(-pallas::Base::one())); let bool_check = k.clone() * k_minus_one.clone();
vec![q_mul_decompose_var * bool_check] // base_y
let base_y = meta.query_advice(self.z_complete, Rotation::cur());
// y_p
let y_p = meta.query_advice(self.add_config.y_p, Rotation::prev());
// k_i = 0 => y_p = -base_y
// k_i = 1 => y_p = base_y
let y_switch = k_minus_one * (base_y.clone() + y_p.clone()) + k * (base_y - y_p);
std::array::IntoIter::new([("bool_check", bool_check), ("y_switch", y_switch)])
.map(move |(name, poly)| (name, q_mul_decompose_var.clone() * poly))
}, },
); );
} }
@ -90,29 +103,7 @@ impl Config {
} }
// Use x_a, y_a output from incomplete addition // Use x_a, y_a output from incomplete addition
let mut acc = { let mut acc = EccPoint { x: *x_a, y: *y_a };
// Copy in x_a output from incomplete addition
let x_a = copy(
region,
|| "x_a output from incomplete addition",
self.add_config.x_qr,
offset,
&x_a.0,
&self.perm,
)?;
// Assign final `y_a` output from incomplete addition
let y_a = copy(
region,
|| "y_a output from incomplete addition",
self.add_config.y_qr,
offset,
&y_a.0,
&self.perm,
)?;
EccPoint { x: x_a, y: y_a }
};
// Copy running sum `z` from incomplete addition // Copy running sum `z` from incomplete addition
let mut z = { let mut z = {
@ -135,16 +126,6 @@ impl Config {
// Each iteration uses 2 rows (two complete additions) // Each iteration uses 2 rows (two complete additions)
let row = 2 * iter; let row = 2 * iter;
// Copy `z` running sum from previous iteration.
copy(
region,
|| "Copy `z` running sum from previous iteration",
self.z_complete,
row + offset,
&z,
&self.perm,
)?;
// Update `z`. // Update `z`.
z = { z = {
// z_next = z_cur * 2 + k_next // z_next = z_cur * 2 + k_next
@ -154,33 +135,29 @@ impl Config {
let z_cell = region.assign_advice( let z_cell = region.assign_advice(
|| "z", || "z",
self.z_complete, self.z_complete,
row + offset + 1, row + offset + 2,
|| z_val.ok_or(Error::SynthesisError), || z_val.ok_or(Error::SynthesisError),
)?; )?;
Z(CellValue::new(z_cell, z_val)) Z(CellValue::new(z_cell, z_val))
}; };
zs.push(z); zs.push(z);
// Assign `x_p` for complete addition
let x_p = {
let x_p_val = base.x.value();
let x_p_cell = region.assign_advice(
|| "x_p",
self.add_config.x_p,
row + offset,
|| x_p_val.ok_or(Error::SynthesisError),
)?;
CellValue::<pallas::Base>::new(x_p_cell, x_p_val)
};
// Assign `y_p` for complete addition. // Assign `y_p` for complete addition.
let y_p = { let y_p = {
let y_p = base.y.value(); let base_y = copy(
region,
|| "Copy `base.y`",
self.z_complete,
row + offset + 1,
&base.y,
&self.perm,
)?;
// If the bit is set, use `y`; if the bit is not set, use `-y` // If the bit is set, use `y`; if the bit is not set, use `-y`
let y_p = y_p let y_p = base_y
.value()
.zip(k.as_ref()) .zip(k.as_ref())
.map(|(y_p, k)| if !k { -y_p } else { y_p }); .map(|(base_y, k)| if !k { -base_y } else { base_y });
let y_p_cell = region.assign_advice( let y_p_cell = region.assign_advice(
|| "y_p", || "y_p",
@ -192,35 +169,13 @@ impl Config {
}; };
// U = P if the bit is set; U = -P is the bit is not set. // U = P if the bit is set; U = -P is the bit is not set.
let U = EccPoint { x: x_p, y: y_p }; let U = EccPoint { x: base.x, y: y_p };
// Acc + U // Acc + U
let tmp_acc = self let tmp_acc = self
.add_config .add_config
.assign_region(&U, &acc, row + offset, region)?; .assign_region(&U, &acc, row + offset, region)?;
// Copy acc from `x_a`, `y_a` over to `x_p`, `y_p` on the next row
acc = {
let acc_x = copy(
region,
|| "copy acc x_a",
self.add_config.x_p,
row + offset + 1,
&acc.x,
&self.perm,
)?;
let acc_y = copy(
region,
|| "copy acc y_a",
self.add_config.y_p,
row + offset + 1,
&acc.y,
&self.perm,
)?;
EccPoint { x: acc_x, y: acc_y }
};
// Acc + U + Acc // Acc + U + Acc
acc = self acc = self
.add_config .add_config