use std::fmt::Debug;
use ff::WithSmallOrderMulGroup;
use group::{prime::PrimeCurveAffine, Curve};
use midnight_curves::{
pairing::{Engine, MultiMillerLoop},
serde::SerdeObject,
CurveAffine, CurveExt,
};
use midnight_proofs::{
circuit::{Layouter, Value},
plonk::Error,
transcript::{Hashable, TranscriptHash},
};
#[cfg(not(feature = "truncated-challenges"))]
use crate::instructions::FieldInstructions;
#[cfg(feature = "truncated-challenges")]
use crate::instructions::NativeInstructions;
use crate::{
ecc::{
curves::{CircuitCurve, WeierstrassCurve},
foreign::weierstrass_chip::ForeignWeierstrassEccChip,
},
field::{decomposition::chip::P2RDecompositionChip, AssignedNative, NativeChip, NativeGadget},
hash::poseidon::{PoseidonChip, PoseidonState},
instructions::{
ecc::EccInstructions, public_input::CommittedInstanceInstructions, AssignmentInstructions,
HashInstructions, PublicInputInstructions, SpongeInstructions,
},
types::{AssignedForeignPoint, InnerValue, Instantiable},
CircuitField,
};
pub trait SelfEmulation: Clone + Debug {
type F: CircuitField + WithSmallOrderMulGroup<3> + Hashable<Self::Hash>;
type C: CurveExt<ScalarExt = Self::F, AffineExt = Self::G1Affine>
+ WeierstrassCurve<CryptographicGroup = Self::C, Base = <Self::C as CurveExt>::Base>
+ Hashable<Self::Hash>;
type AssignedPoint: InnerValue<Element = Self::C> + Instantiable<Self::F> + PartialEq + Eq;
type Hash: TranscriptHash;
#[cfg(feature = "truncated-challenges")]
type ScalarChip: NativeInstructions<Self::F>;
#[cfg(not(feature = "truncated-challenges"))]
type ScalarChip: FieldInstructions<Self::F, AssignedNative<Self::F>>;
type CurveChip: Clone
+ AssignmentInstructions<Self::F, Self::AssignedPoint>
+ PublicInputInstructions<Self::F, Self::AssignedPoint>;
type SpongeChip: Clone
+ SpongeInstructions<Self::F, AssignedNative<Self::F>, AssignedNative<Self::F>>
+ HashInstructions<Self::F, AssignedNative<Self::F>, AssignedNative<Self::F>>;
type G1Affine: CurveAffine<ScalarExt = Self::F, CurveExt = Self::C, Base = <Self::C as CircuitCurve>::Base>
+ Into<Self::C>
+ From<Self::C>
+ SerdeObject;
type G2Affine: PrimeCurveAffine + From<<Self::Engine as Engine>::G2> + SerdeObject;
type Engine: Engine
+ MultiMillerLoop<
Fr = Self::F,
G1 = Self::C,
G1Affine = <Self::C as Curve>::AffineRepr,
G2Affine = Self::G2Affine,
>;
fn msm(
layouter: &mut impl Layouter<Self::F>,
curve_chip: &Self::CurveChip,
scalars: &[(AssignedNative<Self::F>, usize)],
bases: &[Self::AssignedPoint],
) -> Result<Self::AssignedPoint, Error>;
fn constrain_scalar_as_committed_public_input(
layouter: &mut impl Layouter<Self::F>,
scalar_chip: &Self::ScalarChip,
assigned_scalar: &AssignedNative<Self::F>,
) -> Result<(), Error>;
fn assign_without_subgroup_check(
layouter: &mut impl Layouter<Self::F>,
curve_chip: &Self::CurveChip,
base: Value<Self::C>,
) -> Result<Self::AssignedPoint, Error>;
}
#[derive(Clone, Debug)]
pub struct BlstrsEmulation {}
impl SelfEmulation for BlstrsEmulation {
type F = midnight_curves::Fq;
type C = midnight_curves::G1Projective;
type AssignedPoint = AssignedForeignPoint<Self::F, Self::C, Self::C>;
type Hash = PoseidonState<Self::F>;
type ScalarChip = NativeGadget<Self::F, P2RDecompositionChip<Self::F>, NativeChip<Self::F>>;
type CurveChip =
ForeignWeierstrassEccChip<Self::F, Self::C, Self::C, Self::ScalarChip, Self::ScalarChip>;
type SpongeChip = PoseidonChip<Self::F>;
type G1Affine = midnight_curves::G1Affine;
type G2Affine = midnight_curves::G2Affine;
type Engine = midnight_curves::Bls12;
fn msm(
layouter: &mut impl Layouter<Self::F>,
curve_chip: &Self::CurveChip,
scalars: &[(AssignedNative<Self::F>, usize)],
bases: &[Self::AssignedPoint],
) -> Result<Self::AssignedPoint, Error> {
curve_chip.msm_by_bounded_scalars(layouter, scalars, bases)
}
fn constrain_scalar_as_committed_public_input(
layouter: &mut impl Layouter<Self::F>,
scalar_chip: &Self::ScalarChip,
assigned_scalar: &AssignedNative<Self::F>,
) -> Result<(), Error> {
scalar_chip.constrain_as_committed_public_input(layouter, assigned_scalar)
}
fn assign_without_subgroup_check(
layouter: &mut impl Layouter<Self::F>,
curve_chip: &Self::CurveChip,
base: Value<Self::C>,
) -> Result<Self::AssignedPoint, Error> {
curve_chip.assign_without_subgroup_check(layouter, base)
}
}
#[cfg(feature = "dev-curves")]
#[derive(Clone, Debug)]
pub struct BnEmulation {}
#[cfg(feature = "dev-curves")]
impl SelfEmulation for BnEmulation {
type F = midnight_curves::bn256::Fr;
type C = midnight_curves::bn256::G1;
type AssignedPoint = AssignedForeignPoint<Self::F, Self::C, Self::C>;
type Hash = PoseidonState<Self::F>;
type ScalarChip = NativeGadget<Self::F, P2RDecompositionChip<Self::F>, NativeChip<Self::F>>;
type CurveChip =
ForeignWeierstrassEccChip<Self::F, Self::C, Self::C, Self::ScalarChip, Self::ScalarChip>;
type SpongeChip = PoseidonChip<Self::F>;
type G1Affine = midnight_curves::bn256::G1Affine;
type G2Affine = midnight_curves::bn256::G2Affine;
type Engine = midnight_curves::bn256::Bn256;
fn msm(
layouter: &mut impl Layouter<Self::F>,
curve_chip: &Self::CurveChip,
scalars: &[(AssignedNative<Self::F>, usize)],
bases: &[Self::AssignedPoint],
) -> Result<Self::AssignedPoint, Error> {
curve_chip.msm_by_bounded_scalars(layouter, scalars, bases)
}
fn constrain_scalar_as_committed_public_input(
layouter: &mut impl Layouter<Self::F>,
scalar_chip: &Self::ScalarChip,
assigned_scalar: &AssignedNative<Self::F>,
) -> Result<(), Error> {
scalar_chip.constrain_as_committed_public_input(layouter, assigned_scalar)
}
fn assign_without_subgroup_check(
layouter: &mut impl Layouter<Self::F>,
curve_chip: &Self::CurveChip,
base: Value<Self::C>,
) -> Result<Self::AssignedPoint, Error> {
curve_chip.assign(layouter, base)
}
}