use std::fmt::Debug;
use ff::{PrimeField, WithSmallOrderMulGroup};
use group::{prime::PrimeCurveAffine, Curve};
use midnight_curves::{
pairing::{Engine, MultiMillerLoop},
serde::SerdeObject,
CurveAffine, CurveExt,
};
use midnight_proofs::{
circuit::Layouter,
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::ForeignEccChip,
},
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},
};
pub trait SelfEmulation: Clone + Debug {
type F: PrimeField + 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>;
}
#[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 = ForeignEccChip<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)
}
}