Skip to content

Commit

Permalink
Add verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewmilson committed Nov 17, 2024
1 parent 1757562 commit 97b4758
Show file tree
Hide file tree
Showing 23 changed files with 18,232 additions and 100 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
21 changes: 9 additions & 12 deletions stwo_cairo_verifier/src/fri.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ impl FriLayerVerifierImpl of FriLayerVerifierTrait {
};
i += 1;
};
let actual_decommitment_array = array![
column_0.span(), column_1.span(), column_2.span(), column_3.span()
];
let actual_decommitment_array = array![column_0, column_1, column_2, column_3];

let folded_queries = queries.fold(FOLD_STEP);
let folded_queries_snapshot = @folded_queries;
Expand Down Expand Up @@ -107,7 +105,7 @@ impl FriLayerVerifierImpl of FriLayerVerifierTrait {

let decommitment = self.proof.decommitment.clone();
let result = merkle_verifier
.verify(queries_per_log_size, actual_decommitment_array, decommitment.clone());
.verify(queries_per_log_size, @actual_decommitment_array, decommitment.clone());

let evals_at_folded_queries = sparse_evaluation.fold(*self.folding_alpha);
match result {
Expand Down Expand Up @@ -198,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 @@ -318,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 Expand Up @@ -423,7 +420,7 @@ pub impl FriVerifierImpl of FriVerifierTrait {
/// The order of the opening positions corresponds to the order of the column commitment.
fn column_query_positions(
ref self: FriVerifier, ref channel: Channel
) -> (Felt252Dict<Nullable<SparseSubCircleDomain>>, Span<u32>) {
) -> (Felt252Dict<Nullable<@SparseSubCircleDomain>>, Span<u32>) {
let queries = QueriesImpl::generate(
ref channel,
*self.column_bounds[0] + self.config.log_blowup_factor,
Expand Down Expand Up @@ -453,13 +450,13 @@ pub impl FriVerifierImpl of FriVerifierTrait {
/// column opening positions are mapped by their log size.
fn get_opening_positions(
queries: @Queries, column_log_sizes: Span<u32>,
) -> Felt252Dict<Nullable<SparseSubCircleDomain>> {
) -> Felt252Dict<Nullable<@SparseSubCircleDomain>> {
let mut prev_log_size = column_log_sizes[0];
assert!(prev_log_size == queries.log_domain_size);
let mut prev_queries = queries.clone();
let mut positions: Felt252Dict<Nullable<SparseSubCircleDomain>> = Default::default();
let mut positions: Felt252Dict<Nullable<@SparseSubCircleDomain>> = Default::default();
let felt_prev: core::felt252 = (*prev_log_size).into();
positions.insert(felt_prev, NullableTrait::new(prev_queries.opening_positions(FOLD_STEP)));
positions.insert(felt_prev, NullableTrait::new(@prev_queries.opening_positions(FOLD_STEP)));

let mut i = 1;
while i < column_log_sizes.len() {
Expand All @@ -468,7 +465,7 @@ fn get_opening_positions(
let felt_column_log_sizes: core::felt252 = (*column_log_sizes.at(i)).into();
positions
.insert(
felt_column_log_sizes, NullableTrait::new(queries.opening_positions(FOLD_STEP))
felt_column_log_sizes, NullableTrait::new(@queries.opening_positions(FOLD_STEP))
);
prev_log_size = column_log_sizes.at(i);
prev_queries = queries;
Expand Down
20 changes: 10 additions & 10 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 All @@ -17,4 +17,4 @@ fn main() {}
pub type ColumnArray<T> = Array<T>;

/// An array in which each element relates (by index) to a commitment tree.
pub type TreeArray<T> = Array<T>;
pub type TreeArray<T> = Array<T>;
2 changes: 1 addition & 1 deletion stwo_cairo_verifier/src/pcs/verifier.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub impl CommitmentSchemeVerifierImpl of CommitmentSchemeVerifierTrait {
// Verify proof of work.
channel.mix_nonce(proof_of_work);

if channel.trailing_zeros() < *self.config.pow_bits {
if !channel.check_proof_of_work(*self.config.pow_bits) {
return Result::Err(VerificationError::ProofOfWork);
}

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
Loading

0 comments on commit 97b4758

Please sign in to comment.