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_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