//! Gadgets for elliptic curve operations. use std::fmt; use halo2::{ arithmetic::CurveAffine, circuit::{Chip, Layouter}, plonk::Error, }; /// Trait allowing circuit's fixed points to be enumerated. pub trait FixedPoints: Clone + fmt::Debug {} /// The set of circuit instructions required to use the ECC gadgets. pub trait EccInstructions: Chip { /// Variable representing an element of the elliptic curve's scalar field. type Scalar: Clone + fmt::Debug; /// Variable representing an elliptic curve point. type Point: Clone + fmt::Debug; /// Variable representing the set of fixed bases in the circuit. type FixedPoints: FixedPoints; /// Variable representing a fixed elliptic curve point (constant in the circuit). type FixedPoint: Clone + fmt::Debug; /// Witnesses the given scalar as a private input to the circuit. fn witness_scalar( layouter: &mut impl Layouter, value: Option, ) -> Result; /// Witnesses the given point as a private input to the circuit. fn witness_point( layouter: &mut impl Layouter, value: Option, ) -> Result; /// Gets a fixed point into the circuit. fn get_fixed( layouter: &mut impl Layouter, fixed_points: Self::FixedPoints, ) -> Result; /// Performs point addition, returning `a + b`. fn add( layouter: &mut impl Layouter, a: &Self::Point, b: &Self::Point, ) -> Result; /// Performs point doubling, returning `[2] a`. fn double(layouter: &mut impl Layouter, a: &Self::Point) -> Result; /// Performs variable-base scalar multiplication, returning `[scalar] base`. fn mul( layouter: &mut impl Layouter, scalar: &Self::Scalar, base: &Self::Point, ) -> Result; /// Performs fixed-base scalar multiplication, returning `[scalar] base`. fn mul_fixed( layouter: &mut impl Layouter, scalar: &Self::Scalar, base: &Self::FixedPoint, ) -> Result; } /// An element of the given elliptic curve's scalar field. #[derive(Debug)] pub struct Scalar> { inner: EccChip::Scalar, } impl> Scalar { /// Constructs a new point with the given value. pub fn new( mut layouter: impl Layouter, value: Option, ) -> Result { EccChip::witness_scalar(&mut layouter, value).map(|inner| Scalar { inner }) } } /// An elliptic curve point over the given curve. #[derive(Debug)] pub struct Point> { inner: EccChip::Point, } impl> Point { /// Constructs a new point with the given value. pub fn new(mut layouter: impl Layouter, value: Option) -> Result { EccChip::witness_point(&mut layouter, value).map(|inner| Point { inner }) } /// Returns `self + other`. pub fn add(&self, mut layouter: impl Layouter, other: &Self) -> Result { EccChip::add(&mut layouter, &self.inner, &other.inner).map(|inner| Point { inner }) } /// Returns `[2] self`. pub fn double(&self, mut layouter: impl Layouter) -> Result { EccChip::double(&mut layouter, &self.inner).map(|inner| Point { inner }) } /// Returns `[by] self`. pub fn mul( &self, mut layouter: impl Layouter, by: &Scalar, ) -> Result { EccChip::mul(&mut layouter, &by.inner, &self.inner).map(|inner| Point { inner }) } } /// A constant elliptic curve point over the given curve, for which scalar multiplication /// is more efficient. #[derive(Debug)] pub struct FixedPoint> { inner: EccChip::FixedPoint, } impl> FixedPoint { /// Gets a reference to the specified fixed point in the circuit. pub fn get( mut layouter: impl Layouter, point: EccChip::FixedPoints, ) -> Result { EccChip::get_fixed(&mut layouter, point).map(|inner| FixedPoint { inner }) } /// Returns `[by] self`. pub fn mul( &self, mut layouter: impl Layouter, by: &Scalar, ) -> Result, Error> { EccChip::mul_fixed(&mut layouter, &by.inner, &self.inner).map(|inner| Point { inner }) } }