From be69324b9cab8179a61b2b8ee2a51a146665cd8d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 9 Jun 2022 00:01:10 +0000 Subject: [PATCH] Migrate to `halo2_proofs 0.2.0` --- CHANGELOG.md | 2 + Cargo.toml | 6 +- src/builder.rs | 39 ++-- src/circuit.rs | 124 ++++++------- src/circuit/commit_ivk.rs | 120 ++++++------- src/circuit/gadget.rs | 13 +- src/circuit/gadget/add_chip.rs | 7 +- src/circuit/note_commit.rs | 316 ++++++++++++++------------------- 8 files changed, 288 insertions(+), 339 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41f3e8d5..e7dc93fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed +- Migrated to `halo2_proofs 0.2`. ## [0.1.0] - 2022-05-10 ### Changed diff --git a/Cargo.toml b/Cargo.toml index b50a0299..6dc303ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,8 +29,8 @@ blake2b_simd = "1" ff = "0.12" fpe = "0.5" group = "0.12" -halo2_gadgets = "0.1" -halo2_proofs = "0.1" +halo2_gadgets = "0.2" +halo2_proofs = "0.2" hex = "0.4" lazy_static = "1" memuse = { version = "0.2", features = ["nonempty"] } @@ -49,7 +49,7 @@ plotters = { version = "0.3.0", optional = true } [dev-dependencies] criterion = "0.3" -halo2_gadgets = { version = "0.1", features = ["test-dependencies"] } +halo2_gadgets = { version = "0.2", features = ["test-dependencies"] } hex = "0.4" proptest = "1.0.0" zcash_note_encryption = { version = "0.1", features = ["pre-zip-212"] } diff --git a/src/builder.rs b/src/builder.rs index c1a45b76..8ccc6274 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -4,6 +4,7 @@ use core::fmt; use core::iter; use ff::Field; +use halo2_proofs::circuit::Value; use nonempty::NonEmpty; use pasta_curves::pallas; use rand::{prelude::SliceRandom, CryptoRng, RngCore}; @@ -188,25 +189,25 @@ impl ActionInfo { }, ), Circuit { - path: Some(self.spend.merkle_path.auth_path()), - pos: Some(self.spend.merkle_path.position()), - g_d_old: Some(sender_address.g_d()), - pk_d_old: Some(*sender_address.pk_d()), - v_old: Some(self.spend.note.value()), - rho_old: Some(rho_old), - psi_old: Some(psi_old), - rcm_old: Some(rcm_old), - cm_old: Some(self.spend.note.commitment()), - alpha: Some(alpha), - ak: Some(ak), - nk: Some(*self.spend.fvk.nk()), - rivk: Some(self.spend.fvk.rivk(self.spend.scope)), - g_d_new: Some(note.recipient().g_d()), - pk_d_new: Some(*note.recipient().pk_d()), - v_new: Some(note.value()), - psi_new: Some(note.rseed().psi(¬e.rho())), - rcm_new: Some(note.rseed().rcm(¬e.rho())), - rcv: Some(self.rcv), + path: Value::known(self.spend.merkle_path.auth_path()), + pos: Value::known(self.spend.merkle_path.position()), + g_d_old: Value::known(sender_address.g_d()), + pk_d_old: Value::known(*sender_address.pk_d()), + v_old: Value::known(self.spend.note.value()), + rho_old: Value::known(rho_old), + psi_old: Value::known(psi_old), + rcm_old: Value::known(rcm_old), + cm_old: Value::known(self.spend.note.commitment()), + alpha: Value::known(alpha), + ak: Value::known(ak), + nk: Value::known(*self.spend.fvk.nk()), + rivk: Value::known(self.spend.fvk.rivk(self.spend.scope)), + g_d_new: Value::known(note.recipient().g_d()), + pk_d_new: Value::known(*note.recipient().pk_d()), + v_new: Value::known(note.value()), + psi_new: Value::known(note.rseed().psi(¬e.rho())), + rcm_new: Value::known(note.rseed().rcm(¬e.rho())), + rcv: Value::known(self.rcv), }, ) } diff --git a/src/circuit.rs b/src/circuit.rs index f1742a8d..7bcc31d6 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -4,7 +4,7 @@ use core::fmt; use group::{Curve, GroupEncoding}; use halo2_proofs::{ - circuit::{floor_planner, Layouter}, + circuit::{floor_planner, Layouter, Value}, plonk::{ self, Advice, Column, Constraints, Expression, Instance as InstanceColumn, Selector, SingleVerifier, @@ -99,25 +99,25 @@ pub struct Config { /// The Orchard Action circuit. #[derive(Clone, Debug, Default)] pub struct Circuit { - pub(crate) path: Option<[MerkleHashOrchard; MERKLE_DEPTH_ORCHARD]>, - pub(crate) pos: Option, - pub(crate) g_d_old: Option, - pub(crate) pk_d_old: Option, - pub(crate) v_old: Option, - pub(crate) rho_old: Option, - pub(crate) psi_old: Option, - pub(crate) rcm_old: Option, - pub(crate) cm_old: Option, - pub(crate) alpha: Option, - pub(crate) ak: Option, - pub(crate) nk: Option, - pub(crate) rivk: Option, - pub(crate) g_d_new: Option, - pub(crate) pk_d_new: Option, - pub(crate) v_new: Option, - pub(crate) psi_new: Option, - pub(crate) rcm_new: Option, - pub(crate) rcv: Option, + pub(crate) path: Value<[MerkleHashOrchard; MERKLE_DEPTH_ORCHARD]>, + pub(crate) pos: Value, + pub(crate) g_d_old: Value, + pub(crate) pk_d_old: Value, + pub(crate) v_old: Value, + pub(crate) rho_old: Value, + pub(crate) psi_old: Value, + pub(crate) rcm_old: Value, + pub(crate) cm_old: Value, + pub(crate) alpha: Value, + pub(crate) ak: Value, + pub(crate) nk: Value, + pub(crate) rivk: Value, + pub(crate) g_d_new: Value, + pub(crate) pk_d_new: Value, + pub(crate) v_new: Value, + pub(crate) psi_new: Value, + pub(crate) rcm_new: Value, + pub(crate) rcv: Value, } impl plonk::Circuit for Circuit { @@ -358,7 +358,7 @@ impl plonk::Circuit for Circuit { )?; // Witness ak_P. - let ak_P: Option = self.ak.as_ref().map(|ak| ak.into()); + let ak_P: Value = self.ak.as_ref().map(|ak| ak.into()); let ak_P = NonIdentityPoint::new( ecc_chip.clone(), layouter.namespace(|| "witness ak_P"), @@ -408,8 +408,8 @@ impl plonk::Circuit for Circuit { let v_net_magnitude_sign = { // Witness the magnitude and sign of v_net = v_old - v_new let v_net_magnitude_sign = { - let magnitude_sign = self.v_old.zip(self.v_new).map(|(v_old, v_new)| { - let v_net = v_old - v_new; + let v_net = self.v_old - self.v_new; + let magnitude_sign = v_net.map(|v_net| { let (magnitude, sign) = v_net.magnitude_sign(); ( @@ -877,7 +877,7 @@ mod tests { use core::iter; use ff::Field; - use halo2_proofs::dev::MockProver; + use halo2_proofs::{circuit::Value, dev::MockProver}; use pasta_curves::pallas; use rand::{rngs::OsRng, RngCore}; @@ -912,25 +912,25 @@ mod tests { ( Circuit { - path: Some(path.auth_path()), - pos: Some(path.position()), - g_d_old: Some(sender_address.g_d()), - pk_d_old: Some(*sender_address.pk_d()), - v_old: Some(spent_note.value()), - rho_old: Some(spent_note.rho()), - psi_old: Some(spent_note.rseed().psi(&spent_note.rho())), - rcm_old: Some(spent_note.rseed().rcm(&spent_note.rho())), - cm_old: Some(spent_note.commitment()), - alpha: Some(alpha), - ak: Some(ak), - nk: Some(nk), - rivk: Some(rivk), - g_d_new: Some(output_note.recipient().g_d()), - pk_d_new: Some(*output_note.recipient().pk_d()), - v_new: Some(output_note.value()), - psi_new: Some(output_note.rseed().psi(&output_note.rho())), - rcm_new: Some(output_note.rseed().rcm(&output_note.rho())), - rcv: Some(rcv), + path: Value::known(path.auth_path()), + pos: Value::known(path.position()), + g_d_old: Value::known(sender_address.g_d()), + pk_d_old: Value::known(*sender_address.pk_d()), + v_old: Value::known(spent_note.value()), + rho_old: Value::known(spent_note.rho()), + psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), + rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), + cm_old: Value::known(spent_note.commitment()), + alpha: Value::known(alpha), + ak: Value::known(ak), + nk: Value::known(nk), + rivk: Value::known(rivk), + g_d_new: Value::known(output_note.recipient().g_d()), + pk_d_new: Value::known(*output_note.recipient().pk_d()), + v_new: Value::known(output_note.value()), + psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), + rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), + rcv: Value::known(rcv), }, Instance { anchor, @@ -1098,25 +1098,25 @@ mod tests { .unwrap(); let circuit = Circuit { - path: None, - pos: None, - g_d_old: None, - pk_d_old: None, - v_old: None, - rho_old: None, - psi_old: None, - rcm_old: None, - cm_old: None, - alpha: None, - ak: None, - nk: None, - rivk: None, - g_d_new: None, - pk_d_new: None, - v_new: None, - psi_new: None, - rcm_new: None, - rcv: None, + path: Value::unknown(), + pos: Value::unknown(), + g_d_old: Value::unknown(), + pk_d_old: Value::unknown(), + v_old: Value::unknown(), + rho_old: Value::unknown(), + psi_old: Value::unknown(), + rcm_old: Value::unknown(), + cm_old: Value::unknown(), + alpha: Value::unknown(), + ak: Value::unknown(), + nk: Value::unknown(), + rivk: Value::unknown(), + g_d_new: Value::unknown(), + pk_d_new: Value::unknown(), + v_new: Value::unknown(), + psi_new: Value::unknown(), + rcm_new: Value::unknown(), + rcv: Value::unknown(), }; halo2_proofs::dev::CircuitLayout::default() .show_labels(false) diff --git a/src/circuit/commit_ivk.rs b/src/circuit/commit_ivk.rs index 1460c9d8..8001a0ac 100644 --- a/src/circuit/commit_ivk.rs +++ b/src/circuit/commit_ivk.rs @@ -1,7 +1,7 @@ use core::iter; use halo2_proofs::{ - circuit::{AssignedCell, Layouter}, + circuit::{AssignedCell, Layouter, Value}, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, 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 // the running sum at the end of it. If a_prime < 2^130, the running sum // will be 0. - let a_prime = a.value().map(|a| { - let two_pow_130 = pallas::Base::from_u128(1u128 << 65).square(); - let t_p = pallas::Base::from_u128(T_P); - a + two_pow_130 - t_p - }); + let a_prime = { + let two_pow_130 = Value::known(pallas::Base::from_u128(1u128 << 65).square()); + let t_p = Value::known(pallas::Base::from_u128(T_P)); + a.value() + two_pow_130 - t_p + }; let zs = lookup_config.witness_check( layouter.namespace(|| "Decompose low 130 bits of (a + 2^130 - t_P)"), 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 // 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 two_pow_5 = pallas::Base::from(1 << 5); - let two_pow_140 = pallas::Base::from_u128(1u128 << 70).square(); - let t_p = pallas::Base::from_u128(T_P); - b_2 + c * two_pow_5 + two_pow_140 - t_p - }); + let b2_c_prime = { + let two_pow_5 = Value::known(pallas::Base::from(1 << 5)); + let two_pow_140 = Value::known(pallas::Base::from_u128(1u128 << 70).square()); + let t_p = Value::known(pallas::Base::from_u128(T_P)); + b_2.inner().value() + c.value() * two_pow_5 + two_pow_140 - t_p + }; let zs = lookup_config.witness_check( layouter.namespace(|| "Decompose low 140 bits of (b_2 + c * 2^5 + 2^140 - t_P)"), b2_c_prime, @@ -535,7 +535,7 @@ impl CommitIvkConfig { || "Witness b_1", self.advices[4], offset, - || gate_cells.b_1.inner().ok_or(Error::Synthesis), + || *gate_cells.b_1.inner(), )?; // Copy in `b_2` @@ -603,7 +603,7 @@ impl CommitIvkConfig { || "Witness d_1", self.advices[4], offset, - || gate_cells.d_1.inner().ok_or(Error::Synthesis), + || *gate_cells.d_1.inner(), )?; // Copy in z13_c @@ -646,10 +646,10 @@ struct GateCells { ak: AssignedCell, nk: AssignedCell, b_0: RangeConstrained>, - b_1: RangeConstrained>, + b_1: RangeConstrained>, b_2: RangeConstrained>, d_0: RangeConstrained>, - d_1: RangeConstrained>, + d_1: RangeConstrained>, z13_a: AssignedCell, a_prime: AssignedCell, z13_a_prime: AssignedCell, @@ -680,7 +680,7 @@ mod tests { utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, }; use halo2_proofs::{ - circuit::{AssignedCell, Layouter, SimpleFloorPlanner}, + circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; @@ -691,8 +691,8 @@ mod tests { fn commit_ivk() { #[derive(Default)] struct MyCircuit { - ak: Option, - nk: Option, + ak: Value, + nk: Value, } impl UtilitiesInstructions for MyCircuit { @@ -809,8 +809,11 @@ mod tests { // Use a random scalar for rivk let rivk = pallas::Scalar::random(OsRng); - let rivk_gadget = - ScalarFixed::new(ecc_chip.clone(), layouter.namespace(|| "rivk"), Some(rivk))?; + let rivk_gadget = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rivk"), + Value::known(rivk), + )?; let ivk = gadgets::commit_ivk( sinsemilla_chip, @@ -822,34 +825,29 @@ mod tests { rivk_gadget, )?; - let expected_ivk = { - let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION); - // Hash ak || nk - domain - .short_commit( - iter::empty() - .chain( - self.ak - .unwrap() - .to_le_bits() - .iter() - .by_vals() - .take(L_ORCHARD_BASE), + self.ak + .zip(self.nk) + .zip(ivk.inner().value()) + .assert_if_known(|((ak, nk), ivk)| { + let expected_ivk = { + let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION); + // Hash ak || nk + domain + .short_commit( + iter::empty() + .chain( + ak.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), + ) + .chain( + nk.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), + ), + &rivk, ) - .chain( - self.nk - .unwrap() - .to_le_bits() - .iter() - .by_vals() - .take(L_ORCHARD_BASE), - ), - &rivk, - ) - .unwrap() - }; + .unwrap() + }; - assert_eq!(&expected_ivk, ivk.inner().value().unwrap()); + &&expected_ivk == ivk + }); Ok(()) } @@ -860,38 +858,38 @@ mod tests { let circuits = [ // `ak` = 0, `nk` = 0 MyCircuit { - ak: Some(pallas::Base::zero()), - nk: Some(pallas::Base::zero()), + ak: Value::known(pallas::Base::zero()), + nk: Value::known(pallas::Base::zero()), }, // `ak` = T_Q - 1, `nk` = T_Q - 1 MyCircuit { - ak: Some(pallas::Base::from_u128(T_Q - 1)), - nk: Some(pallas::Base::from_u128(T_Q - 1)), + ak: Value::known(pallas::Base::from_u128(T_Q - 1)), + nk: Value::known(pallas::Base::from_u128(T_Q - 1)), }, // `ak` = T_Q, `nk` = T_Q MyCircuit { - ak: Some(pallas::Base::from_u128(T_Q)), - nk: Some(pallas::Base::from_u128(T_Q)), + ak: Value::known(pallas::Base::from_u128(T_Q)), + nk: Value::known(pallas::Base::from_u128(T_Q)), }, // `ak` = 2^127 - 1, `nk` = 2^127 - 1 MyCircuit { - ak: Some(pallas::Base::from_u128((1 << 127) - 1)), - nk: Some(pallas::Base::from_u128((1 << 127) - 1)), + ak: Value::known(pallas::Base::from_u128((1 << 127) - 1)), + nk: Value::known(pallas::Base::from_u128((1 << 127) - 1)), }, // `ak` = 2^127, `nk` = 2^127 MyCircuit { - ak: Some(pallas::Base::from_u128(1 << 127)), - nk: Some(pallas::Base::from_u128(1 << 127)), + ak: Value::known(pallas::Base::from_u128(1 << 127)), + nk: Value::known(pallas::Base::from_u128(1 << 127)), }, // `ak` = 2^254 - 1, `nk` = 2^254 - 1 MyCircuit { - ak: Some(two_pow_254 - pallas::Base::one()), - nk: Some(two_pow_254 - pallas::Base::one()), + ak: Value::known(two_pow_254 - pallas::Base::one()), + nk: Value::known(two_pow_254 - pallas::Base::one()), }, // `ak` = 2^254, `nk` = 2^254 MyCircuit { - ak: Some(two_pow_254), - nk: Some(two_pow_254), + ak: Value::known(two_pow_254), + nk: Value::known(two_pow_254), }, ]; diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index 7fa52ecd..21d24333 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -21,7 +21,7 @@ use halo2_gadgets::{ }; use halo2_proofs::{ arithmetic::FieldExt, - circuit::{AssignedCell, Chip, Layouter}, + circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{self, Advice, Assigned, Column}, }; @@ -96,21 +96,14 @@ pub(in crate::circuit) trait AddInstruction: Chip { pub(in crate::circuit) fn assign_free_advice( mut layouter: impl Layouter, column: Column, - value: Option, + value: Value, ) -> Result, plonk::Error> where for<'v> Assigned: From<&'v V>, { layouter.assign_region( || "load private", - |mut region| { - region.assign_advice( - || "load private", - column, - 0, - || value.ok_or(plonk::Error::Synthesis), - ) - }, + |mut region| region.assign_advice(|| "load private", column, 0, || value), ) } diff --git a/src/circuit/gadget/add_chip.rs b/src/circuit/gadget/add_chip.rs index bf013528..0973a3f3 100644 --- a/src/circuit/gadget/add_chip.rs +++ b/src/circuit/gadget/add_chip.rs @@ -74,12 +74,7 @@ impl AddInstruction for AddChip { b.copy_advice(|| "copy b", &mut region, self.config.b, 0)?; let scalar_val = a.value().zip(b.value()).map(|(a, b)| a + b); - region.assign_advice( - || "c", - self.config.c, - 0, - || scalar_val.ok_or(plonk::Error::Synthesis), - ) + region.assign_advice(|| "c", self.config.c, 0, || scalar_val) }, ) } diff --git a/src/circuit/note_commit.rs b/src/circuit/note_commit.rs index b7163285..1f4a3cec 100644 --- a/src/circuit/note_commit.rs +++ b/src/circuit/note_commit.rs @@ -1,7 +1,7 @@ use core::iter; use halo2_proofs::{ - circuit::{AssignedCell, Layouter}, + circuit::{AssignedCell, Layouter, Value}, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, poly::Rotation, }; @@ -128,8 +128,8 @@ impl DecomposeB { ( NoteCommitPiece, RangeConstrained>, - RangeConstrained>, - RangeConstrained>, + RangeConstrained>, + RangeConstrained>, RangeConstrained>, ), Error, @@ -170,7 +170,7 @@ impl DecomposeB { layouter: &mut impl Layouter, b: NoteCommitPiece, b_0: RangeConstrained>, - b_1: RangeConstrained>, + b_1: RangeConstrained>, b_2: RangeConstrained>, b_3: RangeConstrained>, ) -> Result, Error> { @@ -184,12 +184,7 @@ impl DecomposeB { .copy_advice(|| "b", &mut region, self.col_l, 0)?; b_0.inner() .copy_advice(|| "b_0", &mut region, self.col_m, 0)?; - let b_1 = region.assign_advice( - || "b_1", - self.col_r, - 0, - || b_1.inner().ok_or(Error::Synthesis), - )?; + let b_1 = region.assign_advice(|| "b_1", self.col_r, 0, || *b_1.inner())?; b_2.inner() .copy_advice(|| "b_2", &mut region, self.col_m, 1)?; @@ -277,8 +272,8 @@ impl DecomposeD { ) -> Result< ( NoteCommitPiece, - RangeConstrained>, - RangeConstrained>, + RangeConstrained>, + RangeConstrained>, RangeConstrained>, ), Error, @@ -313,7 +308,7 @@ impl DecomposeD { &self, layouter: &mut impl Layouter, d: NoteCommitPiece, - d_0: RangeConstrained>, + d_0: RangeConstrained>, d_1: RangeConstrained>, d_2: RangeConstrained>, z1_d: AssignedCell, @@ -326,12 +321,7 @@ impl DecomposeD { d.inner() .cell_value() .copy_advice(|| "d", &mut region, self.col_l, 0)?; - let d_0 = region.assign_advice( - || "d_0", - self.col_m, - 0, - || d_0.inner().ok_or(Error::Synthesis), - )?; + let d_0 = region.assign_advice(|| "d_0", self.col_m, 0, || *d_0.inner())?; d_1.inner() .copy_advice(|| "d_1", &mut region, self.col_r, 0)?; @@ -529,7 +519,7 @@ impl DecomposeG { ) -> Result< ( NoteCommitPiece, - RangeConstrained>, + RangeConstrained>, RangeConstrained>, ), Error, @@ -561,7 +551,7 @@ impl DecomposeG { &self, layouter: &mut impl Layouter, g: NoteCommitPiece, - g_0: RangeConstrained>, + g_0: RangeConstrained>, g_1: RangeConstrained>, z1_g: AssignedCell, ) -> Result, Error> { @@ -573,12 +563,7 @@ impl DecomposeG { g.inner() .cell_value() .copy_advice(|| "g", &mut region, self.col_l, 0)?; - let g_0 = region.assign_advice( - || "g_0", - self.col_m, - 0, - || g_0.inner().ok_or(Error::Synthesis), - )?; + let g_0 = region.assign_advice(|| "g_0", self.col_m, 0, || *g_0.inner())?; g_1.inner() .copy_advice(|| "g_1", &mut region, self.col_l, 1)?; @@ -656,7 +641,7 @@ impl DecomposeH { ( NoteCommitPiece, RangeConstrained>, - RangeConstrained>, + RangeConstrained>, ), Error, > { @@ -677,7 +662,7 @@ impl DecomposeH { [ h_0.value(), 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, h: NoteCommitPiece, h_0: RangeConstrained>, - h_1: RangeConstrained>, + h_1: RangeConstrained>, ) -> Result, Error> { layouter.assign_region( || "NoteCommit MessagePiece h", @@ -701,12 +686,7 @@ impl DecomposeH { .copy_advice(|| "h", &mut region, self.col_l, 0)?; h_0.inner() .copy_advice(|| "h_0", &mut region, self.col_m, 0)?; - let h_1 = region.assign_advice( - || "h_1", - self.col_r, - 0, - || h_1.inner().ok_or(Error::Synthesis), - )?; + let h_1 = region.assign_advice(|| "h_1", self.col_r, 0, || *h_1.inner())?; Ok(h_1) }, @@ -1357,10 +1337,10 @@ impl YCanonicity { &self, layouter: &mut impl Layouter, y: AssignedCell, - lsb: RangeConstrained>, + lsb: RangeConstrained>, k_0: RangeConstrained>, k_2: RangeConstrained>, - k_3: RangeConstrained>, + k_3: RangeConstrained>, j: AssignedCell, z1_j: AssignedCell, z13_j: AssignedCell, @@ -1381,12 +1361,7 @@ impl YCanonicity { y.copy_advice(|| "copy y", &mut region, self.advices[5], offset)?; // Witness LSB. let lsb = region - .assign_advice( - || "witness LSB", - self.advices[6], - offset, - || lsb.inner().ok_or(Error::Synthesis), - ) + .assign_advice(|| "witness LSB", self.advices[6], offset, || *lsb.inner()) // SAFETY: This is sound because we just assigned this cell from a // range-constrained value. .map(|cell| RangeConstrained::unsound_unchecked(cell, lsb.num_bits()))?; @@ -1401,7 +1376,7 @@ impl YCanonicity { || "witness k_3", self.advices[9], offset, - || k_3.inner().ok_or(Error::Synthesis), + || *k_3.inner(), )?; lsb @@ -1586,7 +1561,7 @@ impl NoteCommitChip { } pub(in crate::circuit) mod gadgets { - use halo2_proofs::circuit::Chip; + use halo2_proofs::circuit::{Chip, Value}; 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 // the running sum at the end of it. If a_prime < 2^130, the running sum // will be 0. - let a_prime = a.value().map(|a| { - let two_pow_130 = pallas::Base::from_u128(1u128 << 65).square(); - let t_p = pallas::Base::from_u128(T_P); - a + two_pow_130 - t_p - }); + let a_prime = { + let two_pow_130 = Value::known(pallas::Base::from_u128(1u128 << 65).square()); + let t_p = Value::known(pallas::Base::from_u128(T_P)); + a.value() + two_pow_130 - t_p + }; let zs = lookup_config.witness_check( layouter.namespace(|| "Decompose low 130 bits of (a + 2^130 - t_P)"), 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, // and output the running sum at the end of it. // 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 two_pow_4 = pallas::Base::from(1u64 << 4); - let two_pow_140 = pallas::Base::from_u128(1u128 << 70).square(); - let t_p = pallas::Base::from_u128(T_P); - b_3 + (two_pow_4 * c) + two_pow_140 - t_p - }); + let b3_c_prime = { + let two_pow_4 = Value::known(pallas::Base::from(1u64 << 4)); + let two_pow_140 = Value::known(pallas::Base::from_u128(1u128 << 70).square()); + let t_p = Value::known(pallas::Base::from_u128(T_P)); + b_3.inner().value() + (two_pow_4 * c.value()) + two_pow_140 - t_p + }; let zs = lookup_config.witness_check( 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. // - 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 two_pow_4 = pallas::Base::from(1u64 << 4); - let two_pow_140 = pallas::Base::from_u128(1u128 << 70).square(); - let t_p = pallas::Base::from_u128(T_P); - e_1 + (two_pow_4 * f) + two_pow_140 - t_p - }); + let e1_f_prime = { + let two_pow_4 = Value::known(pallas::Base::from(1u64 << 4)); + let two_pow_140 = Value::known(pallas::Base::from_u128(1u128 << 70).square()); + let t_p = Value::known(pallas::Base::from_u128(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, // 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, // and output the running sum at the end of it. // 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 two_pow_9 = pallas::Base::from(1u64 << 9); - let two_pow_130 = pallas::Base::from_u128(1u128 << 65).square(); - let t_p = pallas::Base::from_u128(T_P); - g_1 + (two_pow_9 * g_2) + two_pow_130 - t_p - }); + let g1_g2_prime = { + let two_pow_9 = Value::known(pallas::Base::from(1u64 << 9)); + let two_pow_130 = Value::known(pallas::Base::from_u128(1u128 << 65).square()); + let t_p = Value::known(pallas::Base::from_u128(T_P)); + g_1.inner().value() + (two_pow_9 * g_2.value()) + two_pow_130 - t_p + }; let zs = lookup_config.witness_check( 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, mut layouter: impl Layouter, y: AssignedCell, - lsb: RangeConstrained>, + lsb: RangeConstrained>, ) -> Result>, Error> { // 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. let (j, z1_j, z13_j) = { - let j = lsb - .inner() - .value() - .zip(k_0.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 j = { + let two = Value::known(pallas::Base::from(2)); + let two_pow_10 = Value::known(pallas::Base::from(1 << 10)); + lsb.inner().value() + two * k_0.inner().value() + two_pow_10 * k_1.inner().value() + }; let zs = lookup_config.witness_check( layouter.namespace(|| "Decompose j = LSB + (2)k_0 + (2^10)k_1"), j, @@ -2069,7 +2039,7 @@ mod tests { use ff::{Field, PrimeField, PrimeFieldBits}; use group::Curve; use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, + circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; @@ -2084,12 +2054,12 @@ mod tests { fn note_commit() { #[derive(Default)] struct MyCircuit { - gd_x: Option, - gd_y_lsb: Option, - pkd_x: Option, - pkd_y_lsb: Option, - rho: Option, - psi: Option, + gd_x: Value, + gd_y_lsb: Value, + pkd_x: Value, + pkd_y_lsb: Value, + rho: Value, + psi: Value, } impl Circuit for MyCircuit { @@ -2235,7 +2205,7 @@ mod tests { assign_free_advice( layouter.namespace(|| "witness value"), note_commit_config.advices[0], - Some(value), + Value::known(value), )? }; @@ -2254,8 +2224,11 @@ mod tests { )?; let rcm = pallas::Scalar::random(OsRng); - let rcm_gadget = - ScalarFixed::new(ecc_chip.clone(), layouter.namespace(|| "rcm"), Some(rcm))?; + let rcm_gadget = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcm"), + Value::known(rcm), + )?; let cm = gadgets::note_commit( layouter.namespace(|| "Hash NoteCommit pieces"), @@ -2273,53 +2246,40 @@ mod tests { let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); // Hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi let lsb = |y_lsb: pallas::Base| y_lsb == pallas::Base::one(); - let point = domain - .commit( - iter::empty() - .chain( - self.gd_x - .unwrap() - .to_le_bits() - .iter() - .by_vals() - .take(L_ORCHARD_BASE), + let point = self + .gd_x + .zip(self.gd_y_lsb) + .zip(self.pkd_x.zip(self.pkd_y_lsb)) + .zip(self.rho.zip(self.psi)) + .map(|(((gd_x, gd_y_lsb), (pkd_x, pkd_y_lsb)), (rho, psi))| { + domain + .commit( + iter::empty() + .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()))) - .chain( - self.pkd_x - .unwrap() - .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), - )? + .unwrap() + .to_affine() + }); + NonIdentityPoint::new(ecc_chip, layouter.namespace(|| "witness cm"), point)? }; 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) // `rho` = 0, `psi` = 0 MyCircuit { - gd_x: Some(-pallas::Base::one()), - gd_y_lsb: Some(pallas::Base::one()), - pkd_x: Some(-pallas::Base::one()), - pkd_y_lsb: Some(pallas::Base::one()), - rho: Some(pallas::Base::zero()), - psi: Some(pallas::Base::zero()), + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::one()), + rho: Value::known(pallas::Base::zero()), + psi: Value::known(pallas::Base::zero()), }, // `rho` = T_Q - 1, `psi` = T_Q - 1 MyCircuit { - gd_x: Some(-pallas::Base::one()), - gd_y_lsb: Some(pallas::Base::zero()), - pkd_x: Some(-pallas::Base::one()), - pkd_y_lsb: Some(pallas::Base::zero()), - rho: Some(pallas::Base::from_u128(T_Q - 1)), - psi: Some(pallas::Base::from_u128(T_Q - 1)), + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::zero()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(pallas::Base::from_u128(T_Q - 1)), + psi: Value::known(pallas::Base::from_u128(T_Q - 1)), }, // `rho` = T_Q, `psi` = T_Q MyCircuit { - gd_x: Some(-pallas::Base::one()), - gd_y_lsb: Some(pallas::Base::one()), - pkd_x: Some(-pallas::Base::one()), - pkd_y_lsb: Some(pallas::Base::zero()), - rho: Some(pallas::Base::from_u128(T_Q)), - psi: Some(pallas::Base::from_u128(T_Q)), + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(pallas::Base::from_u128(T_Q)), + psi: Value::known(pallas::Base::from_u128(T_Q)), }, // `rho` = 2^127 - 1, `psi` = 2^127 - 1 MyCircuit { - gd_x: Some(-pallas::Base::one()), - gd_y_lsb: Some(pallas::Base::zero()), - pkd_x: Some(-pallas::Base::one()), - pkd_y_lsb: Some(pallas::Base::one()), - rho: Some(pallas::Base::from_u128((1 << 127) - 1)), - psi: Some(pallas::Base::from_u128((1 << 127) - 1)), + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::zero()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::one()), + rho: Value::known(pallas::Base::from_u128((1 << 127) - 1)), + psi: Value::known(pallas::Base::from_u128((1 << 127) - 1)), }, // `rho` = 2^127, `psi` = 2^127 MyCircuit { - gd_x: Some(-pallas::Base::one()), - gd_y_lsb: Some(pallas::Base::zero()), - pkd_x: Some(-pallas::Base::one()), - pkd_y_lsb: Some(pallas::Base::zero()), - rho: Some(pallas::Base::from_u128(1 << 127)), - psi: Some(pallas::Base::from_u128(1 << 127)), + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::zero()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(pallas::Base::from_u128(1 << 127)), + psi: Value::known(pallas::Base::from_u128(1 << 127)), }, // `rho` = 2^254 - 1, `psi` = 2^254 - 1 MyCircuit { - gd_x: Some(-pallas::Base::one()), - gd_y_lsb: Some(pallas::Base::one()), - pkd_x: Some(-pallas::Base::one()), - pkd_y_lsb: Some(pallas::Base::one()), - rho: Some(two_pow_254 - pallas::Base::one()), - psi: Some(two_pow_254 - pallas::Base::one()), + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::one()), + rho: Value::known(two_pow_254 - pallas::Base::one()), + psi: Value::known(two_pow_254 - pallas::Base::one()), }, // `rho` = 2^254, `psi` = 2^254 MyCircuit { - gd_x: Some(-pallas::Base::one()), - gd_y_lsb: Some(pallas::Base::one()), - pkd_x: Some(-pallas::Base::one()), - pkd_y_lsb: Some(pallas::Base::zero()), - rho: Some(two_pow_254), - psi: Some(two_pow_254), + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(two_pow_254), + psi: Value::known(two_pow_254), }, ];