1#![allow(non_upper_case_globals)]
6#![allow(non_camel_case_types)]
7#![allow(non_snake_case)]
8
9include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
10
11use fff::PrimeField;
12use groupy::EncodedPoint;
13use paired::bls12_381::{Bls12, Fq, Fr, G1Affine, G1Uncompressed, G2Affine, G2Uncompressed};
14use std::path::Path;
15
16extern "C" {
17 pub fn verify_batch_proof_c(
19 proof_bytes: *const u8,
20 num_proofs: usize,
21 public_inputs: *const blst_fr,
22 num_inputs: usize,
23 rand_z: *const blst_scalar,
24 nbits: usize,
25 vk_path: *const u8,
26 vk_len: usize,
27 ) -> bool;
28}
29
30impl From<Fr> for blst_fr {
31 fn from(fr: Fr) -> blst_fr {
32 let mut b_fr = std::mem::MaybeUninit::<blst_fr>::uninit();
33 unsafe {
34 blst_scalar_from_uint64(
35 b_fr.as_mut_ptr() as *mut blst_scalar,
36 fr.into_repr().as_ref().as_ptr(),
37 );
38 b_fr.assume_init()
39 }
40 }
41}
42
43impl From<Fq> for blst_fp {
44 fn from(fq: Fq) -> blst_fp {
45 let mut fp = std::mem::MaybeUninit::<blst_fp>::uninit();
46 unsafe {
47 blst_fp_from_uint64(fp.as_mut_ptr(), fq.into_repr().as_ref().as_ptr());
48 fp.assume_init()
49 }
50 }
51}
52
53impl blst_p1_affine {
54 pub fn transform(p: <Bls12 as paired::Engine>::G1Affine) -> Self {
55 let mut p1 = std::mem::MaybeUninit::<blst_p1_affine>::uninit();
56 unsafe {
57 blst_p1_deserialize(
58 p1.as_mut_ptr(),
59 G1Uncompressed::from_affine(p).as_ref().as_ptr(),
60 );
61 p1.assume_init()
62 }
63 }
64}
65
66impl From<G1Affine> for blst_p1_affine {
68 fn from(p: G1Affine) -> blst_p1_affine {
69 let mut p1 = std::mem::MaybeUninit::<blst_p1_affine>::uninit();
70 unsafe {
71 blst_p1_deserialize(
72 p1.as_mut_ptr(),
73 G1Uncompressed::from_affine(p).as_ref().as_ptr(),
74 );
75 p1.assume_init()
76 }
77 }
78}
79
80impl From<G2Affine> for blst_p2_affine {
81 fn from(p: G2Affine) -> blst_p2_affine {
82 let mut p2 = std::mem::MaybeUninit::<blst_p2_affine>::uninit();
83 unsafe {
84 blst_p2_deserialize(
85 p2.as_mut_ptr(),
86 G2Uncompressed::from_affine(p).as_ref().as_ptr(),
87 );
88 p2.assume_init()
89 }
90 }
91}
92
93pub fn scalar_from_u64(limbs: &[u64; 4]) -> blst_scalar {
94 let mut s = std::mem::MaybeUninit::<blst_scalar>::uninit();
95 unsafe {
96 blst_scalar_from_uint64(s.as_mut_ptr(), &(limbs[0]));
97 s.assume_init()
98 }
99}
100
101pub fn verify_batch_proof(
102 proof_vec: &[u8],
103 num_proofs: usize,
104 public_inputs: &[blst_fr],
105 num_inputs: usize,
106 rand_z: &[blst_scalar],
107 nbits: usize,
108 vk_path: &Path,
109) -> bool {
110 let s = vk_path
111 .to_str()
112 .expect("Path is expected to be valid UTF-8")
113 .to_string();
114 let vk_bytes = s.into_bytes();
115 unsafe {
116 verify_batch_proof_c(
117 &(proof_vec[0]),
118 num_proofs,
119 public_inputs.as_ptr(),
120 num_inputs,
121 &(rand_z[0]),
122 nbits,
123 &(vk_bytes[0]),
124 vk_bytes.len(),
125 )
126 }
127}
128
129pub fn print_bytes(bytes: &[u8], name: &str) {
130 print!("{} ", name);
131 for b in bytes.iter() {
132 print!("{:02x}", b);
133 }
134 println!();
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140 use fff::Field;
142 use groupy::{CurveAffine, CurveProjective};
143 use paired::bls12_381::{Fq, G1Affine, G1Compressed, G1Uncompressed, G1};
144
145 #[test]
146 fn it_works() {
147 unsafe {
148 let mut bp1 = std::mem::MaybeUninit::<blst_p1>::zeroed().assume_init();
149 blst_p1_add_or_double_affine(&mut bp1, &bp1, &BLS12_381_G1);
152 let mut bp1_bytes = [0u8; 48];
155 blst_p1_compress(bp1_bytes.as_mut_ptr(), &bp1);
156
157 print_bytes(&bp1_bytes, "bp1");
158 let zp1 = G1::zero();
161 let zp1_aff = G1Affine::zero();
162
163 println!("zp1 {:?}", zp1);
164 println!("zp1_aff {:?}", zp1_aff);
166
167 let frX = Fr::one();
168 println!("frX {:?}", frX);
169 let frB = blst_fr::from(frX);
170 println!("frB {:?}", frB);
171 let fqX = Fq::one();
177 println!("fqX {:?}", fqX);
178
179 let fpX = blst_fp::from(fqX);
180
181 let mut fpX_bytes = [0u8; 48];
182 blst_bendian_from_fp(fpX_bytes.as_mut_ptr(), &fpX);
183
184 print_bytes(&fpX_bytes, "fpX");
185
186 let mut g1_gen_bytes = [0u8; 48];
189 blst_p1_affine_compress(g1_gen_bytes.as_mut_ptr(), &BLS12_381_G1);
190 print_bytes(&g1_gen_bytes, "G1_Generator");
191
192 let mut g1_gen_z_bytes = G1Compressed::empty();
193 g1_gen_z_bytes.as_mut().copy_from_slice(&g1_gen_bytes);
194 println!("g1_gen_z_bytes {:?}", g1_gen_z_bytes);
195
196 let g1_gen_z = g1_gen_z_bytes.into_affine_unchecked().unwrap();
197
198 let g1_gen_b = blst_p1_affine::from(g1_gen_z);
199 let mut g1_gen_bytes2 = [0u8; 48];
200 blst_p1_affine_compress(g1_gen_bytes2.as_mut_ptr(), &g1_gen_b);
201 print_bytes(&g1_gen_bytes2, "G1_Generator");
202
203 assert_eq!(&g1_gen_bytes[0..48], &g1_gen_bytes2[0..48]);
204
205 let mut g1_gen_bytes_uncomp = [0u8; 96];
208 blst_p1_affine_serialize(g1_gen_bytes_uncomp.as_mut_ptr(), &BLS12_381_G1);
209 print_bytes(&g1_gen_bytes_uncomp, "G1_Generator");
210
211 let mut g1_gen_z_bytes_uncomp = G1Uncompressed::empty();
212 g1_gen_z_bytes_uncomp
213 .as_mut()
214 .copy_from_slice(&g1_gen_bytes_uncomp);
215 println!("g1_gen_z_bytes_uncomp {:?}", g1_gen_z_bytes_uncomp);
216
217 let g1_gen_z_uncomp = g1_gen_z_bytes_uncomp.into_affine_unchecked().unwrap();
218
219 let g1_gen_b_uncomp = blst_p1_affine::from(g1_gen_z_uncomp);
220 let mut g1_gen_bytes_uncomp2 = [0u8; 96];
221 blst_p1_affine_serialize(g1_gen_bytes_uncomp2.as_mut_ptr(), &g1_gen_b_uncomp);
222 print_bytes(&g1_gen_bytes_uncomp2, "G1_Generator");
223
224 assert_eq!(&g1_gen_bytes_uncomp[0..96], &g1_gen_bytes_uncomp2[0..96]);
225 }
226 }
227}