1use alloy::{
5 hex::ToHexExt,
6 primitives::{B256, U256},
7};
8use ark_bn254::{Bn254, Fq, Fr, G1Affine, G2Affine};
9use ark_ff::{Fp2, MontFp};
10use ark_std::{UniformRand, rand::Rng};
11use jf_pcs::prelude::Commitment;
12use jf_plonk::{
13 constants::KECCAK256_STATE_SIZE,
14 proof_system::structs::{OpenKey, Proof, ProofEvaluations, VerifyingKey},
15 testing_apis::Challenges,
16 transcript::SolidityTranscript,
17};
18use jf_plonk_compat::proof_system::structs::{
19 Proof as ProofCompat, VerifyingKey as VerifyingKeyCompat,
20};
21use jf_utils::to_bytes;
22use num_bigint::BigUint;
23use num_traits::Num;
24
25use crate::{field_to_u256, sol_types::*, u256_to_field};
26
27const COSET: [&str; 5] = [
30 "1",
31 "2f8dd1f1a7583c42c4e12a44e110404c73ca6c94813f85835da4fb7bb1301d4a",
32 "1ee678a0470a75a6eaa8fe837060498ba828a3703b311d0f77f010424afeb025",
33 "2042a587a90c187b0a087c03e29c968b950b1db26d5c82d666905a6895790c0a",
34 "2e2b91456103698adf57b799969dea1c8f739da5d8d40dd3eb9222db7c81e881",
35];
36
37const H: [&str; 4] = [
39 "1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed", "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", ];
44
45const BETA_H: [&str; 4] = [
47 "0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0",
48 "260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1",
49 "22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55",
50 "04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4",
51];
52
53pub fn coset_k() -> Vec<Fr> {
57 vec![
58 Fr::from(BigUint::from_str_radix(COSET[0], 16).unwrap()),
59 Fr::from(BigUint::from_str_radix(COSET[1], 16).unwrap()),
60 Fr::from(BigUint::from_str_radix(COSET[2], 16).unwrap()),
61 Fr::from(BigUint::from_str_radix(COSET[3], 16).unwrap()),
62 Fr::from(BigUint::from_str_radix(COSET[4], 16).unwrap()),
63 ]
64}
65
66pub fn open_key() -> OpenKey<Bn254> {
68 let g = G1Affine::new_unchecked(MontFp!("1"), MontFp!("2"));
69 let h = G2Affine::new(
70 Fp2::new(
71 Fq::from(BigUint::from_str_radix(H[0], 16).unwrap()),
72 Fq::from(BigUint::from_str_radix(H[1], 16).unwrap()),
73 ),
74 Fp2::new(
75 Fq::from(BigUint::from_str_radix(H[2], 16).unwrap()),
76 Fq::from(BigUint::from_str_radix(H[3], 16).unwrap()),
77 ),
78 );
79 let beta_h = G2Affine::new(
80 Fp2::new(
81 Fq::from(BigUint::from_str_radix(BETA_H[0], 16).unwrap()),
82 Fq::from(BigUint::from_str_radix(BETA_H[1], 16).unwrap()),
83 ),
84 Fp2::new(
85 Fq::from(BigUint::from_str_radix(BETA_H[2], 16).unwrap()),
86 Fq::from(BigUint::from_str_radix(BETA_H[3], 16).unwrap()),
87 ),
88 );
89
90 OpenKey {
91 g,
92 h,
93 beta_h,
94 powers_of_g: vec![g],
95 powers_of_h: vec![h, beta_h],
96 }
97}
98
99impl From<SolidityTranscript> for TranscriptDataSol {
100 fn from(t: SolidityTranscript) -> Self {
101 let (state, transcript) = t.internal();
102 Self {
103 state: B256::from_slice(&state),
104 transcript: transcript.into(),
105 }
106 }
107}
108
109impl From<TranscriptDataSol> for SolidityTranscript {
110 fn from(t: TranscriptDataSol) -> Self {
111 let mut state = [0u8; KECCAK256_STATE_SIZE];
112 state.copy_from_slice(&t.state.0);
113 Self::from_internal(state, t.transcript.to_vec())
114 }
115}
116
117impl From<VerifyingKey<Bn254>> for VerifyingKeySol {
118 fn from(vk: VerifyingKey<Bn254>) -> Self {
119 let g2_bytes = to_bytes!(&vk.open_key.powers_of_h[1]).unwrap();
120 assert!(g2_bytes.len() == 64);
121 let mut g2_lsb = [0u8; 32];
122 let mut g2_msb = [0u8; 32];
123 g2_lsb.copy_from_slice(&g2_bytes[..32]);
124 g2_msb.copy_from_slice(&g2_bytes[32..]);
125
126 assert_eq!(
134 g2_lsb.encode_hex(),
135 String::from("b0838893ec1f237e8b07323b0744599f4e97b598b3b589bcc2bc37b8d5c41801")
136 );
137 assert_eq!(
138 g2_msb.encode_hex(),
139 String::from("c18393c0fa30fe4e8b038e357ad851eae8de9107584effe7c7f1f651b2010e26")
140 );
141
142 Self {
143 domainSize: U256::from(vk.domain_size),
144 numInputs: U256::from(vk.num_inputs),
145 sigma0: vk.sigma_comms[0].0.into(),
146 sigma1: vk.sigma_comms[1].0.into(),
147 sigma2: vk.sigma_comms[2].0.into(),
148 sigma3: vk.sigma_comms[3].0.into(),
149 sigma4: vk.sigma_comms[4].0.into(),
150 q1: vk.selector_comms[0].0.into(),
151 q2: vk.selector_comms[1].0.into(),
152 q3: vk.selector_comms[2].0.into(),
153 q4: vk.selector_comms[3].0.into(),
154 qM12: vk.selector_comms[4].0.into(),
155 qM34: vk.selector_comms[5].0.into(),
156 qH1: vk.selector_comms[6].0.into(),
157 qH2: vk.selector_comms[7].0.into(),
158 qH3: vk.selector_comms[8].0.into(),
159 qH4: vk.selector_comms[9].0.into(),
160 qO: vk.selector_comms[10].0.into(),
161 qC: vk.selector_comms[11].0.into(),
162 qEcc: vk.selector_comms[12].0.into(),
163 g2LSB: g2_lsb.into(),
164 g2MSB: g2_msb.into(),
165 }
166 }
167}
168
169impl From<VerifyingKeySol> for VerifyingKey<Bn254> {
170 fn from(vk: VerifyingKeySol) -> Self {
171 let sigma_comms = vec![
172 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.sigma0)),
173 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.sigma1)),
174 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.sigma2)),
175 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.sigma3)),
176 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.sigma4)),
177 ];
178
179 let selector_comms = vec![
180 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.q1)),
181 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.q2)),
182 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.q3)),
183 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.q4)),
184 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qM12)),
185 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qM34)),
186 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qH1)),
187 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qH2)),
188 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qH3)),
189 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qH4)),
190 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qO)),
191 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qC)),
192 Commitment::from(<G1PointSol as Into<G1Affine>>::into(vk.qEcc)),
193 ];
194
195 Self {
196 domain_size: vk.domainSize.to::<usize>(),
197 num_inputs: vk.numInputs.to::<usize>(),
198 sigma_comms,
199 selector_comms,
200 k: coset_k(),
201 open_key: open_key(),
202 is_merged: false,
203 plookup_vk: None,
204 }
205 }
206}
207
208impl From<Proof<Bn254>> for PlonkProofSol {
209 fn from(proof: Proof<Bn254>) -> Self {
210 Self {
211 wire0: proof.wires_poly_comms[0].0.into(),
212 wire1: proof.wires_poly_comms[1].0.into(),
213 wire2: proof.wires_poly_comms[2].0.into(),
214 wire3: proof.wires_poly_comms[3].0.into(),
215 wire4: proof.wires_poly_comms[4].0.into(),
216 prodPerm: proof.prod_perm_poly_comm.0.into(),
217 split0: proof.split_quot_poly_comms[0].0.into(),
218 split1: proof.split_quot_poly_comms[1].0.into(),
219 split2: proof.split_quot_poly_comms[2].0.into(),
220 split3: proof.split_quot_poly_comms[3].0.into(),
221 split4: proof.split_quot_poly_comms[4].0.into(),
222 zeta: proof.opening_proof.0.into(),
223 zetaOmega: proof.shifted_opening_proof.0.into(),
224 wireEval0: field_to_u256(proof.poly_evals.wires_evals[0]),
225 wireEval1: field_to_u256(proof.poly_evals.wires_evals[1]),
226 wireEval2: field_to_u256(proof.poly_evals.wires_evals[2]),
227 wireEval3: field_to_u256(proof.poly_evals.wires_evals[3]),
228 wireEval4: field_to_u256(proof.poly_evals.wires_evals[4]),
229 sigmaEval0: field_to_u256(proof.poly_evals.wire_sigma_evals[0]),
230 sigmaEval1: field_to_u256(proof.poly_evals.wire_sigma_evals[1]),
231 sigmaEval2: field_to_u256(proof.poly_evals.wire_sigma_evals[2]),
232 sigmaEval3: field_to_u256(proof.poly_evals.wire_sigma_evals[3]),
233 prodPermZetaOmegaEval: field_to_u256(proof.poly_evals.perm_next_eval),
234 }
235 }
236}
237
238impl From<PlonkProofSol> for Proof<Bn254> {
239 fn from(proof: PlonkProofSol) -> Self {
240 let wires_poly_comms = vec![
241 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.wire0)),
242 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.wire1)),
243 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.wire2)),
244 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.wire3)),
245 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.wire4)),
246 ];
247 let split_quot_poly_comms = vec![
248 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.split0)),
249 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.split1)),
250 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.split2)),
251 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.split3)),
252 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.split4)),
253 ];
254 let prod_perm_poly_comm =
255 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.prodPerm));
256 let opening_proof = Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.zeta));
257 let shifted_opening_proof =
258 Commitment::from(<G1PointSol as Into<G1Affine>>::into(proof.zetaOmega));
259
260 let wires_evals = vec![
261 u256_to_field(proof.wireEval0),
262 u256_to_field(proof.wireEval1),
263 u256_to_field(proof.wireEval2),
264 u256_to_field(proof.wireEval3),
265 u256_to_field(proof.wireEval4),
266 ];
267 let wire_sigma_evals = vec![
268 u256_to_field(proof.sigmaEval0),
269 u256_to_field(proof.sigmaEval1),
270 u256_to_field(proof.sigmaEval2),
271 u256_to_field(proof.sigmaEval3),
272 ];
273 let perm_next_eval = u256_to_field(proof.prodPermZetaOmegaEval);
274
275 Self {
276 wires_poly_comms,
277 prod_perm_poly_comm,
278 split_quot_poly_comms,
279 opening_proof,
280 shifted_opening_proof,
281 poly_evals: ProofEvaluations {
282 wires_evals,
283 wire_sigma_evals,
284 perm_next_eval,
285 },
286 plookup_proof: None,
287 }
288 }
289}
290
291impl PlonkProofSol {
292 pub fn dummy_with_rand_proof_evals<R: Rng>(rng: &mut R) -> Self {
294 let zero = G1Affine::default();
295 Self {
296 wire0: zero.into(),
297 wire1: zero.into(),
298 wire2: zero.into(),
299 wire3: zero.into(),
300 wire4: zero.into(),
301 prodPerm: zero.into(),
302 split0: zero.into(),
303 split1: zero.into(),
304 split2: zero.into(),
305 split3: zero.into(),
306 split4: zero.into(),
307 zeta: zero.into(),
308 zetaOmega: zero.into(),
309 wireEval0: field_to_u256(Fr::rand(rng)),
310 wireEval1: field_to_u256(Fr::rand(rng)),
311 wireEval2: field_to_u256(Fr::rand(rng)),
312 wireEval3: field_to_u256(Fr::rand(rng)),
313 wireEval4: field_to_u256(Fr::rand(rng)),
314 sigmaEval0: field_to_u256(Fr::rand(rng)),
315 sigmaEval1: field_to_u256(Fr::rand(rng)),
316 sigmaEval2: field_to_u256(Fr::rand(rng)),
317 sigmaEval3: field_to_u256(Fr::rand(rng)),
318 prodPermZetaOmegaEval: field_to_u256(Fr::rand(rng)),
319 }
320 }
321
322 pub fn dummy<R: Rng>(rng: &mut R) -> Self {
324 let mut proof = Self::dummy_with_rand_proof_evals(rng);
325 proof.wire0 = G1Affine::rand(rng).into();
326 proof.wire1 = G1Affine::rand(rng).into();
327 proof.wire2 = G1Affine::rand(rng).into();
328 proof.wire3 = G1Affine::rand(rng).into();
329 proof.wire4 = G1Affine::rand(rng).into();
330 proof.prodPerm = G1Affine::rand(rng).into();
331 proof.split0 = G1Affine::rand(rng).into();
332 proof.split1 = G1Affine::rand(rng).into();
333 proof.split2 = G1Affine::rand(rng).into();
334 proof.split3 = G1Affine::rand(rng).into();
335 proof.split4 = G1Affine::rand(rng).into();
336 proof.zeta = G1Affine::rand(rng).into();
337 proof.zetaOmega = G1Affine::rand(rng).into();
338 proof
339 }
340}
341
342impl From<Challenges<Fr>> for ChallengesSol {
343 fn from(c: Challenges<Fr>) -> Self {
344 let alpha_2 = c.alpha * c.alpha;
345 Self {
346 alpha: field_to_u256::<Fr>(c.alpha),
347 alpha2: field_to_u256::<Fr>(alpha_2),
348 alpha3: field_to_u256::<Fr>(c.alpha * alpha_2),
349 beta: field_to_u256::<Fr>(c.beta),
350 gamma: field_to_u256::<Fr>(c.gamma),
351 zeta: field_to_u256::<Fr>(c.zeta),
352 v: field_to_u256::<Fr>(c.v),
353 u: field_to_u256::<Fr>(c.u),
354 }
355 }
356}
357
358impl From<ChallengesSol> for Challenges<Fr> {
359 fn from(c: ChallengesSol) -> Self {
360 Self {
361 tau: None,
362 alpha: u256_to_field(c.alpha),
363 beta: u256_to_field(c.beta),
364 gamma: u256_to_field(c.gamma),
365 zeta: u256_to_field(c.zeta),
366 v: u256_to_field(c.v),
367 u: u256_to_field(c.u),
368 }
369 }
370}
371
372impl ChallengesSol {
373 #[allow(dead_code)]
375 pub fn dummy<R: Rng>(rng: &mut R) -> Self {
376 let alpha = Fr::rand(rng);
377 let alpha_2 = alpha * alpha;
378 let alpha_3 = alpha * alpha_2;
379 Self {
380 alpha: field_to_u256(alpha),
381 alpha2: field_to_u256(alpha_2),
382 alpha3: field_to_u256(alpha_3),
383 beta: field_to_u256(Fr::rand(rng)),
384 gamma: field_to_u256(Fr::rand(rng)),
385 zeta: field_to_u256(Fr::rand(rng)),
386 v: field_to_u256(Fr::rand(rng)),
387 u: field_to_u256(Fr::rand(rng)),
388 }
389 }
390}
391
392impl From<VerifyingKeyCompat<Bn254>> for VerifyingKeySol {
393 fn from(vk: VerifyingKeyCompat<Bn254>) -> Self {
394 let vk: VerifyingKey<Bn254> = unsafe { std::mem::transmute(vk) };
395 vk.into()
396 }
397}
398
399impl From<VerifyingKeySol> for VerifyingKeyCompat<Bn254> {
400 fn from(vk: VerifyingKeySol) -> Self {
401 let vk: VerifyingKey<Bn254> = vk.into();
402 unsafe { std::mem::transmute(vk) }
403 }
404}
405
406impl From<ProofCompat<Bn254>> for PlonkProofSol {
407 fn from(proof: ProofCompat<Bn254>) -> Self {
408 let proof: Proof<Bn254> = unsafe { std::mem::transmute(proof) };
409 proof.into()
410 }
411}
412
413impl From<PlonkProofSol> for ProofCompat<Bn254> {
414 fn from(proof: PlonkProofSol) -> Self {
415 let proof: Proof<Bn254> = proof.into();
416 unsafe { std::mem::transmute(proof) }
417 }
418}