Skip to content

Commit 71eaf88

Browse files
ShuangWu121Schaeff
andauthored
Extend stwo to Support Machines with Varying Degrees (#2280)
### Summary This PR introduces support for proving machines with differing degrees in the `stwo` prover. It enables handling proving columns of varying sizes. --- ### Details 1. **Support for Proving Columns of Different Sizes**: - Machines with different column sizes require their own distinct components. - All components are stored in a single vector, from which a slice is created and passed into the `prove` function to handle the proving process. - Constant columns are indexed globally across all components to ensure consistency and correctness. 2. **Verification**: - The verification function requires the sizes of all columns (including constant columns and witness columns) as input. --- ### Changes - Updated the logic for managing machine-specific components and assembling them for the proving process. - Implemented indexing of constant columns across components. --- ### Testing - Added tests to validate proving functionality with machines of differing degrees for stwo prover. --- --------- Co-authored-by: Thibaut Schaeffer <schaeffer.thibaut@gmail.com>
1 parent 65a2fdd commit 71eaf88

File tree

5 files changed

+238
-135
lines changed

5 files changed

+238
-135
lines changed

backend/src/stwo/circuit_builder.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use core::unreachable;
22
use powdr_ast::parsed::visitor::AllChildren;
33
use powdr_executor_utils::expression_evaluator::{ExpressionEvaluator, TerminalAccess};
44
use std::collections::HashSet;
5-
use std::sync::Arc;
65

76
extern crate alloc;
87
use alloc::collections::btree_map::BTreeMap;
@@ -53,14 +52,18 @@ where
5352
}
5453

5554
pub struct PowdrEval<T> {
56-
analyzed: Arc<Analyzed<T>>,
55+
log_degree: u32,
56+
analyzed: Analyzed<T>,
57+
// the pre-processed are indexed in the whole proof, instead of in each component.
58+
// this offset represents the index of the first pre-processed column in this component
59+
preprocess_col_offset: usize,
5760
witness_columns: BTreeMap<PolyID, usize>,
5861
constant_shifted: BTreeMap<PolyID, usize>,
5962
constant_columns: BTreeMap<PolyID, usize>,
6063
}
6164

6265
impl<T: FieldElement> PowdrEval<T> {
63-
pub fn new(analyzed: Arc<Analyzed<T>>) -> Self {
66+
pub fn new(analyzed: Analyzed<T>, preprocess_col_offset: usize, log_degree: u32) -> Self {
6467
let witness_columns: BTreeMap<PolyID, usize> = analyzed
6568
.definitions_in_source_order(PolynomialType::Committed)
6669
.flat_map(|(symbol, _)| symbol.array_elements())
@@ -86,7 +89,9 @@ impl<T: FieldElement> PowdrEval<T> {
8689
.collect();
8790

8891
Self {
92+
log_degree,
8993
analyzed,
94+
preprocess_col_offset,
9095
witness_columns,
9196
constant_shifted,
9297
constant_columns,
@@ -126,10 +131,10 @@ impl<F: Clone> TerminalAccess<F> for &Data<'_, F> {
126131

127132
impl<T: FieldElement> FrameworkEval for PowdrEval<T> {
128133
fn log_size(&self) -> u32 {
129-
self.analyzed.degree().ilog2()
134+
self.log_degree
130135
}
131136
fn max_constraint_log_degree_bound(&self) -> u32 {
132-
self.analyzed.degree().ilog2() + 1
137+
self.log_degree + 1
133138
}
134139
fn evaluate<E: EvalAtRow>(&self, mut eval: E) -> E {
135140
assert!(
@@ -155,8 +160,9 @@ impl<T: FieldElement> FrameworkEval for PowdrEval<T> {
155160
.map(|(i, poly_id)| {
156161
(
157162
*poly_id,
158-
// PreprocessedColumn::Plonk(i) is unused argument in get_preprocessed_column
159-
eval.get_preprocessed_column(PreprocessedColumn::Plonk(i)),
163+
eval.get_preprocessed_column(PreprocessedColumn::Plonk(
164+
i + self.preprocess_col_offset,
165+
)),
160166
)
161167
})
162168
.collect();
@@ -169,7 +175,7 @@ impl<T: FieldElement> FrameworkEval for PowdrEval<T> {
169175
(
170176
*poly_id,
171177
eval.get_preprocessed_column(PreprocessedColumn::Plonk(
172-
i + constant_eval.len(),
178+
i + constant_eval.len() + self.preprocess_col_offset,
173179
)),
174180
)
175181
})

backend/src/stwo/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ impl<F: FieldElement> BackendFactory<F> for RestrictedFactory {
3939
return Err(Error::BackendError("Proving key unused".to_string()));
4040
}
4141

42-
if pil.degrees().len() > 1 {
43-
return Err(Error::NoVariableDegreeAvailable);
44-
}
45-
4642
let mut stwo: Box<StwoProver<F, SimdBackend, Blake2sMerkleChannel, Blake2sChannel>> =
4743
Box::new(StwoProver::new(pil, fixed)?);
4844

backend/src/stwo/proof.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
use serde::Deserialize;
2-
use serde::Serialize;
1+
use serde::de::DeserializeOwned;
2+
use serde::{Deserialize, Serialize};
33
use std::collections::BTreeMap;
44
use stwo_prover::core::backend::Backend;
55
use stwo_prover::core::backend::Column;
66
use stwo_prover::core::backend::ColumnOps;
7+
use stwo_prover::core::channel::MerkleChannel;
78
use stwo_prover::core::fields::m31::BaseField;
89
use stwo_prover::core::fields::m31::M31;
910
use stwo_prover::core::poly::circle::{CanonicCoset, CircleEvaluation};
1011
use stwo_prover::core::poly::BitReversedOrder;
12+
use stwo_prover::core::prover::StarkProof;
1113
use stwo_prover::core::ColumnVec;
1214

1315
/// For each possible size, the commitment and prover data
@@ -124,3 +126,14 @@ impl<B: Backend> From<StarkProvingKey<B>> for SerializableStarkProvingKey {
124126
Self { preprocessed }
125127
}
126128
}
129+
130+
#[derive(Serialize, Deserialize)]
131+
pub struct Proof<MC: MerkleChannel>
132+
where
133+
MC::H: DeserializeOwned + Serialize,
134+
{
135+
pub stark_proof: StarkProof<MC::H>,
136+
pub constant_col_log_sizes: Vec<u32>,
137+
pub witness_col_log_sizes: Vec<u32>,
138+
pub machine_log_sizes: Vec<u32>,
139+
}

0 commit comments

Comments
 (0)