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).
## [Unreleased]
### Changed
- Migrated to `halo2_proofs 0.2`.
## [0.1.0] - 2022-05-10
### Changed

View File

@ -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"] }

View File

@ -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(&note.rho())),
rcm_new: Some(note.rseed().rcm(&note.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(&note.rho())),
rcm_new: Value::known(note.rseed().rcm(&note.rho())),
rcv: Value::known(self.rcv),
},
)
}

View File

@ -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<u32>,
pub(crate) g_d_old: Option<NonIdentityPallasPoint>,
pub(crate) pk_d_old: Option<DiversifiedTransmissionKey>,
pub(crate) v_old: Option<NoteValue>,
pub(crate) rho_old: Option<Nullifier>,
pub(crate) psi_old: Option<pallas::Base>,
pub(crate) rcm_old: Option<NoteCommitTrapdoor>,
pub(crate) cm_old: Option<NoteCommitment>,
pub(crate) alpha: Option<pallas::Scalar>,
pub(crate) ak: Option<SpendValidatingKey>,
pub(crate) nk: Option<NullifierDerivingKey>,
pub(crate) rivk: Option<CommitIvkRandomness>,
pub(crate) g_d_new: Option<NonIdentityPallasPoint>,
pub(crate) pk_d_new: Option<DiversifiedTransmissionKey>,
pub(crate) v_new: Option<NoteValue>,
pub(crate) psi_new: Option<pallas::Base>,
pub(crate) rcm_new: Option<NoteCommitTrapdoor>,
pub(crate) rcv: Option<ValueCommitTrapdoor>,
pub(crate) path: Value<[MerkleHashOrchard; MERKLE_DEPTH_ORCHARD]>,
pub(crate) pos: Value<u32>,
pub(crate) g_d_old: Value<NonIdentityPallasPoint>,
pub(crate) pk_d_old: Value<DiversifiedTransmissionKey>,
pub(crate) v_old: Value<NoteValue>,
pub(crate) rho_old: Value<Nullifier>,
pub(crate) psi_old: Value<pallas::Base>,
pub(crate) rcm_old: Value<NoteCommitTrapdoor>,
pub(crate) cm_old: Value<NoteCommitment>,
pub(crate) alpha: Value<pallas::Scalar>,
pub(crate) ak: Value<SpendValidatingKey>,
pub(crate) nk: Value<NullifierDerivingKey>,
pub(crate) rivk: Value<CommitIvkRandomness>,
pub(crate) g_d_new: Value<NonIdentityPallasPoint>,
pub(crate) pk_d_new: Value<DiversifiedTransmissionKey>,
pub(crate) v_new: Value<NoteValue>,
pub(crate) psi_new: Value<pallas::Base>,
pub(crate) rcm_new: Value<NoteCommitTrapdoor>,
pub(crate) rcv: Value<ValueCommitTrapdoor>,
}
impl plonk::Circuit<pallas::Base> for Circuit {
@ -358,7 +358,7 @@ impl plonk::Circuit<pallas::Base> for Circuit {
)?;
// 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(
ecc_chip.clone(),
layouter.namespace(|| "witness ak_P"),
@ -408,8 +408,8 @@ impl plonk::Circuit<pallas::Base> 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)

View File

@ -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<pallas::Base, pallas::Base>,
nk: 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>>,
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>,
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},
};
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<pallas::Base>,
nk: Option<pallas::Base>,
ak: Value<pallas::Base>,
nk: Value<pallas::Base>,
}
impl UtilitiesInstructions<pallas::Base> 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),
},
];

View File

@ -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<F: FieldExt>: Chip<F> {
pub(in crate::circuit) fn assign_free_advice<F: Field, V: Copy>(
mut layouter: impl Layouter<F>,
column: Column<Advice>,
value: Option<V>,
value: Value<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),
)
},
|mut region| region.assign_advice(|| "load private", column, 0, || value),
)
}

View File

@ -74,12 +74,7 @@ impl AddInstruction<pallas::Base> 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)
},
)
}

View File

@ -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<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
RangeConstrained<pallas::Base, Option<pallas::Base>>,
RangeConstrained<pallas::Base, Option<pallas::Base>>,
RangeConstrained<pallas::Base, Value<pallas::Base>>,
RangeConstrained<pallas::Base, Value<pallas::Base>>,
RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
),
Error,
@ -170,7 +170,7 @@ impl DecomposeB {
layouter: &mut impl Layouter<pallas::Base>,
b: NoteCommitPiece,
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_3: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
) -> Result<AssignedCell<pallas::Base, pallas::Base>, 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<pallas::Base, Option<pallas::Base>>,
RangeConstrained<pallas::Base, Option<pallas::Base>>,
RangeConstrained<pallas::Base, Value<pallas::Base>>,
RangeConstrained<pallas::Base, Value<pallas::Base>>,
RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
),
Error,
@ -313,7 +308,7 @@ impl DecomposeD {
&self,
layouter: &mut impl Layouter<pallas::Base>,
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_2: RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
z1_d: AssignedCell<pallas::Base, pallas::Base>,
@ -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<pallas::Base, Option<pallas::Base>>,
RangeConstrained<pallas::Base, Value<pallas::Base>>,
RangeConstrained<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
),
Error,
@ -561,7 +551,7 @@ impl DecomposeG {
&self,
layouter: &mut impl Layouter<pallas::Base>,
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>>,
z1_g: AssignedCell<pallas::Base, pallas::Base>,
) -> Result<AssignedCell<pallas::Base, pallas::Base>, 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<pallas::Base, AssignedCell<pallas::Base, pallas::Base>>,
RangeConstrained<pallas::Base, Option<pallas::Base>>,
RangeConstrained<pallas::Base, Value<pallas::Base>>,
),
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<pallas::Base>,
h: NoteCommitPiece,
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> {
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<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_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>,
z1_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)?;
// 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<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>
{
// 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<pallas::Base>,
gd_y_lsb: Option<pallas::Base>,
pkd_x: Option<pallas::Base>,
pkd_y_lsb: Option<pallas::Base>,
rho: Option<pallas::Base>,
psi: Option<pallas::Base>,
gd_x: Value<pallas::Base>,
gd_y_lsb: Value<pallas::Base>,
pkd_x: Value<pallas::Base>,
pkd_y_lsb: Value<pallas::Base>,
rho: Value<pallas::Base>,
psi: Value<pallas::Base>,
}
impl Circuit<pallas::Base> 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),
},
];