Skip to content
Merged
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
11 changes: 11 additions & 0 deletions snark-verifier/src/cost.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
//! Cost estimation.

use std::ops::Add;

/// Cost of verification.
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Cost {
/// Number of instances.
pub num_instance: usize,
/// Number of commitments in proof.
pub num_commitment: usize,
/// Number of evaluations in proof.
pub num_evaluation: usize,
/// Number of scalar multiplications to perform.
pub num_msm: usize,
/// Number of pairings to perform.
pub num_pairing: usize,
}

Expand All @@ -22,8 +30,11 @@ impl Add<Cost> for Cost {
}
}

/// For estimating cost of a verifier.
pub trait CostEstimation<T> {
/// Input for [`CostEstimation::estimate_cost`].
type Input;

/// Estimate cost of verifier given the input.
fn estimate_cost(input: &Self::Input) -> Cost;
}
16 changes: 13 additions & 3 deletions snark-verifier/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#![allow(clippy::type_complexity)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::upper_case_acronyms)]
//! Generic (S)NARK verifier.

#![allow(
clippy::type_complexity,
clippy::too_many_arguments,
clippy::upper_case_acronyms
)]
#![deny(missing_debug_implementations, missing_docs, unsafe_code, rustdoc::all)]

pub mod cost;
pub mod loader;
Expand All @@ -9,10 +14,15 @@ pub mod system;
pub mod util;
pub mod verifier;

/// Error that could happen while verification.
#[derive(Clone, Debug)]
pub enum Error {
/// Instances that don't match the amount specified in protocol.
InvalidInstances,
/// Protocol that is unreasonable for a verifier.
InvalidProtocol(String),
/// Assertion failure while verification.
AssertionFailure(String),
/// Transcript error.
Transcript(std::io::ErrorKind, String),
}
41 changes: 40 additions & 1 deletion snark-verifier/src/loader.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! Abstraction of field element and elliptic curve point for generic verifier
//! implementation.

use crate::{
util::{
arithmetic::{CurveAffine, FieldOps, PrimeField},
Expand All @@ -15,25 +18,34 @@ pub mod evm;
#[cfg(feature = "loader_halo2")]
pub mod halo2;

/// Loaded elliptic curve point.
pub trait LoadedEcPoint<C: CurveAffine>: Clone + Debug + PartialEq {
/// [`Loader`].
type Loader: Loader<C, LoadedEcPoint = Self>;

/// Returns [`Loader`].
fn loader(&self) -> &Self::Loader;
}

/// Loaded field element.
pub trait LoadedScalar<F: PrimeField>: Clone + Debug + PartialEq + FieldOps {
/// [`Loader`].
type Loader: ScalarLoader<F, LoadedScalar = Self>;

/// Returns [`Loader`].
fn loader(&self) -> &Self::Loader;

/// Returns square.
fn square(&self) -> Self {
self.clone() * self
}

/// Returns inverse if any.
fn invert(&self) -> Option<Self> {
FieldOps::invert(self)
}

/// Returns power to exponent.
fn pow_const(&self, mut exp: u64) -> Self {
assert!(exp > 0);

Expand All @@ -55,6 +67,7 @@ pub trait LoadedScalar<F: PrimeField>: Clone + Debug + PartialEq + FieldOps {
acc
}

/// Returns powers up to exponent `n-1`.
fn powers(&self, n: usize) -> Vec<Self> {
iter::once(self.loader().load_one())
.chain(
Expand All @@ -65,53 +78,67 @@ pub trait LoadedScalar<F: PrimeField>: Clone + Debug + PartialEq + FieldOps {
}
}

/// Elliptic curve point loader.
pub trait EcPointLoader<C: CurveAffine> {
/// [`LoadedEcPoint`].
type LoadedEcPoint: LoadedEcPoint<C, Loader = Self>;

/// Load a constant elliptic curve point.
fn ec_point_load_const(&self, value: &C) -> Self::LoadedEcPoint;

/// Load `identity` as constant.
fn ec_point_load_zero(&self) -> Self::LoadedEcPoint {
self.ec_point_load_const(&C::identity())
}

/// Load `generator` as constant.
fn ec_point_load_one(&self) -> Self::LoadedEcPoint {
self.ec_point_load_const(&C::generator())
}

/// Assert lhs and rhs elliptic curve points are equal.
fn ec_point_assert_eq(
&self,
annotation: &str,
lhs: &Self::LoadedEcPoint,
rhs: &Self::LoadedEcPoint,
) -> Result<(), Error>;

/// Perform multi-scalar multiplication.
fn multi_scalar_multiplication(
pairs: &[(&Self::LoadedScalar, &Self::LoadedEcPoint)],
) -> Self::LoadedEcPoint
where
Self: ScalarLoader<C::ScalarExt>;
}

/// Field element loader.
pub trait ScalarLoader<F: PrimeField> {
/// [`LoadedScalar`].
type LoadedScalar: LoadedScalar<F, Loader = Self>;

/// Load a constant field element.
fn load_const(&self, value: &F) -> Self::LoadedScalar;

/// Load `zero` as constant.
fn load_zero(&self) -> Self::LoadedScalar {
self.load_const(&F::zero())
}

/// Load `one` as constant.
fn load_one(&self) -> Self::LoadedScalar {
self.load_const(&F::one())
}

/// Assert lhs and rhs field elements are equal.
fn assert_eq(
&self,
annotation: &str,
lhs: &Self::LoadedScalar,
rhs: &Self::LoadedScalar,
) -> Result<(), Error>;

/// Sum field elements with coefficients and constant.
fn sum_with_coeff_and_const(
&self,
values: &[(F, &Self::LoadedScalar)],
Expand Down Expand Up @@ -140,6 +167,7 @@ pub trait ScalarLoader<F: PrimeField> {
.into_owned()
}

/// Sum product of field elements with coefficients and constant.
fn sum_products_with_coeff_and_const(
&self,
values: &[(F, &Self::LoadedScalar, &Self::LoadedScalar)],
Expand Down Expand Up @@ -167,28 +195,33 @@ pub trait ScalarLoader<F: PrimeField> {
.unwrap()
}

/// Sum field elements with coefficients.
fn sum_with_coeff(&self, values: &[(F, &Self::LoadedScalar)]) -> Self::LoadedScalar {
self.sum_with_coeff_and_const(values, F::zero())
}

/// Sum field elements and constant.
fn sum_with_const(&self, values: &[&Self::LoadedScalar], constant: F) -> Self::LoadedScalar {
self.sum_with_coeff_and_const(
&values.iter().map(|&value| (F::one(), value)).collect_vec(),
constant,
)
}

/// Sum field elements.
fn sum(&self, values: &[&Self::LoadedScalar]) -> Self::LoadedScalar {
self.sum_with_const(values, F::zero())
}

/// Sum product of field elements with coefficients.
fn sum_products_with_coeff(
&self,
values: &[(F, &Self::LoadedScalar, &Self::LoadedScalar)],
) -> Self::LoadedScalar {
self.sum_products_with_coeff_and_const(values, F::zero())
}

/// Sum product of field elements and constant.
fn sum_products_with_const(
&self,
values: &[(&Self::LoadedScalar, &Self::LoadedScalar)],
Expand All @@ -203,19 +236,22 @@ pub trait ScalarLoader<F: PrimeField> {
)
}

/// Sum product of field elements.
fn sum_products(
&self,
values: &[(&Self::LoadedScalar, &Self::LoadedScalar)],
) -> Self::LoadedScalar {
self.sum_products_with_const(values, F::zero())
}

/// Product of field elements.
fn product(&self, values: &[&Self::LoadedScalar]) -> Self::LoadedScalar {
values
.iter()
.fold(self.load_one(), |acc, value| acc * *value)
}

/// Batch invert field elements.
fn batch_invert<'a>(values: impl IntoIterator<Item = &'a mut Self::LoadedScalar>)
where
Self::LoadedScalar: 'a,
Expand All @@ -226,10 +262,13 @@ pub trait ScalarLoader<F: PrimeField> {
}
}

/// [`EcPointLoader`] and [`ScalarLoader`] with some helper methods.
pub trait Loader<C: CurveAffine>:
EcPointLoader<C> + ScalarLoader<C::ScalarExt> + Clone + Debug
{
fn start_cost_metering(&self, _: &str) {}
/// Start cost metering with an `identifier`.
fn start_cost_metering(&self, _identifier: &str) {}

/// End latest started cost metering.
fn end_cost_metering(&self) {}
}
6 changes: 4 additions & 2 deletions snark-verifier/src/loader/evm.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
//! `Loader` implementation for generating yul code as EVM verifier.

mod code;
pub(crate) mod loader;
mod util;
pub(crate) mod util;

#[cfg(test)]
mod test;

pub use loader::{EcPoint, EvmLoader, Scalar};
pub use util::{
compile_yul, encode_calldata, estimate_gas, fe_to_u256, modulus, u256_to_fe, Address,
ExecutorBuilder, MemoryChunk, H256, U256, U512,
ExecutorBuilder, H256, U256, U512,
};

#[cfg(test)]
Expand Down
11 changes: 2 additions & 9 deletions snark-verifier/src/loader/evm/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,13 @@ impl YulCode {
let y_lt_p:bool := lt(y, {base_modulus})
valid := and(x_lt_p, y_lt_p)
}}
{{
let x_is_zero:bool := eq(x, 0)
let y_is_zero:bool := eq(y, 0)
let x_or_y_is_zero:bool := or(x_is_zero, y_is_zero)
let x_and_y_is_not_zero:bool := not(x_or_y_is_zero)
valid := and(x_and_y_is_not_zero, valid)
}}
{{
let y_square := mulmod(y, y, {base_modulus})
let x_square := mulmod(x, x, {base_modulus})
let x_cube := mulmod(x_square, x, {base_modulus})
let x_cube_plus_3 := addmod(x_cube, 3, {base_modulus})
let y_square_eq_x_cube_plus_3:bool := eq(x_cube_plus_3, y_square)
valid := and(y_square_eq_x_cube_plus_3, valid)
let is_affine:bool := eq(x_cube_plus_3, y_square)
valid := and(valid, is_affine)
}}
}}
{}
Expand Down
Loading