Migrate to `halo2_proofs 0.2.0`

This commit is contained in:
Jack Grigg 2022-06-09 00:01:10 +00:00
parent 8aba4c59fd
commit be69324b9c
8 changed files with 288 additions and 339 deletions

View File

@ -6,6 +6,8 @@ and this project adheres to Rust's notion of
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] ## [Unreleased]
### Changed
- Migrated to `halo2_proofs 0.2`.
## [0.1.0] - 2022-05-10 ## [0.1.0] - 2022-05-10
### Changed ### Changed

View File

@ -29,8 +29,8 @@ blake2b_simd = "1"
ff = "0.12" ff = "0.12"
fpe = "0.5" fpe = "0.5"
group = "0.12" group = "0.12"
halo2_gadgets = "0.1" halo2_gadgets = "0.2"
halo2_proofs = "0.1" halo2_proofs = "0.2"
hex = "0.4" hex = "0.4"
lazy_static = "1" lazy_static = "1"
memuse = { version = "0.2", features = ["nonempty"] } memuse = { version = "0.2", features = ["nonempty"] }
@ -49,7 +49,7 @@ plotters = { version = "0.3.0", optional = true }
[dev-dependencies] [dev-dependencies]
criterion = "0.3" criterion = "0.3"
halo2_gadgets = { version = "0.1", features = ["test-dependencies"] } halo2_gadgets = { version = "0.2", features = ["test-dependencies"] }
hex = "0.4" hex = "0.4"
proptest = "1.0.0" proptest = "1.0.0"
zcash_note_encryption = { version = "0.1", features = ["pre-zip-212"] } zcash_note_encryption = { version = "0.1", features = ["pre-zip-212"] }

View File

@ -4,6 +4,7 @@ use core::fmt;
use core::iter; use core::iter;
use ff::Field; use ff::Field;
use halo2_proofs::circuit::Value;
use nonempty::NonEmpty; use nonempty::NonEmpty;
use pasta_curves::pallas; use pasta_curves::pallas;
use rand::{prelude::SliceRandom, CryptoRng, RngCore}; use rand::{prelude::SliceRandom, CryptoRng, RngCore};
@ -188,25 +189,25 @@ impl ActionInfo {
}, },
), ),
Circuit { Circuit {
path: Some(self.spend.merkle_path.auth_path()), path: Value::known(self.spend.merkle_path.auth_path()),
pos: Some(self.spend.merkle_path.position()), pos: Value::known(self.spend.merkle_path.position()),
g_d_old: Some(sender_address.g_d()), g_d_old: Value::known(sender_address.g_d()),
pk_d_old: Some(*sender_address.pk_d()), pk_d_old: Value::known(*sender_address.pk_d()),
v_old: Some(self.spend.note.value()), v_old: Value::known(self.spend.note.value()),
rho_old: Some(rho_old), rho_old: Value::known(rho_old),
psi_old: Some(psi_old), psi_old: Value::known(psi_old),
rcm_old: Some(rcm_old), rcm_old: Value::known(rcm_old),
cm_old: Some(self.spend.note.commitment()), cm_old: Value::known(self.spend.note.commitment()),
alpha: Some(alpha), alpha: Value::known(alpha),
ak: Some(ak), ak: Value::known(ak),
nk: Some(*self.spend.fvk.nk()), nk: Value::known(*self.spend.fvk.nk()),
rivk: Some(self.spend.fvk.rivk(self.spend.scope)), rivk: Value::known(self.spend.fvk.rivk(self.spend.scope)),
g_d_new: Some(note.recipient().g_d()), g_d_new: Value::known(note.recipient().g_d()),
pk_d_new: Some(*note.recipient().pk_d()), pk_d_new: Value::known(*note.recipient().pk_d()),
v_new: Some(note.value()), v_new: Value::known(note.value()),
psi_new: Some(note.rseed().psi(&note.rho())), psi_new: Value::known(note.rseed().psi(&note.rho())),
rcm_new: Some(note.rseed().rcm(&note.rho())), rcm_new: Value::known(note.rseed().rcm(&note.rho())),
rcv: Some(self.rcv), rcv: Value::known(self.rcv),
}, },
) )
} }

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, Layouter}, circuit::{floor_planner, Layouter, Value},
plonk::{ plonk::{
self, Advice, Column, Constraints, Expression, Instance as InstanceColumn, Selector, self, Advice, Column, Constraints, Expression, Instance as InstanceColumn, Selector,
SingleVerifier, SingleVerifier,
@ -99,25 +99,25 @@ pub struct Config {
/// The Orchard Action circuit. /// The Orchard Action circuit.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct Circuit { pub struct Circuit {
pub(crate) path: Option<[MerkleHashOrchard; MERKLE_DEPTH_ORCHARD]>, pub(crate) path: Value<[MerkleHashOrchard; MERKLE_DEPTH_ORCHARD]>,
pub(crate) pos: Option<u32>, pub(crate) pos: Value<u32>,
pub(crate) g_d_old: Option<NonIdentityPallasPoint>, pub(crate) g_d_old: Value<NonIdentityPallasPoint>,
pub(crate) pk_d_old: Option<DiversifiedTransmissionKey>, pub(crate) pk_d_old: Value<DiversifiedTransmissionKey>,
pub(crate) v_old: Option<NoteValue>, pub(crate) v_old: Value<NoteValue>,
pub(crate) rho_old: Option<Nullifier>, pub(crate) rho_old: Value<Nullifier>,
pub(crate) psi_old: Option<pallas::Base>, pub(crate) psi_old: Value<pallas::Base>,
pub(crate) rcm_old: Option<NoteCommitTrapdoor>, pub(crate) rcm_old: Value<NoteCommitTrapdoor>,
pub(crate) cm_old: Option<NoteCommitment>, pub(crate) cm_old: Value<NoteCommitment>,
pub(crate) alpha: Option<pallas::Scalar>, pub(crate) alpha: Value<pallas::Scalar>,
pub(crate) ak: Option<SpendValidatingKey>, pub(crate) ak: Value<SpendValidatingKey>,
pub(crate) nk: Option<NullifierDerivingKey>, pub(crate) nk: Value<NullifierDerivingKey>,
pub(crate) rivk: Option<CommitIvkRandomness>, pub(crate) rivk: Value<CommitIvkRandomness>,
pub(crate) g_d_new: Option<NonIdentityPallasPoint>, pub(crate) g_d_new: Value<NonIdentityPallasPoint>,
pub(crate) pk_d_new: Option<DiversifiedTransmissionKey>, pub(crate) pk_d_new: Value<DiversifiedTransmissionKey>,
pub(crate) v_new: Option<NoteValue>, pub(crate) v_new: Value<NoteValue>,
pub(crate) psi_new: Option<pallas::Base>, pub(crate) psi_new: Value<pallas::Base>,
pub(crate) rcm_new: Option<NoteCommitTrapdoor>, pub(crate) rcm_new: Value<NoteCommitTrapdoor>,
pub(crate) rcv: Option<ValueCommitTrapdoor>, pub(crate) rcv: Value<ValueCommitTrapdoor>,
} }
impl plonk::Circuit<pallas::Base> for Circuit { impl plonk::Circuit<pallas::Base> for Circuit {
@ -358,7 +358,7 @@ impl plonk::Circuit<pallas::Base> for Circuit {
)?; )?;
// Witness ak_P. // Witness ak_P.
let ak_P: Option<pallas::Point> = self.ak.as_ref().map(|ak| ak.into()); let ak_P: Value<pallas::Point> = self.ak.as_ref().map(|ak| ak.into());
let ak_P = NonIdentityPoint::new( let ak_P = NonIdentityPoint::new(
ecc_chip.clone(), ecc_chip.clone(),
layouter.namespace(|| "witness ak_P"), layouter.namespace(|| "witness ak_P"),
@ -408,8 +408,8 @@ impl plonk::Circuit<pallas::Base> for Circuit {
let v_net_magnitude_sign = { let v_net_magnitude_sign = {
// Witness the magnitude and sign of v_net = v_old - v_new // Witness the magnitude and sign of v_net = v_old - v_new
let v_net_magnitude_sign = { let v_net_magnitude_sign = {
let magnitude_sign = self.v_old.zip(self.v_new).map(|(v_old, v_new)| { let v_net = self.v_old - self.v_new;
let v_net = v_old - v_new; let magnitude_sign = v_net.map(|v_net| {
let (magnitude, sign) = v_net.magnitude_sign(); let (magnitude, sign) = v_net.magnitude_sign();
( (
@ -877,7 +877,7 @@ mod tests {
use core::iter; use core::iter;
use ff::Field; use ff::Field;
use halo2_proofs::dev::MockProver; use halo2_proofs::{circuit::Value, dev::MockProver};
use pasta_curves::pallas; use pasta_curves::pallas;
use rand::{rngs::OsRng, RngCore}; use rand::{rngs::OsRng, RngCore};
@ -912,25 +912,25 @@ mod tests {
( (
Circuit { Circuit {
path: Some(path.auth_path()), path: Value::known(path.auth_path()),
pos: Some(path.position()), pos: Value::known(path.position()),
g_d_old: Some(sender_address.g_d()), g_d_old: Value::known(sender_address.g_d()),
pk_d_old: Some(*sender_address.pk_d()), pk_d_old: Value::known(*sender_address.pk_d()),
v_old: Some(spent_note.value()), v_old: Value::known(spent_note.value()),
rho_old: Some(spent_note.rho()), rho_old: Value::known(spent_note.rho()),
psi_old: Some(spent_note.rseed().psi(&spent_note.rho())), psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())),
rcm_old: Some(spent_note.rseed().rcm(&spent_note.rho())), rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())),
cm_old: Some(spent_note.commitment()), cm_old: Value::known(spent_note.commitment()),
alpha: Some(alpha), alpha: Value::known(alpha),
ak: Some(ak), ak: Value::known(ak),
nk: Some(nk), nk: Value::known(nk),
rivk: Some(rivk), rivk: Value::known(rivk),
g_d_new: Some(output_note.recipient().g_d()), g_d_new: Value::known(output_note.recipient().g_d()),
pk_d_new: Some(*output_note.recipient().pk_d()), pk_d_new: Value::known(*output_note.recipient().pk_d()),
v_new: Some(output_note.value()), v_new: Value::known(output_note.value()),
psi_new: Some(output_note.rseed().psi(&output_note.rho())), psi_new: Value::known(output_note.rseed().psi(&output_note.rho())),
rcm_new: Some(output_note.rseed().rcm(&output_note.rho())), rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())),
rcv: Some(rcv), rcv: Value::known(rcv),
}, },
Instance { Instance {
anchor, anchor,
@ -1098,25 +1098,25 @@ mod tests {
.unwrap(); .unwrap();
let circuit = Circuit { let circuit = Circuit {
path: None, path: Value::unknown(),
pos: None, pos: Value::unknown(),
g_d_old: None, g_d_old: Value::unknown(),
pk_d_old: None, pk_d_old: Value::unknown(),
v_old: None, v_old: Value::unknown(),
rho_old: None, rho_old: Value::unknown(),
psi_old: None, psi_old: Value::unknown(),
rcm_old: None, rcm_old: Value::unknown(),
cm_old: None, cm_old: Value::unknown(),
alpha: None, alpha: Value::unknown(),
ak: None, ak: Value::unknown(),
nk: None, nk: Value::unknown(),
rivk: None, rivk: Value::unknown(),
g_d_new: None, g_d_new: Value::unknown(),
pk_d_new: None, pk_d_new: Value::unknown(),
v_new: None, v_new: Value::unknown(),
psi_new: None, psi_new: Value::unknown(),
rcm_new: None, rcm_new: Value::unknown(),
rcv: None, rcv: Value::unknown(),
}; };
halo2_proofs::dev::CircuitLayout::default() halo2_proofs::dev::CircuitLayout::default()
.show_labels(false) .show_labels(false)

View File

@ -1,7 +1,7 @@
use core::iter; use core::iter;
use halo2_proofs::{ use halo2_proofs::{
circuit::{AssignedCell, Layouter}, circuit::{AssignedCell, Layouter, Value},
plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector},
poly::Rotation, poly::Rotation,
}; };
@ -417,11 +417,11 @@ pub(in crate::circuit) mod gadgets {
// Decompose the low 130 bits of a_prime = a + 2^130 - t_P, and output // Decompose the low 130 bits of a_prime = a + 2^130 - t_P, and output
// the running sum at the end of it. If a_prime < 2^130, the running sum // the running sum at the end of it. If a_prime < 2^130, the running sum
// will be 0. // will be 0.
let a_prime = a.value().map(|a| { let a_prime = {
let two_pow_130 = pallas::Base::from_u128(1u128 << 65).square(); let two_pow_130 = Value::known(pallas::Base::from_u128(1u128 << 65).square());
let t_p = pallas::Base::from_u128(T_P); let t_p = Value::known(pallas::Base::from_u128(T_P));
a + two_pow_130 - t_p a.value() + two_pow_130 - t_p
}); };
let zs = lookup_config.witness_check( let zs = lookup_config.witness_check(
layouter.namespace(|| "Decompose low 130 bits of (a + 2^130 - t_P)"), layouter.namespace(|| "Decompose low 130 bits of (a + 2^130 - t_P)"),
a_prime, a_prime,
@ -461,12 +461,12 @@ pub(in crate::circuit) mod gadgets {
// Decompose the low 140 bits of b2_c_prime = b_2 + c * 2^5 + 2^140 - t_P, and output // Decompose the low 140 bits of b2_c_prime = b_2 + c * 2^5 + 2^140 - t_P, and output
// the running sum at the end of it. If b2_c_prime < 2^140, the running sum will be 0. // the running sum at the end of it. If b2_c_prime < 2^140, the running sum will be 0.
let b2_c_prime = b_2.inner().value().zip(c.value()).map(|(b_2, c)| { let b2_c_prime = {
let two_pow_5 = pallas::Base::from(1 << 5); let two_pow_5 = Value::known(pallas::Base::from(1 << 5));
let two_pow_140 = pallas::Base::from_u128(1u128 << 70).square(); let two_pow_140 = Value::known(pallas::Base::from_u128(1u128 << 70).square());
let t_p = pallas::Base::from_u128(T_P); let t_p = Value::known(pallas::Base::from_u128(T_P));
b_2 + c * two_pow_5 + two_pow_140 - t_p b_2.inner().value() + c.value() * two_pow_5 + two_pow_140 - t_p
}); };
let zs = lookup_config.witness_check( let zs = lookup_config.witness_check(
layouter.namespace(|| "Decompose low 140 bits of (b_2 + c * 2^5 + 2^140 - t_P)"), layouter.namespace(|| "Decompose low 140 bits of (b_2 + c * 2^5 + 2^140 - t_P)"),
b2_c_prime, b2_c_prime,
@ -535,7 +535,7 @@ impl CommitIvkConfig {
|| "Witness b_1", || "Witness b_1",
self.advices[4], self.advices[4],
offset, offset,
|| gate_cells.b_1.inner().ok_or(Error::Synthesis), || *gate_cells.b_1.inner(),
)?; )?;
// Copy in `b_2` // Copy in `b_2`
@ -603,7 +603,7 @@ impl CommitIvkConfig {
|| "Witness d_1", || "Witness d_1",
self.advices[4], self.advices[4],
offset, offset,
|| gate_cells.d_1.inner().ok_or(Error::Synthesis), || *gate_cells.d_1.inner(),
)?; )?;
// Copy in z13_c // Copy in z13_c
@ -646,10 +646,10 @@ struct GateCells {
ak: AssignedCell<pallas::Base, pallas::Base>, ak: AssignedCell<pallas::Base, pallas::Base>,
nk: AssignedCell<pallas::Base, pallas::Base>, nk: AssignedCell<pallas::Base, pallas::Base>,
b_0: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, b_0: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
b_1: RangeConstrained<pallas::Base, Option<pallas::Base>>, b_1: RangeConstrained<pallas::Base, Value<pallas::Base>>,
b_2: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, b_2: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
d_0: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, d_0: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
d_1: RangeConstrained<pallas::Base, Option<pallas::Base>>, d_1: RangeConstrained<pallas::Base, Value<pallas::Base>>,
z13_a: AssignedCell<pallas::Base, pallas::Base>, z13_a: AssignedCell<pallas::Base, pallas::Base>,
a_prime: AssignedCell<pallas::Base, pallas::Base>, a_prime: AssignedCell<pallas::Base, pallas::Base>,
z13_a_prime: AssignedCell<pallas::Base, pallas::Base>, z13_a_prime: AssignedCell<pallas::Base, pallas::Base>,
@ -680,7 +680,7 @@ mod tests {
utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions},
}; };
use halo2_proofs::{ use halo2_proofs::{
circuit::{AssignedCell, Layouter, SimpleFloorPlanner}, circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value},
dev::MockProver, dev::MockProver,
plonk::{Circuit, ConstraintSystem, Error}, plonk::{Circuit, ConstraintSystem, Error},
}; };
@ -691,8 +691,8 @@ mod tests {
fn commit_ivk() { fn commit_ivk() {
#[derive(Default)] #[derive(Default)]
struct MyCircuit { struct MyCircuit {
ak: Option<pallas::Base>, ak: Value<pallas::Base>,
nk: Option<pallas::Base>, nk: Value<pallas::Base>,
} }
impl UtilitiesInstructions<pallas::Base> for MyCircuit { impl UtilitiesInstructions<pallas::Base> for MyCircuit {
@ -809,8 +809,11 @@ mod tests {
// Use a random scalar for rivk // Use a random scalar for rivk
let rivk = pallas::Scalar::random(OsRng); let rivk = pallas::Scalar::random(OsRng);
let rivk_gadget = let rivk_gadget = ScalarFixed::new(
ScalarFixed::new(ecc_chip.clone(), layouter.namespace(|| "rivk"), Some(rivk))?; ecc_chip.clone(),
layouter.namespace(|| "rivk"),
Value::known(rivk),
)?;
let ivk = gadgets::commit_ivk( let ivk = gadgets::commit_ivk(
sinsemilla_chip, sinsemilla_chip,
@ -822,34 +825,29 @@ mod tests {
rivk_gadget, rivk_gadget,
)?; )?;
let expected_ivk = { self.ak
let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION); .zip(self.nk)
// Hash ak || nk .zip(ivk.inner().value())
domain .assert_if_known(|((ak, nk), ivk)| {
.short_commit( let expected_ivk = {
iter::empty() let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION);
.chain( // Hash ak || nk
self.ak domain
.unwrap() .short_commit(
.to_le_bits() iter::empty()
.iter() .chain(
.by_vals() ak.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE),
.take(L_ORCHARD_BASE), )
.chain(
nk.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE),
),
&rivk,
) )
.chain( .unwrap()
self.nk };
.unwrap()
.to_le_bits()
.iter()
.by_vals()
.take(L_ORCHARD_BASE),
),
&rivk,
)
.unwrap()
};
assert_eq!(&expected_ivk, ivk.inner().value().unwrap()); &&expected_ivk == ivk
});
Ok(()) Ok(())
} }
@ -860,38 +858,38 @@ mod tests {
let circuits = [ let circuits = [
// `ak` = 0, `nk` = 0 // `ak` = 0, `nk` = 0
MyCircuit { MyCircuit {
ak: Some(pallas::Base::zero()), ak: Value::known(pallas::Base::zero()),
nk: Some(pallas::Base::zero()), nk: Value::known(pallas::Base::zero()),
}, },
// `ak` = T_Q - 1, `nk` = T_Q - 1 // `ak` = T_Q - 1, `nk` = T_Q - 1
MyCircuit { MyCircuit {
ak: Some(pallas::Base::from_u128(T_Q - 1)), ak: Value::known(pallas::Base::from_u128(T_Q - 1)),
nk: Some(pallas::Base::from_u128(T_Q - 1)), nk: Value::known(pallas::Base::from_u128(T_Q - 1)),
}, },
// `ak` = T_Q, `nk` = T_Q // `ak` = T_Q, `nk` = T_Q
MyCircuit { MyCircuit {
ak: Some(pallas::Base::from_u128(T_Q)), ak: Value::known(pallas::Base::from_u128(T_Q)),
nk: Some(pallas::Base::from_u128(T_Q)), nk: Value::known(pallas::Base::from_u128(T_Q)),
}, },
// `ak` = 2^127 - 1, `nk` = 2^127 - 1 // `ak` = 2^127 - 1, `nk` = 2^127 - 1
MyCircuit { MyCircuit {
ak: Some(pallas::Base::from_u128((1 << 127) - 1)), ak: Value::known(pallas::Base::from_u128((1 << 127) - 1)),
nk: Some(pallas::Base::from_u128((1 << 127) - 1)), nk: Value::known(pallas::Base::from_u128((1 << 127) - 1)),
}, },
// `ak` = 2^127, `nk` = 2^127 // `ak` = 2^127, `nk` = 2^127
MyCircuit { MyCircuit {
ak: Some(pallas::Base::from_u128(1 << 127)), ak: Value::known(pallas::Base::from_u128(1 << 127)),
nk: Some(pallas::Base::from_u128(1 << 127)), nk: Value::known(pallas::Base::from_u128(1 << 127)),
}, },
// `ak` = 2^254 - 1, `nk` = 2^254 - 1 // `ak` = 2^254 - 1, `nk` = 2^254 - 1
MyCircuit { MyCircuit {
ak: Some(two_pow_254 - pallas::Base::one()), ak: Value::known(two_pow_254 - pallas::Base::one()),
nk: Some(two_pow_254 - pallas::Base::one()), nk: Value::known(two_pow_254 - pallas::Base::one()),
}, },
// `ak` = 2^254, `nk` = 2^254 // `ak` = 2^254, `nk` = 2^254
MyCircuit { MyCircuit {
ak: Some(two_pow_254), ak: Value::known(two_pow_254),
nk: Some(two_pow_254), nk: Value::known(two_pow_254),
}, },
]; ];

View File

@ -21,7 +21,7 @@ use halo2_gadgets::{
}; };
use halo2_proofs::{ use halo2_proofs::{
arithmetic::FieldExt, arithmetic::FieldExt,
circuit::{AssignedCell, Chip, Layouter}, circuit::{AssignedCell, Chip, Layouter, Value},
plonk::{self, Advice, Assigned, Column}, plonk::{self, Advice, Assigned, Column},
}; };
@ -96,21 +96,14 @@ pub(in crate::circuit) trait AddInstruction<F: FieldExt>: Chip<F> {
pub(in crate::circuit) fn assign_free_advice<F: Field, V: Copy>( pub(in crate::circuit) fn assign_free_advice<F: Field, V: Copy>(
mut layouter: impl Layouter<F>, mut layouter: impl Layouter<F>,
column: Column<Advice>, column: Column<Advice>,
value: Option<V>, value: Value<V>,
) -> Result<AssignedCell<V, F>, plonk::Error> ) -> Result<AssignedCell<V, F>, plonk::Error>
where where
for<'v> Assigned<F>: From<&'v V>, for<'v> Assigned<F>: From<&'v V>,
{ {
layouter.assign_region( layouter.assign_region(
|| "load private", || "load private",
|mut region| { |mut region| region.assign_advice(|| "load private", column, 0, || value),
region.assign_advice(
|| "load private",
column,
0,
|| value.ok_or(plonk::Error::Synthesis),
)
},
) )
} }

View File

@ -74,12 +74,7 @@ impl AddInstruction<pallas::Base> for AddChip {
b.copy_advice(|| "copy b", &mut region, self.config.b, 0)?; b.copy_advice(|| "copy b", &mut region, self.config.b, 0)?;
let scalar_val = a.value().zip(b.value()).map(|(a, b)| a + b); let scalar_val = a.value().zip(b.value()).map(|(a, b)| a + b);
region.assign_advice( region.assign_advice(|| "c", self.config.c, 0, || scalar_val)
|| "c",
self.config.c,
0,
|| scalar_val.ok_or(plonk::Error::Synthesis),
)
}, },
) )
} }

View File

@ -1,7 +1,7 @@
use core::iter; use core::iter;
use halo2_proofs::{ use halo2_proofs::{
circuit::{AssignedCell, Layouter}, circuit::{AssignedCell, Layouter, Value},
plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector},
poly::Rotation, poly::Rotation,
}; };
@ -128,8 +128,8 @@ impl DecomposeB {
( (
NoteCommitPiece, NoteCommitPiece,
RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
RangeConstrained<pallas::Base, Option<pallas::Base>>, RangeConstrained<pallas::Base, Value<pallas::Base>>,
RangeConstrained<pallas::Base, Option<pallas::Base>>, RangeConstrained<pallas::Base, Value<pallas::Base>>,
RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
), ),
Error, Error,
@ -170,7 +170,7 @@ impl DecomposeB {
layouter: &mut impl Layouter<pallas::Base>, layouter: &mut impl Layouter<pallas::Base>,
b: NoteCommitPiece, b: NoteCommitPiece,
b_0: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, b_0: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
b_1: RangeConstrained<pallas::Base, Option<pallas::Base>>, b_1: RangeConstrained<pallas::Base, Value<pallas::Base>>,
b_2: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, b_2: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
b_3: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, b_3: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
) -> Result<AssignedCell<pallas::Base, pallas::Base>, Error> { ) -> Result<AssignedCell<pallas::Base, pallas::Base>, Error> {
@ -184,12 +184,7 @@ impl DecomposeB {
.copy_advice(|| "b", &mut region, self.col_l, 0)?; .copy_advice(|| "b", &mut region, self.col_l, 0)?;
b_0.inner() b_0.inner()
.copy_advice(|| "b_0", &mut region, self.col_m, 0)?; .copy_advice(|| "b_0", &mut region, self.col_m, 0)?;
let b_1 = region.assign_advice( let b_1 = region.assign_advice(|| "b_1", self.col_r, 0, || *b_1.inner())?;
|| "b_1",
self.col_r,
0,
|| b_1.inner().ok_or(Error::Synthesis),
)?;
b_2.inner() b_2.inner()
.copy_advice(|| "b_2", &mut region, self.col_m, 1)?; .copy_advice(|| "b_2", &mut region, self.col_m, 1)?;
@ -277,8 +272,8 @@ impl DecomposeD {
) -> Result< ) -> Result<
( (
NoteCommitPiece, NoteCommitPiece,
RangeConstrained<pallas::Base, Option<pallas::Base>>, RangeConstrained<pallas::Base, Value<pallas::Base>>,
RangeConstrained<pallas::Base, Option<pallas::Base>>, RangeConstrained<pallas::Base, Value<pallas::Base>>,
RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
), ),
Error, Error,
@ -313,7 +308,7 @@ impl DecomposeD {
&self, &self,
layouter: &mut impl Layouter<pallas::Base>, layouter: &mut impl Layouter<pallas::Base>,
d: NoteCommitPiece, d: NoteCommitPiece,
d_0: RangeConstrained<pallas::Base, Option<pallas::Base>>, d_0: RangeConstrained<pallas::Base, Value<pallas::Base>>,
d_1: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, d_1: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
d_2: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, d_2: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
z1_d: AssignedCell<pallas::Base, pallas::Base>, z1_d: AssignedCell<pallas::Base, pallas::Base>,
@ -326,12 +321,7 @@ impl DecomposeD {
d.inner() d.inner()
.cell_value() .cell_value()
.copy_advice(|| "d", &mut region, self.col_l, 0)?; .copy_advice(|| "d", &mut region, self.col_l, 0)?;
let d_0 = region.assign_advice( let d_0 = region.assign_advice(|| "d_0", self.col_m, 0, || *d_0.inner())?;
|| "d_0",
self.col_m,
0,
|| d_0.inner().ok_or(Error::Synthesis),
)?;
d_1.inner() d_1.inner()
.copy_advice(|| "d_1", &mut region, self.col_r, 0)?; .copy_advice(|| "d_1", &mut region, self.col_r, 0)?;
@ -529,7 +519,7 @@ impl DecomposeG {
) -> Result< ) -> Result<
( (
NoteCommitPiece, NoteCommitPiece,
RangeConstrained<pallas::Base, Option<pallas::Base>>, RangeConstrained<pallas::Base, Value<pallas::Base>>,
RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
), ),
Error, Error,
@ -561,7 +551,7 @@ impl DecomposeG {
&self, &self,
layouter: &mut impl Layouter<pallas::Base>, layouter: &mut impl Layouter<pallas::Base>,
g: NoteCommitPiece, g: NoteCommitPiece,
g_0: RangeConstrained<pallas::Base, Option<pallas::Base>>, g_0: RangeConstrained<pallas::Base, Value<pallas::Base>>,
g_1: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, g_1: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
z1_g: AssignedCell<pallas::Base, pallas::Base>, z1_g: AssignedCell<pallas::Base, pallas::Base>,
) -> Result<AssignedCell<pallas::Base, pallas::Base>, Error> { ) -> Result<AssignedCell<pallas::Base, pallas::Base>, Error> {
@ -573,12 +563,7 @@ impl DecomposeG {
g.inner() g.inner()
.cell_value() .cell_value()
.copy_advice(|| "g", &mut region, self.col_l, 0)?; .copy_advice(|| "g", &mut region, self.col_l, 0)?;
let g_0 = region.assign_advice( let g_0 = region.assign_advice(|| "g_0", self.col_m, 0, || *g_0.inner())?;
|| "g_0",
self.col_m,
0,
|| g_0.inner().ok_or(Error::Synthesis),
)?;
g_1.inner() g_1.inner()
.copy_advice(|| "g_1", &mut region, self.col_l, 1)?; .copy_advice(|| "g_1", &mut region, self.col_l, 1)?;
@ -656,7 +641,7 @@ impl DecomposeH {
( (
NoteCommitPiece, NoteCommitPiece,
RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
RangeConstrained<pallas::Base, Option<pallas::Base>>, RangeConstrained<pallas::Base, Value<pallas::Base>>,
), ),
Error, Error,
> { > {
@ -677,7 +662,7 @@ impl DecomposeH {
[ [
h_0.value(), h_0.value(),
h_1, h_1,
RangeConstrained::bitrange_of(Some(&pallas::Base::zero()), 0..4), RangeConstrained::bitrange_of(Value::known(&pallas::Base::zero()), 0..4),
], ],
)?; )?;
@ -689,7 +674,7 @@ impl DecomposeH {
layouter: &mut impl Layouter<pallas::Base>, layouter: &mut impl Layouter<pallas::Base>,
h: NoteCommitPiece, h: NoteCommitPiece,
h_0: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, h_0: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
h_1: RangeConstrained<pallas::Base, Option<pallas::Base>>, h_1: RangeConstrained<pallas::Base, Value<pallas::Base>>,
) -> Result<AssignedCell<pallas::Base, pallas::Base>, Error> { ) -> Result<AssignedCell<pallas::Base, pallas::Base>, Error> {
layouter.assign_region( layouter.assign_region(
|| "NoteCommit MessagePiece h", || "NoteCommit MessagePiece h",
@ -701,12 +686,7 @@ impl DecomposeH {
.copy_advice(|| "h", &mut region, self.col_l, 0)?; .copy_advice(|| "h", &mut region, self.col_l, 0)?;
h_0.inner() h_0.inner()
.copy_advice(|| "h_0", &mut region, self.col_m, 0)?; .copy_advice(|| "h_0", &mut region, self.col_m, 0)?;
let h_1 = region.assign_advice( let h_1 = region.assign_advice(|| "h_1", self.col_r, 0, || *h_1.inner())?;
|| "h_1",
self.col_r,
0,
|| h_1.inner().ok_or(Error::Synthesis),
)?;
Ok(h_1) Ok(h_1)
}, },
@ -1357,10 +1337,10 @@ impl YCanonicity {
&self, &self,
layouter: &mut impl Layouter<pallas::Base>, layouter: &mut impl Layouter<pallas::Base>,
y: AssignedCell<pallas::Base, pallas::Base>, y: AssignedCell<pallas::Base, pallas::Base>,
lsb: RangeConstrained<pallas::Base, Option<pallas::Base>>, lsb: RangeConstrained<pallas::Base, Value<pallas::Base>>,
k_0: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, k_0: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
k_2: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, k_2: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
k_3: RangeConstrained<pallas::Base, Option<pallas::Base>>, k_3: RangeConstrained<pallas::Base, Value<pallas::Base>>,
j: AssignedCell<pallas::Base, pallas::Base>, j: AssignedCell<pallas::Base, pallas::Base>,
z1_j: AssignedCell<pallas::Base, pallas::Base>, z1_j: AssignedCell<pallas::Base, pallas::Base>,
z13_j: AssignedCell<pallas::Base, pallas::Base>, z13_j: AssignedCell<pallas::Base, pallas::Base>,
@ -1381,12 +1361,7 @@ impl YCanonicity {
y.copy_advice(|| "copy y", &mut region, self.advices[5], offset)?; y.copy_advice(|| "copy y", &mut region, self.advices[5], offset)?;
// Witness LSB. // Witness LSB.
let lsb = region let lsb = region
.assign_advice( .assign_advice(|| "witness LSB", self.advices[6], offset, || *lsb.inner())
|| "witness LSB",
self.advices[6],
offset,
|| lsb.inner().ok_or(Error::Synthesis),
)
// SAFETY: This is sound because we just assigned this cell from a // SAFETY: This is sound because we just assigned this cell from a
// range-constrained value. // range-constrained value.
.map(|cell| RangeConstrained::unsound_unchecked(cell, lsb.num_bits()))?; .map(|cell| RangeConstrained::unsound_unchecked(cell, lsb.num_bits()))?;
@ -1401,7 +1376,7 @@ impl YCanonicity {
|| "witness k_3", || "witness k_3",
self.advices[9], self.advices[9],
offset, offset,
|| k_3.inner().ok_or(Error::Synthesis), || *k_3.inner(),
)?; )?;
lsb lsb
@ -1586,7 +1561,7 @@ impl NoteCommitChip {
} }
pub(in crate::circuit) mod gadgets { pub(in crate::circuit) mod gadgets {
use halo2_proofs::circuit::Chip; use halo2_proofs::circuit::{Chip, Value};
use super::*; use super::*;
@ -1817,11 +1792,11 @@ pub(in crate::circuit) mod gadgets {
// Decompose the low 130 bits of a_prime = a + 2^130 - t_P, and output // Decompose the low 130 bits of a_prime = a + 2^130 - t_P, and output
// the running sum at the end of it. If a_prime < 2^130, the running sum // the running sum at the end of it. If a_prime < 2^130, the running sum
// will be 0. // will be 0.
let a_prime = a.value().map(|a| { let a_prime = {
let two_pow_130 = pallas::Base::from_u128(1u128 << 65).square(); let two_pow_130 = Value::known(pallas::Base::from_u128(1u128 << 65).square());
let t_p = pallas::Base::from_u128(T_P); let t_p = Value::known(pallas::Base::from_u128(T_P));
a + two_pow_130 - t_p a.value() + two_pow_130 - t_p
}); };
let zs = lookup_config.witness_check( let zs = lookup_config.witness_check(
layouter.namespace(|| "Decompose low 130 bits of (a + 2^130 - t_P)"), layouter.namespace(|| "Decompose low 130 bits of (a + 2^130 - t_P)"),
a_prime, a_prime,
@ -1856,12 +1831,12 @@ pub(in crate::circuit) mod gadgets {
// Decompose the low 140 bits of b3_c_prime = b_3 + 2^4 c + 2^140 - t_P, // Decompose the low 140 bits of b3_c_prime = b_3 + 2^4 c + 2^140 - t_P,
// and output the running sum at the end of it. // and output the running sum at the end of it.
// If b3_c_prime < 2^140, the running sum will be 0. // If b3_c_prime < 2^140, the running sum will be 0.
let b3_c_prime = b_3.inner().value().zip(c.value()).map(|(b_3, c)| { let b3_c_prime = {
let two_pow_4 = pallas::Base::from(1u64 << 4); let two_pow_4 = Value::known(pallas::Base::from(1u64 << 4));
let two_pow_140 = pallas::Base::from_u128(1u128 << 70).square(); let two_pow_140 = Value::known(pallas::Base::from_u128(1u128 << 70).square());
let t_p = pallas::Base::from_u128(T_P); let t_p = Value::known(pallas::Base::from_u128(T_P));
b_3 + (two_pow_4 * c) + two_pow_140 - t_p b_3.inner().value() + (two_pow_4 * c.value()) + two_pow_140 - t_p
}); };
let zs = lookup_config.witness_check( let zs = lookup_config.witness_check(
layouter.namespace(|| "Decompose low 140 bits of (b_3 + 2^4 c + 2^140 - t_P)"), layouter.namespace(|| "Decompose low 140 bits of (b_3 + 2^4 c + 2^140 - t_P)"),
@ -1894,12 +1869,12 @@ pub(in crate::circuit) mod gadgets {
// to 130 bits. z13_f == 0 is directly checked in the gate. // to 130 bits. z13_f == 0 is directly checked in the gate.
// - 0 ≤ e_1 + 2^4 f + 2^140 - t_P < 2^140 (14 ten-bit lookups) // - 0 ≤ e_1 + 2^4 f + 2^140 - t_P < 2^140 (14 ten-bit lookups)
let e1_f_prime = e_1.inner().value().zip(f.value()).map(|(e_1, f)| { let e1_f_prime = {
let two_pow_4 = pallas::Base::from(1u64 << 4); let two_pow_4 = Value::known(pallas::Base::from(1u64 << 4));
let two_pow_140 = pallas::Base::from_u128(1u128 << 70).square(); let two_pow_140 = Value::known(pallas::Base::from_u128(1u128 << 70).square());
let t_p = pallas::Base::from_u128(T_P); let t_p = Value::known(pallas::Base::from_u128(T_P));
e_1 + (two_pow_4 * f) + two_pow_140 - t_p e_1.inner().value() + (two_pow_4 * f.value()) + two_pow_140 - t_p
}); };
// Decompose the low 140 bits of e1_f_prime = e_1 + 2^4 f + 2^140 - t_P, // Decompose the low 140 bits of e1_f_prime = e_1 + 2^4 f + 2^140 - t_P,
// and output the running sum at the end of it. // and output the running sum at the end of it.
@ -1936,12 +1911,12 @@ pub(in crate::circuit) mod gadgets {
// Decompose the low 130 bits of g1_g2_prime = g_1 + (2^9)g_2 + 2^130 - t_P, // Decompose the low 130 bits of g1_g2_prime = g_1 + (2^9)g_2 + 2^130 - t_P,
// and output the running sum at the end of it. // and output the running sum at the end of it.
// If g1_g2_prime < 2^130, the running sum will be 0. // If g1_g2_prime < 2^130, the running sum will be 0.
let g1_g2_prime = g_1.inner().value().zip(g_2.value()).map(|(g_1, g_2)| { let g1_g2_prime = {
let two_pow_9 = pallas::Base::from(1u64 << 9); let two_pow_9 = Value::known(pallas::Base::from(1u64 << 9));
let two_pow_130 = pallas::Base::from_u128(1u128 << 65).square(); let two_pow_130 = Value::known(pallas::Base::from_u128(1u128 << 65).square());
let t_p = pallas::Base::from_u128(T_P); let t_p = Value::known(pallas::Base::from_u128(T_P));
g_1 + (two_pow_9 * g_2) + two_pow_130 - t_p g_1.inner().value() + (two_pow_9 * g_2.value()) + two_pow_130 - t_p
}); };
let zs = lookup_config.witness_check( let zs = lookup_config.witness_check(
layouter.namespace(|| "Decompose low 130 bits of (g_1 + (2^9)g_2 + 2^130 - t_P)"), layouter.namespace(|| "Decompose low 130 bits of (g_1 + (2^9)g_2 + 2^130 - t_P)"),
@ -1966,7 +1941,7 @@ pub(in crate::circuit) mod gadgets {
y_canon: &YCanonicity, y_canon: &YCanonicity,
mut layouter: impl Layouter<pallas::Base>, mut layouter: impl Layouter<pallas::Base>,
y: AssignedCell<pallas::Base, pallas::Base>, y: AssignedCell<pallas::Base, pallas::Base>,
lsb: RangeConstrained<pallas::Base, Option<pallas::Base>>, lsb: RangeConstrained<pallas::Base, Value<pallas::Base>>,
) -> Result<RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, Error> ) -> Result<RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>, Error>
{ {
// Decompose the field element // Decompose the field element
@ -1997,16 +1972,11 @@ pub(in crate::circuit) mod gadgets {
// Decompose j = LSB + (2)k_0 + (2^10)k_1 using 25 ten-bit lookups. // Decompose j = LSB + (2)k_0 + (2^10)k_1 using 25 ten-bit lookups.
let (j, z1_j, z13_j) = { let (j, z1_j, z13_j) = {
let j = lsb let j = {
.inner() let two = Value::known(pallas::Base::from(2));
.value() let two_pow_10 = Value::known(pallas::Base::from(1 << 10));
.zip(k_0.inner().value()) lsb.inner().value() + two * k_0.inner().value() + two_pow_10 * k_1.inner().value()
.zip(k_1.inner().value()) };
.map(|((lsb, k_0), k_1)| {
let two = pallas::Base::from(2);
let two_pow_10 = pallas::Base::from(1 << 10);
lsb + two * k_0 + two_pow_10 * k_1
});
let zs = lookup_config.witness_check( let zs = lookup_config.witness_check(
layouter.namespace(|| "Decompose j = LSB + (2)k_0 + (2^10)k_1"), layouter.namespace(|| "Decompose j = LSB + (2)k_0 + (2^10)k_1"),
j, j,
@ -2069,7 +2039,7 @@ mod tests {
use ff::{Field, PrimeField, PrimeFieldBits}; use ff::{Field, PrimeField, PrimeFieldBits};
use group::Curve; use group::Curve;
use halo2_proofs::{ use halo2_proofs::{
circuit::{Layouter, SimpleFloorPlanner}, circuit::{Layouter, SimpleFloorPlanner, Value},
dev::MockProver, dev::MockProver,
plonk::{Circuit, ConstraintSystem, Error}, plonk::{Circuit, ConstraintSystem, Error},
}; };
@ -2084,12 +2054,12 @@ mod tests {
fn note_commit() { fn note_commit() {
#[derive(Default)] #[derive(Default)]
struct MyCircuit { struct MyCircuit {
gd_x: Option<pallas::Base>, gd_x: Value<pallas::Base>,
gd_y_lsb: Option<pallas::Base>, gd_y_lsb: Value<pallas::Base>,
pkd_x: Option<pallas::Base>, pkd_x: Value<pallas::Base>,
pkd_y_lsb: Option<pallas::Base>, pkd_y_lsb: Value<pallas::Base>,
rho: Option<pallas::Base>, rho: Value<pallas::Base>,
psi: Option<pallas::Base>, psi: Value<pallas::Base>,
} }
impl Circuit<pallas::Base> for MyCircuit { impl Circuit<pallas::Base> for MyCircuit {
@ -2235,7 +2205,7 @@ mod tests {
assign_free_advice( assign_free_advice(
layouter.namespace(|| "witness value"), layouter.namespace(|| "witness value"),
note_commit_config.advices[0], note_commit_config.advices[0],
Some(value), Value::known(value),
)? )?
}; };
@ -2254,8 +2224,11 @@ mod tests {
)?; )?;
let rcm = pallas::Scalar::random(OsRng); let rcm = pallas::Scalar::random(OsRng);
let rcm_gadget = let rcm_gadget = ScalarFixed::new(
ScalarFixed::new(ecc_chip.clone(), layouter.namespace(|| "rcm"), Some(rcm))?; ecc_chip.clone(),
layouter.namespace(|| "rcm"),
Value::known(rcm),
)?;
let cm = gadgets::note_commit( let cm = gadgets::note_commit(
layouter.namespace(|| "Hash NoteCommit pieces"), layouter.namespace(|| "Hash NoteCommit pieces"),
@ -2273,53 +2246,40 @@ mod tests {
let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION);
// Hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi // Hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi
let lsb = |y_lsb: pallas::Base| y_lsb == pallas::Base::one(); let lsb = |y_lsb: pallas::Base| y_lsb == pallas::Base::one();
let point = domain let point = self
.commit( .gd_x
iter::empty() .zip(self.gd_y_lsb)
.chain( .zip(self.pkd_x.zip(self.pkd_y_lsb))
self.gd_x .zip(self.rho.zip(self.psi))
.unwrap() .map(|(((gd_x, gd_y_lsb), (pkd_x, pkd_y_lsb)), (rho, psi))| {
.to_le_bits() domain
.iter() .commit(
.by_vals() iter::empty()
.take(L_ORCHARD_BASE), .chain(
gd_x.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE),
)
.chain(Some(lsb(gd_y_lsb)))
.chain(
pkd_x
.to_le_bits()
.iter()
.by_vals()
.take(L_ORCHARD_BASE),
)
.chain(Some(lsb(pkd_y_lsb)))
.chain(value.to_le_bits().iter().by_vals().take(L_VALUE))
.chain(
rho.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE),
)
.chain(
psi.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE),
),
&rcm,
) )
.chain(Some(lsb(self.gd_y_lsb.unwrap()))) .unwrap()
.chain( .to_affine()
self.pkd_x });
.unwrap() NonIdentityPoint::new(ecc_chip, layouter.namespace(|| "witness cm"), point)?
.to_le_bits()
.iter()
.by_vals()
.take(L_ORCHARD_BASE),
)
.chain(Some(lsb(self.pkd_y_lsb.unwrap())))
.chain(value.to_le_bits().iter().by_vals().take(L_VALUE))
.chain(
self.rho
.unwrap()
.to_le_bits()
.iter()
.by_vals()
.take(L_ORCHARD_BASE),
)
.chain(
self.psi
.unwrap()
.to_le_bits()
.iter()
.by_vals()
.take(L_ORCHARD_BASE),
),
&rcm,
)
.unwrap()
.to_affine();
NonIdentityPoint::new(
ecc_chip,
layouter.namespace(|| "witness cm"),
Some(point),
)?
}; };
cm.constrain_equal(layouter.namespace(|| "cm == expected cm"), &expected_cm) cm.constrain_equal(layouter.namespace(|| "cm == expected cm"), &expected_cm)
} }
@ -2331,66 +2291,66 @@ mod tests {
// `gd_x` = -1, `pkd_x` = -1 (these have to be x-coordinates of curve points) // `gd_x` = -1, `pkd_x` = -1 (these have to be x-coordinates of curve points)
// `rho` = 0, `psi` = 0 // `rho` = 0, `psi` = 0
MyCircuit { MyCircuit {
gd_x: Some(-pallas::Base::one()), gd_x: Value::known(-pallas::Base::one()),
gd_y_lsb: Some(pallas::Base::one()), gd_y_lsb: Value::known(pallas::Base::one()),
pkd_x: Some(-pallas::Base::one()), pkd_x: Value::known(-pallas::Base::one()),
pkd_y_lsb: Some(pallas::Base::one()), pkd_y_lsb: Value::known(pallas::Base::one()),
rho: Some(pallas::Base::zero()), rho: Value::known(pallas::Base::zero()),
psi: Some(pallas::Base::zero()), psi: Value::known(pallas::Base::zero()),
}, },
// `rho` = T_Q - 1, `psi` = T_Q - 1 // `rho` = T_Q - 1, `psi` = T_Q - 1
MyCircuit { MyCircuit {
gd_x: Some(-pallas::Base::one()), gd_x: Value::known(-pallas::Base::one()),
gd_y_lsb: Some(pallas::Base::zero()), gd_y_lsb: Value::known(pallas::Base::zero()),
pkd_x: Some(-pallas::Base::one()), pkd_x: Value::known(-pallas::Base::one()),
pkd_y_lsb: Some(pallas::Base::zero()), pkd_y_lsb: Value::known(pallas::Base::zero()),
rho: Some(pallas::Base::from_u128(T_Q - 1)), rho: Value::known(pallas::Base::from_u128(T_Q - 1)),
psi: Some(pallas::Base::from_u128(T_Q - 1)), psi: Value::known(pallas::Base::from_u128(T_Q - 1)),
}, },
// `rho` = T_Q, `psi` = T_Q // `rho` = T_Q, `psi` = T_Q
MyCircuit { MyCircuit {
gd_x: Some(-pallas::Base::one()), gd_x: Value::known(-pallas::Base::one()),
gd_y_lsb: Some(pallas::Base::one()), gd_y_lsb: Value::known(pallas::Base::one()),
pkd_x: Some(-pallas::Base::one()), pkd_x: Value::known(-pallas::Base::one()),
pkd_y_lsb: Some(pallas::Base::zero()), pkd_y_lsb: Value::known(pallas::Base::zero()),
rho: Some(pallas::Base::from_u128(T_Q)), rho: Value::known(pallas::Base::from_u128(T_Q)),
psi: Some(pallas::Base::from_u128(T_Q)), psi: Value::known(pallas::Base::from_u128(T_Q)),
}, },
// `rho` = 2^127 - 1, `psi` = 2^127 - 1 // `rho` = 2^127 - 1, `psi` = 2^127 - 1
MyCircuit { MyCircuit {
gd_x: Some(-pallas::Base::one()), gd_x: Value::known(-pallas::Base::one()),
gd_y_lsb: Some(pallas::Base::zero()), gd_y_lsb: Value::known(pallas::Base::zero()),
pkd_x: Some(-pallas::Base::one()), pkd_x: Value::known(-pallas::Base::one()),
pkd_y_lsb: Some(pallas::Base::one()), pkd_y_lsb: Value::known(pallas::Base::one()),
rho: Some(pallas::Base::from_u128((1 << 127) - 1)), rho: Value::known(pallas::Base::from_u128((1 << 127) - 1)),
psi: Some(pallas::Base::from_u128((1 << 127) - 1)), psi: Value::known(pallas::Base::from_u128((1 << 127) - 1)),
}, },
// `rho` = 2^127, `psi` = 2^127 // `rho` = 2^127, `psi` = 2^127
MyCircuit { MyCircuit {
gd_x: Some(-pallas::Base::one()), gd_x: Value::known(-pallas::Base::one()),
gd_y_lsb: Some(pallas::Base::zero()), gd_y_lsb: Value::known(pallas::Base::zero()),
pkd_x: Some(-pallas::Base::one()), pkd_x: Value::known(-pallas::Base::one()),
pkd_y_lsb: Some(pallas::Base::zero()), pkd_y_lsb: Value::known(pallas::Base::zero()),
rho: Some(pallas::Base::from_u128(1 << 127)), rho: Value::known(pallas::Base::from_u128(1 << 127)),
psi: Some(pallas::Base::from_u128(1 << 127)), psi: Value::known(pallas::Base::from_u128(1 << 127)),
}, },
// `rho` = 2^254 - 1, `psi` = 2^254 - 1 // `rho` = 2^254 - 1, `psi` = 2^254 - 1
MyCircuit { MyCircuit {
gd_x: Some(-pallas::Base::one()), gd_x: Value::known(-pallas::Base::one()),
gd_y_lsb: Some(pallas::Base::one()), gd_y_lsb: Value::known(pallas::Base::one()),
pkd_x: Some(-pallas::Base::one()), pkd_x: Value::known(-pallas::Base::one()),
pkd_y_lsb: Some(pallas::Base::one()), pkd_y_lsb: Value::known(pallas::Base::one()),
rho: Some(two_pow_254 - pallas::Base::one()), rho: Value::known(two_pow_254 - pallas::Base::one()),
psi: Some(two_pow_254 - pallas::Base::one()), psi: Value::known(two_pow_254 - pallas::Base::one()),
}, },
// `rho` = 2^254, `psi` = 2^254 // `rho` = 2^254, `psi` = 2^254
MyCircuit { MyCircuit {
gd_x: Some(-pallas::Base::one()), gd_x: Value::known(-pallas::Base::one()),
gd_y_lsb: Some(pallas::Base::one()), gd_y_lsb: Value::known(pallas::Base::one()),
pkd_x: Some(-pallas::Base::one()), pkd_x: Value::known(-pallas::Base::one()),
pkd_y_lsb: Some(pallas::Base::zero()), pkd_y_lsb: Value::known(pallas::Base::zero()),
rho: Some(two_pow_254), rho: Value::known(two_pow_254),
psi: Some(two_pow_254), psi: Value::known(two_pow_254),
}, },
]; ];