Skip to content

Commit 9d9af7f

Browse files
alon-fclaude
andcommitted
Add BlakeGGate AIR component with full prove+verify
Integrates the auto-generated BlakeGGate into the circuit prover: - BlakeGGate added to ComponentList, CircuitComponents, trace writing, interaction trace, statement, and prover - Preprocessed column IDs renamed to match the AIR (blake_g_gate_input_addr_a/b/c/d/f0/f1, blake_g_gate_output_addr_a/b/c/d, blake_g_gate_multiplicity) - Padding for blake_g gates in finalize_context - Full prove+verify test (test_prove_and_stark_verify_blake_g_gate_context) - Updated FIBONACCI_CIRCUIT_PREPROCESSED_ROOT for N_COMPONENTS=18 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent fd97a69 commit 9d9af7f

16 files changed

Lines changed: 215 additions & 103 deletions

File tree

_typos.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
[files]
22
extend-exclude = [
33
"crates/cairo_air/src/components/",
4+
"crates/circuit_air/src/circuit_eval_components/",
5+
"crates/circuit_air/src/components/",
6+
"crates/circuit_prover/src/witness/components/",
47
"test_data/privacy/privacy_simple_bootloader_compiled.json",
58
]
69
[default.extend-words]

crates/cairo_air/src/privacy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub const PRIVACY_CAIRO_VERIFIER_CONSTS_HASH: [u32; 8] =
2121
[628232622, 595225213, 313313883, 84916707, 1055901365, 2035362632, 1591192737, 169200];
2222

2323
pub const PRIVACY_RECURSION_CIRCUIT_CONSTS_HASH: [u32; 8] =
24-
[265232987, 822253498, 1042354533, 1199589796, 811253900, 1354313564, 985444759, 349528097];
24+
[1113069059, 1898251533, 1233855572, 2065402037, 43826136, 1485963904, 73733830, 1152555881];
2525

2626
pub const PRIVACY_RECURSION_CIRCUIT_PREPROCESSED_ROOT: [u32; 8] =
2727
[736666193, 671587538, 1100540541, 1401951855, 202000446, 1284259076, 1586213897, 825089717];

crates/cairo_air/src/privacy_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,5 +314,5 @@ fn test_privacy_proof_info() {
314314
let proof_info = ProofInfo::from_config(&proof_config);
315315
println!("{proof_info}");
316316
// Assert the total size in bytes.
317-
assert_eq!(proof_info.total_bytes(), 344348);
317+
assert_eq!(proof_info.total_bytes(), 373140);
318318
}

crates/circuit_air/src/circuit_eval_components/m_31_to_u_32.rs

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@ pub const N_TRACE_COLUMNS: usize = 4;
44
pub const N_INTERACTION_COLUMNS: usize = 12;
55

66
pub const RELATION_USES_PER_ROW: [RelationUse; 2] = [
7-
RelationUse {
8-
relation_id: "Gate",
9-
uses: 1,
10-
},
11-
RelationUse {
12-
relation_id: "RangeCheck_16",
13-
uses: 3,
14-
},
7+
RelationUse { relation_id: "Gate", uses: 1 },
8+
RelationUse { relation_id: "RangeCheck_16", uses: 3 },
159
];
1610

1711
#[allow(unused_variables)]
@@ -23,44 +17,31 @@ pub fn accumulate_constraints<Value: IValue>(
2317
) {
2418
let [input_m31_col0, input_u32_limb_0_col1, input_u32_limb_1_col2, inv_or_one_col3] =
2519
input.try_into().unwrap();
26-
let m31_to_u32_input_addr = acc.get_preprocessed_column(&PreProcessedColumnId {
27-
id: "m31_to_u32_input_addr".to_owned(),
28-
});
20+
let m31_to_u32_input_addr = acc
21+
.get_preprocessed_column(&PreProcessedColumnId { id: "m31_to_u32_input_addr".to_owned() });
2922
let m31_to_u32_multiplicity = acc.get_preprocessed_column(&PreProcessedColumnId {
3023
id: "m31_to_u32_multiplicity".to_owned(),
3124
});
32-
let m31_to_u32_output_addr = acc.get_preprocessed_column(&PreProcessedColumnId {
33-
id: "m31_to_u32_output_addr".to_owned(),
34-
});
25+
let m31_to_u32_output_addr = acc
26+
.get_preprocessed_column(&PreProcessedColumnId { id: "m31_to_u32_output_addr".to_owned() });
3527
// Use RangeCheck_16.
36-
let tuple_0 = &[
37-
eval!(context, 1008385708),
38-
eval!(context, input_u32_limb_0_col1),
39-
];
28+
let tuple_0 = &[eval!(context, 1008385708), eval!(context, input_u32_limb_0_col1)];
4029
let numerator_0 = eval!(context, 1);
4130
acc.add_to_relation(context, numerator_0, tuple_0);
4231

4332
// Use RangeCheck_16.
44-
let tuple_1 = &[
45-
eval!(context, 1008385708),
46-
eval!(context, input_u32_limb_1_col2),
47-
];
33+
let tuple_1 = &[eval!(context, 1008385708), eval!(context, input_u32_limb_1_col2)];
4834
let numerator_1 = eval!(context, 1);
4935
acc.add_to_relation(context, numerator_1, tuple_1);
5036

5137
// Use RangeCheck_16.
52-
let tuple_2 = &[
53-
eval!(context, 1008385708),
54-
eval!(context, (32767) - (input_u32_limb_1_col2)),
55-
];
38+
let tuple_2 = &[eval!(context, 1008385708), eval!(context, (32767) - (input_u32_limb_1_col2))];
5639
let numerator_2 = eval!(context, 1);
5740
acc.add_to_relation(context, numerator_2, tuple_2);
5841

5942
//input is zero then limb_low is zero.
60-
let constraint_3_value = eval!(
61-
context,
62-
(((input_m31_col0) * (inv_or_one_col3)) - (1)) * (input_u32_limb_0_col1)
63-
);
43+
let constraint_3_value =
44+
eval!(context, (((input_m31_col0) * (inv_or_one_col3)) - (1)) * (input_u32_limb_0_col1));
6445
acc.add_constraint(context, constraint_3_value);
6546

6647
//input reconstruction.
@@ -164,24 +145,16 @@ mod tests {
164145
];
165146
let preprocessed_columns = HashMap::from([
166147
(
167-
PreProcessedColumnId {
168-
id: "m31_to_u32_input_addr".to_owned(),
169-
},
148+
PreProcessedColumnId { id: "m31_to_u32_input_addr".to_owned() },
170149
context.constant(qm31_from_u32s(15668215, 1851966168, 874056991, 2075313468)),
171150
),
172151
(
173-
PreProcessedColumnId {
174-
id: "m31_to_u32_output_addr".to_owned(),
175-
},
152+
PreProcessedColumnId { id: "m31_to_u32_output_addr".to_owned() },
176153
context.constant(qm31_from_u32s(701904311, 1125291129, 1904795215, 38357025)),
177154
),
178155
(
179-
PreProcessedColumnId {
180-
id: "m31_to_u32_multiplicity".to_owned(),
181-
},
182-
context.constant(qm31_from_u32s(
183-
1979029033, 1524573277, 1930122227, 1490762084,
184-
)),
156+
PreProcessedColumnId { id: "m31_to_u32_multiplicity".to_owned() },
157+
context.constant(qm31_from_u32s(1979029033, 1524573277, 1930122227, 1490762084)),
185158
),
186159
]);
187160
let public_params = HashMap::from([]);

crates/circuit_air/src/components/m_31_to_u_32.rs

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,8 @@ use crate::components::prelude::*;
22

33
pub const N_TRACE_COLUMNS: usize = 4;
44
pub const RELATION_USES_PER_ROW: [RelationUse; 2] = [
5-
RelationUse {
6-
relation_id: "Gate",
7-
uses: 1,
8-
},
9-
RelationUse {
10-
relation_id: "RangeCheck_16",
11-
uses: 3,
12-
},
5+
RelationUse { relation_id: "Gate", uses: 1 },
6+
RelationUse { relation_id: "RangeCheck_16", uses: 3 },
137
];
148

159
pub struct Eval {
@@ -92,10 +86,7 @@ impl FrameworkEval for Eval {
9286
eval.add_to_relation(RelationEntry::new(
9387
&self.common_lookup_elements,
9488
E::EF::one(),
95-
&[
96-
M31_1008385708.clone(),
97-
(M31_32767.clone() - input_u32_limb_1_col2.clone()),
98-
],
89+
&[M31_1008385708.clone(), (M31_32767.clone() - input_u32_limb_1_col2.clone())],
9990
));
10091

10192
//input is zero then limb_low is zero.
@@ -112,11 +103,7 @@ impl FrameworkEval for Eval {
112103
eval.add_to_relation(RelationEntry::new(
113104
&self.common_lookup_elements,
114105
E::EF::one(),
115-
&[
116-
M31_378353459.clone(),
117-
m31_to_u32_input_addr.clone(),
118-
input_m31_col0.clone(),
119-
],
106+
&[M31_378353459.clone(), m31_to_u32_input_addr.clone(), input_m31_col0.clone()],
120107
));
121108

122109
eval.add_to_relation(RelationEntry::new(

crates/circuit_air/src/components/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ define_component_list! {
4242
BlakeG,
4343
BlakeOutput,
4444
TripleXor32,
45+
BlakeGGate,
4546
M31ToU32,
4647
TripleXor,
4748
VerifyBitwiseXor8,
@@ -62,6 +63,7 @@ pub struct CircuitComponents {
6263
pub blake_g: blake_g::Component,
6364
pub blake_output: blake_output::Component,
6465
pub triple_xor_32: triple_xor_32::Component,
66+
pub blake_g_gate: blake_g_gate::Component,
6567
pub m_31_to_u_32: m_31_to_u_32::Component,
6668
pub triple_xor: triple_xor::Component,
6769
pub verify_bitwise_xor_8: verify_bitwise_xor_8::Component,
@@ -157,6 +159,16 @@ impl CircuitComponents {
157159
},
158160
interaction_claim.claimed_sums[ComponentList::TripleXor32 as usize],
159161
);
162+
let blake_g_gate_component = blake_g_gate::Component::new(
163+
tree_span_provider,
164+
blake_g_gate::Eval {
165+
claim: blake_g_gate::Claim {
166+
log_size: circuit_claim.log_sizes[ComponentList::BlakeGGate as usize],
167+
},
168+
common_lookup_elements: interaction_elements.common_lookup_elements.clone(),
169+
},
170+
interaction_claim.claimed_sums[ComponentList::BlakeGGate as usize],
171+
);
160172
let m_31_to_u_32_component = m_31_to_u_32::Component::new(
161173
tree_span_provider,
162174
m_31_to_u_32::Eval {
@@ -242,6 +254,7 @@ impl CircuitComponents {
242254
blake_g: blake_g_component,
243255
blake_output: blake_output_component,
244256
triple_xor_32: triple_xor_32_component,
257+
blake_g_gate: blake_g_gate_component,
245258
m_31_to_u_32: m_31_to_u_32_component,
246259
triple_xor: triple_xor_component,
247260
verify_bitwise_xor_8: verify_bitwise_xor_8_component,
@@ -264,6 +277,7 @@ impl CircuitComponents {
264277
Box::new(self.blake_g) as Box<dyn Component>,
265278
Box::new(self.blake_output) as Box<dyn Component>,
266279
Box::new(self.triple_xor_32) as Box<dyn Component>,
280+
Box::new(self.blake_g_gate) as Box<dyn Component>,
267281
Box::new(self.m_31_to_u_32) as Box<dyn Component>,
268282
Box::new(self.triple_xor) as Box<dyn Component>,
269283
Box::new(self.verify_bitwise_xor_8) as Box<dyn Component>,

crates/circuit_air/src/statement.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::circuit_eval_components::{
2-
blake_g, blake_gate, blake_output, blake_round, blake_round_sigma, m_31_to_u_32,
2+
blake_g, blake_g_gate, blake_gate, blake_output, blake_round, blake_round_sigma, m_31_to_u_32,
33
range_check_15, range_check_16, triple_xor, triple_xor_32, verify_bitwise_xor_4,
44
verify_bitwise_xor_7, verify_bitwise_xor_8, verify_bitwise_xor_9, verify_bitwise_xor_12,
55
};
@@ -152,6 +152,7 @@ pub fn all_circuit_components<Value: IValue>() -> Vec<Box<dyn CircuitEval<Value>
152152
Box::new(blake_g::Component {}),
153153
Box::new(blake_output::Component {}),
154154
Box::new(triple_xor_32::Component {}),
155+
Box::new(blake_g_gate::Component {}),
155156
Box::new(m_31_to_u_32::Component {}),
156157
Box::new(triple_xor::Component {}),
157158
Box::new(verify_bitwise_xor_8::Component {}),

crates/circuit_common/src/finalize.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::N_LANES;
22
use circuits::blake::{HashValue, blake};
3-
use circuits::circuit::{M31ToU32Gate, TripleXorGate};
3+
use circuits::circuit::{BlakeGGate, M31ToU32Gate, TripleXorGate};
44
use circuits::context::{Context, Var};
55
use circuits::eval;
66
use circuits::ivalue::{IValue, qm31_from_u32s};
@@ -54,6 +54,30 @@ fn pad_blake(context: &mut Context<impl IValue>) {
5454
}
5555
}
5656

57+
fn pad_blake_g(context: &mut Context<impl IValue>) {
58+
let n_rows = context.circuit.blake_g.len();
59+
let padded = std::cmp::max(n_rows.next_power_of_two(), N_LANES);
60+
let zero = context.zero();
61+
for _ in n_rows..padded {
62+
let out_a = context.new_var(IValue::from_qm31(0.into()));
63+
let out_b = context.new_var(IValue::from_qm31(0.into()));
64+
let out_c = context.new_var(IValue::from_qm31(0.into()));
65+
let out_d = context.new_var(IValue::from_qm31(0.into()));
66+
context.circuit.blake_g.push(BlakeGGate {
67+
a: zero.idx,
68+
b: zero.idx,
69+
c: zero.idx,
70+
d: zero.idx,
71+
m0: zero.idx,
72+
m1: zero.idx,
73+
out_a: out_a.idx,
74+
out_b: out_b.idx,
75+
out_c: out_c.idx,
76+
out_d: out_d.idx,
77+
});
78+
}
79+
}
80+
5781
fn pad_m31_to_u32(context: &mut Context<impl IValue>) {
5882
let n_rows = context.circuit.m31_to_u32.len();
5983
let padded = std::cmp::max(n_rows.next_power_of_two(), N_LANES);
@@ -72,10 +96,12 @@ fn pad_triple_xor(context: &mut Context<impl IValue>) {
7296
for _ in n_rows..padded {
7397
// Pad with gates that XOR zeros: 0 ^ 0 ^ 0 = 0.
7498
let out = context.new_var(IValue::from_qm31(0.into()));
75-
context
76-
.circuit
77-
.triple_xor
78-
.push(TripleXorGate { a: zero.idx, b: zero.idx, c: zero.idx, out: out.idx });
99+
context.circuit.triple_xor.push(TripleXorGate {
100+
a: zero.idx,
101+
b: zero.idx,
102+
c: zero.idx,
103+
out: out.idx,
104+
});
79105
}
80106
}
81107

@@ -102,6 +128,7 @@ pub fn finalize_context(context: &mut Context<impl IValue>) {
102128
pad_eq(context);
103129
pad_qm31_ops(context);
104130
pad_blake(context);
131+
pad_blake_g(context);
105132
pad_m31_to_u32(context);
106133
pad_triple_xor(context);
107134
}

crates/circuit_common/src/preprocessed.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -397,11 +397,7 @@ fn add_m31_to_u32_to_preprocessed_trace(
397397
let mut columns: [_; N_M31_TO_U32_PP_COLUMNS] = std::array::from_fn(|_| vec![]);
398398
fill_m31_to_u32_columns(&circuit.m31_to_u32, multiplicities, &mut columns);
399399

400-
let ids = [
401-
"m31_to_u32_input_addr",
402-
"m31_to_u32_output_addr",
403-
"m31_to_u32_multiplicity",
404-
];
400+
let ids = ["m31_to_u32_input_addr", "m31_to_u32_output_addr", "m31_to_u32_multiplicity"];
405401
for (id, column) in zip_eq(ids, columns) {
406402
pp_trace.push_column(PreProcessedColumnId { id: id.to_owned() }, column);
407403
}
@@ -459,17 +455,17 @@ fn add_blake_g_to_preprocessed_trace(
459455
fill_blake_g_columns(&circuit.blake_g, multiplicities, &mut columns);
460456

461457
let ids = [
462-
"blake_g_a_address",
463-
"blake_g_b_address",
464-
"blake_g_c_address",
465-
"blake_g_d_address",
466-
"blake_g_m0_address",
467-
"blake_g_m1_address",
468-
"blake_g_out_a_address",
469-
"blake_g_out_b_address",
470-
"blake_g_out_c_address",
471-
"blake_g_out_d_address",
472-
"blake_g_mult",
458+
"blake_g_gate_input_addr_a",
459+
"blake_g_gate_input_addr_b",
460+
"blake_g_gate_input_addr_c",
461+
"blake_g_gate_input_addr_d",
462+
"blake_g_gate_input_addr_f0",
463+
"blake_g_gate_input_addr_f1",
464+
"blake_g_gate_output_addr_a",
465+
"blake_g_gate_output_addr_b",
466+
"blake_g_gate_output_addr_c",
467+
"blake_g_gate_output_addr_d",
468+
"blake_g_gate_multiplicity",
473469
];
474470
for (id, column) in zip_eq(ids, columns) {
475471
pp_trace.push_column(PreProcessedColumnId { id: id.to_owned() }, column);

crates/circuit_common/src/preprocessed_test.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,12 @@ fn test_preprocess_decomposed_gates() {
196196
assert!(m31_mult.iter().all(|&m| m > 0));
197197

198198
// Verify BlakeG columns exist and have correct addresses.
199-
let bg_a = pp_trace.get_column(&PreProcessedColumnId { id: "blake_g_a_address".to_owned() });
199+
let bg_a =
200+
pp_trace.get_column(&PreProcessedColumnId { id: "blake_g_gate_input_addr_a".to_owned() });
200201
let bg_out_a =
201-
pp_trace.get_column(&PreProcessedColumnId { id: "blake_g_out_a_address".to_owned() });
202-
let bg_mult = pp_trace.get_column(&PreProcessedColumnId { id: "blake_g_mult".to_owned() });
202+
pp_trace.get_column(&PreProcessedColumnId { id: "blake_g_gate_output_addr_a".to_owned() });
203+
let bg_mult =
204+
pp_trace.get_column(&PreProcessedColumnId { id: "blake_g_gate_multiplicity".to_owned() });
203205
assert_eq!(bg_a.len(), 16);
204206
assert_eq!(bg_a[0], 16); // First gate's a = wire 16.
205207
assert_eq!(bg_out_a[0], 32); // First gate's out_a = wire 32.

0 commit comments

Comments
 (0)