Skip to content

Commit e7053d7

Browse files
committed
Integrate finalize_constants in the main flow.
1 parent 7fe8a65 commit e7053d7

17 files changed

Lines changed: 149 additions & 132 deletions

File tree

crates/cairo_verifier/src/statement_test.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::statement::{
22
CasmState, PubMemoryM31Value, PublicData, PublicMemory, SegmentRange, public_logup_sum,
33
};
44
use circuits::context::{TraceContext, Var};
5+
use circuits::finalize_constants::finalize_constants;
56
use circuits::ivalue::qm31_from_u32s;
67
use circuits::wrappers::M31Wrapper;
78

@@ -261,6 +262,7 @@ fn test_public_logup_sum() {
261262
assert_eq!(result_value, expected);
262263

263264
// Validate the circuit
265+
finalize_constants(&mut context);
264266
context.check_vars_used();
265267
context.finalize_guessed_vars();
266268
context.circuit.check_yields();

crates/cairo_verifier/src/test.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use cairo_air::utils::{binary_deserialize_from_file, binary_serialize_to_file};
99
use cairo_air::verifier::INTERACTION_POW_BITS;
1010
use cairo_vm::types::layout_name::LayoutName;
1111
use circuits::context::Context;
12+
use circuits::finalize_constants::finalize_constants;
1213
use circuits::ivalue::NoValue;
1314
use circuits::ops::Guess;
1415
use circuits_stark_verifier::constraint_eval::CircuitEval;
@@ -146,6 +147,7 @@ fn test_verify() {
146147

147148
let proof_vars = empty_proof.guess(&mut novalue_context);
148149
verify(&mut novalue_context, &proof_vars, &config, &statement);
150+
finalize_constants(&mut novalue_context);
149151
novalue_context.finalize_guessed_vars();
150152
novalue_context.check_vars_used();
151153
novalue_context.circuit.check_yields();

crates/cairo_verifier/src/verify.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use cairo_air::air::PublicData;
77
use cairo_air::flat_claims::FlatClaim;
88
use circuits::blake::HashValue;
99
use circuits::context::{Context, TraceContext};
10+
use circuits::finalize_constants::finalize_constants;
1011
use circuits::ivalue::{IValue, NoValue};
1112
use circuits::ops::Guess;
1213
use circuits_stark_verifier::constraint_eval::CircuitEval;
@@ -124,6 +125,7 @@ pub fn build_fixed_cairo_circuit(
124125

125126
let proof_vars = proof.guess(&mut context);
126127
verify(&mut context, &proof_vars, config, &statement);
128+
finalize_constants(&mut context);
127129
context.finalize_guessed_vars();
128130

129131
context
@@ -155,6 +157,7 @@ pub fn build_cairo_verifier_circuit(verifier_config: &CairoVerifierConfig) -> Co
155157

156158
let proof_vars = empty_proof(config).guess(&mut context);
157159
verify(&mut context, &proof_vars, config, &statement);
160+
finalize_constants(&mut context);
158161
context.finalize_guessed_vars();
159162
context
160163
}

crates/circuit_common/src/finalize.rs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::N_LANES;
2-
use circuits::blake::{HashValue, blake, blake_g_gate};
3-
use circuits::context::{Context, Var};
2+
use circuits::blake::blake_g_gate;
3+
use circuits::context::Context;
44
use circuits::eval;
55
use circuits::ivalue::{IValue, qm31_from_u32s};
6-
use circuits::ops::{eq, output};
6+
use circuits::ops::eq;
77
use rand_chacha::rand_core::{RngCore, SeedableRng};
88

99
fn pad_qm31_ops(context: &mut Context<impl IValue>) {
@@ -80,25 +80,12 @@ fn pad_blake_g_gate(context: &mut Context<impl IValue>) {
8080
}
8181
}
8282

83-
fn hash_constants(context: &mut Context<impl IValue>) -> HashValue<Var> {
84-
let constants: Vec<_> = context.constants().values().copied().collect();
85-
let n_bytes = constants.len() * 16;
86-
blake(context, &constants, n_bytes)
87-
}
88-
89-
/// Finalizes the context by appending gates to the context for:
90-
/// - Hashing the constants.
91-
/// - Hashing the outputs.
92-
/// - Padding the components to a power of two.
83+
/// Pad the components to a power of two.
84+
/// Appends gates to the context so that the resulting AIR components have length equal to a power
85+
/// of two.
9386
// TODO(Gali): Have it under a trait.
9487
// TODO(Ilya): Make it pub(crate).
9588
pub fn finalize_context(context: &mut Context<impl IValue>) {
96-
let HashValue(hash0, hash1) = hash_constants(context);
97-
// Add the hash of the constants to the outputs.
98-
// TODO(Leo): consider storing these values at a fixed address.
99-
output(context, hash0);
100-
output(context, hash1);
101-
10289
// Padding the components to a power of two.
10390
pad_eq(context);
10491
pad_qm31_ops(context);

crates/circuit_prover/src/prover_test.rs

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use circuit_verifier::verify::{CircuitConfig, verify_circuit};
1010
use circuits::blake::{blake, blake_g_gate, m31_to_u32, triple_xor};
1111
use circuits::context::Var;
1212
use circuits::eval;
13+
use circuits::finalize_constants::finalize_constants;
1314
use circuits::ivalue::{IValue, qm31_from_u32s};
1415
use circuits::ops::{output, permute};
1516
use circuits::{context::Context, ops::guess};
@@ -21,6 +22,7 @@ use stwo::core::channel::Blake2sM31Channel;
2122
use stwo::core::channel::Channel;
2223
use stwo::core::fields::qm31::QM31;
2324
use stwo::core::pcs::{CommitmentSchemeVerifier, PcsConfig};
25+
use stwo::core::vcs::blake2_hash::Blake2sHash;
2426
use stwo::core::vcs_lifted::blake2_merkle::Blake2sM31MerkleChannel;
2527
use stwo::core::vcs_lifted::blake2_merkle::Blake2sM31MerkleHasher;
2628
// Not a power of 2 so that we can test component padding.
@@ -247,6 +249,7 @@ fn stwo_verify(
247249
#[test]
248250
fn test_prove_and_stark_verify_blake_gate_context() {
249251
let mut blake_gate_context = build_blake_gate_context();
252+
finalize_constants(&mut blake_gate_context);
250253
blake_gate_context.finalize_guessed_vars();
251254
blake_gate_context.validate_circuit();
252255

@@ -264,6 +267,7 @@ fn test_prove_and_stark_verify_blake_gate_context() {
264267
#[test]
265268
fn test_prove_and_stark_verify_permutation_context() {
266269
let mut permutation_context = build_permutation_context();
270+
finalize_constants(&mut permutation_context);
267271
permutation_context.finalize_guessed_vars();
268272
permutation_context.validate_circuit();
269273

@@ -281,6 +285,7 @@ fn test_prove_and_stark_verify_permutation_context() {
281285
#[test]
282286
fn test_prove_and_stark_verify_fibonacci_context() {
283287
let mut fibonacci_context = build_fibonacci_context();
288+
finalize_constants(&mut fibonacci_context);
284289
fibonacci_context.finalize_guessed_vars();
285290
fibonacci_context.validate_circuit();
286291

@@ -298,6 +303,7 @@ fn test_prove_and_stark_verify_fibonacci_context() {
298303
#[test]
299304
fn test_prove_and_stark_verify_triple_xor_context() {
300305
let mut triple_xor_context = build_triple_xor_context();
306+
finalize_constants(&mut triple_xor_context);
301307
triple_xor_context.finalize_guessed_vars();
302308
triple_xor_context.validate_circuit();
303309

@@ -315,6 +321,7 @@ fn test_prove_and_stark_verify_triple_xor_context() {
315321
#[test]
316322
fn test_prove_and_stark_verify_m31_to_u32_context() {
317323
let mut m31_to_u32_context = build_m31_to_u32_context();
324+
finalize_constants(&mut m31_to_u32_context);
318325
m31_to_u32_context.finalize_guessed_vars();
319326
m31_to_u32_context.validate_circuit();
320327

@@ -332,6 +339,7 @@ fn test_prove_and_stark_verify_m31_to_u32_context() {
332339
#[test]
333340
fn test_prove_and_stark_verify_blake_g_gate_context() {
334341
let mut blake_g_gate_context = build_blake_g_gate_context();
342+
finalize_constants(&mut blake_g_gate_context);
335343
blake_g_gate_context.finalize_guessed_vars();
336344
blake_g_gate_context.validate_circuit();
337345

@@ -374,12 +382,10 @@ fn circuit_verify(
374382
verify_circuit(circuit_config, proof, public_data).unwrap();
375383
}
376384

377-
const TRIPLE_XOR_CIRCUIT_PREPROCESSED_ROOT: [u32; 8] =
378-
[383878560, 777803796, 83194896, 1011084203, 160550306, 637440927, 339198671, 1031359971];
379-
380385
#[test]
381386
fn test_prove_and_circuit_verify_triple_xor_context() {
382387
let mut triple_xor_context = build_triple_xor_context();
388+
finalize_constants(&mut triple_xor_context);
383389
triple_xor_context.finalize_guessed_vars();
384390
triple_xor_context.validate_circuit();
385391

@@ -391,15 +397,23 @@ fn test_prove_and_circuit_verify_triple_xor_context() {
391397
PcsConfig::default(),
392398
)
393399
.unwrap();
394-
circuit_verify(circuit_proof, &preprocessed_circuit, TRIPLE_XOR_CIRCUIT_PREPROCESSED_ROOT);
400+
let preprocessed_root = preprocessed_root_from_proof(&circuit_proof);
401+
expect!["[1171063850, 1111600624, 1633001715, 1807620201, 319861310, 456396523, 1450019685, 1107101120]"]
402+
.assert_eq(&format!("{preprocessed_root:?}"));
403+
circuit_verify(circuit_proof, &preprocessed_circuit, preprocessed_root);
395404
}
396405

397-
const FIBONACCI_CIRCUIT_PREPROCESSED_ROOT: [u32; 8] =
398-
[938280935, 1980664971, 866203874, 1147299749, 1683668505, 390015812, 137596665, 365486364];
406+
/// Extract the preprocessed-trace Merkle root (`commitments[0]`) from a `CircuitProof` as
407+
/// `[u32; 8]`, matching the layout `HashValue<QM31>` consumes via `From<[u32; 8]>`.
408+
fn preprocessed_root_from_proof(circuit_proof: &CircuitProof<Blake2sM31MerkleHasher>) -> [u32; 8] {
409+
let hash: Blake2sHash = circuit_proof.stark_proof.proof.commitments[0];
410+
std::array::from_fn(|i| u32::from_le_bytes(hash.0[i * 4..(i + 1) * 4].try_into().unwrap()))
411+
}
399412

400413
#[test]
401414
fn test_prove_and_circuit_verify_fibonacci_context() {
402415
let mut fibonacci_context = build_fibonacci_context();
416+
finalize_constants(&mut fibonacci_context);
403417
fibonacci_context.finalize_guessed_vars();
404418
fibonacci_context.validate_circuit();
405419

@@ -411,15 +425,16 @@ fn test_prove_and_circuit_verify_fibonacci_context() {
411425
PcsConfig::default(),
412426
)
413427
.unwrap();
414-
circuit_verify(circuit_proof, &preprocessed_circuit, FIBONACCI_CIRCUIT_PREPROCESSED_ROOT);
428+
let preprocessed_root = preprocessed_root_from_proof(&circuit_proof);
429+
expect!["[1652958260, 1473705547, 1322148911, 426200657, 1375192488, 2052166177, 2061891994, 1346989032]"]
430+
.assert_eq(&format!("{preprocessed_root:?}"));
431+
circuit_verify(circuit_proof, &preprocessed_circuit, preprocessed_root);
415432
}
416433

417-
const M31_TO_U32_CIRCUIT_PREPROCESSED_ROOT: [u32; 8] =
418-
[119960690, 584326386, 331600676, 1678406228, 411117252, 2142234173, 1676458105, 924266087];
419-
420434
#[test]
421435
fn test_prove_and_circuit_verify_m31_to_u32_context() {
422436
let mut m31_to_u32_context = build_m31_to_u32_context();
437+
finalize_constants(&mut m31_to_u32_context);
423438
m31_to_u32_context.finalize_guessed_vars();
424439
m31_to_u32_context.validate_circuit();
425440

@@ -431,15 +446,18 @@ fn test_prove_and_circuit_verify_m31_to_u32_context() {
431446
PcsConfig::default(),
432447
)
433448
.unwrap();
434-
circuit_verify(circuit_proof, &preprocessed_circuit, M31_TO_U32_CIRCUIT_PREPROCESSED_ROOT);
449+
let preprocessed_root = preprocessed_root_from_proof(&circuit_proof);
450+
expect![
451+
"[938872239, 1375737105, 1191518666, 1663828004, 7943535, 657469305, 191549109, 752041387]"
452+
]
453+
.assert_eq(&format!("{preprocessed_root:?}"));
454+
circuit_verify(circuit_proof, &preprocessed_circuit, preprocessed_root);
435455
}
436456

437-
const BLAKE_G_GATE_CIRCUIT_PREPROCESSED_ROOT: [u32; 8] =
438-
[1547637094, 1628188007, 1109367239, 1655363258, 1038162931, 368611637, 1915980358, 1225437881];
439-
440457
#[test]
441458
fn test_prove_and_circuit_verify_blake_g_gate_context() {
442459
let mut blake_g_gate_context = build_blake_g_gate_context();
460+
finalize_constants(&mut blake_g_gate_context);
443461
blake_g_gate_context.finalize_guessed_vars();
444462
blake_g_gate_context.validate_circuit();
445463

@@ -451,7 +469,10 @@ fn test_prove_and_circuit_verify_blake_g_gate_context() {
451469
PcsConfig::default(),
452470
)
453471
.unwrap();
454-
circuit_verify(circuit_proof, &preprocessed_circuit, BLAKE_G_GATE_CIRCUIT_PREPROCESSED_ROOT);
472+
let preprocessed_root = preprocessed_root_from_proof(&circuit_proof);
473+
expect!["[1600972583, 323912908, 1627322779, 821304140, 535689503, 707220338, 1484882728, 1361575593]"]
474+
.assert_eq(&format!("{preprocessed_root:?}"));
475+
circuit_verify(circuit_proof, &preprocessed_circuit, preprocessed_root);
455476
}
456477

457478
#[test]

crates/circuit_verifier/src/verify.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use circuit_common::order_hash_map::OrderedHashMap;
2-
use circuits::{blake::HashValue, context::Context, ivalue::IValue, ops::Guess};
2+
use circuits::{
3+
blake::HashValue, context::Context, finalize_constants::finalize_constants, ivalue::IValue,
4+
ops::Guess,
5+
};
36
use circuits_stark_verifier::{
47
proof::{Proof, ProofConfig},
58
statement::Statement,
@@ -48,6 +51,7 @@ pub fn build_verification_circuit<Value: IValue>(
4851
let proof_vars = proof.guess(&mut context);
4952

5053
verify(&mut context, &proof_vars, &proof_config, &statement);
54+
finalize_constants(&mut context);
5155
context.finalize_guessed_vars();
5256
#[cfg(test)]
5357
context.circuit.check_yields();

crates/circuits/src/blake_test.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use stwo::core::vcs::blake2_hash::reduce_to_m31;
44

55
use crate::blake::{blake, blake_from_gates, blake_qm31, qm31_from_bytes};
66
use crate::context::TraceContext;
7+
use crate::finalize_constants::finalize_constants;
78
use crate::ivalue::qm31_from_u32s;
89
use crate::ops::{Guess, eq, guess};
910
use crate::stats::Stats;
@@ -40,10 +41,10 @@ fn test_blake(#[case] wrong_output: bool) {
4041
eq(&mut context, output.0, out0);
4142
eq(&mut context, output.1, out1);
4243

43-
assert_eq!(context.stats, Stats { blake_updates: 2, guess: 9, equals: 2, ..Stats::default() });
44+
assert_eq!(context.stats, Stats { blake_updates: 2, guess: 7, equals: 2, ..Stats::default() });
4445

46+
crate::finalize_constants::finalize_constants(&mut context);
4547
context.finalize_guessed_vars();
46-
assert_eq!(context.circuit.compute_multiplicities().0, vec![13, 1, 2, 2, 2, 2, 2, 1, 1, 2, 2]);
4748
context.circuit.check_yields();
4849

4950
assert_eq!(context.is_circuit_valid(), !wrong_output);
@@ -69,6 +70,7 @@ fn test_blake_from_gates_equal_old_blake() {
6970
eq(&mut context, out_mono.0, out_decomposed.0);
7071
eq(&mut context, out_mono.1, out_decomposed.1);
7172

73+
finalize_constants(&mut context);
7274
context.finalize_guessed_vars();
7375
context.circuit.check_yields();
7476
assert!(context.is_circuit_valid());
@@ -102,6 +104,7 @@ fn test_blake_from_gates_independent() {
102104
eq(&mut context, output.0, out0);
103105
eq(&mut context, output.1, out1);
104106

107+
finalize_constants(&mut context);
105108
context.finalize_guessed_vars();
106109
context.circuit.check_yields();
107110
assert!(context.is_circuit_valid());

crates/circuits/src/context.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use num_traits::{One, Zero};
44
use stwo::core::fields::qm31::QM31;
55

66
use crate::circuit::{Add, Circuit};
7-
use crate::ivalue::IValue;
8-
use crate::ops::guess;
7+
use crate::ivalue::{IValue, qm31_from_u32s};
98
use crate::stats::Stats;
109

1110
#[cfg(test)]
@@ -50,7 +49,7 @@ pub struct Context<Value: IValue> {
5049
///
5150
/// `None` if the set of guessed variables has already been finalized.
5251
///
53-
/// See [guess].
52+
/// See [crate::ops::guess].
5453
pub guessed_vars: Option<Vec<usize>>,
5554
/// Debug only. If true, equality is asserted when adding the `eq` gate; if false, no
5655
/// assertion is made during construction and equality can be checked later at validation.
@@ -94,7 +93,7 @@ impl<Value: IValue> Context<Value> {
9493
if let Some(var) = self.constants.get(&value) {
9594
*var
9695
} else {
97-
let var = guess(self, Value::from_qm31(value));
96+
let var = self.new_var(Value::from_qm31(value));
9897
self.constants.insert(value, var);
9998
var
10099
}
@@ -161,9 +160,11 @@ impl<Value: IValue> Default for Context<Value> {
161160
guessed_vars: Some(vec![]),
162161
assert_eq_on_eval: false,
163162
};
164-
// Register zero and one as the first constants.
163+
// Register zero, one, and u as the first constants.
165164
res.constant(QM31::zero());
166165
res.constant(QM31::one());
166+
res.constant(qm31_from_u32s(0, 0, 1, 0)); // u at idx 2
167+
167168
res
168169
}
169170
}

crates/circuits/src/context_test.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::context::{Context, TraceContext};
2+
use crate::finalize_constants::finalize_constants;
23
use crate::ivalue::qm31_from_u32s;
34

45
#[test]
@@ -11,14 +12,11 @@ fn test_constants() {
1112
let c = context.constant(x);
1213
assert_eq!(a.idx, c.idx);
1314

14-
assert_eq!(context.values(), &vec![0.into(), 1.into(), x, x + x]);
15+
let u = qm31_from_u32s(0, 0, 1, 0);
16+
assert_eq!(context.values(), &vec![0.into(), 1.into(), u, x, x + x]);
1517

18+
finalize_constants(&mut context);
1619
context.finalize_guessed_vars();
17-
assert_eq!(
18-
format!("{:?}", context.circuit),
19-
"[0] = [0] + [0]\n[1] = [1] + [0]\n[2] = [2] + [0]\n[3] = [3] + [0]\n"
20-
);
21-
2220
context.validate_circuit();
2321
}
2422

0 commit comments

Comments
 (0)