Circuit: Check pk_d_old = derived_pk_d_old only when split_flag = 0 (#64)

In the circuit derived_pk_d_old is evaluated from rivk, ak, nk and g_d_old.
rivk, ak and nk comes from the FullViewingKey stored in the spent note.
For split note, the FullViewingKey stored in the spent note is random in order to derive a random Nullifier nf_old.
Thus, the constraint pk_d_old = derived_pk_d_old must not be checked for split note (split_flag=1).
This commit is contained in:
Constance Beguier 2023-05-29 12:06:30 +02:00 committed by GitHub
parent b4f628133e
commit 95fcf88407
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 2794 additions and 2575 deletions

View File

@ -225,6 +225,7 @@ impl plonk::Circuit<pallas::Base> for Circuit {
// Constrain split_flag = 1 or nf_old = nf_old_pub
// Constrain is_native_asset to be boolean
// Constraint if is_native_asset = 1 then asset = native_asset else asset != native_asset
// Constraint split_flag = 1 or derived_pk_d_old = pk_d_old
let q_orchard = meta.selector();
meta.create_gate("Orchard circuit checks", |meta| {
let q_orchard = meta.query_selector(q_orchard);
@ -261,6 +262,11 @@ impl plonk::Circuit<pallas::Base> for Circuit {
let diff_asset_x = asset_x - Expression::Constant(*native_asset.x());
let diff_asset_y = asset_y - Expression::Constant(*native_asset.y());
let pk_d_old_x = meta.query_advice(advices[6], Rotation::next());
let pk_d_old_y = meta.query_advice(advices[7], Rotation::next());
let derived_pk_d_old_x = meta.query_advice(advices[8], Rotation::next());
let derived_pk_d_old_y = meta.query_advice(advices[9], Rotation::next());
Constraints::with_selector(
q_orchard,
[
@ -285,7 +291,7 @@ impl plonk::Circuit<pallas::Base> for Circuit {
),
(
"split_flag = 1 or nf_old = nf_old_pub",
(one.clone() - split_flag) * (nf_old - nf_old_pub),
(one.clone() - split_flag.clone()) * (nf_old - nf_old_pub),
),
(
"bool_check is_native_asset",
@ -308,7 +314,22 @@ impl plonk::Circuit<pallas::Base> for Circuit {
"(is_native_asset = 0) => (asset != native_asset)",
(one.clone() - is_native_asset)
* (diff_asset_x * diff_asset_x_inv - one.clone())
* (diff_asset_y * diff_asset_y_inv - one),
* (diff_asset_y * diff_asset_y_inv - one.clone()),
),
// Constrain derived pk_d_old to equal witnessed pk_d_old
//
// This equality constraint is technically superfluous, because the assigned
// value of `derived_pk_d_old` is an equivalent witness. But it's nice to see
// an explicit connection between circuit-synthesized values, and explicit
// prover witnesses. We could get the best of both worlds with a write-on-copy
// abstraction (https://github.com/zcash/halo2/issues/334).
(
"split_flag = 1 or pk_d_old_x = derived_pk_d_old_x",
(one.clone() - split_flag.clone()) * (pk_d_old_x - derived_pk_d_old_x),
),
(
"split_flag = 1 or pk_d_old_y = derived_pk_d_old_y",
(one - split_flag) * (pk_d_old_y - derived_pk_d_old_y),
),
],
)
@ -669,7 +690,7 @@ impl plonk::Circuit<pallas::Base> for Circuit {
}
// Diversified address integrity (https://p.z.cash/ZKS:action-addr-integrity?partial).
let pk_d_old = {
let (derived_pk_d_old, pk_d_old) = {
let ivk = {
let ak = ak_P.extract_p().inner().clone();
let rivk = ScalarFixed::new(
@ -696,22 +717,13 @@ impl plonk::Circuit<pallas::Base> for Circuit {
let (derived_pk_d_old, _ivk) =
g_d_old.mul(layouter.namespace(|| "[ivk] g_d_old"), ivk)?;
// Constrain derived pk_d_old to equal witnessed pk_d_old
//
// This equality constraint is technically superfluous, because the assigned
// value of `derived_pk_d_old` is an equivalent witness. But it's nice to see
// an explicit connection between circuit-synthesized values, and explicit
// prover witnesses. We could get the best of both worlds with a write-on-copy
// abstraction (https://github.com/zcash/halo2/issues/334).
let pk_d_old = NonIdentityPoint::new(
ecc_chip.clone(),
layouter.namespace(|| "witness pk_d_old"),
self.pk_d_old.map(|pk_d_old| pk_d_old.inner().to_affine()),
)?;
derived_pk_d_old
.constrain_equal(layouter.namespace(|| "pk_d_old equality"), &pk_d_old)?;
pk_d_old
(derived_pk_d_old, pk_d_old)
};
// Old note commitment integrity (https://p.z.cash/ZKS:action-cm-old-integrity?partial).
@ -933,6 +945,31 @@ impl plonk::Circuit<pallas::Base> for Circuit {
},
)?;
pk_d_old.inner().x().copy_advice(
|| "pk_d_old_x",
&mut region,
config.advices[6],
1,
)?;
pk_d_old.inner().y().copy_advice(
|| "pk_d_old_y",
&mut region,
config.advices[7],
1,
)?;
derived_pk_d_old.inner().x().copy_advice(
|| "derived_pk_d_old_x",
&mut region,
config.advices[8],
1,
)?;
derived_pk_d_old.inner().y().copy_advice(
|| "derived_pk_d_old_y",
&mut region,
config.advices[9],
1,
)?;
config.q_orchard.enable(&mut region, 0)
},
)?;

File diff suppressed because it is too large Load Diff

Binary file not shown.