note_commit.rs: Test canonicity check for different input values.

This commit is contained in:
therealyingtong 2021-06-16 17:47:58 +08:00
parent 3feda9724c
commit 84172e0326
1 changed files with 252 additions and 0 deletions

View File

@ -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(()));
}
}
}