Skip to content

Commit

Permalink
Add state machine AIR
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewmilson committed Dec 16, 2024
1 parent 1fc25f3 commit b92874c
Show file tree
Hide file tree
Showing 60 changed files with 58,985 additions and 128 deletions.
2 changes: 1 addition & 1 deletion stwo_cairo_verifier/.cairofmtignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
tests/verifier/proofs
*_proof.cairo
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-11-19
scarb nightly-2024-12-14
starknet-foundry 0.33.0
4 changes: 2 additions & 2 deletions stwo_cairo_verifier/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ Modify [`Scarb.toml`](./Scarb.toml) to use [Starknet Foundary](https://github.co

```diff
[dev-dependencies]
- cairo_test = "2.8.5"
- cairo_test = "2.9.2"
+ snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.33.0" }
+ assert_macros = "2.8.5"
+ assert_macros = "2.9.2"
+
+ [scripts]
+ test = "snforge test --max-n-steps 100000000"
Expand Down
17 changes: 16 additions & 1 deletion stwo_cairo_verifier/Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,22 @@ name = "bounded_int"
version = "0.1.0"

[[package]]
name = "stwo_cairo_verifier"
name = "stwo_cairo_air"
version = "0.1.0"
dependencies = [
"stwo_constraint_framework",
"stwo_verifier_core",
]

[[package]]
name = "stwo_constraint_framework"
version = "0.1.0"
dependencies = [
"stwo_verifier_core",
]

[[package]]
name = "stwo_verifier_core"
version = "0.1.0"
dependencies = [
"bounded_int",
Expand Down
24 changes: 6 additions & 18 deletions stwo_cairo_verifier/Scarb.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
[workspace]
members = ["bounded_int"]

[package]
name = "stwo_cairo_verifier"
version = "0.1.0"
edition = "2024_07"

[lib]
casm = true

[tool.fmt]
sort-module-level-items = true

[dependencies]
bounded_int = { path = "bounded_int" }

[dev-dependencies]
cairo_test = "2.8.5"
members = [
"crates/bounded_int",
"crates/cairo_air",
"crates/constraint_framework",
"crates/verifier_core",
]
11 changes: 11 additions & 0 deletions stwo_cairo_verifier/cairo_project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[crate_roots]
verifier = "src"
bounded_int = "bounded_int/src"

[config.override.verifier]
edition = "2024_07"

[config.override.verifier.dependencies.bounded_int]

[config.override.bounded_int]
edition = "2023_10"
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! Utility crate that exports internal corelib function.
//! This crate is compiled with an older edition that does not enforce visibity rules.

use core::integer::upcast;
use core::internal::bounded_int::{
BoundedInt, add, constrain, div_rem, sub, AddHelper, ConstrainHelper, DivRemHelper, SubHelper,
AddHelper, BoundedInt, ConstrainHelper, DivRemHelper, SubHelper, add, constrain, div_rem, sub,
};

use core::integer::upcast;
17 changes: 17 additions & 0 deletions stwo_cairo_verifier/crates/cairo_air/Scarb.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "stwo_cairo_air"
version = "0.1.0"
edition = "2024_07"

[lib]
casm = true

[tool.fmt]
sort-module-level-items = true

[dependencies]
stwo_verifier_core = { path = "../verifier_core" }
stwo_constraint_framework = { path = "../constraint_framework" }

[dev-dependencies]
cairo_test = "2.9.2"
32 changes: 32 additions & 0 deletions stwo_cairo_verifier/crates/cairo_air/src/components.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use stwo_constraint_framework::PreprocessedMaskValues;
use stwo_verifier_core::ColumnSpan;
use stwo_verifier_core::circle::CirclePoint;
use stwo_verifier_core::fields::qm31::QM31;

pub mod addr_to_id;
pub mod genericopcode;
pub mod id_to_f252;
pub mod range_check;
pub mod ret_opcode;
pub mod verify_instruction;

pub trait CairoComponent<T> {
fn mask_points(
self: @T,
ref trace_mask_points: Array<Array<CirclePoint<QM31>>>,
ref interaction_trace_mask_points: Array<Array<CirclePoint<QM31>>>,
point: CirclePoint<QM31>,
);

fn max_constraint_log_degree_bound(self: @T) -> u32;

fn evaluate_constraints_at_point(
self: @T,
ref sum: QM31,
ref preprocessed_mask_values: PreprocessedMaskValues,
ref trace_mask_values: ColumnSpan<Array<QM31>>,
ref interaction_trace_mask_values: ColumnSpan<Array<QM31>>,
random_coeff: QM31,
point: CirclePoint<QM31>,
);
}
110 changes: 110 additions & 0 deletions stwo_cairo_verifier/crates/cairo_air/src/components/addr_to_id.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use crate::components::CairoComponent;
use crate::utils::U32Impl;
use stwo_constraint_framework::{
PreprocessedColumn, PreprocessedMaskValues, PreprocessedMaskValuesImpl,
};
use stwo_verifier_core::channel::{Channel, ChannelImpl};
use stwo_verifier_core::circle::CirclePoint;
use stwo_verifier_core::fields::qm31::{QM31, QM31Zero, QM31_EXTENSION_DEGREE};
use stwo_verifier_core::poly::circle::CanonicCosetImpl;
use stwo_verifier_core::utils::ArrayImpl;
use stwo_verifier_core::{ColumnArray, ColumnSpan, TreeArray};

mod constraints;

pub const N_ADDR_TO_ID_COLUMNS: usize = 3;

#[derive(Drop, Serde, Copy)]
pub struct Claim {
pub log_size: u32,
}

#[generate_trait]
pub impl ClaimImpl of ClaimTrait {
fn log_sizes(self: @Claim) -> TreeArray<Span<u32>> {
let log_size = *self.log_size;
let preprocessed_log_sizes = array![log_size].span();
let trace_log_sizes = ArrayImpl::new_repeated(N_ADDR_TO_ID_COLUMNS, log_size).span();
let interaction_log_sizes = ArrayImpl::new_repeated(QM31_EXTENSION_DEGREE, log_size).span();
array![preprocessed_log_sizes, trace_log_sizes, interaction_log_sizes]
}

fn mix_into(self: @Claim, ref channel: Channel) {
channel.mix_nonce((*self.log_size).into());
}
}

#[derive(Drop, Serde, Copy)]
pub struct InteractionClaim {
pub claimed_sum: QM31,
}

#[generate_trait]
pub impl InteractionClaimImpl of InteractionClaimTrait {
fn mix_into(self: @InteractionClaim, ref channel: Channel) {
channel.mix_felts([*self.claimed_sum].span());
}
}

#[derive(Drop)]
pub struct Component {
pub claim: Claim,
pub interaction_claim: InteractionClaim,
pub lookup_elements: super::super::AddrToIdElements,
}

pub impl ComponentImpl of CairoComponent<Component> {
fn mask_points(
self: @Component,
ref trace_mask_points: ColumnArray<Array<CirclePoint<QM31>>>,
ref interaction_trace_mask_points: ColumnArray<Array<CirclePoint<QM31>>>,
point: CirclePoint<QM31>,
) {
let trace_gen = CanonicCosetImpl::new(*self.claim.log_size).coset.step_size;
constraints::mask_points(
ref trace_mask_points, ref interaction_trace_mask_points, point, trace_gen,
);
}

fn max_constraint_log_degree_bound(self: @Component) -> u32 {
*self.claim.log_size + 1
}

fn evaluate_constraints_at_point(
self: @Component,
ref sum: QM31,
ref preprocessed_mask_values: PreprocessedMaskValues,
ref trace_mask_values: ColumnSpan<Array<QM31>>,
ref interaction_trace_mask_values: ColumnSpan<Array<QM31>>,
random_coeff: QM31,
point: CirclePoint<QM31>,
) {
let mut addr_to_id_alpha_powers = self.lookup_elements.alpha_powers.span();
let addr_to_id_alpha_0 = *addr_to_id_alpha_powers.pop_front().unwrap();
let addr_to_id_alpha_1 = *addr_to_id_alpha_powers.pop_front().unwrap();
let addr_to_id_z = *addr_to_id_alpha_powers.pop_front().unwrap();

let log_size = *self.claim.log_size;

let params = constraints::ConstraintParams {
AddrToId_alpha0: addr_to_id_alpha_0,
AddrToId_alpha1: addr_to_id_alpha_1,
AddrToId_z: addr_to_id_z,
preprocessed_is_first: preprocessed_mask_values
.get(PreprocessedColumn::IsFirst(log_size)),
total_sum: *self.interaction_claim.claimed_sum,
};

let trace_domain = CanonicCosetImpl::new(log_size);
let vanish_eval = trace_domain.eval_vanishing(point);

constraints::evaluate_constraints_at_point(
ref sum,
ref trace_mask_values,
ref interaction_trace_mask_values,
params,
random_coeff,
vanish_eval,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use stwo_verifier_core::circle::{
CirclePoint, CirclePointIndex, CirclePointIndexImpl, CirclePointQM31AddCirclePointM31Impl,
};
use stwo_verifier_core::fields::m31::{M31, m31};
use stwo_verifier_core::fields::qm31::{QM31, QM31Impl, qm31};

use stwo_verifier_core::{ColumnArray, ColumnSpan};


pub fn mask_points(
ref trace_mask_points: ColumnArray<Array<CirclePoint<QM31>>>,
ref interaction_trace_mask_points: ColumnArray<Array<CirclePoint<QM31>>>,
point: CirclePoint<QM31>,
trace_gen: CirclePointIndex,
) {
let point_offset_neg_1 = point.add_circle_point_m31(-trace_gen.mul(1).to_point());
trace_mask_points.append(array![point]);
trace_mask_points.append(array![point]);
trace_mask_points.append(array![point]);
interaction_trace_mask_points.append(array![point_offset_neg_1, point]);
interaction_trace_mask_points.append(array![point_offset_neg_1, point]);
interaction_trace_mask_points.append(array![point_offset_neg_1, point]);
interaction_trace_mask_points.append(array![point_offset_neg_1, point]);
}

#[derive(Drop)]
pub struct ConstraintParams {
pub AddrToId_alpha0: QM31,
pub AddrToId_alpha1: QM31,
pub AddrToId_z: QM31,
pub preprocessed_is_first: QM31,
pub total_sum: QM31,
}

pub fn evaluate_constraints_at_point(
ref sum: QM31,
ref trace_mask_values: ColumnSpan<Array<QM31>>,
ref interaction_mask_values: ColumnSpan<Array<QM31>>,
params: ConstraintParams,
random_coeff: QM31,
domain_vanish_at_point_inv: QM31,
) {
let ConstraintParams {
AddrToId_alpha0, AddrToId_alpha1, AddrToId_z, preprocessed_is_first, total_sum,
} = params;

let mut trace_1_column_0 = trace_mask_values.pop_front().unwrap().span();
let trace_1_column_0_offset_0 = *trace_1_column_0.pop_front().unwrap();
let mut trace_1_column_1 = trace_mask_values.pop_front().unwrap().span();
let trace_1_column_1_offset_0 = *trace_1_column_1.pop_front().unwrap();
let mut trace_1_column_2 = trace_mask_values.pop_front().unwrap().span();
let trace_1_column_2_offset_0 = *trace_1_column_2.pop_front().unwrap();
let mut trace_2_column_3 = interaction_mask_values.pop_front().unwrap().span();
let trace_2_column_3_offset_neg_1 = *trace_2_column_3.pop_front().unwrap();
let trace_2_column_3_offset_0 = *trace_2_column_3.pop_front().unwrap();
let mut trace_2_column_4 = interaction_mask_values.pop_front().unwrap().span();
let trace_2_column_4_offset_neg_1 = *trace_2_column_4.pop_front().unwrap();
let trace_2_column_4_offset_0 = *trace_2_column_4.pop_front().unwrap();
let mut trace_2_column_5 = interaction_mask_values.pop_front().unwrap().span();
let trace_2_column_5_offset_neg_1 = *trace_2_column_5.pop_front().unwrap();
let trace_2_column_5_offset_0 = *trace_2_column_5.pop_front().unwrap();
let mut trace_2_column_6 = interaction_mask_values.pop_front().unwrap().span();
let trace_2_column_6_offset_neg_1 = *trace_2_column_6.pop_front().unwrap();
let trace_2_column_6_offset_0 = *trace_2_column_6.pop_front().unwrap();
let intermediate0 = (AddrToId_alpha0) * (trace_1_column_0_offset_0)
+ (AddrToId_alpha1) * (trace_1_column_1_offset_0)
- (AddrToId_z);

let constraint_0 = (QM31Impl::from_partial_evals(
[
trace_2_column_3_offset_0, trace_2_column_4_offset_0, trace_2_column_5_offset_0,
trace_2_column_6_offset_0,
],
)
- (QM31Impl::from_partial_evals(
[
trace_2_column_3_offset_neg_1, trace_2_column_4_offset_neg_1,
trace_2_column_5_offset_neg_1, trace_2_column_6_offset_neg_1,
],
)
- ((total_sum) * (preprocessed_is_first))))
* (intermediate0)
- (-(trace_1_column_2_offset_0));
// TODO: Batch `domain_vanish_at_point_inv` multiplication.
sum = sum * random_coeff + constraint_0 * domain_vanish_at_point_inv;
}

Loading

0 comments on commit b92874c

Please sign in to comment.