Skip to content

Commit 08adf4a

Browse files
committed
integrate m31_to_u32 gate in stwo-circuit
1 parent 634bdaf commit 08adf4a

20 files changed

Lines changed: 773 additions & 18 deletions

File tree

crates/cairo_air/src/privacy_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,5 +254,5 @@ fn test_privacy_proof_info() {
254254
let proof_info = ProofInfo::from_config(&proof_config);
255255
println!("{proof_info}");
256256
// Assert the total size in bytes.
257-
assert_eq!(proof_info.total_bytes(), 344316);
257+
assert_eq!(proof_info.total_bytes(), 347360);
258258
}

crates/circuit_air/src/circuit_components.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::circuit_claim::{CircuitClaim, CircuitInteractionClaim, CircuitInteractionElements};
22
use crate::components::{
3-
blake_g, blake_gate, blake_output, blake_round, blake_round_sigma, eq, qm31_ops,
3+
blake_g, blake_gate, blake_output, blake_round, blake_round_sigma, eq, m_31_to_u_32, qm31_ops,
44
range_check_15, range_check_16, triple_xor_32, verify_bitwise_xor_4, verify_bitwise_xor_7,
55
verify_bitwise_xor_8, verify_bitwise_xor_9, verify_bitwise_xor_12,
66
};
@@ -26,6 +26,7 @@ define_component_list! {
2626
BlakeG,
2727
BlakeOutput,
2828
TripleXor32,
29+
M31ToU32,
2930
VerifyBitwiseXor8,
3031
VerifyBitwiseXor12,
3132
VerifyBitwiseXor4,
@@ -44,6 +45,7 @@ pub struct CircuitComponents {
4445
pub blake_g: blake_g::Component,
4546
pub blake_output: blake_output::Component,
4647
pub triple_xor_32: triple_xor_32::Component,
48+
pub m_31_to_u_32: m_31_to_u_32::Component,
4749
pub verify_bitwise_xor_8: verify_bitwise_xor_8::Component,
4850
pub verify_bitwise_xor_12: verify_bitwise_xor_12::Component,
4951
pub verify_bitwise_xor_4: verify_bitwise_xor_4::Component,
@@ -137,6 +139,16 @@ impl CircuitComponents {
137139
},
138140
interaction_claim.claimed_sums[ComponentList::TripleXor32 as usize],
139141
);
142+
let m_31_to_u_32_component = m_31_to_u_32::Component::new(
143+
tree_span_provider,
144+
m_31_to_u_32::Eval {
145+
claim: m_31_to_u_32::Claim {
146+
log_size: circuit_claim.log_sizes[ComponentList::M31ToU32 as usize],
147+
},
148+
common_lookup_elements: interaction_elements.common_lookup_elements.clone(),
149+
},
150+
interaction_claim.claimed_sums[ComponentList::M31ToU32 as usize],
151+
);
140152
let verify_bitwise_xor_8_component = verify_bitwise_xor_8::Component::new(
141153
tree_span_provider,
142154
verify_bitwise_xor_8::Eval {
@@ -202,6 +214,7 @@ impl CircuitComponents {
202214
blake_g: blake_g_component,
203215
blake_output: blake_output_component,
204216
triple_xor_32: triple_xor_32_component,
217+
m_31_to_u_32: m_31_to_u_32_component,
205218
verify_bitwise_xor_8: verify_bitwise_xor_8_component,
206219
verify_bitwise_xor_12: verify_bitwise_xor_12_component,
207220
verify_bitwise_xor_4: verify_bitwise_xor_4_component,
@@ -222,6 +235,7 @@ impl CircuitComponents {
222235
Box::new(self.blake_g) as Box<dyn Component>,
223236
Box::new(self.blake_output) as Box<dyn Component>,
224237
Box::new(self.triple_xor_32) as Box<dyn Component>,
238+
Box::new(self.m_31_to_u_32) as Box<dyn Component>,
225239
Box::new(self.verify_bitwise_xor_8) as Box<dyn Component>,
226240
Box::new(self.verify_bitwise_xor_12) as Box<dyn Component>,
227241
Box::new(self.verify_bitwise_xor_4) as Box<dyn Component>,
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// This file was created by the AIR team.
2+
3+
use super::prelude::*;
4+
5+
pub const N_TRACE_COLUMNS: usize = 4;
6+
pub const N_INTERACTION_COLUMNS: usize = 12;
7+
8+
pub const RELATION_USES_PER_ROW: [RelationUse; 2] = [
9+
RelationUse { relation_id: "Gate", uses: 1 },
10+
RelationUse { relation_id: "RangeCheck_16", uses: 3 },
11+
];
12+
13+
#[allow(unused_variables)]
14+
pub fn accumulate_constraints<Value: IValue>(
15+
input: &[Var],
16+
context: &mut Context<Value>,
17+
component_data: &dyn ComponentDataTrait<Value>,
18+
acc: &mut CompositionConstraintAccumulator,
19+
) {
20+
let [input_m31_col0, input_u32_limb_0_col1, input_u32_limb_1_col2, inv_or_one_col3] =
21+
input.try_into().unwrap();
22+
let m31_to_u32_input_addr = acc
23+
.get_preprocessed_column(&PreProcessedColumnId { id: "m31_to_u32_input_addr".to_owned() });
24+
let m31_to_u32_multiplicity = acc.get_preprocessed_column(&PreProcessedColumnId {
25+
id: "m31_to_u32_multiplicity".to_owned(),
26+
});
27+
let m31_to_u32_output_addr = acc
28+
.get_preprocessed_column(&PreProcessedColumnId { id: "m31_to_u32_output_addr".to_owned() });
29+
30+
// Use RangeCheck_16.
31+
let tuple_0 = &[eval!(context, 1008385708), eval!(context, input_u32_limb_0_col1)];
32+
let numerator_0 = eval!(context, 1);
33+
acc.add_to_relation(context, numerator_0, tuple_0);
34+
35+
// Use RangeCheck_16.
36+
let tuple_1 = &[eval!(context, 1008385708), eval!(context, input_u32_limb_1_col2)];
37+
let numerator_1 = eval!(context, 1);
38+
acc.add_to_relation(context, numerator_1, tuple_1);
39+
40+
// Use RangeCheck_16.
41+
let tuple_2 = &[eval!(context, 1008385708), eval!(context, (32767) - (input_u32_limb_1_col2))];
42+
let numerator_2 = eval!(context, 1);
43+
acc.add_to_relation(context, numerator_2, tuple_2);
44+
45+
//input is zero then limb_low is zero.
46+
let constraint_3_value =
47+
eval!(context, (((input_m31_col0) * (inv_or_one_col3)) - (1)) * (input_u32_limb_0_col1));
48+
acc.add_constraint(context, constraint_3_value);
49+
50+
//input reconstruction.
51+
let constraint_4_value = eval!(
52+
context,
53+
(input_m31_col0) - ((input_u32_limb_0_col1) + ((input_u32_limb_1_col2) * (65536)))
54+
);
55+
acc.add_constraint(context, constraint_4_value);
56+
57+
// Use Gate.
58+
let tuple_5 = &[
59+
eval!(context, 378353459),
60+
eval!(context, m31_to_u32_input_addr),
61+
eval!(context, input_m31_col0),
62+
];
63+
let numerator_5 = eval!(context, 1);
64+
acc.add_to_relation(context, numerator_5, tuple_5);
65+
66+
// Yield Gate.
67+
let tuple_6 = &[
68+
eval!(context, 378353459),
69+
eval!(context, m31_to_u32_output_addr),
70+
eval!(context, input_u32_limb_0_col1),
71+
eval!(context, input_u32_limb_1_col2),
72+
];
73+
let numerator_6 = eval!(context, -(m31_to_u32_multiplicity));
74+
acc.add_to_relation(context, numerator_6, tuple_6);
75+
}
76+
77+
pub struct Component {}
78+
impl<Value: IValue> CircuitEval<Value> for Component {
79+
fn name(&self) -> String {
80+
"m_31_to_u_32".to_string()
81+
}
82+
83+
fn evaluate(
84+
&self,
85+
context: &mut Context<Value>,
86+
component_data: &dyn ComponentDataTrait<Value>,
87+
acc: &mut CompositionConstraintAccumulator,
88+
) {
89+
accumulate_constraints(component_data.trace_columns(), context, component_data, acc);
90+
}
91+
92+
fn trace_columns(&self) -> usize {
93+
N_TRACE_COLUMNS
94+
}
95+
96+
fn interaction_columns(&self) -> usize {
97+
N_INTERACTION_COLUMNS
98+
}
99+
100+
fn relation_uses_per_row(&self) -> &[RelationUse] {
101+
&RELATION_USES_PER_ROW
102+
}
103+
}
104+
#[cfg(test)]
105+
mod tests {
106+
use std::collections::HashMap;
107+
use stwo::core::fields::qm31::QM31;
108+
109+
#[allow(unused_imports)]
110+
use crate::components::prelude::PreProcessedColumnId;
111+
use crate::sample_evaluations::*;
112+
use circuits::context::Context;
113+
use circuits::ivalue::qm31_from_u32s;
114+
use circuits_stark_verifier::constraint_eval::*;
115+
use circuits_stark_verifier::test_utils::TestComponentData;
116+
117+
use super::Component;
118+
119+
#[test]
120+
fn test_evaluation_result() {
121+
let component = Component {};
122+
let mut context: Context<QM31> = Default::default();
123+
context.enable_assert_eq_on_eval();
124+
let trace_columns = [
125+
qm31_from_u32s(1659099300, 905558730, 651199673, 1375009625),
126+
qm31_from_u32s(1591990121, 771341002, 584090809, 1375009625),
127+
qm31_from_u32s(1793317658, 1173994186, 785417401, 1375009625),
128+
qm31_from_u32s(1726208479, 1039776458, 718308537, 1375009625),
129+
];
130+
let interaction_columns = [
131+
qm31_from_u32s(1005168032, 79980996, 1847888101, 1941984119),
132+
qm31_from_u32s(1072277211, 214198724, 1914996965, 1941984119),
133+
qm31_from_u32s(1139386390, 348416452, 1982105829, 1941984119),
134+
];
135+
let component_data = TestComponentData::from_values(
136+
&mut context,
137+
&trace_columns,
138+
&interaction_columns,
139+
qm31_from_u32s(1115374022, 1127856551, 489657863, 643630026),
140+
32768,
141+
);
142+
let random_coeff =
143+
context.new_var(qm31_from_u32s(474642921, 876336632, 1911695779, 974600512));
144+
let interaction_elements = [
145+
context.new_var(qm31_from_u32s(445623802, 202571636, 1360224996, 131355117)),
146+
context.new_var(qm31_from_u32s(476823935, 939223384, 62486082, 122423602)),
147+
];
148+
let preprocessed_columns = HashMap::from([
149+
(
150+
PreProcessedColumnId { id: "m31_to_u32_input_addr".to_owned() },
151+
context.constant(qm31_from_u32s(15668215, 1851966168, 874056991, 2075313468)),
152+
),
153+
(
154+
PreProcessedColumnId { id: "m31_to_u32_output_addr".to_owned() },
155+
context.constant(qm31_from_u32s(701904311, 1125291129, 1904795215, 38357025)),
156+
),
157+
(
158+
PreProcessedColumnId { id: "m31_to_u32_multiplicity".to_owned() },
159+
context.constant(qm31_from_u32s(1979029033, 1524573277, 1930122227, 1490762084)),
160+
),
161+
]);
162+
let public_params = HashMap::from([]);
163+
let mut accumulator = CompositionConstraintAccumulator::new(
164+
&mut context,
165+
preprocessed_columns,
166+
public_params,
167+
random_coeff,
168+
interaction_elements,
169+
);
170+
component.evaluate(&mut context, &component_data, &mut accumulator);
171+
let claimed_sum =
172+
context.new_var(qm31_from_u32s(1398335417, 314974026, 1722107152, 821933968));
173+
accumulator.finalize_logup_in_pairs(
174+
&mut context,
175+
<TestComponentData as ComponentDataTrait<QM31>>::interaction_columns(&component_data),
176+
&component_data,
177+
claimed_sum,
178+
);
179+
180+
let result = accumulator.finalize();
181+
let result_value = context.get(result);
182+
assert_eq!(result_value, M_31_TO_U_32_SAMPLE_EVAL_RESULT)
183+
}
184+
}

crates/circuit_air/src/circuit_eval_components/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub mod blake_gate;
33
pub mod blake_output;
44
pub mod blake_round;
55
pub mod blake_round_sigma;
6+
pub mod m_31_to_u_32;
67
pub mod prelude;
78
pub mod range_check_15;
89
pub mod range_check_16;
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use crate::components::prelude::*;
2+
3+
pub const N_TRACE_COLUMNS: usize = 4;
4+
pub const RELATION_USES_PER_ROW: [RelationUse; 2] = [
5+
RelationUse { relation_id: "Gate", uses: 1 },
6+
RelationUse { relation_id: "RangeCheck_16", uses: 3 },
7+
];
8+
9+
pub struct Eval {
10+
pub claim: Claim,
11+
pub common_lookup_elements: relations::CommonLookupElements,
12+
}
13+
14+
#[derive(Copy, Clone, Serialize, Deserialize)]
15+
pub struct Claim {
16+
pub log_size: u32,
17+
}
18+
impl Claim {
19+
pub fn log_sizes(&self) -> TreeVec<Vec<u32>> {
20+
let trace_log_sizes = vec![self.log_size; N_TRACE_COLUMNS];
21+
let interaction_log_sizes = vec![self.log_size; SECURE_EXTENSION_DEGREE * 3];
22+
TreeVec::new(vec![vec![], trace_log_sizes, interaction_log_sizes])
23+
}
24+
}
25+
26+
#[derive(Copy, Clone, Serialize, Deserialize)]
27+
pub struct InteractionClaim {
28+
pub claimed_sum: SecureField,
29+
}
30+
31+
pub type Component = FrameworkComponent<Eval>;
32+
33+
impl FrameworkEval for Eval {
34+
fn log_size(&self) -> u32 {
35+
self.claim.log_size
36+
}
37+
38+
fn max_constraint_log_degree_bound(&self) -> u32 {
39+
self.log_size() + 1
40+
}
41+
42+
#[allow(unused_parens)]
43+
#[allow(clippy::double_parens)]
44+
#[allow(non_snake_case)]
45+
fn evaluate<E: EvalAtRow>(&self, mut eval: E) -> E {
46+
let M31_1 = E::F::from(M31::from(1));
47+
let M31_1008385708 = E::F::from(M31::from(1008385708));
48+
let M31_32767 = E::F::from(M31::from(32767));
49+
let M31_378353459 = E::F::from(M31::from(378353459));
50+
let M31_65536 = E::F::from(M31::from(65536));
51+
let m31_to_u32_input_addr = eval.get_preprocessed_column(PreProcessedColumnId {
52+
id: "m31_to_u32_input_addr".to_owned(),
53+
});
54+
let m31_to_u32_output_addr = eval.get_preprocessed_column(PreProcessedColumnId {
55+
id: "m31_to_u32_output_addr".to_owned(),
56+
});
57+
let m31_to_u32_multiplicity = eval.get_preprocessed_column(PreProcessedColumnId {
58+
id: "m31_to_u32_multiplicity".to_owned(),
59+
});
60+
let input_m31_col0 = eval.next_trace_mask();
61+
let input_u32_limb_0_col1 = eval.next_trace_mask();
62+
let input_u32_limb_1_col2 = eval.next_trace_mask();
63+
let inv_or_one_col3 = eval.next_trace_mask();
64+
65+
eval.add_to_relation(RelationEntry::new(
66+
&self.common_lookup_elements,
67+
E::EF::from(M31_1.clone()),
68+
&[M31_1008385708.clone(), input_u32_limb_0_col1.clone()],
69+
));
70+
71+
eval.add_to_relation(RelationEntry::new(
72+
&self.common_lookup_elements,
73+
E::EF::from(M31_1.clone()),
74+
&[M31_1008385708.clone(), input_u32_limb_1_col2.clone()],
75+
));
76+
77+
eval.add_to_relation(RelationEntry::new(
78+
&self.common_lookup_elements,
79+
E::EF::from(M31_1.clone()),
80+
&[M31_1008385708.clone(), (M31_32767.clone() - input_u32_limb_1_col2.clone())],
81+
));
82+
83+
//input is zero then limb_low is zero.
84+
eval.add_constraint(
85+
(((input_m31_col0.clone() * inv_or_one_col3.clone()) - M31_1.clone())
86+
* input_u32_limb_0_col1.clone()),
87+
);
88+
//input reconstruction.
89+
eval.add_constraint(
90+
(input_m31_col0.clone()
91+
- (input_u32_limb_0_col1.clone()
92+
+ (input_u32_limb_1_col2.clone() * M31_65536.clone()))),
93+
);
94+
eval.add_to_relation(RelationEntry::new(
95+
&self.common_lookup_elements,
96+
E::EF::from(M31_1.clone()),
97+
&[M31_378353459.clone(), m31_to_u32_input_addr.clone(), input_m31_col0.clone()],
98+
));
99+
100+
eval.add_to_relation(RelationEntry::new(
101+
&self.common_lookup_elements,
102+
-E::EF::from(m31_to_u32_multiplicity.clone()),
103+
&[
104+
M31_378353459.clone(),
105+
m31_to_u32_output_addr.clone(),
106+
input_u32_limb_0_col1.clone(),
107+
input_u32_limb_1_col2.clone(),
108+
],
109+
));
110+
111+
eval.finalize_logup_in_pairs();
112+
eval
113+
}
114+
}

crates/circuit_air/src/components/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod blake_output;
44
pub mod blake_round;
55
pub mod blake_round_sigma;
66
pub mod eq;
7+
pub mod m_31_to_u_32;
78
pub mod prelude;
89
pub mod qm31_ops;
910
pub mod range_check_15;

crates/circuit_air/src/sample_evaluations.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ pub const BLAKE_ROUND_SIGMA_SAMPLE_EVAL_RESULT: QM31 =
1010
QM31(CM31(M31(512577297), M31(1730381685)), CM31(M31(592485643), M31(1900393320)));
1111
pub const CIRCUIT_BLAKE_ROUND_SAMPLE_EVAL_RESULT: QM31 =
1212
QM31(CM31(M31(672285719), M31(923434662)), CM31(M31(1482064263), M31(572523000)));
13+
pub const M_31_TO_U_32_SAMPLE_EVAL_RESULT: QM31 =
14+
QM31(CM31(M31(1862418699), M31(91648105)), CM31(M31(1944338824), M31(462064706)));
1315
pub const QM_31_OPS_SAMPLE_EVAL_RESULT: QM31 =
1416
QM31(CM31(M31(2064789890), M31(2068382720)), CM31(M31(24618579), M31(2071480927)));
1517
pub const RANGE_CHECK_15_SAMPLE_EVAL_RESULT: QM31 =

0 commit comments

Comments
 (0)