Skip to main content

midnight_circuits/verifier/
types.rs

1// This file is part of MIDNIGHT-ZK.
2// Copyright (C) Midnight Foundation
3// SPDX-License-Identifier: Apache-2.0
4// Licensed under the Apache License, Version 2.0 (the "License");
5// You may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7// http://www.apache.org/licenses/LICENSE-2.0
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14//! Module that contains type and generic bounds.
15//! Its purpose is to minimize complexity in the rest of the verifier chip.
16
17use std::fmt::Debug;
18
19use ff::WithSmallOrderMulGroup;
20use group::{prime::PrimeCurveAffine, Curve};
21use midnight_curves::{
22    pairing::{Engine, MultiMillerLoop},
23    serde::SerdeObject,
24    CurveAffine, CurveExt,
25};
26use midnight_proofs::{
27    circuit::{Layouter, Value},
28    plonk::Error,
29    transcript::{Hashable, TranscriptHash},
30};
31
32#[cfg(not(feature = "truncated-challenges"))]
33use crate::instructions::FieldInstructions;
34#[cfg(feature = "truncated-challenges")]
35use crate::instructions::NativeInstructions;
36use crate::{
37    ecc::{
38        curves::{CircuitCurve, WeierstrassCurve},
39        foreign::weierstrass_chip::ForeignWeierstrassEccChip,
40    },
41    field::{decomposition::chip::P2RDecompositionChip, AssignedNative, NativeChip, NativeGadget},
42    hash::poseidon::{PoseidonChip, PoseidonState},
43    instructions::{
44        ecc::EccInstructions, public_input::CommittedInstanceInstructions, AssignmentInstructions,
45        HashInstructions, PublicInputInstructions, SpongeInstructions,
46    },
47    types::{AssignedForeignPoint, InnerValue, Instantiable},
48    CircuitField,
49};
50
51/// A trait for parametrizing the VerifierGadget.
52pub trait SelfEmulation: Clone + Debug {
53    /// The native field.
54    type F: CircuitField + WithSmallOrderMulGroup<3> + Hashable<Self::Hash>;
55
56    /// The underlying curve of the self-emulation proof.
57    type C: CurveExt<ScalarExt = Self::F, AffineExt = Self::G1Affine>
58        + WeierstrassCurve<CryptographicGroup = Self::C, Base = <Self::C as CurveExt>::Base>
59        + Hashable<Self::Hash>;
60
61    /// An assigned point of curve C.
62    type AssignedPoint: InnerValue<Element = Self::C> + Instantiable<Self::F> + PartialEq + Eq;
63
64    /// A type for the Fiat-Shamir hashing.
65    type Hash: TranscriptHash;
66
67    #[cfg(feature = "truncated-challenges")]
68    /// A chip implementing native field arithmetic operations.
69    type ScalarChip: NativeInstructions<Self::F>;
70    #[cfg(not(feature = "truncated-challenges"))]
71    /// A chip implementing native field arithmetic operations.
72    type ScalarChip: FieldInstructions<Self::F, AssignedNative<Self::F>>;
73
74    /// A chip implementing assignment operations for [Self::AssignedPoint].
75    type CurveChip: Clone
76        + AssignmentInstructions<Self::F, Self::AssignedPoint>
77        + PublicInputInstructions<Self::F, Self::AssignedPoint>;
78
79    /// A chip implementing sponge operations over the native field.
80    type SpongeChip: Clone
81        + SpongeInstructions<Self::F, AssignedNative<Self::F>, AssignedNative<Self::F>>
82        + HashInstructions<Self::F, AssignedNative<Self::F>, AssignedNative<Self::F>>;
83
84    /// C in affine form (first source group).
85    type G1Affine: CurveAffine<ScalarExt = Self::F, CurveExt = Self::C, Base = <Self::C as CircuitCurve>::Base>
86        + Into<Self::C>
87        + From<Self::C>
88        + SerdeObject;
89
90    /// The second source group.
91    type G2Affine: PrimeCurveAffine + From<<Self::Engine as Engine>::G2> + SerdeObject;
92
93    /// Wrapper type for the pairing engine.
94    type Engine: Engine
95        + MultiMillerLoop<
96            Fr = Self::F,
97            G1 = Self::C,
98            G1Affine = <Self::C as Curve>::AffineRepr,
99            G2Affine = Self::G2Affine,
100        >;
101
102    /// Variable-base multi-scalar multiplication, the `usize` next to each
103    /// scalar is an (inclusive) upper-bound on their bit-length.
104    ///
105    /// # Panics
106    ///
107    /// If `|scalars| != |bases|`.
108    fn msm(
109        layouter: &mut impl Layouter<Self::F>,
110        curve_chip: &Self::CurveChip,
111        scalars: &[(AssignedNative<Self::F>, usize)],
112        bases: &[Self::AssignedPoint],
113    ) -> Result<Self::AssignedPoint, Error>;
114
115    /// Constrains the given scalar as a committed public input.
116    fn constrain_scalar_as_committed_public_input(
117        layouter: &mut impl Layouter<Self::F>,
118        scalar_chip: &Self::ScalarChip,
119        assigned_scalar: &AssignedNative<Self::F>,
120    ) -> Result<(), Error>;
121
122    /// Assigns a point without checking that it is part of the prime order
123    /// subgroup.
124    /// Allowing points outside the subgroup does not give any advantage to an
125    /// adversary in PLONK.
126    // TODO: Provide a formal analysis of subgroup soundness in this context.
127    fn assign_without_subgroup_check(
128        layouter: &mut impl Layouter<Self::F>,
129        curve_chip: &Self::CurveChip,
130        base: Value<Self::C>,
131    ) -> Result<Self::AssignedPoint, Error>;
132}
133
134// Implementations
135
136/// Implementation of the SelfEmulation trait for blstrs.
137#[derive(Clone, Debug)]
138pub struct BlstrsEmulation {}
139
140impl SelfEmulation for BlstrsEmulation {
141    type F = midnight_curves::Fq;
142    type C = midnight_curves::G1Projective;
143    type AssignedPoint = AssignedForeignPoint<Self::F, Self::C, Self::C>;
144    type Hash = PoseidonState<Self::F>;
145
146    type ScalarChip = NativeGadget<Self::F, P2RDecompositionChip<Self::F>, NativeChip<Self::F>>;
147    type CurveChip =
148        ForeignWeierstrassEccChip<Self::F, Self::C, Self::C, Self::ScalarChip, Self::ScalarChip>;
149    type SpongeChip = PoseidonChip<Self::F>;
150
151    type G1Affine = midnight_curves::G1Affine;
152    type G2Affine = midnight_curves::G2Affine;
153    type Engine = midnight_curves::Bls12;
154
155    fn msm(
156        layouter: &mut impl Layouter<Self::F>,
157        curve_chip: &Self::CurveChip,
158        scalars: &[(AssignedNative<Self::F>, usize)],
159        bases: &[Self::AssignedPoint],
160    ) -> Result<Self::AssignedPoint, Error> {
161        curve_chip.msm_by_bounded_scalars(layouter, scalars, bases)
162    }
163
164    fn constrain_scalar_as_committed_public_input(
165        layouter: &mut impl Layouter<Self::F>,
166        scalar_chip: &Self::ScalarChip,
167        assigned_scalar: &AssignedNative<Self::F>,
168    ) -> Result<(), Error> {
169        scalar_chip.constrain_as_committed_public_input(layouter, assigned_scalar)
170    }
171
172    fn assign_without_subgroup_check(
173        layouter: &mut impl Layouter<Self::F>,
174        curve_chip: &Self::CurveChip,
175        base: Value<Self::C>,
176    ) -> Result<Self::AssignedPoint, Error> {
177        curve_chip.assign_without_subgroup_check(layouter, base)
178    }
179}
180
181/// Implementation of the SelfEmulation trait for bn256.
182#[cfg(feature = "dev-curves")]
183#[derive(Clone, Debug)]
184pub struct BnEmulation {}
185
186#[cfg(feature = "dev-curves")]
187impl SelfEmulation for BnEmulation {
188    type F = midnight_curves::bn256::Fr;
189    type C = midnight_curves::bn256::G1;
190    type AssignedPoint = AssignedForeignPoint<Self::F, Self::C, Self::C>;
191    type Hash = PoseidonState<Self::F>;
192
193    type ScalarChip = NativeGadget<Self::F, P2RDecompositionChip<Self::F>, NativeChip<Self::F>>;
194    type CurveChip =
195        ForeignWeierstrassEccChip<Self::F, Self::C, Self::C, Self::ScalarChip, Self::ScalarChip>;
196    type SpongeChip = PoseidonChip<Self::F>;
197
198    type G1Affine = midnight_curves::bn256::G1Affine;
199    type G2Affine = midnight_curves::bn256::G2Affine;
200    type Engine = midnight_curves::bn256::Bn256;
201
202    fn msm(
203        layouter: &mut impl Layouter<Self::F>,
204        curve_chip: &Self::CurveChip,
205        scalars: &[(AssignedNative<Self::F>, usize)],
206        bases: &[Self::AssignedPoint],
207    ) -> Result<Self::AssignedPoint, Error> {
208        curve_chip.msm_by_bounded_scalars(layouter, scalars, bases)
209    }
210
211    fn constrain_scalar_as_committed_public_input(
212        layouter: &mut impl Layouter<Self::F>,
213        scalar_chip: &Self::ScalarChip,
214        assigned_scalar: &AssignedNative<Self::F>,
215    ) -> Result<(), Error> {
216        scalar_chip.constrain_as_committed_public_input(layouter, assigned_scalar)
217    }
218
219    fn assign_without_subgroup_check(
220        layouter: &mut impl Layouter<Self::F>,
221        curve_chip: &Self::CurveChip,
222        base: Value<Self::C>,
223    ) -> Result<Self::AssignedPoint, Error> {
224        curve_chip.assign(layouter, base)
225    }
226}