Replace `UtilitiesInstructions` usage with a dedicated helper

The new helper enables returning typed `AssignedCell`s, rather than only
`AssignedCell<F, F>`.
This commit is contained in:
Jack Grigg 2022-05-03 20:02:29 +00:00
parent 314728aada
commit 0bad10d3eb
3 changed files with 53 additions and 28 deletions

View File

@ -4,7 +4,7 @@ use core::fmt;
use group::{Curve, GroupEncoding}; use group::{Curve, GroupEncoding};
use halo2_proofs::{ use halo2_proofs::{
circuit::{floor_planner, AssignedCell, Layouter}, circuit::{floor_planner, Layouter},
plonk::{ plonk::{
self, Advice, Column, Constraints, Expression, Instance as InstanceColumn, Selector, self, Advice, Column, Constraints, Expression, Instance as InstanceColumn, Selector,
SingleVerifier, SingleVerifier,
@ -18,7 +18,10 @@ use rand::RngCore;
use self::{ use self::{
commit_ivk::{CommitIvkChip, CommitIvkConfig}, commit_ivk::{CommitIvkChip, CommitIvkConfig},
gadget::add_chip::{AddChip, AddConfig}, gadget::{
add_chip::{AddChip, AddConfig},
assign_free_advice,
},
note_commit::NoteCommitConfig, note_commit::NoteCommitConfig,
}; };
use crate::{ use crate::{
@ -53,7 +56,7 @@ use halo2_gadgets::{
MerklePath, MerklePath,
}, },
}, },
utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, utilities::lookup_range_check::LookupRangeCheckConfig,
}; };
mod commit_ivk; mod commit_ivk;
@ -118,10 +121,6 @@ pub struct Circuit {
pub(crate) rcv: Option<ValueCommitTrapdoor>, pub(crate) rcv: Option<ValueCommitTrapdoor>,
} }
impl UtilitiesInstructions<pallas::Base> for Circuit {
type Var = AssignedCell<pallas::Base, pallas::Base>;
}
impl plonk::Circuit<pallas::Base> for Circuit { impl plonk::Circuit<pallas::Base> for Circuit {
type Config = Config; type Config = Config;
type FloorPlanner = floor_planner::V1; type FloorPlanner = floor_planner::V1;
@ -332,14 +331,14 @@ impl plonk::Circuit<pallas::Base> for Circuit {
// Witness private inputs that are used across multiple checks. // Witness private inputs that are used across multiple checks.
let (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) = { let (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) = {
// Witness psi_old // Witness psi_old
let psi_old = self.load_private( let psi_old = assign_free_advice(
layouter.namespace(|| "witness psi_old"), layouter.namespace(|| "witness psi_old"),
config.advices[0], config.advices[0],
self.psi_old, self.psi_old,
)?; )?;
// Witness rho_old // Witness rho_old
let rho_old = self.load_private( let rho_old = assign_free_advice(
layouter.namespace(|| "witness rho_old"), layouter.namespace(|| "witness rho_old"),
config.advices[0], config.advices[0],
self.rho_old.map(|rho| rho.0), self.rho_old.map(|rho| rho.0),
@ -368,21 +367,21 @@ impl plonk::Circuit<pallas::Base> for Circuit {
)?; )?;
// Witness nk. // Witness nk.
let nk = self.load_private( let nk = assign_free_advice(
layouter.namespace(|| "witness nk"), layouter.namespace(|| "witness nk"),
config.advices[0], config.advices[0],
self.nk.map(|nk| nk.inner()), self.nk.map(|nk| nk.inner()),
)?; )?;
// Witness v_old. // Witness v_old.
let v_old = self.load_private( let v_old = assign_free_advice(
layouter.namespace(|| "witness v_old"), layouter.namespace(|| "witness v_old"),
config.advices[0], config.advices[0],
self.v_old.map(|v_old| pallas::Base::from(v_old.inner())), self.v_old.map(|v_old| pallas::Base::from(v_old.inner())),
)?; )?;
// Witness v_new. // Witness v_new.
let v_new = self.load_private( let v_new = assign_free_advice(
layouter.namespace(|| "witness v_new"), layouter.namespace(|| "witness v_new"),
config.advices[0], config.advices[0],
self.v_new.map(|v_new| pallas::Base::from(v_new.inner())), self.v_new.map(|v_new| pallas::Base::from(v_new.inner())),
@ -426,12 +425,12 @@ impl plonk::Circuit<pallas::Base> for Circuit {
) )
}); });
let magnitude = self.load_private( let magnitude = assign_free_advice(
layouter.namespace(|| "v_net magnitude"), layouter.namespace(|| "v_net magnitude"),
config.advices[9], config.advices[9],
magnitude_sign.map(|m_s| m_s.0), magnitude_sign.map(|m_s| m_s.0),
)?; )?;
let sign = self.load_private( let sign = assign_free_advice(
layouter.namespace(|| "v_net sign"), layouter.namespace(|| "v_net sign"),
config.advices[9], config.advices[9],
magnitude_sign.map(|m_s| m_s.1), magnitude_sign.map(|m_s| m_s.1),
@ -582,7 +581,7 @@ impl plonk::Circuit<pallas::Base> for Circuit {
let rho_new = nf_old.inner().clone(); let rho_new = nf_old.inner().clone();
// Witness psi_new // Witness psi_new
let psi_new = self.load_private( let psi_new = assign_free_advice(
layouter.namespace(|| "witness psi_new"), layouter.namespace(|| "witness psi_new"),
config.advices[0], config.advices[0],
self.psi_new, self.psi_new,

View File

@ -1,5 +1,6 @@
//! Gadgets used in the Orchard circuit. //! Gadgets used in the Orchard circuit.
use ff::Field;
use pasta_curves::pallas; use pasta_curves::pallas;
use super::commit_ivk::CommitIvkChip; use super::commit_ivk::CommitIvkChip;
@ -18,7 +19,7 @@ use halo2_gadgets::{
use halo2_proofs::{ use halo2_proofs::{
arithmetic::FieldExt, arithmetic::FieldExt,
circuit::{AssignedCell, Chip, Layouter}, circuit::{AssignedCell, Chip, Layouter},
plonk, plonk::{self, Advice, Assigned, Column},
}; };
pub(in crate::circuit) mod add_chip; pub(in crate::circuit) mod add_chip;
@ -76,6 +77,32 @@ pub(in crate::circuit) trait AddInstruction<F: FieldExt>: Chip<F> {
) -> Result<AssignedCell<F, F>, plonk::Error>; ) -> Result<AssignedCell<F, F>, plonk::Error>;
} }
/// Witnesses the given value in a standalone region.
///
/// Usages of this helper are technically superfluous, as the single-cell region is only
/// ever used in equality constraints. We could eliminate them with a write-on-copy
/// abstraction (https://github.com/zcash/halo2/issues/334).
pub(in crate::circuit) fn assign_free_advice<F: Field, V: Copy>(
mut layouter: impl Layouter<F>,
column: Column<Advice>,
value: Option<V>,
) -> Result<AssignedCell<V, F>, plonk::Error>
where
for<'v> Assigned<F>: From<&'v V>,
{
layouter.assign_region(
|| "load private",
|mut region| {
region.assign_advice(
|| "load private",
column,
0,
|| value.ok_or(plonk::Error::Synthesis),
)
},
)
}
/// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]. /// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)].
/// ///
/// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit /// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit

View File

@ -1488,9 +1488,12 @@ mod tests {
use core::iter; use core::iter;
use super::NoteCommitConfig; use super::NoteCommitConfig;
use crate::constants::{ use crate::{
fixed_bases::NOTE_COMMITMENT_PERSONALIZATION, OrchardCommitDomains, OrchardFixedBases, circuit::gadget::assign_free_advice,
OrchardHashDomains, L_ORCHARD_BASE, L_VALUE, T_Q, constants::{
fixed_bases::NOTE_COMMITMENT_PERSONALIZATION, OrchardCommitDomains, OrchardFixedBases,
OrchardHashDomains, L_ORCHARD_BASE, L_VALUE, T_Q,
},
}; };
use halo2_gadgets::{ use halo2_gadgets::{
ecc::{ ecc::{
@ -1499,13 +1502,13 @@ mod tests {
}, },
primitives::sinsemilla::CommitDomain, primitives::sinsemilla::CommitDomain,
sinsemilla::chip::SinsemillaChip, sinsemilla::chip::SinsemillaChip,
utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, utilities::lookup_range_check::LookupRangeCheckConfig,
}; };
use ff::{Field, PrimeField, PrimeFieldBits}; use ff::{Field, PrimeField, PrimeFieldBits};
use group::Curve; use group::Curve;
use halo2_proofs::{ use halo2_proofs::{
circuit::{AssignedCell, Layouter, SimpleFloorPlanner}, circuit::{Layouter, SimpleFloorPlanner},
dev::MockProver, dev::MockProver,
plonk::{Circuit, ConstraintSystem, Error}, plonk::{Circuit, ConstraintSystem, Error},
}; };
@ -1528,10 +1531,6 @@ mod tests {
psi: Option<pallas::Base>, psi: Option<pallas::Base>,
} }
impl UtilitiesInstructions<pallas::Base> for MyCircuit {
type Var = AssignedCell<pallas::Base, pallas::Base>;
}
impl Circuit<pallas::Base> for MyCircuit { impl Circuit<pallas::Base> for MyCircuit {
type Config = (NoteCommitConfig, EccConfig<OrchardFixedBases>); type Config = (NoteCommitConfig, EccConfig<OrchardFixedBases>);
type FloorPlanner = SimpleFloorPlanner; type FloorPlanner = SimpleFloorPlanner;
@ -1669,7 +1668,7 @@ mod tests {
pallas::Base::from(rng.next_u64()) pallas::Base::from(rng.next_u64())
}; };
let value_var = { let value_var = {
self.load_private( assign_free_advice(
layouter.namespace(|| "witness value"), layouter.namespace(|| "witness value"),
note_commit_config.advices[0], note_commit_config.advices[0],
Some(value), Some(value),
@ -1677,14 +1676,14 @@ mod tests {
}; };
// Witness rho // Witness rho
let rho = self.load_private( let rho = assign_free_advice(
layouter.namespace(|| "witness rho"), layouter.namespace(|| "witness rho"),
note_commit_config.advices[0], note_commit_config.advices[0],
self.rho, self.rho,
)?; )?;
// Witness psi // Witness psi
let psi = self.load_private( let psi = assign_free_advice(
layouter.namespace(|| "witness psi"), layouter.namespace(|| "witness psi"),
note_commit_config.advices[0], note_commit_config.advices[0],
self.psi, self.psi,