Skip to content

Commit 6b5c843

Browse files
Merge lifted into dev. (#1307)
* Add lifted Merkle verifier. (#1234) * Add SIMD MerkleOpsLifted. (#1235) * Add auxiliary structs to vcs_lifted. (#1247) * Add generic blake for lifted vcs. (#1252) * Change queries from vec to slice. (#1250) * Add lift_and_accumulate. (#1245) * Modify finalize of DomainEvaluationAccumulator. (#1246) * Add skeleton of lifted quotient ops. (#1248) All the code related to the previous architecture of quotient ops has been removed. * Add empty poseidon merkle hasher lifted. (#1253) * Change channel's assoc type to MerkleHasherLifted. (#1254) * Add CPU QuotientOps impl. (#1249) * Make pcs prove lifted values. (#1251) * Add pcs verifier lifted. (#1255) * Modify trace step in masks and eval at point. (#1257) * Add CpuBackend impl to ComponentProver. (#1258) * Add mixed wide fibonacci test. (#1259) * Add m31 blake hasher to simd. (#1260) * Allow small traces with cpu, fix bug. (#1261) * Add lift and accumulate in simd. (#1262) * Add simd impl of accumulate_numerators. (#1263) * Add `compute_quotients_and_combine`. (#1266) * Change fri decommit to return a vec of query positions. (#1269) * Commit to a single column in fri. (#1270) * Update docs and rename. (#1271) * Remove iterations in fri verifier decommit. (#1272) * Remove unneeded structure. (#1273) * Update docs. (#1274) * Add poseidon hasher. (#1283) * Add SIMD implementation of poseidon MerkleOpsLifted. (#1280) * Adapt the queries for the preprocessed trees. (#1281) Co-authored-by: Alon F <alonf@starkware.co> * Fix non-parallel bugs. (#1287) * Adapt barycentric weights to the lifted protocol. (#1288) * Change order of the alphas to the samples order. (#1292) * Change queried values layout. (#1293) * Add periodicity samples. (#1294) * Improve performance of cpu merkle. (#1284) * Fix lifting size in fri_answers and add test. (#1296) * Optimize blake simd merkle lifted. (#1291) * Add maximal size periodicity checks. (#1301) * Add dummy serde and reexport MerkleHasherLifted. (#1297) These changes make it easier to integrate with stwo_cairo_prover. --------- Co-authored-by: Alon F <alonf@starkware.co>
1 parent 2e57d72 commit 6b5c843

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+3181
-1383
lines changed

Cargo.lock

Lines changed: 24 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/constraint-framework/src/component.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,9 @@ impl<E: FrameworkEval> Component for FrameworkComponent<E> {
220220
fn mask_points(
221221
&self,
222222
point: CirclePoint<SecureField>,
223+
max_log_degree_bound: u32,
223224
) -> TreeVec<ColumnVec<Vec<CirclePoint<SecureField>>>> {
224-
let trace_step = CanonicCoset::new(self.eval.log_size()).step();
225+
let trace_step = CanonicCoset::new(max_log_degree_bound).step();
225226
self.info.mask_offsets.as_ref().map_cols(|col_offsets| {
226227
col_offsets
227228
.iter()
@@ -239,6 +240,7 @@ impl<E: FrameworkEval> Component for FrameworkComponent<E> {
239240
point: CirclePoint<SecureField>,
240241
mask: &TreeVec<ColumnVec<Vec<SecureField>>>,
241242
evaluation_accumulator: &mut PointEvaluationAccumulator,
243+
max_log_degree_bound: u32,
242244
) {
243245
let preprocessed_mask = self
244246
.preprocessed_column_indices
@@ -252,7 +254,7 @@ impl<E: FrameworkEval> Component for FrameworkComponent<E> {
252254
self.eval.evaluate(PointEvaluator::new(
253255
mask_points,
254256
evaluation_accumulator,
255-
coset_vanishing(CanonicCoset::new(self.eval.log_size()).coset, point).inverse(),
257+
coset_vanishing(CanonicCoset::new(max_log_degree_bound).coset, point).inverse(),
256258
self.eval.log_size(),
257259
self.claimed_sum,
258260
));

crates/constraint-framework/src/prover/component_prover.rs

Lines changed: 118 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ use rayon::prelude::*;
66
use stwo::core::air::Component;
77
use stwo::core::constraints::coset_vanishing;
88
use stwo::core::fields::m31::BaseField;
9+
use stwo::core::fields::qm31::SecureField;
910
use stwo::core::pcs::TreeVec;
1011
use stwo::core::poly::circle::CanonicCoset;
1112
use stwo::core::utils::bit_reverse;
1213
use stwo::prover::backend::simd::column::VeryPackedSecureColumnByCoords;
1314
use stwo::prover::backend::simd::m31::LOG_N_LANES;
1415
use stwo::prover::backend::simd::very_packed_m31::{VeryPackedBaseField, LOG_N_VERY_PACKED_ELEMS};
1516
use stwo::prover::backend::simd::SimdBackend;
17+
use stwo::prover::backend::CpuBackend;
1618
use stwo::prover::poly::circle::{CircleEvaluation, PolyOps};
1719
use stwo::prover::poly::BitReversedOrder;
1820
use stwo::prover::secure_column::SecureColumnByCoords;
@@ -70,7 +72,7 @@ impl<E: FrameworkEval + Sync> ComponentProver<SimdBackend> for FrameworkComponen
7072
.collect_vec();
7173
bit_reverse(&mut denom_inv);
7274

73-
// Accumulator.
75+
// Note that `accum` is a mutable reference to a column in `evaluation_accumulator`.
7476
let [mut accum] =
7577
evaluation_accumulator.columns([(eval_domain.log_size(), self.n_constraints())]);
7678
accum.random_coeff_powers.reverse();
@@ -82,32 +84,19 @@ impl<E: FrameworkEval + Sync> ComponentProver<SimdBackend> for FrameworkComponen
8284
)
8385
.entered();
8486

87+
// Fall back to CPU if the trace is too small.
8588
if trace_domain.log_size() < LOG_N_LANES + LOG_N_VERY_PACKED_ELEMS {
86-
// Fall back to CPU if the trace is too small.
87-
let mut col = accum.col.to_cpu();
88-
89-
for row in 0..(1 << eval_domain.log_size()) {
90-
let trace_cols = trace.as_cols_ref().map_cols(|c| c.to_cpu());
91-
let trace_cols = trace_cols.as_cols_ref();
92-
93-
// Evaluate constrains at row.
94-
let eval = CpuDomainEvaluator::new(
95-
&trace_cols,
96-
row,
97-
&accum.random_coeff_powers,
98-
trace_domain.log_size(),
99-
eval_domain.log_size(),
100-
self.eval.log_size(),
101-
self.claimed_sum,
102-
);
103-
let row_res = self.eval.evaluate(eval).row_res;
104-
105-
// Finalize row.
106-
let denom_inv = denom_inv[row >> trace_domain.log_size()];
107-
col.set(row, col.at(row) + row_res * denom_inv)
108-
}
109-
let col = SecureColumnByCoords::from_cpu(col);
110-
*accum.col = col;
89+
let trace_cols = trace.as_cols_ref().map_cols(|c| c.to_cpu());
90+
let trace_cols = trace_cols.as_cols_ref();
91+
*accum.col = SecureColumnByCoords::from_cpu(accumulate_pointwise_cpu(
92+
self,
93+
trace_cols,
94+
eval_domain.log_size(),
95+
trace_domain.log_size(),
96+
denom_inv,
97+
&accum.random_coeff_powers,
98+
&accum.col.to_cpu(),
99+
));
111100
return;
112101
}
113102

@@ -148,16 +137,117 @@ impl<E: FrameworkEval + Sync> ComponentProver<SimdBackend> for FrameworkComponen
148137

149138
// Finalize row.
150139
unsafe {
151-
let denom_inv = VeryPackedBaseField::broadcast(
140+
let row_denom_inv = VeryPackedBaseField::broadcast(
152141
denom_inv[vec_row
153142
>> (trace_domain.log_size() - LOG_N_LANES - LOG_N_VERY_PACKED_ELEMS)],
154143
);
155144
chunk.set_packed(
156145
idx_in_chunk,
157-
chunk.packed_at(idx_in_chunk) + row_res * denom_inv,
146+
chunk.packed_at(idx_in_chunk) + row_res * row_denom_inv,
158147
)
159148
}
160149
}
161150
});
162151
}
163152
}
153+
154+
impl<E: FrameworkEval + Sync> ComponentProver<CpuBackend> for FrameworkComponent<E> {
155+
/// Almost all this implementation is equal to the one above for `SimdBackend`.
156+
fn evaluate_constraint_quotients_on_domain(
157+
&self,
158+
trace: &Trace<'_, CpuBackend>,
159+
evaluation_accumulator: &mut DomainEvaluationAccumulator<CpuBackend>,
160+
) {
161+
if self.n_constraints() == 0 {
162+
return;
163+
}
164+
let eval_domain = CanonicCoset::new(self.max_constraint_log_degree_bound()).circle_domain();
165+
let trace_domain = CanonicCoset::new(self.eval.log_size());
166+
167+
let mut component_polys = trace.polys.sub_tree(&self.trace_locations);
168+
component_polys[PREPROCESSED_TRACE_IDX] = self
169+
.preprocessed_column_indices
170+
.iter()
171+
.map(|idx| &trace.polys[PREPROCESSED_TRACE_IDX][*idx])
172+
.collect();
173+
174+
// Extend trace if necessary.
175+
// TODO: Don't extend when eval_size < committed_size. Instead, pick a good
176+
// subdomain. (For larger blowup factors).
177+
let need_to_extend = component_polys
178+
.iter()
179+
.flatten()
180+
.any(|c| c.evals.domain.log_size() != eval_domain.log_size());
181+
let trace: TreeVec<
182+
Vec<Cow<'_, CircleEvaluation<CpuBackend, BaseField, BitReversedOrder>>>,
183+
> = if need_to_extend {
184+
let _span = span!(Level::INFO, "Constraint Extension").entered();
185+
let twiddles = CpuBackend::precompute_twiddles(eval_domain.half_coset);
186+
component_polys
187+
.as_cols_ref()
188+
.map_cols(|col| Cow::Owned(col.get_evaluation_on_domain(eval_domain, &twiddles)))
189+
} else {
190+
component_polys.map_cols(|c| Cow::Borrowed(&c.evals))
191+
};
192+
193+
// Denom inverses.
194+
let log_expand = eval_domain.log_size() - trace_domain.log_size();
195+
let mut denom_inv = (0..1 << log_expand)
196+
.map(|i| coset_vanishing(trace_domain.coset(), eval_domain.at(i)).inverse())
197+
.collect_vec();
198+
bit_reverse(&mut denom_inv);
199+
200+
// Accumulator.
201+
let [mut accum] =
202+
evaluation_accumulator.columns([(eval_domain.log_size(), self.n_constraints())]);
203+
accum.random_coeff_powers.reverse();
204+
205+
let _span = span!(
206+
Level::INFO,
207+
"Constraint point-wise eval",
208+
class = "ConstraintEval"
209+
)
210+
.entered();
211+
let trace_cols = trace.as_cols_ref().map_cols(|c| c.as_ref());
212+
213+
*accum.col = accumulate_pointwise_cpu(
214+
self,
215+
trace_cols,
216+
eval_domain.log_size(),
217+
trace_domain.log_size(),
218+
denom_inv,
219+
&accum.random_coeff_powers,
220+
accum.col,
221+
);
222+
}
223+
}
224+
225+
fn accumulate_pointwise_cpu<E: FrameworkEval>(
226+
component: &FrameworkComponent<E>,
227+
trace_cols: TreeVec<Vec<&CircleEvaluation<CpuBackend, BaseField, BitReversedOrder>>>,
228+
eval_log_size: u32,
229+
trace_log_size: u32,
230+
denom_inv: Vec<BaseField>,
231+
random_coeff_powers: &[SecureField],
232+
accum: &SecureColumnByCoords<CpuBackend>,
233+
) -> SecureColumnByCoords<CpuBackend> {
234+
let mut res = SecureColumnByCoords::zeros(1 << eval_log_size);
235+
for row in 0..(1 << eval_log_size) {
236+
// Evaluate constrains at row.
237+
let eval = CpuDomainEvaluator::new(
238+
&trace_cols,
239+
row,
240+
random_coeff_powers,
241+
trace_log_size,
242+
eval_log_size,
243+
component.eval.log_size(),
244+
component.claimed_sum,
245+
);
246+
let row_res = component.eval.evaluate(eval).row_res;
247+
248+
// Finalize row.
249+
let row_denom_inv = denom_inv[row >> trace_log_size];
250+
res.set(row, accum.at(row) + row_res * row_denom_inv)
251+
}
252+
res
253+
}

crates/examples/src/blake/air.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use stwo::core::fields::qm31::SecureField;
99
use stwo::core::pcs::{CommitmentSchemeVerifier, PcsConfig, TreeVec};
1010
use stwo::core::poly::circle::CanonicCoset;
1111
use stwo::core::proof::StarkProof;
12-
use stwo::core::vcs::MerkleHasher;
12+
use stwo::core::vcs_lifted::merkle_hasher::MerkleHasherLifted;
1313
use stwo::core::verifier::{verify, VerificationError};
1414
use stwo::prover::backend::simd::m31::LOG_N_LANES;
1515
use stwo::prover::backend::simd::SimdBackend;
@@ -149,7 +149,7 @@ impl BlakeStatement1 {
149149
}
150150
}
151151

152-
pub struct BlakeProof<H: MerkleHasher> {
152+
pub struct BlakeProof<H: MerkleHasherLifted> {
153153
stmt0: BlakeStatement0,
154154
stmt1: BlakeStatement1,
155155
stark_proof: StarkProof<H>,
@@ -306,7 +306,6 @@ where
306306
// Setup protocol.
307307
let channel = &mut MC::C::default();
308308
let mut commitment_scheme = CommitmentSchemeProver::new(config, &twiddles);
309-
310309
// Preprocessed trace.
311310
// TODO(ShaharS): share is_first column between components when constant columns support this.
312311
let span = span!(Level::INFO, "Preprocessed Trace").entered();
@@ -521,7 +520,7 @@ mod tests {
521520
use std::env;
522521

523522
use stwo::core::pcs::PcsConfig;
524-
use stwo::core::vcs::blake2_merkle::Blake2sMerkleChannel;
523+
use stwo::core::vcs_lifted::blake2_merkle::Blake2sMerkleChannel;
525524

526525
use crate::blake::air::{prove_blake, verify_blake};
527526

crates/examples/src/plonk/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use stwo::core::fields::qm31::SecureField;
66
use stwo::core::pcs::{PcsConfig, TreeSubspan};
77
use stwo::core::poly::circle::CanonicCoset;
88
use stwo::core::proof::StarkProof;
9-
use stwo::core::vcs::blake2_merkle::{Blake2sMerkleChannel, Blake2sMerkleHasher};
9+
use stwo::core::vcs_lifted::blake2_merkle::{Blake2sMerkleChannel, Blake2sMerkleHasher};
1010
use stwo::core::ColumnVec;
1111
use stwo::prover::backend::simd::column::BaseColumn;
1212
use stwo::prover::backend::simd::m31::LOG_N_LANES;
@@ -293,7 +293,7 @@ mod tests {
293293
use stwo::core::channel::Blake2sChannel;
294294
use stwo::core::fri::FriConfig;
295295
use stwo::core::pcs::{CommitmentSchemeVerifier, PcsConfig};
296-
use stwo::core::vcs::blake2_merkle::Blake2sMerkleChannel;
296+
use stwo::core::vcs_lifted::blake2_merkle::Blake2sMerkleChannel;
297297
use stwo::core::verifier::verify;
298298

299299
use crate::plonk::{prove_fibonacci_plonk, PlonkLookupElements};

crates/examples/src/poseidon/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use stwo::core::fields::FieldExpOps;
1313
use stwo::core::pcs::PcsConfig;
1414
use stwo::core::poly::circle::CanonicCoset;
1515
use stwo::core::proof::StarkProof;
16-
use stwo::core::vcs::blake2_merkle::{Blake2sMerkleChannel, Blake2sMerkleHasher};
16+
use stwo::core::vcs_lifted::blake2_merkle::{Blake2sMerkleChannel, Blake2sMerkleHasher};
1717
use stwo::core::ColumnVec;
1818
use stwo::prover::backend::simd::column::BaseColumn;
1919
use stwo::prover::backend::simd::m31::{PackedBaseField, LOG_N_LANES};
@@ -404,7 +404,7 @@ mod tests {
404404
use stwo::core::fri::FriConfig;
405405
use stwo::core::pcs::{CommitmentSchemeVerifier, PcsConfig, TreeVec};
406406
use stwo::core::poly::circle::CanonicCoset;
407-
use stwo::core::vcs::blake2_merkle::Blake2sMerkleChannel;
407+
use stwo::core::vcs_lifted::blake2_merkle::Blake2sMerkleChannel;
408408
use stwo::core::verifier::verify;
409409
use stwo_constraint_framework::assert_constraints_on_polys;
410410

@@ -486,6 +486,7 @@ mod tests {
486486
);
487487
}
488488

489+
#[ignore = "AIRs with constraint degree >= 2 are not supported yet in the lifted protocol."]
489490
#[test_log::test]
490491
fn test_simd_poseidon_prove() {
491492
// Note: To see time measurement, run test with
@@ -529,6 +530,7 @@ mod tests {
529530
verify(&[&component], channel, commitment_scheme, proof).unwrap();
530531
}
531532

533+
#[ignore = "AIRs with constraint degree >= 2 are not supported yet in the lifted protocol."]
532534
#[cfg(feature = "tracing")]
533535
#[test]
534536
fn trace_simd_poseidon_prove() {

crates/examples/src/state_machine/components.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use stwo::core::fields::m31::{BaseField, M31};
66
use stwo::core::fields::qm31::{SecureField, QM31};
77
use stwo::core::pcs::TreeVec;
88
use stwo::core::proof::StarkProof;
9-
use stwo::core::vcs::MerkleHasher;
9+
use stwo::core::vcs_lifted::merkle_hasher::MerkleHasherLifted;
1010
use stwo::prover::backend::simd::SimdBackend;
1111
use stwo::prover::poly::circle::CircleEvaluation;
1212
use stwo::prover::poly::BitReversedOrder;
@@ -148,7 +148,7 @@ pub fn track_state_machine_relations(
148148
.collect()
149149
}
150150

151-
pub struct StateMachineProof<H: MerkleHasher> {
151+
pub struct StateMachineProof<H: MerkleHasherLifted> {
152152
pub public_input: [State; 2], // Initial and final state.
153153
pub stmt0: StateMachineStatement0,
154154
pub stmt1: StateMachineStatement1,

0 commit comments

Comments
 (0)