light_circuitlib_rs/gnark/
proof_helpers.rs1use serde::{Deserialize, Serialize};
2type G1 = ark_bn254::g1::G1Affine;
3use std::ops::Neg;
4
5use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate};
6use num_traits::Num;
7use solana_program::alt_bn128::compression::prelude::{
8 alt_bn128_g1_compress, alt_bn128_g2_compress, convert_endianness,
9};
10
11#[derive(Serialize, Deserialize, Debug)]
12pub struct GnarkProofJson {
13 pub ar: Vec<String>,
14 pub bs: Vec<Vec<String>>,
15 pub krs: Vec<String>,
16}
17
18pub fn deserialize_gnark_proof_json(json_data: &str) -> serde_json::Result<GnarkProofJson> {
19 let deserialized_data: GnarkProofJson = serde_json::from_str(json_data)?;
20 Ok(deserialized_data)
21}
22
23pub fn deserialize_hex_string_to_be_bytes(hex_str: &str) -> [u8; 32] {
24 let trimmed_str = hex_str.trim_start_matches("0x");
25 let big_int = num_bigint::BigInt::from_str_radix(trimmed_str, 16).unwrap();
26 let big_int_bytes = big_int.to_bytes_be().1;
27 if big_int_bytes.len() < 32 {
28 let mut result = [0u8; 32];
29 result[32 - big_int_bytes.len()..].copy_from_slice(&big_int_bytes);
30 result
31 } else {
32 big_int_bytes.try_into().unwrap()
33 }
34}
35
36pub fn compress_proof(
37 proof_a: &[u8; 64],
38 proof_b: &[u8; 128],
39 proof_c: &[u8; 64],
40) -> ([u8; 32], [u8; 64], [u8; 32]) {
41 let proof_a = alt_bn128_g1_compress(proof_a).unwrap();
42 let proof_b = alt_bn128_g2_compress(proof_b).unwrap();
43 let proof_c = alt_bn128_g1_compress(proof_c).unwrap();
44 (proof_a, proof_b, proof_c)
45}
46
47pub fn proof_from_json_struct(json: GnarkProofJson) -> ([u8; 64], [u8; 128], [u8; 64]) {
48 let proof_a_x = deserialize_hex_string_to_be_bytes(&json.ar[0]);
49 let proof_a_y = deserialize_hex_string_to_be_bytes(&json.ar[1]);
50 let proof_a: [u8; 64] = [proof_a_x, proof_a_y].concat().try_into().unwrap();
51 let proof_a = negate_g1(&proof_a);
52 let proof_b_x_0 = deserialize_hex_string_to_be_bytes(&json.bs[0][0]);
53 let proof_b_x_1 = deserialize_hex_string_to_be_bytes(&json.bs[0][1]);
54 let proof_b_y_0 = deserialize_hex_string_to_be_bytes(&json.bs[1][0]);
55 let proof_b_y_1 = deserialize_hex_string_to_be_bytes(&json.bs[1][1]);
56 let proof_b: [u8; 128] = [proof_b_x_0, proof_b_x_1, proof_b_y_0, proof_b_y_1]
57 .concat()
58 .try_into()
59 .unwrap();
60
61 let proof_c_x = deserialize_hex_string_to_be_bytes(&json.krs[0]);
62 let proof_c_y = deserialize_hex_string_to_be_bytes(&json.krs[1]);
63 let proof_c: [u8; 64] = [proof_c_x, proof_c_y].concat().try_into().unwrap();
64 (proof_a, proof_b, proof_c)
65}
66
67pub fn negate_g1(g1_be: &[u8; 64]) -> [u8; 64] {
68 let g1_le = convert_endianness::<32, 64>(g1_be);
69 let g1: G1 = G1::deserialize_with_mode(g1_le.as_slice(), Compress::No, Validate::No).unwrap();
70
71 let g1_neg = g1.neg();
72 let mut g1_neg_be = [0u8; 64];
73 g1_neg
74 .x
75 .serialize_with_mode(&mut g1_neg_be[..32], Compress::No)
76 .unwrap();
77 g1_neg
78 .y
79 .serialize_with_mode(&mut g1_neg_be[32..], Compress::No)
80 .unwrap();
81 let g1_neg_be: [u8; 64] = convert_endianness::<32, 64>(&g1_neg_be);
82 g1_neg_be
83}