Skip to content

Commit a95c8f1

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 a95c8f1

16 files changed

Lines changed: 136 additions & 71 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/statement.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,12 @@ impl<Value: IValue> CairoStatement<Value> {
163163
///
164164
/// Assumes that the start and end addresses of the segment ranges are less than 2^27 (this is
165165
/// guaranteed by `segment_ranges_logup_sum`).
166-
pub fn verify_builtins(&self, context: &mut Context<Value>, component_sizes: &[Var]) {
166+
pub fn verify_builtins(
167+
&self,
168+
context: &mut Context<Value>,
169+
component_sizes: &[Var],
170+
enable_bits: &[bool],
171+
) {
167172
let [
168173
output_segment_range,
169174
pedersen_segment_range,
@@ -241,9 +246,10 @@ impl<Value: IValue> CairoStatement<Value> {
241246

242247
for ((name, _size), actual_uses) in zip_eq(builtin_instance_sizes, actual_uses_iter) {
243248
let index = all_components.get_index_of(name).unwrap();
244-
if self.components[index].is_disabled() {
249+
if !enable_bits[index] {
245250
// Component is disabled - actual_uses must be 0.
246251
eq(context, actual_uses, context.zero());
252+
continue;
247253
}
248254

249255
let component_size = component_sizes[index];
@@ -404,10 +410,11 @@ impl<Value: IValue> Statement<Value> for CairoStatement<Value> {
404410
context: &mut Context<Value>,
405411
component_sizes: &[Var],
406412
shifted_relation_uses: &HashMap<&'static str, Var>,
413+
enable_bits: &[bool],
407414
) {
408415
let PublicData { initial_state, final_state, public_memory: _ } = &self.public_data;
409416

410-
self.verify_builtins(context, component_sizes);
417+
self.verify_builtins(context, component_sizes, enable_bits);
411418
// TODO(ilya): Consider adding sanity checks on the content of the program segment.
412419

413420
let CasmState { pc: initial_pc, ap: initial_ap, fp: initial_fp } = initial_state;

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
}

0 commit comments

Comments
 (0)