Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upstream Diff, for reference only. #18

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,10 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: tarpaulin
# Extend the timeout to 3600 to ensure the code coverage test pass
args: >
${{ steps.prepare.outputs.feature-flags }}
--timeout 600
--timeout 3600
--out Xml
- name: Upload coverage to Codecov
uses: codecov/[email protected]
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

144 changes: 126 additions & 18 deletions halo2_gadgets/src/ecc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::fmt::Debug;

use halo2_proofs::{
arithmetic::CurveAffine,
circuit::{Chip, Layouter, Value},
circuit::{AssignedCell, Chip, Layouter, Value},
plonk::Error,
};

Expand Down Expand Up @@ -60,6 +60,15 @@ pub trait EccInstructions<C: CurveAffine>:
value: Value<C>,
) -> Result<Self::Point, Error>;

/// Witnesses the given constant point as a private input to the circuit.
/// This allows the point to be the identity, mapped to (0, 0) in
/// affine coordinates.
fn witness_point_from_constant(
&self,
layouter: &mut impl Layouter<C::Base>,
value: C,
) -> Result<Self::Point, Error>;

/// Witnesses the given point as a private input to the circuit.
/// This returns an error if the point is the identity.
fn witness_point_non_id(
Expand Down Expand Up @@ -111,6 +120,15 @@ pub trait EccInstructions<C: CurveAffine>:
b: &B,
) -> Result<Self::Point, Error>;

/// Performs variable-base sign-scalar multiplication, returning `[sign] point`
/// `sign` must be in {-1, 1}.
fn mul_sign(
&self,
layouter: &mut impl Layouter<C::Base>,
sign: &AssignedCell<C::Base, C::Base>,
point: &Self::Point,
) -> Result<Self::Point, Error>;

/// Performs variable-base scalar multiplication, returning `[scalar] base`.
fn mul(
&self,
Expand Down Expand Up @@ -390,6 +408,17 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> Point<C,
point.map(|inner| Point { chip, inner })
}

/// Witnesses the given constant point as a private input to the circuit.
/// This allows the point to be the identity, mapped to (0, 0) in affine coordinates.
pub fn new_from_constant(
chip: EccChip,
mut layouter: impl Layouter<C::Base>,
value: C,
) -> Result<Self, Error> {
let point = chip.witness_point_from_constant(&mut layouter, value);
point.map(|inner| Point { chip, inner })
}

/// Constrains this point to be equal in value to another point.
pub fn constrain_equal<Other: Into<Point<C, EccChip>> + Clone>(
&self,
Expand Down Expand Up @@ -432,6 +461,21 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> Point<C,
inner,
})
}

/// Returns `[sign] self`.
/// `sign` must be in {-1, 1}.
pub fn mul_sign(
&self,
mut layouter: impl Layouter<C::Base>,
sign: &AssignedCell<C::Base, C::Base>,
) -> Result<Point<C, EccChip>, Error> {
self.chip
.mul_sign(&mut layouter, sign, &self.inner)
.map(|point| Point {
chip: self.chip.clone(),
inner: point,
})
}
}

/// The affine short Weierstrass x-coordinate of a point on a specific elliptic curve.
Expand Down Expand Up @@ -579,14 +623,7 @@ impl<C: CurveAffine, EccChip: EccInstructions<C>> FixedPointShort<C, EccChip> {
pub(crate) mod tests {
use ff::PrimeField;
use group::{prime::PrimeCurveAffine, Curve, Group};

use halo2_proofs::{
circuit::{Layouter, SimpleFloorPlanner, Value},
dev::MockProver,
plonk::{Circuit, ConstraintSystem, Error},
};
use lazy_static::lazy_static;
use pasta_curves::pallas;
use std::marker::PhantomData;

use super::{
chip::{
Expand All @@ -595,7 +632,19 @@ pub(crate) mod tests {
},
FixedPoints,
};
use crate::utilities::lookup_range_check::LookupRangeCheckConfig;
use crate::{
tests::test_utils::test_against_stored_circuit,
utilities::lookup_range_check::{
PallasLookupRangeCheck, PallasLookupRangeCheck4_5BConfig, PallasLookupRangeCheckConfig,
},
};
use halo2_proofs::{
circuit::{Layouter, SimpleFloorPlanner, Value},
dev::MockProver,
plonk::{Circuit, ConstraintSystem, Error},
};
use lazy_static::lazy_static;
use pasta_curves::pallas;

#[derive(Debug, Eq, PartialEq, Clone)]
pub(crate) struct TestFixedBases;
Expand Down Expand Up @@ -723,17 +772,27 @@ pub(crate) mod tests {
type Base = BaseField;
}

struct MyCircuit {
struct EccCircuit<Lookup: PallasLookupRangeCheck> {
test_errors: bool,
_lookup_marker: PhantomData<Lookup>,
}

impl<Lookup: PallasLookupRangeCheck> EccCircuit<Lookup> {
fn new(test_errors: bool) -> Self {
Self {
test_errors,
_lookup_marker: PhantomData,
}
}
}

#[allow(non_snake_case)]
impl Circuit<pallas::Base> for MyCircuit {
type Config = EccConfig<TestFixedBases>;
impl<Lookup: PallasLookupRangeCheck> Circuit<pallas::Base> for EccCircuit<Lookup> {
type Config = EccConfig<TestFixedBases, Lookup>;
type FloorPlanner = SimpleFloorPlanner;

fn without_witnesses(&self) -> Self {
MyCircuit { test_errors: false }
EccCircuit::new(false)
}

fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
Expand Down Expand Up @@ -764,8 +823,13 @@ pub(crate) mod tests {
let constants = meta.fixed_column();
meta.enable_constant(constants);

let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup_table);
EccChip::<TestFixedBases>::configure(meta, advices, lagrange_coeffs, range_check)
let range_check = Lookup::configure(meta, advices[9], lookup_table);
EccChip::<TestFixedBases, Lookup>::configure(
meta,
advices,
lagrange_coeffs,
range_check,
)
}

fn synthesize(
Expand Down Expand Up @@ -865,6 +929,14 @@ pub(crate) mod tests {
)?;
}

// Test variable-base sign-scalar multiplication
{
super::chip::mul_fixed::short::tests::test_mul_sign(
chip.clone(),
layouter.namespace(|| "variable-base sign-scalar mul"),
)?;
}

// Test full-width fixed-base scalar multiplication
{
super::chip::mul_fixed::full_width::tests::test_mul_fixed(
Expand Down Expand Up @@ -896,11 +968,17 @@ pub(crate) mod tests {
#[test]
fn ecc_chip() {
let k = 13;
let circuit = MyCircuit { test_errors: true };
let circuit = EccCircuit::<PallasLookupRangeCheckConfig>::new(true);
let prover = MockProver::run(k, &circuit, vec![]).unwrap();
assert_eq!(prover.verify(), Ok(()))
}

#[test]
fn test_ecc_chip_against_stored_circuit() {
let circuit = EccCircuit::<PallasLookupRangeCheckConfig>::new(false);
test_against_stored_circuit(circuit, "ecc_chip", 3872);
}

#[cfg(feature = "test-dev-graph")]
#[test]
fn print_ecc_chip() {
Expand All @@ -910,7 +988,37 @@ pub(crate) mod tests {
root.fill(&WHITE).unwrap();
let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap();

let circuit = MyCircuit { test_errors: false };
let circuit = EccCircuit::<PallasLookupRangeCheckConfig>::new(false);
halo2_proofs::dev::CircuitLayout::default()
.render(13, &circuit, &root)
.unwrap();
}

#[test]
fn ecc_chip_4_5b() {
let k = 13;
let circuit = EccCircuit::<PallasLookupRangeCheck4_5BConfig>::new(true);
let prover = MockProver::run(k, &circuit, vec![]).unwrap();

assert_eq!(prover.verify(), Ok(()))
}

#[test]
fn test_against_stored_ecc_chip_4_5b() {
let circuit = EccCircuit::<PallasLookupRangeCheck4_5BConfig>::new(false);
test_against_stored_circuit(circuit, "ecc_chip_4_5b", 3968);
}

#[cfg(feature = "test-dev-graph")]
#[test]
fn print_ecc_chip_4_5b() {
use plotters::prelude::*;

let root = BitMapBackend::new("ecc-chip-4_5b-layout.png", (1024, 7680)).into_drawing_area();
root.fill(&WHITE).unwrap();
let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap();

let circuit = EccCircuit::<PallasLookupRangeCheck4_5BConfig>::new(false);
halo2_proofs::dev::CircuitLayout::default()
.render(13, &circuit, &root)
.unwrap();
Expand Down
Loading
Loading