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