Skip to content

Commit

Permalink
Create proofs for Cairo
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewmilson committed Nov 27, 2024
1 parent af9250e commit 90ff535
Show file tree
Hide file tree
Showing 9 changed files with 349 additions and 37 deletions.
7 changes: 7 additions & 0 deletions crates/prover/proof.cairo

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion crates/prover/src/core/backend/simd/poseidon252.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use itertools::Itertools;
#[cfg(feature = "parallel")]
use rayon::prelude::*;
use starknet_ff::FieldElement as FieldElement252;

use super::SimdBackend;
Expand All @@ -8,6 +10,7 @@ use crate::core::fields::m31::BaseField;
use crate::core::vcs::ops::MerkleHasher;
use crate::core::vcs::ops::MerkleOps;
use crate::core::vcs::poseidon252_merkle::Poseidon252MerkleHasher;
use crate::parallel_iter;

impl ColumnOps<FieldElement252> for SimdBackend {
type Column = Vec<FieldElement252>;
Expand All @@ -24,7 +27,7 @@ impl MerkleOps<Poseidon252MerkleHasher> for SimdBackend {
prev_layer: Option<&Vec<FieldElement252>>,
columns: &[&Col<Self, BaseField>],
) -> Vec<FieldElement252> {
(0..(1 << log_size))
parallel_iter!(0..(1 << log_size))
.map(|i| {
Poseidon252MerkleHasher::hash_node(
prev_layer.map(|prev_layer| (prev_layer[2 * i], prev_layer[2 * i + 1])),
Expand Down
181 changes: 156 additions & 25 deletions crates/prover/src/core/fri.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions crates/prover/src/core/poly/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ pub struct LinePoly {
///
/// The coefficients are stored in bit-reversed order.
#[allow(rustdoc::private_intra_doc_links)]
coeffs: Vec<SecureField>,
pub coeffs: Vec<SecureField>,
/// The number of coefficients stored as `log2(len(coeffs))`.
log_size: u32,
pub log_size: u32,
}

impl LinePoly {
Expand Down
6 changes: 5 additions & 1 deletion crates/prover/src/core/test_utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::backend::cpu::CpuCircleEvaluation;
use super::channel::Blake2sChannel;
use super::channel::{Blake2sChannel, Poseidon252Channel};
use super::fields::m31::BaseField;
use super::fields::qm31::SecureField;

Expand All @@ -15,3 +15,7 @@ pub fn secure_eval_to_base_eval<EvalOrder>(
pub fn test_channel() -> Blake2sChannel {
Blake2sChannel::default()
}

pub fn test_poseidon_channel() -> Poseidon252Channel {
Poseidon252Channel::default()
}
11 changes: 10 additions & 1 deletion crates/prover/src/examples/blake/air.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ pub fn verify_blake<MC: MerkleChannel>(
mod tests {
use std::env;

use crate::core::fri::FriConfig;
use crate::core::pcs::PcsConfig;
use crate::core::vcs::blake2_merkle::Blake2sMerkleChannel;
use crate::examples::blake::air::{prove_blake, verify_blake};
Expand All @@ -547,7 +548,15 @@ mod tests {
.unwrap_or_else(|_| "6".to_string())
.parse::<u32>()
.unwrap();
let config = PcsConfig::default();
// let config = PcsConfig::default();
let config = PcsConfig {
pow_bits: 10,
fri_config: FriConfig {
log_blowup_factor: 1,
log_last_layer_degree_bound: 6,
n_queries: 50,
},
};

// Prove.
let proof = prove_blake::<Blake2sMerkleChannel>(log_n_instances, config);
Expand Down
2 changes: 1 addition & 1 deletion crates/prover/src/examples/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ pub mod plonk;
pub mod poseidon;
pub mod state_machine;
pub mod wide_fibonacci;
pub mod xor;
// pub mod xor;
165 changes: 159 additions & 6 deletions crates/prover/src/examples/wide_fibonacci/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,12 @@ pub fn generate_trace<const N: usize>(

#[cfg(test)]
mod tests {
use std::fs::File;
use std::io::Write;

use itertools::Itertools;
use num_traits::{One, Zero};
use starknet_ff::FieldElement;

use super::WideFibonacciEval;
use crate::constraint_framework::{
Expand All @@ -85,17 +89,23 @@ mod tests {
use crate::core::channel::Poseidon252Channel;
use crate::core::fields::m31::BaseField;
use crate::core::fields::qm31::SecureField;
use crate::core::pcs::{CommitmentSchemeProver, CommitmentSchemeVerifier, PcsConfig, TreeVec};
use crate::core::fri::{FriLayerProof, FriProof};
use crate::core::pcs::{
CommitmentSchemeProof, CommitmentSchemeProver, CommitmentSchemeVerifier, PcsConfig, TreeVec,
};
use crate::core::poly::circle::{CanonicCoset, CircleEvaluation, PolyOps};
use crate::core::poly::line::LinePoly;
use crate::core::poly::BitReversedOrder;
use crate::core::prover::{prove, verify};
use crate::core::prover::{prove, verify, StarkProof};
use crate::core::vcs::blake2_merkle::Blake2sMerkleChannel;
#[cfg(not(target_arch = "wasm32"))]
use crate::core::vcs::poseidon252_merkle::Poseidon252MerkleChannel;
use crate::core::vcs::poseidon252_merkle::Poseidon252MerkleHasher;
use crate::core::vcs::prover::MerkleDecommitment;
use crate::core::ColumnVec;
use crate::examples::wide_fibonacci::{generate_trace, FibInput, WideFibonacciComponent};

const FIB_SEQUENCE_LENGTH: usize = 100;
const FIB_SEQUENCE_LENGTH: usize = 64;

fn generate_test_trace(
log_n_instances: u32,
Expand Down Expand Up @@ -153,7 +163,7 @@ mod tests {
#[test]
#[should_panic]
fn test_wide_fibonacci_constraints_fails() {
const LOG_N_INSTANCES: u32 = 6;
const LOG_N_INSTANCES: u32 = 125;

let mut trace = generate_test_trace(LOG_N_INSTANCES);
// Modify the trace such that a constraint fail.
Expand Down Expand Up @@ -229,8 +239,15 @@ mod tests {
#[test]
#[cfg(not(target_arch = "wasm32"))]
fn test_wide_fib_prove_with_poseidon() {
const LOG_N_INSTANCES: u32 = 6;
let config = PcsConfig::default();
use std::time::Instant;

use crate::core::fri::FriConfig;

const LOG_N_INSTANCES: u32 = 20;
let config = PcsConfig {
pow_bits: 0,
fri_config: FriConfig::new(6, 1, 60),
};
// Precompute twiddles.
let twiddles = SimdBackend::precompute_twiddles(
CanonicCoset::new(LOG_N_INSTANCES + 1 + config.fri_config.log_blowup_factor)
Expand All @@ -249,11 +266,18 @@ mod tests {
tree_builder.extend_evals([]);
tree_builder.commit(prover_channel);

let now = Instant::now();
// Trace.
let trace = generate_test_trace(LOG_N_INSTANCES);

println!("test trace took: {:?}", now.elapsed());

let now = Instant::now();

let mut tree_builder = commitment_scheme.tree_builder();
tree_builder.extend_evals(trace);
tree_builder.commit(prover_channel);
println!("extend took: {:?}", now.elapsed());

// Prove constraints.
let component = WideFibonacciComponent::new(
Expand All @@ -263,22 +287,151 @@ mod tests {
},
(SecureField::zero(), None),
);
let now = Instant::now();
let proof = prove::<SimdBackend, Poseidon252MerkleChannel>(
&[&component],
prover_channel,
commitment_scheme,
)
.unwrap();

println!("proving took: {:?}", now.elapsed());

// _serialize_proof_cairo1(&proof);
_serialize_proof_cairo1_array(&proof);

// Verify.
let verifier_channel = &mut Poseidon252Channel::default();
let commitment_scheme =
&mut CommitmentSchemeVerifier::<Poseidon252MerkleChannel>::new(config);

// Retrieve the expected column sizes in each commitment interaction, from the AIR.
let sizes = component.trace_log_degree_bounds();
println!("commitments: {:?}", proof.commitments[0]);
println!("sizes: {:?}", &sizes[0]);
commitment_scheme.commit(proof.commitments[0], &sizes[0], verifier_channel);
commitment_scheme.commit(proof.commitments[1], &sizes[1], verifier_channel);
verify(&[&component], verifier_channel, commitment_scheme, proof).unwrap();
}

fn _serialize_proof_cairo1_array(proof: &StarkProof<Poseidon252MerkleHasher>) {
trait CairoSerialize {
fn serialize(&self, buffer: &mut Vec<FieldElement>);
}

impl CairoSerialize for BaseField {
fn serialize(&self, buffer: &mut Vec<FieldElement>) {
buffer.push(self.0.into());
}
}

impl CairoSerialize for SecureField {
fn serialize(&self, buffer: &mut Vec<FieldElement>) {
buffer.extend(self.to_m31_array().map(|c| FieldElement::from(c.0)));
}
}

impl CairoSerialize for MerkleDecommitment<Poseidon252MerkleHasher> {
fn serialize(&self, buffer: &mut Vec<FieldElement>) {
let Self {
hash_witness,
column_witness,
} = self;
hash_witness.serialize(buffer);
column_witness.serialize(buffer);
}
}

impl CairoSerialize for LinePoly {
fn serialize(&self, buffer: &mut Vec<FieldElement>) {
let Self { coeffs, log_size } = self;
coeffs.serialize(buffer);
buffer.push((*log_size).into());
}
}

impl CairoSerialize for FriLayerProof<Poseidon252MerkleHasher> {
fn serialize(&self, buffer: &mut Vec<FieldElement>) {
let Self {
fri_witness,
decommitment,
commitment,
} = self;
fri_witness.serialize(buffer);
decommitment.serialize(buffer);
commitment.serialize(buffer);
}
}

impl CairoSerialize for FriProof<Poseidon252MerkleHasher> {
fn serialize(&self, buffer: &mut Vec<FieldElement>) {
let Self {
first_layer,
inner_layers,
last_layer_poly,
} = self;
first_layer.serialize(buffer);
inner_layers.serialize(buffer);
last_layer_poly.serialize(buffer);
}
}

impl CairoSerialize for FieldElement {
fn serialize(&self, buffer: &mut Vec<FieldElement>) {
buffer.push(*self);
}
}

impl CairoSerialize for CommitmentSchemeProof<Poseidon252MerkleHasher> {
fn serialize(&self, buffer: &mut Vec<FieldElement>) {
let Self {
commitments,
sampled_values,
decommitments,
queried_values,
proof_of_work,
fri_proof,
} = self;
commitments.serialize(buffer);
sampled_values.serialize(buffer);
decommitments.serialize(buffer);
queried_values.serialize(buffer);
buffer.push((*proof_of_work).into());
fri_proof.serialize(buffer);
}
}

impl CairoSerialize for StarkProof<Poseidon252MerkleHasher> {
fn serialize(&self, buffer: &mut Vec<FieldElement>) {
let Self(commitment_scheme_proof) = self;
commitment_scheme_proof.serialize(buffer);
}
}

impl<T: CairoSerialize> CairoSerialize for Vec<T> {
fn serialize(&self, buffer: &mut Vec<FieldElement>) {
buffer.push(self.len().into());
self.iter().for_each(|v| v.serialize(buffer));
}
}

let mut values = Vec::new();
proof.serialize(&mut values);

println!("proof size: {} field elements", values.len());

let ser_proof = format!(
r#"
use stwo_cairo_verifier::verifier::StarkProof;
pub fn proof() -> StarkProof {{
let mut proof_data = array![{}].span();
Serde::deserialize(ref proof_data).unwrap()
}}"#,
values.iter().map(|v| v.to_string()).join(",")
);

let mut file = File::create("proof.cairo").unwrap();
file.write_all(ser_proof.as_bytes()).unwrap();
}
}
5 changes: 5 additions & 0 deletions crates/prover/src/examples/xor/gkr_lookups/mle_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,13 @@ impl<'twiddles, 'oracle, O: MleCoeffColumnOracle> Component
) {
// Consistency check the MLE coeffs column polynomial and oracle.
let mle_coeff_col_eval = self.mle_coeff_column_poly.eval_at_point(point);
<<<<<<< Updated upstream:crates/prover/src/examples/xor/gkr_lookups/mle_eval.rs
let oracle_mle_coeff_col_eval = self.mle_coeff_column_oracle.evaluate_at_point(point, mask);
assert_eq!(mle_coeff_col_eval, oracle_mle_coeff_col_eval);
=======
let _oracle_mle_coeff_col_eval =
self.mle_coeff_column_oracle.evaluate_at_point(point, mask);
>>>>>>> Stashed changes:crates/prover/src/examples/blake_gkr/gkr_lookups/mle_eval.rs

let component_mask = mask.sub_tree(&self.trace_locations);
let trace_coset = CanonicCoset::new(self.log_size()).coset;
Expand Down

0 comments on commit 90ff535

Please sign in to comment.