mirror of https://github.com/zcash/halo2.git
note_commit.rs: Test canonicity check for different input values.
This commit is contained in:
parent
3feda9724c
commit
84172e0326
|
@ -1271,3 +1271,255 @@ struct GateCells {
|
||||||
z13_f: CellValue<pallas::Base>,
|
z13_f: CellValue<pallas::Base>,
|
||||||
z13_g: CellValue<pallas::Base>,
|
z13_g: CellValue<pallas::Base>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::NoteCommitConfig;
|
||||||
|
use crate::{
|
||||||
|
circuit::gadget::{
|
||||||
|
ecc::{
|
||||||
|
chip::{EccChip, EccConfig},
|
||||||
|
Point,
|
||||||
|
},
|
||||||
|
sinsemilla::chip::SinsemillaChip,
|
||||||
|
utilities::{CellValue, UtilitiesInstructions},
|
||||||
|
},
|
||||||
|
constants::T_Q,
|
||||||
|
};
|
||||||
|
|
||||||
|
use ff::Field;
|
||||||
|
use halo2::{
|
||||||
|
circuit::{Layouter, SimpleFloorPlanner},
|
||||||
|
dev::MockProver,
|
||||||
|
plonk::{Circuit, ConstraintSystem, Error},
|
||||||
|
};
|
||||||
|
use pasta_curves::{
|
||||||
|
arithmetic::{CurveAffine, FieldExt},
|
||||||
|
pallas,
|
||||||
|
};
|
||||||
|
|
||||||
|
use rand::{rngs::OsRng, RngCore};
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn note_commit() {
|
||||||
|
#[derive(Default)]
|
||||||
|
struct MyCircuit {
|
||||||
|
gd_x: Option<pallas::Base>,
|
||||||
|
pkd_x: Option<pallas::Base>,
|
||||||
|
rho: Option<pallas::Base>,
|
||||||
|
psi: Option<pallas::Base>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UtilitiesInstructions<pallas::Base> for MyCircuit {
|
||||||
|
type Var = CellValue<pallas::Base>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Circuit<pallas::Base> for MyCircuit {
|
||||||
|
type Config = (NoteCommitConfig, EccConfig);
|
||||||
|
type FloorPlanner = SimpleFloorPlanner;
|
||||||
|
|
||||||
|
fn without_witnesses(&self) -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
|
||||||
|
let advices = [
|
||||||
|
meta.advice_column(),
|
||||||
|
meta.advice_column(),
|
||||||
|
meta.advice_column(),
|
||||||
|
meta.advice_column(),
|
||||||
|
meta.advice_column(),
|
||||||
|
meta.advice_column(),
|
||||||
|
meta.advice_column(),
|
||||||
|
meta.advice_column(),
|
||||||
|
meta.advice_column(),
|
||||||
|
meta.advice_column(),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Shared fixed columns for loading constants.
|
||||||
|
// TODO: Replace with public inputs API.
|
||||||
|
let ecc_constants = [meta.fixed_column(), meta.fixed_column()];
|
||||||
|
let sinsemilla_constants = [
|
||||||
|
meta.fixed_column(),
|
||||||
|
meta.fixed_column(),
|
||||||
|
meta.fixed_column(),
|
||||||
|
meta.fixed_column(),
|
||||||
|
meta.fixed_column(),
|
||||||
|
meta.fixed_column(),
|
||||||
|
];
|
||||||
|
|
||||||
|
for advice in advices.iter() {
|
||||||
|
meta.enable_equality((*advice).into());
|
||||||
|
}
|
||||||
|
for fixed in ecc_constants.iter() {
|
||||||
|
meta.enable_equality((*fixed).into());
|
||||||
|
}
|
||||||
|
for fixed in sinsemilla_constants.iter() {
|
||||||
|
meta.enable_equality((*fixed).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let table_idx = meta.fixed_column();
|
||||||
|
let lookup = (table_idx, meta.fixed_column(), meta.fixed_column());
|
||||||
|
let sinsemilla_config = SinsemillaChip::configure(
|
||||||
|
meta,
|
||||||
|
advices[..5].try_into().unwrap(),
|
||||||
|
lookup,
|
||||||
|
sinsemilla_constants,
|
||||||
|
);
|
||||||
|
let note_commit_config =
|
||||||
|
NoteCommitConfig::configure(meta, advices, sinsemilla_config);
|
||||||
|
|
||||||
|
let ecc_config = EccChip::configure(meta, advices, table_idx, ecc_constants);
|
||||||
|
|
||||||
|
(note_commit_config, ecc_config)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn synthesize(
|
||||||
|
&self,
|
||||||
|
config: Self::Config,
|
||||||
|
mut layouter: impl Layouter<pallas::Base>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let (note_commit_config, ecc_config) = config;
|
||||||
|
|
||||||
|
// Load the Sinsemilla generator lookup table used by the whole circuit.
|
||||||
|
SinsemillaChip::load(note_commit_config.sinsemilla_config.clone(), &mut layouter)?;
|
||||||
|
|
||||||
|
// Construct a Sinsemilla chip
|
||||||
|
let sinsemilla_chip =
|
||||||
|
SinsemillaChip::construct(note_commit_config.sinsemilla_config.clone());
|
||||||
|
|
||||||
|
// Construct an ECC chip
|
||||||
|
let ecc_chip = EccChip::construct(ecc_config);
|
||||||
|
|
||||||
|
// Witness g_d
|
||||||
|
let g_d = {
|
||||||
|
let g_d = self.gd_x.map(|x| {
|
||||||
|
// Calculate y = (x^3 + 5).sqrt()
|
||||||
|
let y = (x.square() * x + pallas::Affine::b()).sqrt().unwrap();
|
||||||
|
pallas::Affine::from_xy(x, y).unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
Point::new(ecc_chip.clone(), layouter.namespace(|| "witness g_d"), g_d)?
|
||||||
|
};
|
||||||
|
|
||||||
|
// Witness pk_d
|
||||||
|
let pk_d = {
|
||||||
|
let pk_d = self.pkd_x.map(|x| {
|
||||||
|
// Calculate y = (x^3 + 5).sqrt()
|
||||||
|
let y = (x.square() * x + pallas::Affine::b()).sqrt().unwrap();
|
||||||
|
pallas::Affine::from_xy(x, y).unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
Point::new(
|
||||||
|
ecc_chip.clone(),
|
||||||
|
layouter.namespace(|| "witness pk_d"),
|
||||||
|
pk_d,
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
|
// Witness a random non-negative u64 note value
|
||||||
|
// A note value cannot be negative.
|
||||||
|
let value = {
|
||||||
|
let mut rng = OsRng;
|
||||||
|
let value = pallas::Base::from_u64(rng.next_u64());
|
||||||
|
self.load_private(
|
||||||
|
layouter.namespace(|| "witness value"),
|
||||||
|
note_commit_config.advices[0],
|
||||||
|
Some(value),
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
|
// Witness rho
|
||||||
|
let rho = self.load_private(
|
||||||
|
layouter.namespace(|| "witness rho"),
|
||||||
|
note_commit_config.advices[0],
|
||||||
|
self.rho,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Witness psi
|
||||||
|
let psi = self.load_private(
|
||||||
|
layouter.namespace(|| "witness psi"),
|
||||||
|
note_commit_config.advices[0],
|
||||||
|
self.psi,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let rcm = Some(pallas::Scalar::rand());
|
||||||
|
|
||||||
|
let _cm = note_commit_config.assign_region(
|
||||||
|
layouter.namespace(|| "Hash NoteCommit pieces"),
|
||||||
|
sinsemilla_chip,
|
||||||
|
ecc_chip,
|
||||||
|
g_d.inner(),
|
||||||
|
pk_d.inner(),
|
||||||
|
value,
|
||||||
|
rho,
|
||||||
|
psi,
|
||||||
|
rcm,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let two_pow_254 = pallas::Base::from_u128(1 << 127).square();
|
||||||
|
// Test different values of `ak`, `nk`
|
||||||
|
let circuits = [
|
||||||
|
// `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()),
|
||||||
|
pkd_x: Some(-pallas::Base::one()),
|
||||||
|
rho: Some(pallas::Base::zero()),
|
||||||
|
psi: Some(pallas::Base::zero()),
|
||||||
|
},
|
||||||
|
// `rho` = T_Q - 1, `psi` = T_Q - 1
|
||||||
|
MyCircuit {
|
||||||
|
gd_x: Some(-pallas::Base::one()),
|
||||||
|
pkd_x: Some(-pallas::Base::one()),
|
||||||
|
rho: Some(pallas::Base::from_u128(T_Q - 1)),
|
||||||
|
psi: Some(pallas::Base::from_u128(T_Q - 1)),
|
||||||
|
},
|
||||||
|
// `rho` = T_Q, `psi` = T_Q
|
||||||
|
MyCircuit {
|
||||||
|
gd_x: Some(-pallas::Base::one()),
|
||||||
|
pkd_x: Some(-pallas::Base::one()),
|
||||||
|
rho: Some(pallas::Base::from_u128(T_Q)),
|
||||||
|
psi: Some(pallas::Base::from_u128(T_Q)),
|
||||||
|
},
|
||||||
|
// `rho` = 2^127 - 1, `psi` = 2^127 - 1
|
||||||
|
MyCircuit {
|
||||||
|
gd_x: Some(-pallas::Base::one()),
|
||||||
|
pkd_x: Some(-pallas::Base::one()),
|
||||||
|
rho: Some(pallas::Base::from_u128((1 << 127) - 1)),
|
||||||
|
psi: Some(pallas::Base::from_u128((1 << 127) - 1)),
|
||||||
|
},
|
||||||
|
// `rho` = 2^127, `psi` = 2^127
|
||||||
|
MyCircuit {
|
||||||
|
gd_x: Some(-pallas::Base::one()),
|
||||||
|
pkd_x: Some(-pallas::Base::one()),
|
||||||
|
rho: Some(pallas::Base::from_u128(1 << 127)),
|
||||||
|
psi: Some(pallas::Base::from_u128(1 << 127)),
|
||||||
|
},
|
||||||
|
// `rho` = 2^254 - 1, `psi` = 2^254 - 1
|
||||||
|
MyCircuit {
|
||||||
|
gd_x: Some(-pallas::Base::one()),
|
||||||
|
pkd_x: Some(-pallas::Base::one()),
|
||||||
|
rho: Some(two_pow_254 - pallas::Base::one()),
|
||||||
|
psi: Some(two_pow_254 - pallas::Base::one()),
|
||||||
|
},
|
||||||
|
// `rho` = 2^254, `psi` = 2^254
|
||||||
|
MyCircuit {
|
||||||
|
gd_x: Some(-pallas::Base::one()),
|
||||||
|
pkd_x: Some(-pallas::Base::one()),
|
||||||
|
rho: Some(two_pow_254),
|
||||||
|
psi: Some(two_pow_254),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for circuit in circuits.iter() {
|
||||||
|
let prover = MockProver::<pallas::Base>::run(11, circuit, vec![]).unwrap();
|
||||||
|
assert_eq!(prover.verify(), Ok(()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue