Skip to content

Commit

Permalink
Add verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewmilson committed Nov 18, 2024
1 parent 038b46c commit 0db0be9
Show file tree
Hide file tree
Showing 22 changed files with 18,166 additions and 41 deletions.
1 change: 0 additions & 1 deletion .gitignore

This file was deleted.

1 change: 1 addition & 0 deletions stwo_cairo_verifier/.cairofmtignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests/proofs
2 changes: 2 additions & 0 deletions stwo_cairo_verifier/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Excluded proof files from GitHub stats and hide in diffs.
tests/proofs/* linguist-generated
4 changes: 4 additions & 0 deletions stwo_cairo_verifier/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
target
snfoundry_trace
.snfoundry_cache
.snfoundry_versioned_programs
profile.pb.gz
2 changes: 1 addition & 1 deletion stwo_cairo_verifier/.tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
scarb nightly-2024-08-31
starknet-foundry 0.30.0
starknet-foundry 0.32.0
1 change: 0 additions & 1 deletion stwo_cairo_verifier/src/channel.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use core::poseidon::{poseidon_hash_span, hades_permutation};
use core::traits::DivRem;
use stwo_cairo_verifier::fields::qm31::QM31Trait;
use stwo_cairo_verifier::utils::pack4;

use stwo_cairo_verifier::{BaseField, SecureField};

/// Equals `2^31`.
Expand Down
2 changes: 1 addition & 1 deletion stwo_cairo_verifier/src/fields/cm31.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub struct CM31 {
#[generate_trait]
pub impl CM31Impl of CM31Trait {
fn inverse(self: CM31) -> CM31 {
assert_ne!(self, Zero::zero());
assert!(self.is_non_zero());
let denom_inverse: M31 = (self.a * self.a + self.b * self.b).inverse();
CM31 { a: self.a * denom_inverse, b: -self.b * denom_inverse }
}
Expand Down
2 changes: 1 addition & 1 deletion stwo_cairo_verifier/src/fields/m31.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub impl M31Impl of M31Trait {
}

fn inverse(self: M31) -> M31 {
assert_ne!(self, core::num::traits::Zero::zero());
assert!(self.is_non_zero());
let t0 = Self::sqn(self, 2) * self;
let t1 = Self::sqn(t0, 1) * t0;
let t2 = Self::sqn(t1, 3) * t0;
Expand Down
19 changes: 18 additions & 1 deletion stwo_cairo_verifier/src/fields/qm31.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use super::m31::{M31, M31Impl, UnreducedM31};
/// Equals `(2^31 - 1)^4`.
pub const P4: u128 = 21267647892944572736998860269687930881;

pub const QM31_EXTENSION_DEGREE: usize = 4;

pub const R: CM31 = CM31 { a: M31 { inner: 2 }, b: M31 { inner: 1 } };

#[derive(Copy, Drop, Debug, PartialEq)]
Expand All @@ -29,7 +31,7 @@ pub impl QM31Impl of QM31Trait {
}

fn inverse(self: QM31) -> QM31 {
assert_ne!(self, Zero::zero());
assert!(self.is_non_zero());
let b2 = self.b * self.b;
let ib2 = CM31 { a: -b2.b, b: b2.a };
let denom = self.a * self.a - (b2 + b2 + ib2);
Expand Down Expand Up @@ -130,6 +132,13 @@ pub impl QM31Impl of QM31Trait {
d: PP16 + aa_t_bb_b + ab_t_ba_b
}
}

/// Returns the combined value, given the values of its composing base field polynomials at that
/// point.
fn from_partial_evals(evals: [QM31; QM31_EXTENSION_DEGREE]) -> QM31 {
let [e0, e1, e2, e3] = evals;
e0 + e1 * qm31(0, 1, 0, 0) + e2 * qm31(0, 0, 1, 0) + e3 * qm31(0, 0, 0, 1)
}
}

pub impl QM31Add of core::traits::Add<QM31> {
Expand All @@ -153,6 +162,14 @@ pub impl QM31Mul of core::traits::Mul<QM31> {
}
}

pub impl QM31Div of core::traits::Div<QM31> {
#[inline]
fn div(lhs: QM31, rhs: QM31) -> QM31 {
// (a + bu) * (c + du) = (ac + rbd) + (ad + bc)u.
lhs * rhs.inverse()
}
}

pub impl QM31AddAssign of AddAssign<QM31, QM31> {
#[inline]
fn add_assign(ref self: QM31, rhs: QM31) {
Expand Down
7 changes: 3 additions & 4 deletions stwo_cairo_verifier/src/fri.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use stwo_cairo_verifier::vcs::verifier::{MerkleDecommitment, MerkleVerifier, Mer
pub const CIRCLE_TO_LINE_FOLD_STEP: u32 = 1;
pub const FOLD_STEP: u32 = 1;

#[derive(Debug, Clone, Drop, PartialEq)]
#[derive(Debug, Drop, PartialEq)]
pub enum FriVerificationError {
InvalidNumFriLayers,
LastLayerDegreeInvalid,
Expand Down Expand Up @@ -196,14 +196,13 @@ pub struct FriConfig {
pub n_queries: usize,
}


/// Stores a subset of evaluations in a fri layer with their corresponding merkle decommitments.
///
/// The subset corresponds to the set of evaluations needed by a FRI verifier.
#[derive(Drop, Clone, Debug)]
pub struct FriLayerProof {
pub evals_subset: Array<QM31>,
pub decommitment: MerkleDecommitment::<PoseidonMerkleHasher>,
pub decommitment: MerkleDecommitment<PoseidonMerkleHasher>,
pub commitment: felt252,
}

Expand Down Expand Up @@ -316,7 +315,7 @@ pub impl FriVerifierImpl of FriVerifierTrait {
fn decommit_on_queries(
self: @FriVerifier, queries: @Queries, decommitted_values: Array<SparseCircleEvaluation>
) -> Result<(), FriVerificationError> {
assert_eq!(queries.log_domain_size, self.expected_query_log_domain_size);
assert!(queries.log_domain_size == self.expected_query_log_domain_size);

let (last_layer_queries, last_layer_query_evals) = self
.decommit_inner_layers(queries, @decommitted_values)?;
Expand Down
18 changes: 9 additions & 9 deletions stwo_cairo_verifier/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
mod channel;
mod circle;
mod fields;
mod fri;
mod pcs;
mod poly;
pub mod channel;
pub mod circle;
pub mod fields;
pub mod fri;
pub mod pcs;
pub mod poly;
mod queries;
mod utils;
mod vcs;
mod verifier;
pub mod utils;
pub mod vcs;
pub mod verifier;

pub use fields::{BaseField, SecureField};

Expand Down
19 changes: 16 additions & 3 deletions stwo_cairo_verifier/src/poly/circle.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use stwo_cairo_verifier::circle::{
Coset, CosetImpl, CirclePoint, CirclePointM31Impl, CirclePointIndex, CirclePointIndexImpl
Coset, CosetImpl, CirclePoint, CirclePointM31Impl, CirclePointIndex, CirclePointIndexImpl,
CirclePointTrait
};
use stwo_cairo_verifier::fields::m31::M31;
use stwo_cairo_verifier::fields::qm31::QM31;
Expand Down Expand Up @@ -97,6 +98,18 @@ pub impl CanonicCosetImpl of CanonicCosetTrait {
fn circle_domain(self: @CanonicCoset) -> CircleDomain {
CircleDomainImpl::new(self.half_coset())
}

/// Evaluates the coset's vanishing polynomial at point `p`.
fn eval_vanishing(self: @CanonicCoset, p: CirclePoint<QM31>) -> QM31 {
let mut x = p.x;

// The formula for the x coordinate of the double of a point.
for _ in 1..*self.coset.log_size {
x = CirclePointTrait::double_x(x);
};

x
}
}

/// An evaluation defined on a [`CircleDomain`].
Expand Down Expand Up @@ -130,14 +143,14 @@ pub impl SparseCircleEvaluationImpl of SparseCircleEvaluationImplTrait {
fn accumulate(
self: @SparseCircleEvaluation, rhs: @SparseCircleEvaluation, alpha: QM31
) -> SparseCircleEvaluation {
assert_eq!(self.subcircle_evals.len(), rhs.subcircle_evals.len());
assert!(self.subcircle_evals.len() == rhs.subcircle_evals.len());
let mut subcircle_evals = array![];
let mut i = 0;
while i < self.subcircle_evals.len() {
let lhs = self.subcircle_evals[i];
let rhs = rhs.subcircle_evals[i];
let mut values = array![];
assert_eq!(lhs.bit_reversed_values.len(), rhs.bit_reversed_values.len());
assert!(lhs.bit_reversed_values.len() == rhs.bit_reversed_values.len());
let mut j = 0;
while j < lhs.bit_reversed_values.len() {
values.append(*lhs.bit_reversed_values[j] * alpha + *rhs.bit_reversed_values[j]);
Expand Down
2 changes: 1 addition & 1 deletion stwo_cairo_verifier/src/poly/line.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub struct LineEvaluation {
pub impl LineEvaluationImpl of LineEvaluationTrait {
/// Creates new [LineEvaluation] from a set of polynomial evaluations over a [LineDomain].
fn new(domain: LineDomain, values: Array<QM31>) -> LineEvaluation {
assert_eq!(values.len(), domain.size());
assert!(values.len() == domain.size());
LineEvaluation { values: values, domain: domain }
}
}
Expand Down
23 changes: 11 additions & 12 deletions stwo_cairo_verifier/src/utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use core::box::BoxTrait;
use core::dict::Felt252Dict;
use core::dict::Felt252DictEntryTrait;
use core::dict::Felt252DictTrait;
use core::iter::IntoIterator;
use core::iter::Iterator;
use core::iter::{Iterator, IntoIterator};
use core::num::traits::BitSize;
use core::traits::DivRem;
use core::traits::PanicDestruct;
Expand All @@ -31,7 +30,7 @@ pub impl OptBoxImpl<T> of OptBoxTrait<T> {
}

#[generate_trait]
pub impl ArrayImpl<T, +Copy<T>, +Drop<T>> of ArrayExTrait<T> {
pub impl ArrayImpl<T, +Drop<T>> of ArrayExTrait<T> {
fn pop_n(ref self: Array<T>, mut n: usize) -> Array<T> {
let mut res = array![];
while n != 0 {
Expand All @@ -45,12 +44,12 @@ pub impl ArrayImpl<T, +Copy<T>, +Drop<T>> of ArrayExTrait<T> {
res
}

fn max<+PartialOrd<T>>(mut self: @Array<T>) -> Option<@T> {
fn max<+Copy<T>, +PartialOrd<T>>(mut self: @Array<T>) -> Option<@T> {
self.span().max()
}

/// Sorts an array in ascending order. Uses quicksort algorithm.
fn sort_ascending<+PartialOrd<T>>(self: Array<T>) -> Array<T> {
fn sort_ascending<+Clone<T>, +PartialOrd<T>>(self: Array<T>) -> Array<T> {
if self.len() <= 1 {
return self;
}
Expand All @@ -61,7 +60,7 @@ pub impl ArrayImpl<T, +Copy<T>, +Drop<T>> of ArrayExTrait<T> {
let pivot = iter.next().unwrap();

for v in iter {
if v > pivot {
if v.clone() > pivot.clone() {
rhs.append(v);
} else {
lhs.append(v);
Expand All @@ -87,22 +86,22 @@ pub impl ArrayImpl<T, +Copy<T>, +Drop<T>> of ArrayExTrait<T> {
}

let mut iter = self.into_iter();
let mut last_value = iter.next().unwrap();
let mut res = array![last_value];
let mut res = array![iter.next().unwrap()];
let mut last_value = res[0];
for value in iter {
if value != last_value {
if @value != last_value {
last_value = @value;
res.append(value);
last_value = value;
}
};

res
}

fn new_repeated(n: usize, v: T) -> Array<T> {
fn new_repeated<+Clone<T>>(n: usize, v: T) -> Array<T> {
let mut res = array![];
for _ in 0..n {
res.append(v);
res.append(v.clone());
};
res
}
Expand Down
8 changes: 3 additions & 5 deletions stwo_cairo_verifier/src/vcs/verifier.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,9 @@ impl MerkleVerifierImpl<
self: @MerkleVerifier<H>,
mut queries_per_log_size: Felt252Dict<Nullable<Span<usize>>>,
queried_values: @Array<Array<BaseField>>,
mut decommitment: MerkleDecommitment<H>,
decommitment: MerkleDecommitment<H>,
) -> Result<(), MerkleVerificationError> {
let MerkleDecommitment { hash_witness: mut hash_witness,
column_witness: mut column_witness, } =
decommitment;
let MerkleDecommitment { mut hash_witness, mut column_witness } = decommitment;

let mut layer_log_size = *self.column_log_sizes.max().unwrap();
let mut cols_by_size = Self::cols_by_size(self);
Expand Down Expand Up @@ -271,7 +269,7 @@ fn fetch_prev_node_hash<H, +Copy<H>, +Drop<H>>(
Option::None
}

#[derive(Copy, Drop, Debug)]
#[derive(Drop, Debug)]
pub enum MerkleVerificationError {
WitnessTooShort,
WitnessTooLong,
Expand Down
Loading

0 comments on commit 0db0be9

Please sign in to comment.