mul_fixed::*::tests: Witness expected point and constrain result to be equal.

This commit is contained in:
therealyingtong 2021-07-08 15:06:47 +08:00
parent 22ec16f129
commit e2ea443fad
4 changed files with 246 additions and 113 deletions

View File

@ -544,7 +544,6 @@ mod tests {
super::chip::mul_fixed::full_width::tests::test_mul_fixed(
chip.clone(),
layouter.namespace(|| "full-width fixed-base scalar mul"),
&zero,
)?;
}
@ -553,7 +552,6 @@ mod tests {
super::chip::mul_fixed::short::tests::test_mul_fixed_short(
chip.clone(),
layouter.namespace(|| "signed short fixed-base scalar mul"),
&zero,
)?;
}
@ -562,7 +560,6 @@ mod tests {
super::chip::mul_fixed::base_field_elem::tests::test_mul_fixed_base_field(
chip,
layouter.namespace(|| "fixed-base scalar mul with base field element"),
&zero,
)?;
}

View File

@ -494,6 +494,7 @@ impl Config {
#[cfg(test)]
pub mod tests {
use group::Curve;
use halo2::{
circuit::{Chip, Layouter},
plonk::Error,
@ -512,7 +513,6 @@ pub mod tests {
pub fn test_mul_fixed_base_field(
chip: EccChip,
mut layouter: impl Layouter<pallas::Base>,
zero: &Point<pallas::Affine, EccChip>,
) -> Result<(), Error> {
impl UtilitiesInstructions<pallas::Base> for EccChip {
type Var = CellValue<pallas::Base>;
@ -520,52 +520,47 @@ pub mod tests {
// commit_ivk_r
let commit_ivk_r = OrchardFixedBasesFull::CommitIvkR;
let commit_ivk_r = FixedPoint::from_inner(chip.clone(), commit_ivk_r);
test_single_base(
chip.clone(),
layouter.namespace(|| "commit_ivk_r"),
commit_ivk_r,
zero,
FixedPoint::from_inner(chip.clone(), commit_ivk_r),
commit_ivk_r.generator(),
)?;
// note_commit_r
let note_commit_r = OrchardFixedBasesFull::NoteCommitR;
let note_commit_r = FixedPoint::from_inner(chip.clone(), note_commit_r);
test_single_base(
chip.clone(),
layouter.namespace(|| "note_commit_r"),
note_commit_r,
zero,
FixedPoint::from_inner(chip.clone(), note_commit_r),
note_commit_r.generator(),
)?;
// nullifier_k
let nullifier_k = OrchardFixedBasesFull::NullifierK;
let nullifier_k = FixedPoint::from_inner(chip.clone(), nullifier_k);
test_single_base(
chip.clone(),
layouter.namespace(|| "nullifier_k"),
nullifier_k,
zero,
FixedPoint::from_inner(chip.clone(), nullifier_k),
nullifier_k.generator(),
)?;
// value_commit_r
let value_commit_r = OrchardFixedBasesFull::ValueCommitR;
let value_commit_r = FixedPoint::from_inner(chip.clone(), value_commit_r);
test_single_base(
chip.clone(),
layouter.namespace(|| "value_commit_r"),
value_commit_r,
zero,
FixedPoint::from_inner(chip.clone(), value_commit_r),
value_commit_r.generator(),
)?;
// spend_auth_g
let spend_auth_g = OrchardFixedBasesFull::SpendAuthG;
let spend_auth_g = FixedPoint::from_inner(chip.clone(), spend_auth_g);
test_single_base(
chip,
chip.clone(),
layouter.namespace(|| "spend_auth_g"),
spend_auth_g,
zero,
FixedPoint::from_inner(chip, spend_auth_g),
spend_auth_g.generator(),
)?;
Ok(())
@ -576,20 +571,44 @@ pub mod tests {
chip: EccChip,
mut layouter: impl Layouter<pallas::Base>,
base: FixedPoint<pallas::Affine, EccChip>,
zero: &Point<pallas::Affine, EccChip>,
base_val: pallas::Affine,
) -> Result<(), Error> {
let column = chip.config().advices[0];
fn constrain_equal(
chip: EccChip,
mut layouter: impl Layouter<pallas::Base>,
base_val: pallas::Affine,
scalar_val: pallas::Base,
result: Point<pallas::Affine, EccChip>,
) -> Result<(), Error> {
// Case scalar from base field into scalar field
let scalar = pallas::Scalar::from_bytes(&scalar_val.to_bytes()).unwrap();
let expected = Point::new(
chip,
layouter.namespace(|| "expected point"),
Some((base_val * scalar).to_affine()),
)?;
result.constrain_equal(layouter.namespace(|| "constrain result"), &expected)
}
// [a]B
{
let scalar_fixed = pallas::Base::rand();
let result = {
let scalar_fixed = chip.load_private(
layouter.namespace(|| "witness random base field element"),
layouter.namespace(|| "random base field element"),
column,
Some(scalar_fixed),
)?;
base.mul_base_field_elem(layouter.namespace(|| "mul"), scalar_fixed)?;
base.mul_base_field_elem(layouter.namespace(|| "random [a]B"), scalar_fixed)?
};
constrain_equal(
chip.clone(),
layouter.namespace(|| "random [a]B"),
base_val,
scalar_fixed,
result,
)?;
}
// There is a single canonical sequence of window values for which a doubling occurs on the last step:
@ -603,39 +622,56 @@ pub mod tests {
.fold(pallas::Base::zero(), |acc, c| {
acc * &h + &pallas::Base::from_u64(c.to_digit(8).unwrap().into())
});
let result = {
let scalar_fixed = chip.load_private(
layouter.namespace(|| "mul with double"),
column,
Some(scalar_fixed),
)?;
base.mul_base_field_elem(layouter.namespace(|| "mul with double"), scalar_fixed)?;
base.mul_base_field_elem(layouter.namespace(|| "mul with double"), scalar_fixed)?
};
constrain_equal(
chip.clone(),
layouter.namespace(|| "mul with double"),
base_val,
scalar_fixed,
result,
)?;
}
// [0]B should return (0,0) since it uses complete addition
// on the last step.
{
let scalar_fixed = pallas::Base::zero();
let scalar_fixed = chip.load_private(
let result = {
let scalar_fixed =
chip.load_private(layouter.namespace(|| "zero"), column, Some(scalar_fixed))?;
base.mul_base_field_elem(layouter.namespace(|| "mul by zero"), scalar_fixed)?
};
constrain_equal(
chip.clone(),
layouter.namespace(|| "mul by zero"),
column,
Some(scalar_fixed),
base_val,
scalar_fixed,
result,
)?;
let result =
base.mul_base_field_elem(layouter.namespace(|| "mul by zero"), scalar_fixed)?;
result.constrain_equal(layouter.namespace(|| "[0]B = 𝒪"), zero)?;
}
// [-1]B is the largest base field element
{
let scalar_fixed = -pallas::Base::one();
let scalar_fixed = chip.load_private(
let result = {
let scalar_fixed =
chip.load_private(layouter.namespace(|| "-1"), column, Some(scalar_fixed))?;
base.mul_base_field_elem(layouter.namespace(|| "mul by -1"), scalar_fixed)?
};
constrain_equal(
chip,
layouter.namespace(|| "mul by -1"),
column,
Some(scalar_fixed),
base_val,
scalar_fixed,
result,
)?;
base.mul_base_field_elem(layouter.namespace(|| "mul by -1"), scalar_fixed)?;
}
Ok(())

View File

@ -66,7 +66,7 @@ impl<const NUM_WINDOWS: usize> Config<NUM_WINDOWS> {
#[cfg(test)]
pub mod tests {
use ff::PrimeFieldBits;
use group::Curve;
use halo2::{circuit::Layouter, plonk::Error};
use pasta_curves::{arithmetic::FieldExt, pallas};
@ -79,56 +79,50 @@ pub mod tests {
pub fn test_mul_fixed(
chip: EccChip,
mut layouter: impl Layouter<pallas::Base>,
zero: &Point<pallas::Affine, EccChip>,
) -> Result<(), Error> {
// commit_ivk_r
let commit_ivk_r = OrchardFixedBasesFull::CommitIvkR;
let commit_ivk_r = FixedPoint::from_inner(chip.clone(), commit_ivk_r);
test_single_base(
chip.clone(),
layouter.namespace(|| "commit_ivk_r"),
commit_ivk_r,
zero,
FixedPoint::from_inner(chip.clone(), commit_ivk_r),
commit_ivk_r.generator(),
)?;
// note_commit_r
let note_commit_r = OrchardFixedBasesFull::NoteCommitR;
let note_commit_r = FixedPoint::from_inner(chip.clone(), note_commit_r);
test_single_base(
chip.clone(),
layouter.namespace(|| "note_commit_r"),
note_commit_r,
zero,
FixedPoint::from_inner(chip.clone(), note_commit_r),
note_commit_r.generator(),
)?;
// nullifier_k
let nullifier_k = OrchardFixedBasesFull::NullifierK;
let nullifier_k = FixedPoint::from_inner(chip.clone(), nullifier_k);
test_single_base(
chip.clone(),
layouter.namespace(|| "nullifier_k"),
nullifier_k,
zero,
FixedPoint::from_inner(chip.clone(), nullifier_k),
nullifier_k.generator(),
)?;
// value_commit_r
let value_commit_r = OrchardFixedBasesFull::ValueCommitR;
let value_commit_r = FixedPoint::from_inner(chip.clone(), value_commit_r);
test_single_base(
chip.clone(),
layouter.namespace(|| "value_commit_r"),
value_commit_r,
zero,
FixedPoint::from_inner(chip.clone(), value_commit_r),
value_commit_r.generator(),
)?;
// spend_auth_g
let spend_auth_g = OrchardFixedBasesFull::SpendAuthG;
let spend_auth_g = FixedPoint::from_inner(chip.clone(), spend_auth_g);
test_single_base(
chip,
chip.clone(),
layouter.namespace(|| "spend_auth_g"),
spend_auth_g,
zero,
FixedPoint::from_inner(chip, spend_auth_g),
spend_auth_g.generator(),
)?;
Ok(())
@ -139,22 +133,43 @@ pub mod tests {
chip: EccChip,
mut layouter: impl Layouter<pallas::Base>,
base: FixedPoint<pallas::Affine, EccChip>,
zero: &Point<pallas::Affine, EccChip>,
) -> Result<(), Error>
where
pallas::Scalar: PrimeFieldBits,
{
base_val: pallas::Affine,
) -> Result<(), Error> {
fn constrain_equal(
chip: EccChip,
mut layouter: impl Layouter<pallas::Base>,
base_val: pallas::Affine,
scalar_val: pallas::Scalar,
result: Point<pallas::Affine, EccChip>,
) -> Result<(), Error> {
let expected = Point::new(
chip,
layouter.namespace(|| "expected point"),
Some((base_val * scalar_val).to_affine()),
)?;
result.constrain_equal(layouter.namespace(|| "constrain result"), &expected)
}
// [a]B
{
let scalar_fixed = pallas::Scalar::rand();
let result = {
let scalar_fixed = ScalarFixed::new(
chip.clone(),
layouter.namespace(|| "ScalarFixed"),
layouter.namespace(|| "random scalar"),
Some(scalar_fixed),
)?;
base.mul(layouter.namespace(|| "random [a]B"), &scalar_fixed)?
};
base.mul(layouter.namespace(|| "mul"), &scalar_fixed)?;
constrain_equal(
chip.clone(),
layouter.namespace(|| "random [a]B"),
base_val,
scalar_fixed,
result,
)?;
}
// There is a single canonical sequence of window values for which a doubling occurs on the last step:
@ -168,38 +183,63 @@ pub mod tests {
.fold(pallas::Scalar::zero(), |acc, c| {
acc * &h + &pallas::Scalar::from_u64(c.to_digit(8).unwrap().into())
});
let result = {
let scalar_fixed = ScalarFixed::new(
chip.clone(),
layouter.namespace(|| "ScalarFixed"),
layouter.namespace(|| "mul with double"),
Some(scalar_fixed),
)?;
base.mul(layouter.namespace(|| "mul with double"), &scalar_fixed)?
};
base.mul(layouter.namespace(|| "mul with double"), &scalar_fixed)?;
constrain_equal(
chip.clone(),
layouter.namespace(|| "mul with double"),
base_val,
scalar_fixed,
result,
)?;
}
// [0]B should return (0,0) since it uses complete addition
// on the last step.
{
let scalar_fixed = pallas::Scalar::zero();
let result = {
let scalar_fixed = ScalarFixed::new(
chip.clone(),
layouter.namespace(|| "ScalarFixed"),
layouter.namespace(|| "zero"),
Some(scalar_fixed),
)?;
let result = base.mul(layouter.namespace(|| "mul by zero"), &scalar_fixed)?;
result.constrain_equal(layouter.namespace(|| "[0]B = 𝒪"), zero)?;
base.mul(layouter.namespace(|| "mul by zero"), &scalar_fixed)?
};
constrain_equal(
chip.clone(),
layouter.namespace(|| "mul by zero"),
base_val,
scalar_fixed,
result,
)?;
}
// [-1]B is the largest scalar field element.
{
let scalar_fixed = -pallas::Scalar::one();
let result = {
let scalar_fixed = ScalarFixed::new(
chip,
layouter.namespace(|| "ScalarFixed"),
chip.clone(),
layouter.namespace(|| "-1"),
Some(scalar_fixed),
)?;
base.mul(layouter.namespace(|| "mul by -1"), &scalar_fixed)?;
base.mul(layouter.namespace(|| "mul by -1"), &scalar_fixed)?
};
constrain_equal(
chip,
layouter.namespace(|| "mul by -1"),
base_val,
scalar_fixed,
result,
)?;
}
Ok(())

View File

@ -164,7 +164,7 @@ impl<const NUM_WINDOWS: usize> Config<NUM_WINDOWS> {
#[cfg(test)]
pub mod tests {
use ff::PrimeFieldBits;
use group::Curve;
use halo2::{circuit::Layouter, plonk::Error};
use pasta_curves::{arithmetic::FieldExt, pallas};
@ -175,26 +175,46 @@ pub mod tests {
pub fn test_mul_fixed_short(
chip: EccChip,
mut layouter: impl Layouter<pallas::Base>,
zero: &Point<pallas::Affine, EccChip>,
) -> Result<(), Error>
where
pallas::Scalar: PrimeFieldBits,
{
) -> Result<(), Error> {
// value_commit_v
let value_commit_v = ValueCommitV::get();
let base_val = value_commit_v.generator;
let value_commit_v = FixedPointShort::from_inner(chip.clone(), value_commit_v);
fn constrain_equal(
chip: EccChip,
mut layouter: impl Layouter<pallas::Base>,
base_val: pallas::Affine,
scalar_val: pallas::Scalar,
result: Point<pallas::Affine, EccChip>,
) -> Result<(), Error> {
let expected = Point::new(
chip,
layouter.namespace(|| "expected point"),
Some((base_val * scalar_val).to_affine()),
)?;
result.constrain_equal(layouter.namespace(|| "constrain result"), &expected)
}
// [0]B should return (0,0) since it uses complete addition
// on the last step.
{
let scalar_fixed = pallas::Scalar::zero();
let result = {
let scalar_fixed = ScalarFixedShort::new(
chip.clone(),
layouter.namespace(|| "ScalarFixedShort"),
layouter.namespace(|| "zero"),
Some(scalar_fixed),
)?;
let result = value_commit_v.mul(layouter.namespace(|| "mul by zero"), &scalar_fixed)?;
result.constrain_equal(layouter.namespace(|| "[0]B = 𝒪"), zero)?;
value_commit_v.mul(layouter.namespace(|| "mul by zero"), &scalar_fixed)?
};
constrain_equal(
chip.clone(),
layouter.namespace(|| "mul by zero"),
base_val,
scalar_fixed,
result,
)?;
}
// Random [a]B
@ -206,36 +226,64 @@ pub mod tests {
}
let scalar_fixed_short = sign * &scalar_fixed_short;
let result = {
let scalar_fixed_short = ScalarFixedShort::new(
chip.clone(),
layouter.namespace(|| "ScalarFixedShort"),
layouter.namespace(|| "random short scalar"),
Some(scalar_fixed_short),
)?;
value_commit_v.mul(layouter.namespace(|| "mul fixed"), &scalar_fixed_short)?;
value_commit_v.mul(layouter.namespace(|| "random [a]B"), &scalar_fixed_short)?
};
constrain_equal(
chip.clone(),
layouter.namespace(|| "random [a]B"),
base_val,
scalar_fixed_short,
result,
)?;
}
// [2^64 - 1]B
{
let scalar_fixed_short = pallas::Scalar::from_u64(0xFFFF_FFFF_FFFF_FFFFu64);
let result = {
let scalar_fixed_short = ScalarFixedShort::new(
chip.clone(),
layouter.namespace(|| "ScalarFixedShort"),
layouter.namespace(|| "2^64 - 1"),
Some(scalar_fixed_short),
)?;
value_commit_v.mul(layouter.namespace(|| "mul fixed"), &scalar_fixed_short)?;
value_commit_v.mul(layouter.namespace(|| "[2^64 - 1]B"), &scalar_fixed_short)?
};
constrain_equal(
chip.clone(),
layouter.namespace(|| "[2^64 - 1]B"),
base_val,
scalar_fixed_short,
result,
)?;
}
// [-(2^64 - 1)]B
{
let scalar_fixed_short = -pallas::Scalar::from_u64(0xFFFF_FFFF_FFFF_FFFFu64);
let result = {
let scalar_fixed_short = ScalarFixedShort::new(
chip.clone(),
layouter.namespace(|| "ScalarFixedShort"),
layouter.namespace(|| "-(2^64 - 1)"),
Some(scalar_fixed_short),
)?;
value_commit_v.mul(layouter.namespace(|| "mul fixed"), &scalar_fixed_short)?;
value_commit_v.mul(layouter.namespace(|| "[-(2^64 - 1)]B"), &scalar_fixed_short)?
};
constrain_equal(
chip.clone(),
layouter.namespace(|| "[-2^64 - 1]B"),
base_val,
scalar_fixed_short,
result,
)?;
}
// There is a single canonical sequence of window values for which a doubling occurs on the last step:
@ -244,12 +292,24 @@ pub mod tests {
{
let scalar_fixed_short = pallas::Scalar::from_u64(0xB6DB_6DB6_DB6D_B6DCu64);
let result = {
let scalar_fixed_short = ScalarFixedShort::new(
chip,
layouter.namespace(|| "ScalarFixedShort"),
chip.clone(),
layouter.namespace(|| "mul with double"),
Some(scalar_fixed_short),
)?;
value_commit_v.mul(layouter.namespace(|| "mul fixed"), &scalar_fixed_short)?;
value_commit_v.mul(
layouter.namespace(|| "mul with double"),
&scalar_fixed_short,
)?
};
constrain_equal(
chip,
layouter.namespace(|| "mul with double"),
base_val,
scalar_fixed_short,
result,
)?;
}
Ok(())