fil_blst/
lib.rs

1// Copyright Supranational LLC
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#![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 print_blst_fr(fr: *const blst_fr);
18    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
66// TODO - Is there a better way than deserializing?
67impl 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 groupy::{CurveAffine, CurveProjective, EncodedPoint};
141    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            //let mut bp1_aff = std::mem::MaybeUninit::<blst_p1_affine>::zeroed().assume_init();
150
151            blst_p1_add_or_double_affine(&mut bp1, &bp1, &BLS12_381_G1);
152            //blst_p1_to_affine(&mut bp1_aff, &bp1);
153
154            let mut bp1_bytes = [0u8; 48];
155            blst_p1_compress(bp1_bytes.as_mut_ptr(), &bp1);
156
157            print_bytes(&bp1_bytes, "bp1");
158            //assert_eq!(bp1_aff, BLS12_381_NEG_G1);
159
160            let zp1 = G1::zero();
161            let zp1_aff = G1Affine::zero();
162
163            println!("zp1 {:?}", zp1);
164            //println!("zp1.x {:?}", zp1.x);
165            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            //print_blst_fr(&frB);
172            // let mut frB_bytes = [0u8; 32];
173            // blst_bendian_from_fr(frX_bytes.as_mut_ptr(), &frB);
174            // print_bytes(&frB_bytes, "frB");
175
176            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            // Use compressed
187
188            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            // Use uncompressed
206
207            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}