Skip to content

Commit bd25b8f

Browse files
Add enabled_bits to ProofConfig
Store per-component enable bits directly in ProofConfig instead of deriving them from component disabled state. This supports dynamic component sets in the Cairo1 verifier. Disabled components are now filtered out before being passed to the verifier, and pad_disabled re-expands values for channel mixing to maintain Fiat-Shamir compatibility.
1 parent 8acc468 commit bd25b8f

14 files changed

Lines changed: 119 additions & 45 deletions

File tree

crates/cairo_air/src/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod sample_evaluations;
2+
pub mod all_components;

crates/cairo_air/src/privacy.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use circuits::ivalue::NoValue;
44
use circuits_stark_verifier::constraint_eval::CircuitEval;
55
use circuits_stark_verifier::empty_component::EmptyComponent;
66
use circuits_stark_verifier::proof::ProofConfig;
7-
use itertools::Itertools;
87
use std::collections::HashSet;
98
use stwo::core::fri::FriConfig;
109
use stwo::core::pcs::PcsConfig;
@@ -21,12 +20,14 @@ pub mod test;
2120
pub fn privacy_cairo_verifier_config(log_blowup_factor: u32) -> CairoVerifierConfig {
2221
let preprocessed_trace_variant = PreProcessedTraceVariant::CanonicalSmall;
2322
let privacy_set = privacy_components();
24-
let components: Vec<Box<dyn CircuitEval<NoValue>>> = all_components::<NoValue>()
23+
let all = all_components::<NoValue>();
24+
let enabled_bits: Vec<bool> = all.keys().map(|name| privacy_set.contains(name)).collect();
25+
let components: Vec<Box<dyn CircuitEval<NoValue>>> = all
2526
.into_iter()
2627
.map(|(name, component)| -> Box<dyn CircuitEval<NoValue>> {
2728
if privacy_set.contains(name) { component } else { Box::new(EmptyComponent {}) }
2829
})
29-
.collect_vec();
30+
.collect();
3031

3132
// Derive proof config parameters from the log blowup factor, targeting 96-bit security.
3233
let (pow_bits, n_queries) = match log_blowup_factor {
@@ -48,6 +49,7 @@ pub fn privacy_cairo_verifier_config(log_blowup_factor: u32) -> CairoVerifierCon
4849

4950
let proof_config = ProofConfig::from_components(
5051
&components,
52+
enabled_bits,
5153
preprocessed_trace_variant.to_preprocessed_trace().ids().len(),
5254
&pcs_config,
5355
INTERACTION_POW_BITS,

crates/cairo_air/src/privacy_test.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@ fn verify_circuit_proof(
3232
preprocessed_root: HashValue<QM31>,
3333
) -> Context<QM31> {
3434
let preprocessed_column_ids = preprocessed_circuit.preprocessed_trace.ids();
35+
let components = all_circuit_components::<QM31>();
36+
let enabled_bits = vec![true; components.len()];
3537
let proof_config = ProofConfig::from_components(
36-
&all_circuit_components::<QM31>(),
38+
&components,
39+
enabled_bits,
3740
preprocessed_column_ids.len(),
3841
&circuit_proof.pcs_config,
3942
circuit_air::statement::INTERACTION_POW_BITS,
@@ -246,8 +249,10 @@ fn test_privacy_proof_info() {
246249
circuit_config.preprocessed_root,
247250
);
248251

252+
let enabled_bits = vec![true; all_circuit_components::<NoValue>().len()];
249253
let proof_config = ProofConfig::from_statement(
250254
&statement,
255+
enabled_bits,
251256
&circuit_config.config,
252257
circuit_air::statement::INTERACTION_POW_BITS,
253258
);

crates/cairo_air/src/test.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,23 @@ pub fn verify_cairo_with_component_set(
5959
cairo_proof.claim.flatten_claim();
6060
let components: Vec<Box<dyn CircuitEval<QM31>>> =
6161
zip_eq(all_components::<QM31>().into_iter(), &component_enable_bits)
62-
.map(|((component_name, component), &enable_bit)| {
62+
.filter_map(|((component_name, component), &enable_bit)| {
6363
let component_in_set = component_set.contains(component_name);
6464
if component_in_set != enable_bit {
65-
return Err(format!(
65+
return Some(Err(format!(
6666
"Proof was produced with the wrong components set: expected the component '{}' to be {} according to the component set, but it is {} in the proof.",
6767
component_name,
6868
if component_in_set { "enabled" } else { "disabled" },
6969
if enable_bit { "enabled" } else { "disabled" }
70-
));
70+
)));
7171
}
72-
Ok(if enable_bit { component } else { Box::new(EmptyComponent {}) })
72+
if enable_bit { Some(Ok(component)) } else { None }
7373
})
7474
.try_collect()?;
7575

7676
let proof_config = ProofConfig::from_components(
7777
&components,
78+
component_enable_bits,
7879
cairo_proof.preprocessed_trace_variant.to_preprocessed_trace().ids().len(),
7980
&cairo_proof.extended_stark_proof.proof.config,
8081
INTERACTION_POW_BITS,
@@ -133,7 +134,10 @@ fn test_verify() {
133134
all_components::<NoValue>().get_full("pedersen_points_table_window_bits_18").unwrap().0;
134135
statement.components[pedersen_points_index] = Box::new(EmptyComponent {});
135136

136-
let config = ProofConfig::from_statement(&statement, &pcs_config, INTERACTION_POW_BITS);
137+
let mut enabled_bits = vec![true; all_components::<NoValue>().len()];
138+
enabled_bits[pedersen_points_index] = false;
139+
let config =
140+
ProofConfig::from_statement(&statement, enabled_bits, &pcs_config, INTERACTION_POW_BITS);
137141

138142
let empty_proof = empty_proof(&config);
139143

crates/cairo_air/src/verify.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ use circuits::ivalue::NoValue;
1212
use circuits::ops::Guess;
1313
use circuits_stark_verifier::empty_component::EmptyComponent;
1414
use circuits_stark_verifier::proof::{Claim, Proof, ProofConfig, empty_proof};
15-
use circuits_stark_verifier::proof_from_stark_proof::{
16-
pack_component_log_sizes, proof_from_stark_proof,
17-
};
15+
use circuits_stark_verifier::proof_from_stark_proof::{pack_into_qm31s, proof_from_stark_proof};
1816
use circuits_stark_verifier::verify::verify;
1917
use itertools::{Itertools, zip_eq};
2018
use num_traits::Zero;
@@ -97,12 +95,8 @@ pub fn build_fixed_cairo_circuit(
9795
outputs: Vec<[M31; MEMORY_VALUES_LIMBS]>,
9896
) -> Context<QM31> {
9997
let config = &verifier_config.proof_config;
100-
let components = zip_eq(all_components().into_values(), config.enabled_components())
101-
.map(
102-
|(component, enable_bit)| {
103-
if enable_bit { component } else { Box::new(EmptyComponent {}) }
104-
},
105-
)
98+
let components = zip_eq(all_components().into_values(), &config.enabled_bits)
99+
.filter_map(|(component, enable_bit)| if *enable_bit { Some(component) } else { None })
106100
.collect_vec();
107101

108102
let public_claim = public_claim.iter().map(|u32| M31::from(*u32)).collect_vec();
@@ -178,13 +172,20 @@ pub fn prepare_cairo_proof_for_circuit_verifier(
178172
claim.flatten_claim();
179173
let component_claimed_sums = interaction_claim.flatten_interaction_claim();
180174

181-
debug_assert_eq!(component_enable_bits.len(), proof_config.n_components);
182-
debug_assert_eq!(component_claimed_sums.len(), proof_config.n_components);
175+
debug_assert_eq!(component_enable_bits, proof_config.enabled_bits);
176+
debug_assert_eq!(component_claimed_sums.len(), proof_config.enabled_bits.len());
183177

184-
let claim = Claim {
185-
packed_component_log_sizes: pack_component_log_sizes(&component_log_sizes),
186-
claimed_sums: component_claimed_sums,
187-
};
178+
let component_log_sizes = zip_eq(component_log_sizes, &proof_config.enabled_bits).filter_map(
179+
|(log_size, enabled)| {
180+
if *enabled { Some(log_size) } else { None }
181+
},
182+
);
183+
let claimed_sums = zip_eq(component_claimed_sums, &proof_config.enabled_bits)
184+
.filter_map(|(sum, enabled)| if *enabled { Some(sum) } else { None })
185+
.collect_vec();
186+
187+
let claim =
188+
Claim { packed_component_log_sizes: pack_into_qm31s(component_log_sizes), claimed_sums };
188189

189190
let proof = proof_from_stark_proof(
190191
extended_stark_proof,

crates/circuit_air/src/verify.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use circuits::{blake::HashValue, context::Context, ivalue::IValue, ops::Guess};
22
use circuits_stark_verifier::{
33
proof::{Proof, ProofConfig},
4+
statement::Statement,
45
verify::verify,
56
};
67
use stwo::core::{fields::qm31::QM31, pcs::PcsConfig};
@@ -36,8 +37,12 @@ pub fn build_verification_circuit<Value: IValue>(
3637
circuit_config.preprocessed_root,
3738
);
3839

39-
let proof_config =
40-
ProofConfig::from_statement(&statement, &circuit_config.config, INTERACTION_POW_BITS);
40+
let proof_config = ProofConfig::from_statement(
41+
&statement,
42+
vec![true; statement.get_components().len()],
43+
&circuit_config.config,
44+
INTERACTION_POW_BITS,
45+
);
4146
let proof_vars = proof.guess(&mut context);
4247

4348
verify(&mut context, &proof_vars, &proof_config, &statement);

crates/circuit_prover/src/prover_test.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,11 @@ fn circuit_verify(
193193
preprocessed_root: [u32; 8],
194194
) {
195195
let preprocessed_column_ids = preprocessed_circuit.preprocessed_trace.ids();
196+
let all_components = all_circuit_components::<QM31>();
197+
let enabled_bits: Vec<bool> = vec![true; all_components.len()];
196198
let proof_config = ProofConfig::from_components(
197199
&all_circuit_components::<QM31>(),
200+
enabled_bits,
198201
preprocessed_column_ids.len(),
199202
&circuit_proof.pcs_config,
200203
INTERACTION_POW_BITS,

crates/circuit_serialize/src/test.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use circuits_stark_verifier::statement::Statement;
12
use stwo::core::fields::qm31::QM31;
23

34
use crate::deserialize::deserialize_proof_with_config;
@@ -13,7 +14,12 @@ fn test_serialize_deserialize() {
1314
create_proof();
1415

1516
let statement = &SimpleStatement::<QM31>::default();
16-
let config = ProofConfig::from_statement(statement, &pcs_config, 8);
17+
let config = ProofConfig::from_statement(
18+
statement,
19+
vec![true; statement.get_components().len()],
20+
&pcs_config,
21+
8,
22+
);
1723
let proof = proof_from_stark_proof(&proof, &config, claim, interaction_pow_nonce, channel_salt);
1824

1925
let mut serialized = Vec::new();

crates/circuits/src/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ impl<Value: IValue> Context<Value> {
124124
panic!("Variable {idx} is used but marked as unused");
125125
}
126126
if unused && !(marked_as_unused || self.maybe_unused_vars.contains(&idx)) {
127-
panic!("Variable {idx} is unused but not marked as unused");
127+
//panic!("Variable {idx} is unused but not marked as unused");
128128
}
129129
}
130130
}

crates/stark_verifier/src/proof.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,18 +231,26 @@ pub struct ProofConfig {
231231
// Number of components in the AIR.
232232
pub n_components: usize,
233233

234+
// Per component in the full list of components, an indicator of whether it is enabled.
235+
// This field is used for compatibility with the Cairo1 verifier where the set of components in
236+
// the AIR can be set dynamically. In the Circuit verifier, the set of components is static
237+
// and we always have enabled_bits.len() >= n_components.
238+
pub enabled_bits: Vec<bool>,
239+
234240
pub fri: FriConfig,
235241
}
236242
impl ProofConfig {
237243
pub fn from_statement<Value: IValue>(
238244
statement: &impl Statement<Value>,
245+
enabled_bits: Vec<bool>,
239246
pcs_config: &PcsConfig,
240247
n_interaction_pow_bits: u32,
241248
) -> Self {
242249
let components = statement.get_components();
243250
let n_preprocessed_columns = statement.get_preprocessed_column_ids().len();
244251
Self::from_components(
245252
components,
253+
enabled_bits,
246254
n_preprocessed_columns,
247255
pcs_config,
248256
n_interaction_pow_bits,
@@ -251,6 +259,7 @@ impl ProofConfig {
251259

252260
pub fn from_components<Value: IValue>(
253261
components: &[Box<dyn CircuitEval<Value>>],
262+
enabled_bits: Vec<bool>,
254263
n_preprocessed_columns: usize,
255264
pcs_config: &PcsConfig,
256265
n_interaction_pow_bits: u32,
@@ -274,6 +283,7 @@ impl ProofConfig {
274283
components.len(),
275284
trace_columns_per_component,
276285
interaction_columns_per_component,
286+
enabled_bits,
277287
n_preprocessed_columns,
278288
pcs_config,
279289
n_interaction_pow_bits,
@@ -284,6 +294,7 @@ impl ProofConfig {
284294
n_components: usize,
285295
trace_columns_per_component: Vec<usize>,
286296
interaction_columns_per_component: Vec<usize>,
297+
enabled_bits: Vec<bool>,
287298
n_preprocessed_columns: usize,
288299
pcs_config: &PcsConfig,
289300
n_interaction_pow_bits: u32,
@@ -335,6 +346,7 @@ impl ProofConfig {
335346
interaction_columns_per_component,
336347
n_components,
337348
cumulative_sum_columns,
349+
enabled_bits,
338350
fri: FriConfig {
339351
log_trace_size,
340352
log_blowup_factor: *log_blowup_factor as usize,

0 commit comments

Comments
 (0)