mirror of https://github.com/zcash/orchard.git
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:
parent
b4f628133e
commit
95fcf88407
|
@ -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.
Loading…
Reference in New Issue