|
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}, |
4 | 7 | }; |
5 | 8 |
|
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; |
10 | 169 |
|
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 { |
12 | 183 | commitments, |
13 | 184 | proof, |
14 | 185 | evals, |
15 | 186 | ft_eval1, |
16 | 187 | prev_challenges, |
17 | 188 | }; |
| 189 | + |
18 | 190 | todo!() |
19 | 191 | } |
20 | 192 |
|
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 | + } |
23 | 347 | } |
0 commit comments