1use alloy::{
5 hex::ToHexExt,
6 primitives::{B256, U256},
7};
8use ark_bn254::{Bn254, Fq, Fr, G1Affine, G2Affine};
9use ark_ec::{
10 short_weierstrass::{Affine, SWCurveConfig},
11 twisted_edwards::{self, TECurveConfig},
12 AffineRepr,
13};
14use ark_ff::{Fp2, Fp2Config, MontFp, PrimeField};
15use ark_std::{rand::Rng, UniformRand};
16use jf_pcs::prelude::Commitment;
17use jf_plonk::{
18 constants::KECCAK256_STATE_SIZE,
19 proof_system::structs::{OpenKey, Proof, ProofEvaluations, VerifyingKey},
20 testing_apis::Challenges,
21 transcript::SolidityTranscript,
22};
23use jf_plonk_compat::proof_system::structs::{
24 Proof as ProofCompat, VerifyingKey as VerifyingKeyCompat,
25};
26use jf_utils::to_bytes;
27use num_bigint::BigUint;
28use num_traits::Num;
29
30use crate::{field_to_u256, sol_types::*, u256_to_field};
31
32impl<P: SWCurveConfig> From<Affine<P>> for G1PointSol
33where
34 P::BaseField: PrimeField,
35{
36 fn from(p: Affine<P>) -> Self {
37 if p.is_zero() {
38 Self {
40 x: U256::from(0),
41 y: U256::from(0),
42 }
43 } else {
44 Self {
45 x: field_to_u256::<P::BaseField>(p.x().unwrap()),
46 y: field_to_u256::<P::BaseField>(p.y().unwrap()),
47 }
48 }
49 }
50}
51
52impl<P: SWCurveConfig> From<G1PointSol> for Affine<P>
53where
54 P::BaseField: PrimeField,
55{
56 fn from(p: G1PointSol) -> Self {
57 if p == G1PointSol::default() {
58 Self::default()
59 } else {
60 Self::new_unchecked(
61 u256_to_field::<P::BaseField>(p.x),
62 u256_to_field::<P::BaseField>(p.y),
63 )
64 }
65 }
66}
67
68impl<P: SWCurveConfig<BaseField = Fp2<C>>, C> From<G2PointSol> for Affine<P>
69where
70 C: Fp2Config,
71{
72 fn from(p: G2PointSol) -> Self {
73 Self::new_unchecked(
74 Fp2::new(u256_to_field(p.x0), u256_to_field(p.x1)),
75 Fp2::new(u256_to_field(p.y0), u256_to_field(p.y1)),
76 )
77 }
78}
79
80impl<P: SWCurveConfig<BaseField = Fp2<C>>, C> From<Affine<P>> for G2PointSol
81where
82 C: Fp2Config,
83{
84 fn from(p: Affine<P>) -> Self {
85 Self {
86 x0: field_to_u256(p.x().unwrap().c0),
87 x1: field_to_u256(p.x().unwrap().c1),
88 y0: field_to_u256(p.y().unwrap().c0),
89 y1: field_to_u256(p.y().unwrap().c1),
90 }
91 }
92}
93
94impl<P: TECurveConfig> From<twisted_edwards::Affine<P>> for EdOnBN254PointSol
95where
96 P::BaseField: PrimeField,
97{
98 fn from(p: twisted_edwards::Affine<P>) -> Self {
99 Self {
100 x: field_to_u256::<P::BaseField>(p.x().unwrap()),
101 y: field_to_u256::<P::BaseField>(p.y().unwrap()),
102 }
103 }
104}
105
106impl<P: TECurveConfig> From<EdOnBN254PointSol> for twisted_edwards::Affine<P>
107where
108 P::BaseField: PrimeField,
109{
110 fn from(p: EdOnBN254PointSol) -> Self {
111 Self::new_unchecked(
112 u256_to_field::<P::BaseField>(p.x),
113 u256_to_field::<P::BaseField>(p.y),
114 )
115 }
116}
117
118const COSET: [&str; 5] = [
121 "1",
122 "2f8dd1f1a7583c42c4e12a44e110404c73ca6c94813f85835da4fb7bb1301d4a",
123 "1ee678a0470a75a6eaa8fe837060498ba828a3703b311d0f77f010424afeb025",
124 "2042a587a90c187b0a087c03e29c968b950b1db26d5c82d666905a6895790c0a",
125 "2e2b91456103698adf57b799969dea1c8f739da5d8d40dd3eb9222db7c81e881",
126];
127
128const H: [&str; 4] = [
130 "1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed", "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", ];
135
136const BETA_H: [&str; 4] = [
138 "0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0",
139 "260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1",
140 "22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55",
141 "04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4",
142];
143
144pub fn coset_k() -> Vec<Fr> {
148 vec![
149 Fr::from(BigUint::from_str_radix(COSET[0], 16).unwrap()),
150 Fr::from(BigUint::from_str_radix(COSET[1], 16).unwrap()),
151 Fr::from(BigUint::from_str_radix(COSET[2], 16).unwrap()),
152 Fr::from(BigUint::from_str_radix(COSET[3], 16).unwrap()),
153 Fr::from(BigUint::from_str_radix(COSET[4], 16).unwrap()),
154 ]
155}
156
157pub fn open_key() -> OpenKey<Bn254> {
159 let g = G1Affine::new_unchecked(MontFp!("1"), MontFp!("2"));
160 let h = G2Affine::new(
161 Fp2::new(
162 Fq::from(BigUint::from_str_radix(H[0], 16).unwrap()),
163 Fq::from(BigUint::from_str_radix(H[1], 16).unwrap()),
164 ),
165 Fp2::new(
166 Fq::from(BigUint::from_str_radix(H[2], 16).unwrap()),
167 Fq::from(BigUint::from_str_radix(H[3], 16).unwrap()),
168 ),
169 );
170 let beta_h = G2Affine::new(
171 Fp2::new(
172 Fq::from(BigUint::from_str_radix(BETA_H[0], 16).unwrap()),
173 Fq::from(BigUint::from_str_radix(BETA_H[1], 16).unwrap()),
174 ),
175 Fp2::new(
176 Fq::from(BigUint::from_str_radix(BETA_H[2], 16).unwrap()),
177 Fq::from(BigUint::from_str_radix(BETA_H[3], 16).unwrap()),
178 ),
179 );
180
181 OpenKey {
182 g,
183 h,
184 beta_h,
185 powers_of_g: vec![g],
186 powers_of_h: vec![h, beta_h],
187 }
188}
189
190impl From<SolidityTranscript> for TranscriptDataSol {
191 fn from(t: SolidityTranscript) -> Self {
192 let (state, transcript) = t.internal();
193 Self {
194 state: B256::from_slice(&state),
195 transcript: transcript.into(),
196 }
197 }
198}
199
200impl From<TranscriptDataSol> for SolidityTranscript {
201 fn from(t: TranscriptDataSol) -> Self {
202 let mut state = [0u8; KECCAK256_STATE_SIZE];
203 state.copy_from_slice(&t.state.0);
204 Self::from_internal(state, t.transcript.to_vec())
205 }
206}
207
208impl From<VerifyingKey<Bn254>> for VerifyingKeySol {
209 fn from(vk: VerifyingKey<Bn254>) -> Self {
210 let g2_bytes = to_bytes!(&vk.open_key.powers_of_h[1]).unwrap();
211 assert!(g2_bytes.len() == 64);
212 let mut g2_lsb = [0u8; 32];
213 let mut g2_msb = [0u8; 32];
214 g2_lsb.copy_from_slice(&g2_bytes[..32]);
215 g2_msb.copy_from_slice(&g2_bytes[32..]);
216
217 assert_eq!(
225 g2_lsb.encode_hex(),
226 String::from("b0838893ec1f237e8b07323b0744599f4e97b598b3b589bcc2bc37b8d5c41801")
227 );
228 assert_eq!(
229 g2_msb.encode_hex(),
230 String::from("c18393c0fa30fe4e8b038e357ad851eae8de9107584effe7c7f1f651b2010e26")
231 );
232
233 Self {
234 domainSize: U256::from(vk.domain_size),
235 numInputs: U256::from(vk.num_inputs),
236 sigma0: vk.sigma_comms[0].0.into(),
237 sigma1: vk.sigma_comms[1].0.into(),
238 sigma2: vk.sigma_comms[2].0.into(),
239 sigma3: vk.sigma_comms[3].0.into(),
240 sigma4: vk.sigma_comms[4].0.into(),
241 q1: vk.selector_comms[0].0.into(),
242 q2: vk.selector_comms[1].0.into(),
243 q3: vk.selector_comms[2].0.into(),
244 q4: vk.selector_comms[3].0.into(),
245 qM12: vk.selector_comms[4].0.into(),
246 qM34: vk.selector_comms[5].0.into(),
247 qH1: vk.selector_comms[6].0.into(),
248 qH2: vk.selector_comms[7].0.into(),
249 qH3: vk.selector_comms[8].0.into(),
250 qH4: vk.selector_comms[9].0.into(),
251 qO: vk.selector_comms[10].0.into(),
252 qC: vk.selector_comms[11].0.into(),
253 qEcc: vk.selector_comms[12].0.into(),
254 g2LSB: g2_lsb.into(),
255 g2MSB: g2_msb.into(),
256 }
257 }
258}
259
260impl From<VerifyingKeySol> for VerifyingKey<Bn254> {
261 fn from(vk: VerifyingKeySol) -> Self {
262 let sigma_comms = vec![
263 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.sigma0)),
264 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.sigma1)),
265 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.sigma2)),
266 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.sigma3)),
267 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.sigma4)),
268 ];
269
270 let selector_comms = vec![
271 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.q1)),
272 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.q2)),
273 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.q3)),
274 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.q4)),
275 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qM12)),
276 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qM34)),
277 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qH1)),
278 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qH2)),
279 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qH3)),
280 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qH4)),
281 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qO)),
282 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qC)),
283 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qEcc)),
284 ];
285
286 Self {
287 domain_size: vk.domainSize.to::<usize>(),
288 num_inputs: vk.numInputs.to::<usize>(),
289 sigma_comms,
290 selector_comms,
291 k: coset_k(),
292 open_key: open_key(),
293 is_merged: false,
294 plookup_vk: None,
295 }
296 }
297}
298
299impl From<Proof<Bn254>> for PlonkProofSol {
300 fn from(proof: Proof<Bn254>) -> Self {
301 Self {
302 wire0: proof.wires_poly_comms[0].0.into(),
303 wire1: proof.wires_poly_comms[1].0.into(),
304 wire2: proof.wires_poly_comms[2].0.into(),
305 wire3: proof.wires_poly_comms[3].0.into(),
306 wire4: proof.wires_poly_comms[4].0.into(),
307 prodPerm: proof.prod_perm_poly_comm.0.into(),
308 split0: proof.split_quot_poly_comms[0].0.into(),
309 split1: proof.split_quot_poly_comms[1].0.into(),
310 split2: proof.split_quot_poly_comms[2].0.into(),
311 split3: proof.split_quot_poly_comms[3].0.into(),
312 split4: proof.split_quot_poly_comms[4].0.into(),
313 zeta: proof.opening_proof.0.into(),
314 zetaOmega: proof.shifted_opening_proof.0.into(),
315 wireEval0: field_to_u256(proof.poly_evals.wires_evals[0]),
316 wireEval1: field_to_u256(proof.poly_evals.wires_evals[1]),
317 wireEval2: field_to_u256(proof.poly_evals.wires_evals[2]),
318 wireEval3: field_to_u256(proof.poly_evals.wires_evals[3]),
319 wireEval4: field_to_u256(proof.poly_evals.wires_evals[4]),
320 sigmaEval0: field_to_u256(proof.poly_evals.wire_sigma_evals[0]),
321 sigmaEval1: field_to_u256(proof.poly_evals.wire_sigma_evals[1]),
322 sigmaEval2: field_to_u256(proof.poly_evals.wire_sigma_evals[2]),
323 sigmaEval3: field_to_u256(proof.poly_evals.wire_sigma_evals[3]),
324 prodPermZetaOmegaEval: field_to_u256(proof.poly_evals.perm_next_eval),
325 }
326 }
327}
328
329impl From<PlonkProofSol> for Proof<Bn254> {
330 fn from(proof: PlonkProofSol) -> Self {
331 let wires_poly_comms = vec![
332 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.wire0)),
333 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.wire1)),
334 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.wire2)),
335 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.wire3)),
336 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.wire4)),
337 ];
338 let split_quot_poly_comms = vec![
339 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.split0)),
340 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.split1)),
341 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.split2)),
342 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.split3)),
343 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.split4)),
344 ];
345 let prod_perm_poly_comm =
346 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.prodPerm));
347 let opening_proof = Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.zeta));
348 let shifted_opening_proof =
349 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.zetaOmega));
350
351 let wires_evals = vec![
352 u256_to_field(proof.wireEval0),
353 u256_to_field(proof.wireEval1),
354 u256_to_field(proof.wireEval2),
355 u256_to_field(proof.wireEval3),
356 u256_to_field(proof.wireEval4),
357 ];
358 let wire_sigma_evals = vec![
359 u256_to_field(proof.sigmaEval0),
360 u256_to_field(proof.sigmaEval1),
361 u256_to_field(proof.sigmaEval2),
362 u256_to_field(proof.sigmaEval3),
363 ];
364 let perm_next_eval = u256_to_field(proof.prodPermZetaOmegaEval);
365
366 Self {
367 wires_poly_comms,
368 prod_perm_poly_comm,
369 split_quot_poly_comms,
370 opening_proof,
371 shifted_opening_proof,
372 poly_evals: ProofEvaluations {
373 wires_evals,
374 wire_sigma_evals,
375 perm_next_eval,
376 },
377 plookup_proof: None,
378 }
379 }
380}
381
382impl PlonkProofSol {
383 pub fn dummy_with_rand_proof_evals<R: Rng>(rng: &mut R) -> Self {
385 let zero = G1Affine::default();
386 Self {
387 wire0: zero.into(),
388 wire1: zero.into(),
389 wire2: zero.into(),
390 wire3: zero.into(),
391 wire4: zero.into(),
392 prodPerm: zero.into(),
393 split0: zero.into(),
394 split1: zero.into(),
395 split2: zero.into(),
396 split3: zero.into(),
397 split4: zero.into(),
398 zeta: zero.into(),
399 zetaOmega: zero.into(),
400 wireEval0: field_to_u256(Fr::rand(rng)),
401 wireEval1: field_to_u256(Fr::rand(rng)),
402 wireEval2: field_to_u256(Fr::rand(rng)),
403 wireEval3: field_to_u256(Fr::rand(rng)),
404 wireEval4: field_to_u256(Fr::rand(rng)),
405 sigmaEval0: field_to_u256(Fr::rand(rng)),
406 sigmaEval1: field_to_u256(Fr::rand(rng)),
407 sigmaEval2: field_to_u256(Fr::rand(rng)),
408 sigmaEval3: field_to_u256(Fr::rand(rng)),
409 prodPermZetaOmegaEval: field_to_u256(Fr::rand(rng)),
410 }
411 }
412
413 pub fn dummy<R: Rng>(rng: &mut R) -> Self {
415 let mut proof = Self::dummy_with_rand_proof_evals(rng);
416 proof.wire0 = G1Affine::rand(rng).into();
417 proof.wire1 = G1Affine::rand(rng).into();
418 proof.wire2 = G1Affine::rand(rng).into();
419 proof.wire3 = G1Affine::rand(rng).into();
420 proof.wire4 = G1Affine::rand(rng).into();
421 proof.prodPerm = G1Affine::rand(rng).into();
422 proof.split0 = G1Affine::rand(rng).into();
423 proof.split1 = G1Affine::rand(rng).into();
424 proof.split2 = G1Affine::rand(rng).into();
425 proof.split3 = G1Affine::rand(rng).into();
426 proof.split4 = G1Affine::rand(rng).into();
427 proof.zeta = G1Affine::rand(rng).into();
428 proof.zetaOmega = G1Affine::rand(rng).into();
429 proof
430 }
431}
432
433impl From<Challenges<Fr>> for ChallengesSol {
434 fn from(c: Challenges<Fr>) -> Self {
435 let alpha_2 = c.alpha * c.alpha;
436 Self {
437 alpha: field_to_u256::<Fr>(c.alpha),
438 alpha2: field_to_u256::<Fr>(alpha_2),
439 alpha3: field_to_u256::<Fr>(c.alpha * alpha_2),
440 beta: field_to_u256::<Fr>(c.beta),
441 gamma: field_to_u256::<Fr>(c.gamma),
442 zeta: field_to_u256::<Fr>(c.zeta),
443 v: field_to_u256::<Fr>(c.v),
444 u: field_to_u256::<Fr>(c.u),
445 }
446 }
447}
448
449impl From<ChallengesSol> for Challenges<Fr> {
450 fn from(c: ChallengesSol) -> Self {
451 Self {
452 tau: None,
453 alpha: u256_to_field(c.alpha),
454 beta: u256_to_field(c.beta),
455 gamma: u256_to_field(c.gamma),
456 zeta: u256_to_field(c.zeta),
457 v: u256_to_field(c.v),
458 u: u256_to_field(c.u),
459 }
460 }
461}
462
463impl ChallengesSol {
464 #[allow(dead_code)]
466 pub fn dummy<R: Rng>(rng: &mut R) -> Self {
467 let alpha = Fr::rand(rng);
468 let alpha_2 = alpha * alpha;
469 let alpha_3 = alpha * alpha_2;
470 Self {
471 alpha: field_to_u256(alpha),
472 alpha2: field_to_u256(alpha_2),
473 alpha3: field_to_u256(alpha_3),
474 beta: field_to_u256(Fr::rand(rng)),
475 gamma: field_to_u256(Fr::rand(rng)),
476 zeta: field_to_u256(Fr::rand(rng)),
477 v: field_to_u256(Fr::rand(rng)),
478 u: field_to_u256(Fr::rand(rng)),
479 }
480 }
481}
482
483impl From<VerifyingKeyCompat<Bn254>> for VerifyingKeySol {
484 fn from(vk: VerifyingKeyCompat<Bn254>) -> Self {
485 let vk: VerifyingKey<Bn254> = unsafe { std::mem::transmute(vk) };
486 vk.into()
487 }
488}
489
490impl From<VerifyingKeySol> for VerifyingKeyCompat<Bn254> {
491 fn from(vk: VerifyingKeySol) -> Self {
492 let vk: VerifyingKey<Bn254> = vk.into();
493 unsafe { std::mem::transmute(vk) }
494 }
495}
496
497impl From<ProofCompat<Bn254>> for PlonkProofSol {
498 fn from(proof: ProofCompat<Bn254>) -> Self {
499 let proof: Proof<Bn254> = unsafe { std::mem::transmute(proof) };
500 proof.into()
501 }
502}
503
504impl From<PlonkProofSol> for ProofCompat<Bn254> {
505 fn from(proof: PlonkProofSol) -> Self {
506 let proof: Proof<Bn254> = proof.into();
507 unsafe { std::mem::transmute(proof) }
508 }
509}