Skip to content

Commit f398d7d

Browse files
authored
Merge pull request #2 from lambdaclass/wrap_preproc
Wrap proof deserializer and `prev_challenges` computation
2 parents a88bb48 + 98989f9 commit f398d7d

6 files changed

Lines changed: 468 additions & 56 deletions

File tree

operator/mina/lib/Cargo.lock

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

operator/mina/lib/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ ark-poly = { version = "0.3.0", features = ["parallel"] }
1919
serde = "1.0.197"
2020
rmp-serde = "1.1.2"
2121
ark-serialize = "0.3.0"
22+
serde_json = "1.0.118"
23+
hex = "0.4.3"

operator/mina/lib/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use kimchi::{
1313
verifier_index::VerifierIndex,
1414
};
1515

16-
mod pickles_preproc;
16+
pub mod pickles_preproc;
1717

1818
const MAX_PROOF_SIZE: usize = 10 * 1024;
1919
const MAX_PUB_INPUT_SIZE: usize = 50 * 1024;
Lines changed: 334 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,347 @@
1-
use crate::{
2-
state_proof::StateProof,
3-
type_aliases::{WrapProverCommitments, WrapProverProof, WrapVerifierIndex},
1+
use kimchi::{
2+
circuits::wires::{COLUMNS, PERMUTS},
3+
mina_curves::pasta::{Fq, Pallas},
4+
mina_poseidon::sponge::ScalarChallenge,
5+
poly_commitment::{srs::endos, PolyComm},
6+
proof::{PointEvaluations, RecursionChallenge},
47
};
58

6-
pub fn preprocess_state_proof(
7-
state_proof_json: StateProof,
8-
) -> (WrapVerifierIndex, WrapProverProof) {
9-
let commitments = WrapProverCommitments {};
9+
use crate::pickles_preproc::{
10+
state_proof::{Bulletproof, Commitments, Evaluations, WRAP_PREV_CHALLENGES},
11+
type_aliases::{
12+
WrapECPoint, WrapOpeningProof, WrapPointEvaluations, WrapProofEvaluations,
13+
WrapProverCommitments, WrapScalar,
14+
},
15+
};
16+
17+
use super::{
18+
state_proof::{
19+
BulletproofChallenge, HexPointCoordinates, StateProof, WRAP_SCALARS_PER_CHALLENGE,
20+
},
21+
type_aliases::{WrapProverProof, WrapVerifierIndex},
22+
};
23+
24+
pub fn deserialize_state_proof(
25+
state_proof: StateProof,
26+
) -> Result<(WrapVerifierIndex, WrapProverProof), String> {
27+
let Commitments {
28+
w_comm: hex_w_comm,
29+
z_comm: hex_z_comm,
30+
t_comm: hex_t_comm,
31+
} = state_proof.proof.commitments;
32+
33+
// w_comm are single-point commitments
34+
let mut w_comm: [PolyComm<Pallas>; COLUMNS] = std::array::from_fn(|_| PolyComm {
35+
elems: Vec::with_capacity(1),
36+
});
37+
for (hex_point, comm) in hex_w_comm.into_iter().zip(w_comm.iter_mut()) {
38+
comm.elems.push(WrapECPoint::try_from(hex_point)?.0);
39+
}
40+
41+
// z_comm is a single-point commitment
42+
let z_comm = PolyComm {
43+
elems: vec![WrapECPoint::try_from(hex_z_comm)?.0],
44+
};
45+
// t_comm is a multi-point commitment
46+
let t_comm = PolyComm {
47+
elems: hex_t_comm
48+
.into_iter()
49+
.map(|hex_point| WrapECPoint::try_from(hex_point).map(|point| point.0))
50+
.collect::<Result<_, _>>()?,
51+
};
52+
let lookup = None;
53+
54+
let commitments = WrapProverCommitments {
55+
w_comm,
56+
z_comm,
57+
t_comm,
58+
lookup,
59+
};
60+
61+
let Bulletproof {
62+
challenge_polynomial_commitment: hex_sg,
63+
delta: hex_delta,
64+
lr: hex_lr,
65+
z_1: hex_z_1,
66+
z_2: hex_z_2,
67+
} = state_proof.proof.bulletproof;
68+
let sg = WrapECPoint::try_from(hex_sg)?.0;
69+
let delta = WrapECPoint::try_from(hex_delta)?.0;
70+
let lr = hex_lr
71+
.into_iter()
72+
.map(|(hex_p1, hex_p2)| -> Result<(Pallas, Pallas), String> {
73+
let p1 = WrapECPoint::try_from(hex_p1)?.0;
74+
let p2 = WrapECPoint::try_from(hex_p2)?.0;
75+
Ok((p1, p2))
76+
})
77+
.collect::<Result<_, _>>()?;
78+
let z1 = WrapScalar::try_from(hex_z_1)?.0;
79+
let z2 = WrapScalar::try_from(hex_z_2)?.0;
80+
81+
let proof = WrapOpeningProof {
82+
sg,
83+
delta,
84+
lr,
85+
z1,
86+
z2,
87+
};
88+
89+
let Evaluations {
90+
coefficients: hex_coefficients,
91+
complete_add_selector: hex_complete_add_selector,
92+
emul_selector: hex_emul_selector,
93+
endomul_scalar_selector: hex_endomul_scalar_selector,
94+
generic_selector: hex_generic_selector,
95+
mul_selector: hex_mul_selector,
96+
poseidon_selector: hex_poseidon_selector,
97+
s: hex_s,
98+
w: hex_w,
99+
z: hex_z,
100+
} = state_proof.proof.evaluations;
101+
102+
let mut w: [PointEvaluations<Vec<Fq>>; COLUMNS] = std::array::from_fn(|_| PointEvaluations {
103+
zeta: Vec::with_capacity(1),
104+
zeta_omega: Vec::with_capacity(1),
105+
});
106+
for (hex_eval, eval) in hex_w.into_iter().zip(w.iter_mut()) {
107+
*eval = WrapPointEvaluations::try_from(hex_eval)?.0;
108+
}
109+
110+
let z = WrapPointEvaluations::try_from(hex_z)?.0;
111+
112+
let mut s: [PointEvaluations<Vec<Fq>>; PERMUTS - 1] =
113+
std::array::from_fn(|_| PointEvaluations {
114+
zeta: Vec::with_capacity(1),
115+
zeta_omega: Vec::with_capacity(1),
116+
});
117+
for (hex_eval, eval) in hex_s.into_iter().zip(s.iter_mut()) {
118+
*eval = WrapPointEvaluations::try_from(hex_eval)?.0;
119+
}
120+
121+
let mut coefficients: [PointEvaluations<Vec<Fq>>; COLUMNS] =
122+
std::array::from_fn(|_| PointEvaluations {
123+
zeta: Vec::with_capacity(1),
124+
zeta_omega: Vec::with_capacity(1),
125+
});
126+
for (hex_eval, eval) in hex_coefficients.into_iter().zip(coefficients.iter_mut()) {
127+
*eval = WrapPointEvaluations::try_from(hex_eval)?.0;
128+
}
129+
130+
let generic_selector = WrapPointEvaluations::try_from(hex_generic_selector)?.0;
131+
let poseidon_selector = WrapPointEvaluations::try_from(hex_poseidon_selector)?.0;
132+
let complete_add_selector = WrapPointEvaluations::try_from(hex_complete_add_selector)?.0;
133+
let mul_selector = WrapPointEvaluations::try_from(hex_mul_selector)?.0;
134+
let emul_selector = WrapPointEvaluations::try_from(hex_emul_selector)?.0;
135+
let endomul_scalar_selector = WrapPointEvaluations::try_from(hex_endomul_scalar_selector)?.0;
136+
137+
let public = None; // TODO: Calculate public poly evaluations
138+
139+
let evals = WrapProofEvaluations {
140+
public,
141+
w,
142+
z,
143+
s,
144+
coefficients,
145+
generic_selector,
146+
poseidon_selector,
147+
complete_add_selector,
148+
mul_selector,
149+
emul_selector,
150+
endomul_scalar_selector,
151+
range_check0_selector: None,
152+
range_check1_selector: None,
153+
foreign_field_add_selector: None,
154+
foreign_field_mul_selector: None,
155+
xor_selector: None,
156+
rot_selector: None,
157+
lookup_aggregation: None,
158+
lookup_table: None,
159+
lookup_sorted: std::array::from_fn(|_| None),
160+
runtime_lookup_table: None,
161+
runtime_lookup_table_selector: None,
162+
xor_lookup_selector: None,
163+
lookup_gate_lookup_selector: None,
164+
range_check_lookup_selector: None,
165+
foreign_field_mul_lookup_selector: None,
166+
};
167+
168+
let ft_eval1 = WrapScalar::try_from(state_proof.proof.ft_eval1)?.0;
10169

11-
let prover_proof = WrapProverProof {
170+
let prev_challenges = compute_prev_challenges(
171+
state_proof
172+
.statement
173+
.proof_state
174+
.messages_for_next_wrap_proof
175+
.old_bulletproof_challenges,
176+
state_proof
177+
.statement
178+
.messages_for_next_step_proof
179+
.challenge_polynomial_commitments,
180+
)?;
181+
182+
let _prover_proof = WrapProverProof {
12183
commitments,
13184
proof,
14185
evals,
15186
ft_eval1,
16187
prev_challenges,
17188
};
189+
18190
todo!()
19191
}
20192

21-
pub fn compute_prev_challenges() {
22-
todo!()
193+
pub fn compute_prev_challenges(
194+
old_bulletproof_challenges: [[BulletproofChallenge; WRAP_SCALARS_PER_CHALLENGE];
195+
WRAP_PREV_CHALLENGES],
196+
challenge_polynomial_commitments: [HexPointCoordinates; WRAP_PREV_CHALLENGES],
197+
) -> Result<Vec<RecursionChallenge<Pallas>>, String> {
198+
let mut recursion_challenges = Vec::with_capacity(WRAP_PREV_CHALLENGES);
199+
200+
for (chal, comm) in old_bulletproof_challenges
201+
.into_iter()
202+
.zip(challenge_polynomial_commitments.into_iter())
203+
{
204+
let mut chals = Vec::with_capacity(WRAP_SCALARS_PER_CHALLENGE);
205+
for prechallenge in chal.into_iter().map(|chal| chal.prechallenge) {
206+
let [limb0, limb1] = prechallenge.inner;
207+
208+
let limb0 = u64::from_be_bytes(
209+
limb0
210+
.parse::<i64>()
211+
.map_err(|err| err.to_string())?
212+
.to_be_bytes(),
213+
) as u128;
214+
let limb1 = u64::from_be_bytes(
215+
limb1
216+
.parse::<i64>()
217+
.map_err(|err| err.to_string())?
218+
.to_be_bytes(),
219+
) as u128;
220+
221+
let field = Fq::from(limb0 | (limb1 << 64));
222+
223+
let (_, endo_r) = endos::<Pallas>();
224+
chals.push(ScalarChallenge(field).to_field(&endo_r));
225+
}
226+
227+
let comm = PolyComm {
228+
elems: vec![WrapECPoint::try_from(comm)?.0],
229+
};
230+
231+
recursion_challenges.push(RecursionChallenge { chals, comm });
232+
}
233+
234+
Ok(recursion_challenges)
235+
}
236+
237+
#[cfg(test)]
238+
mod tests {
239+
use kimchi::{
240+
mina_curves::pasta::{Fp, Fq, Pallas},
241+
poly_commitment::PolyComm,
242+
};
243+
use o1_utils::FieldHelpers;
244+
245+
use crate::pickles_preproc::state_proof::{
246+
BulletproofChallenge, Prechallenge, WRAP_SCALARS_PER_CHALLENGE,
247+
};
248+
249+
use super::compute_prev_challenges;
250+
251+
#[test]
252+
fn prev_challenges_tests() {
253+
// reference values were taken from OpenMina's tests, and checked by calling Mina's
254+
// `to_field()` OCaml function.
255+
// https://github.com/openmina/openmina/blob/main/ledger/src/proofs/public_input/scalar_challenge.rs#L120
256+
257+
let bulletproof_challenges_1: [BulletproofChallenge; WRAP_SCALARS_PER_CHALLENGE] = [
258+
["7486980280913238963", "4173194488927267133"],
259+
["-8437921285878338178", "-2241273202573544127"],
260+
["7651331705457292674", "-3583141513394030281"],
261+
["-3464302417307075879", "-436261906098457727"],
262+
["8255044994932440761", "5640094314955753085"],
263+
["-2513734760972484960", "1161566061253204655"],
264+
["7525998242613288472", "3436443803216159028"],
265+
["6809231383204761158", "-1877195934091894696"],
266+
["-2746520749286704399", "-3783224604272248786"],
267+
["-36686536733916892", "-7835584350097226223"],
268+
["-487486487490201322", "2756145684490201109"],
269+
["-2928903316653004982", "346819656816504982"],
270+
["-6510054999844554738", "5242613218253829938"],
271+
["-9192160905410203809", "9069127704639200224"],
272+
["-1805085648820294365", "4705625510417283644"],
273+
]
274+
.map(|prechallenge| BulletproofChallenge {
275+
prechallenge: Prechallenge {
276+
inner: prechallenge.map(str::to_string),
277+
},
278+
});
279+
let bulletproof_challenges_0: [BulletproofChallenge; WRAP_SCALARS_PER_CHALLENGE] = [
280+
["7486980280913238963", "4173194488927267133"],
281+
["-8437921285878338178", "-2241273202573544127"],
282+
["7651331705457292674", "-3583141513394030281"],
283+
["-3464302417307075879", "-436261906098457727"],
284+
["8255044994932440761", "5640094314955753085"],
285+
["-2513734760972484960", "1161566061253204655"],
286+
["7525998242613288472", "3436443803216159028"],
287+
["6809231383204761158", "-1877195934091894696"],
288+
["-2746520749286704399", "-3783224604272248786"],
289+
["-36686536733916892", "-7835584350097226223"],
290+
["-487486487490201322", "2756145684490201109"],
291+
["-2928903316653004982", "346819656816504982"],
292+
["-6510054999844554738", "5242613218253829938"],
293+
["-9192160905410203809", "9069127704639200224"],
294+
["-1805085648820294365", "4705625510417283644"],
295+
]
296+
.map(|prechallenge| BulletproofChallenge {
297+
prechallenge: Prechallenge {
298+
inner: prechallenge.map(str::to_string),
299+
},
300+
});
301+
302+
let old_bulletproof_challenges = [bulletproof_challenges_0, bulletproof_challenges_1];
303+
let challenge_polynomial_commitments = [
304+
[
305+
"40000000000000000000000000000000224698FC094CF91B992D30ED00000000",
306+
"2",
307+
]
308+
.map(str::to_string),
309+
[
310+
"40000000000000000000000000000000224698FC094CF91B992D30ED00000000",
311+
"2",
312+
]
313+
.map(str::to_string),
314+
];
315+
316+
let prev_challenges =
317+
compute_prev_challenges(old_bulletproof_challenges, challenge_polynomial_commitments)
318+
.unwrap();
319+
320+
let ocaml_results = [
321+
"A922DE10BD19D506BE5E5240287AFCD2F809D02FF05EDFA4AF352AEE2353DA29",
322+
"242A7448F2F61420595B4E9B15D7D14E1B804FDE3C12E3B0D22F980D4A60521D",
323+
"B412F4446AB1ABD794F3D9F07F37A70DA9EB34E70A61945F34A0F21B5D7D4007",
324+
"C57F9E4102427BF3EBB6B634815A7ED8DEAC7CD0E66BE4CE6FF3CC072156350D",
325+
"739B1283E3850AEF8F7B8206FE2FAE458692CAE72FC44B0F9C0E4059D04A1808",
326+
"03B3F202827A43CE0A5C6168C62EE07623F50FA0D15C75782462E9A59FBB503E",
327+
"35F8321ACA4EEFAB50E354E656A802D2D7981BF1F534D8B9A2C59482A4537906",
328+
"9F3C63C9296EEB7AFCC6EFCB347DAB907CC633FB79C75A919BE9036D89B6AD11",
329+
"02E73F47455B53F464FDBE744507A1767D12531FC731D0ADCBC1530630B8172F",
330+
"4F8D1EA54FD29176EBF6D8421769D3B4CEAFACAD47C4ABAAA702F99532C98F2D",
331+
"A44B7B1491C7396203C1A5D0BB7B1FC6DA0FB85FC5D7A2DE0710C4A7A4916B2D",
332+
"345ECA59C151C182D4AD1A0A10B29E181C30236E6EB64C688F5B5B0221A2BD28",
333+
"391609C56024448F2B05A61D9116AB3C56496C9E65A8BF019476C0B029ECD826",
334+
"C611063B76383AC746012DDDD9E2D831A00B15FE22BC211BF383A0391FAB4814",
335+
"730FC9A8BF1DCCE3E36286BEB51EAB8F0B0092A8FEE6901FAF158D1E5DBFBE05",
336+
]
337+
.map(|hex| Fq::from_hex(hex).unwrap());
338+
339+
assert_eq!(prev_challenges[0].chals, ocaml_results);
340+
assert_eq!(
341+
prev_challenges[0].comm,
342+
PolyComm {
343+
elems: vec![Pallas::new(Fp::from(-1), Fp::from(2), false)]
344+
}
345+
);
346+
}
23347
}

0 commit comments

Comments
 (0)