Skip to content

Commit

Permalink
Add ECC test
Browse files Browse the repository at this point in the history
  • Loading branch information
therealyingtong committed Apr 28, 2021
1 parent 87a9d3a commit c942bb1
Showing 1 changed file with 136 additions and 0 deletions.
136 changes: 136 additions & 0 deletions src/circuit/gadget/ecc/chip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -779,3 +779,139 @@ impl<C: CurveAffine> EccInstructions<C> for EccChip<C> {
Ok(point)
}
}

#[cfg(test)]
mod tests {
use crate::constants;
use group::{Curve, Group};
use halo2::{
arithmetic::{CurveAffine, FieldExt},
circuit::layouter::SingleChipLayouter,
dev::MockProver,
pasta::pallas,
plonk::{Assignment, Circuit, ConstraintSystem, Error},
};

use super::super::EccInstructions;
use super::{EccChip, EccConfig, OrchardFixedBases};

struct MyCircuit<C: CurveAffine> {
_marker: std::marker::PhantomData<C>,
}

#[allow(non_snake_case)]
impl<C: CurveAffine> Circuit<C::Base> for MyCircuit<C> {
type Config = EccConfig;

fn configure(meta: &mut ConstraintSystem<C::Base>) -> Self::Config {
let bits = meta.advice_column();
let P = (meta.advice_column(), meta.advice_column());
let lambda = (meta.advice_column(), meta.advice_column());
let extras = [
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
];

EccChip::<C>::configure(meta, bits, P, lambda, extras)
}

fn synthesize(
&self,
cs: &mut impl Assignment<C::Base>,
config: Self::Config,
) -> Result<(), Error> {
let loaded = EccChip::<C>::load();
let chip = EccChip::construct(config, loaded);
let mut layouter = SingleChipLayouter::new(cs)?;

// Generate a random point
let point_val = C::CurveExt::random(rand::rngs::OsRng).to_affine(); // P
let point = chip.witness_point(&mut layouter, Some(point_val))?;

// Check doubled point [2]P
let real_doubled = point_val * C::Scalar::from_u64(2); // [2]P
let doubled = chip.add(&mut layouter, &point, &point)?;
if let (Some(x), Some(y)) = (doubled.x.value, doubled.y.value) {
assert_eq!(real_doubled.to_affine(), C::from_xy(x, y).unwrap());
}

let real_added = point_val * C::Scalar::from_u64(3); // [3]P

// Check incomplete addition point [3]P
{
let added = chip.add(&mut layouter, &point, &doubled)?;
if let (Some(x), Some(y)) = (added.x.value, added.y.value) {
assert_eq!(real_added.to_affine(), C::from_xy(x, y).unwrap());
}
}

// Check complete addition point [3]P
{
let added_complete = chip.add_complete(&mut layouter, &point, &doubled)?;
if let (Some(x), Some(y)) = (added_complete.x.value, added_complete.y.value) {
if C::from_xy(x, y).is_some().into() {
assert_eq!(real_added.to_affine(), C::from_xy(x, y).unwrap());
}
}
}

// Check fixed-base scalar multiplication
{
let scalar_fixed = C::Scalar::rand();
let nullifier_k = constants::nullifier_k::generator();
let base = nullifier_k.0.value();
let real_mul_fixed = base * scalar_fixed;

let scalar_fixed = chip.witness_scalar_fixed(&mut layouter, Some(scalar_fixed))?;
let nullifier_k = chip.get_fixed(OrchardFixedBases::NullifierK(nullifier_k))?;
let mul_fixed = chip.mul_fixed(&mut layouter, &scalar_fixed, &nullifier_k)?;
if let (Some(x), Some(y)) = (mul_fixed.x.value, mul_fixed.y.value) {
assert_eq!(real_mul_fixed.to_affine(), C::from_xy(x, y).unwrap());
}
}

// Check short signed fixed-base scalar multiplication
{
let scalar_fixed_short = C::Scalar::from_u64(rand::random::<u64>());
let value_commit_v = constants::value_commit_v::generator();
let real_mul_fixed_short = value_commit_v.0.value() * scalar_fixed_short;

let scalar_fixed_short =
chip.witness_scalar_fixed_short(&mut layouter, Some(scalar_fixed_short))?;
let value_commit_v =
chip.get_fixed(OrchardFixedBases::ValueCommitV(value_commit_v))?;
let mul_fixed_short =
chip.mul_fixed_short(&mut layouter, &scalar_fixed_short, &value_commit_v)?;
if let (Some(x), Some(y)) = (mul_fixed_short.x.value, mul_fixed_short.y.value) {
assert_eq!(real_mul_fixed_short.to_affine(), C::from_xy(x, y).unwrap());
}
}

// Check variable-base scalar multiplication
{
let scalar_val = C::Scalar::rand();
let real_mul = point_val * scalar_val;

let mul = chip.mul(&mut layouter, scalar_val, &point)?;
if let (Some(x), Some(y)) = (mul.x.value, mul.y.value) {
assert_eq!(real_mul.to_affine(), C::from_xy(x, y).unwrap());
}
}

Ok(())
}
}

#[test]
fn ecc() {
let k = 11;
let circuit = MyCircuit::<pallas::Affine> {
_marker: std::marker::PhantomData,
};
let prover = MockProver::run(k, &circuit, vec![]).unwrap();
assert_eq!(prover.verify(), Ok(()))
}
}

0 comments on commit c942bb1

Please sign in to comment.