rust_witness/
lib.rs

1use fnv::FnvHasher;
2use num_bigint::BigInt;
3use num_traits::{ToPrimitive, Zero};
4pub use paste;
5use std::hash::Hasher;
6
7pub mod transpile;
8
9#[macro_export]
10macro_rules! witness {
11    ($x: ident) => {
12        rust_witness::paste::item! {
13            extern "C" {
14                pub fn [<$x Instantiate>](i: *mut std::ffi::c_void, resolveImports: *mut std::ffi::c_void);
15                pub fn [<$x FreeInstance>](i: *mut std::ffi::c_void);
16                pub fn [<$x _getFieldNumLen32>](i: *mut std::ffi::c_void) -> u32;
17                pub fn [<$x _getRawPrime>](i: *mut std::ffi::c_void);
18                pub fn [<$x _getWitnessSize>](i: *mut std::ffi::c_void) -> u32;
19                pub fn [<$x _readSharedRWMemory>](i: *mut std::ffi::c_void, l0: u32) -> u32;
20                pub fn [<$x _writeSharedRWMemory>](i: *mut std::ffi::c_void, l0: u32, l1: u32);
21                pub fn [<$x _setInputSignal>](i: *mut std::ffi::c_void, l0: u32, l1: u32, l2: u32);
22                pub fn [<$x _getWitness>](i: *mut std::ffi::c_void, l0: u32);
23                pub fn [<$x _init>](i: *mut std::ffi::c_void, l0: u32);
24            }
25        }
26        rust_witness::paste::item! {
27            pub fn [<$x _witness>]<I: IntoIterator<Item = (String, Vec<num_bigint::BigInt>)>>(inputs: I) -> Vec<num_bigint::BigInt> {
28                // used for keying the values to signals
29                unsafe {
30                    let instance = rust_witness::c_init();
31                    let resolver = rust_witness::c_resolver();
32                    // instantiate the memory structures
33
34                    [<$x Instantiate>](instance, resolver);
35
36                    // ready to build the witness
37
38                    let n32 = [<$x _getFieldNumLen32>](instance);
39                    [<$x _getRawPrime>](instance);
40                    let mut arr = vec![0; n32 as usize];
41                    for x in 0..n32 {
42                        let res = [<$x _readSharedRWMemory>](instance, x);
43                        arr[(n32 as usize) - (x as usize) - 1] = res;
44                    }
45                    // let prime = from_array32(arr);
46                    // let n64 = ((prime.bits() - 1) / 64 + 1) as u32;
47
48                    // prepare for building the witness
49                    [<$x _init>](instance, 0);
50
51                    // allocate the inputs
52                    for (name, values) in inputs.into_iter() {
53                        let (msb, lsb) = rust_witness::fnv(&name);
54
55                        for (i, value) in values.into_iter().enumerate() {
56                            let f_arr = rust_witness::to_array32(&value, n32 as usize);
57                            for j in 0..n32 {
58                                [<$x _writeSharedRWMemory>](
59                                    instance,
60                                    j,
61                                    f_arr[(n32 as usize) - 1 - (j as usize)],
62                                );
63                            }
64                            [<$x _setInputSignal>](instance, msb, lsb, i as u32);
65                        }
66                    }
67
68                    let mut w = Vec::new();
69
70                    let witness_size = [<$x _getWitnessSize>](instance);
71                    for i in 0..witness_size {
72                        [<$x _getWitness>](instance, i);
73                        let mut arr = vec![0; n32 as usize];
74                        for j in 0..n32 {
75                            arr[(n32 as usize) - 1 - (j as usize)] =
76                                [<$x _readSharedRWMemory>](instance, j);
77                        }
78                        w.push(rust_witness::from_array32(arr));
79                    }
80
81                    // cleanup the c memory
82                    [<$x FreeInstance>](instance);
83                    rust_witness::c_cleanup(instance);
84
85                    w
86
87                    // If the witness program produces negative values or values above the prime we should
88                    // bring the values into range like below
89
90                    // // convert it to field elements
91                    // w.into_iter()
92                    //     .map(|w| {
93                    //         let w = if w.sign() == num_bigint::Sign::Minus {
94                    //             // Need to negate the witness element if negative
95                    //             prime.to_biguint().unwrap() - w.abs().to_biguint().unwrap()
96                    //         } else {
97                    //             w.to_biguint().unwrap()
98                    //         };
99                    //         w
100                    //     })
101                    //     .collect::<Vec<_>>()
102                }
103            }
104        }
105    };
106}
107
108// shared global functions
109extern "C" {
110    pub fn witness_c_init() -> *mut std::ffi::c_void;
111    pub fn witness_c_resolver() -> *mut std::ffi::c_void;
112    pub fn witness_c_cleanup(instance: *mut std::ffi::c_void);
113}
114
115// Public functions to make the above functions accessible
116// in the crate namespace
117pub fn c_init() -> *mut std::ffi::c_void {
118    unsafe { witness_c_init() }
119}
120
121pub fn c_resolver() -> *mut std::ffi::c_void {
122    unsafe { witness_c_resolver() }
123}
124
125pub fn c_cleanup(v: *mut std::ffi::c_void) {
126    unsafe {
127        witness_c_cleanup(v);
128    }
129}
130
131pub fn fnv(inp: &str) -> (u32, u32) {
132    let mut hasher = FnvHasher::default();
133    hasher.write(inp.as_bytes());
134    let h = hasher.finish();
135
136    ((h >> 32) as u32, h as u32)
137}
138
139pub fn from_array32(arr: Vec<u32>) -> BigInt {
140    let mut res = BigInt::zero();
141    let radix = BigInt::from(0x100000000u64);
142    for &val in arr.iter() {
143        res = res * &radix + BigInt::from(val);
144    }
145    res
146}
147
148pub fn to_array32(s: &BigInt, size: usize) -> Vec<u32> {
149    let mut res = vec![0; size];
150    let mut rem = s.clone();
151    let radix = BigInt::from(0x100000000u64);
152    let mut c = size;
153    while !rem.is_zero() {
154        c -= 1;
155        res[c] = (&rem % &radix).to_u32().unwrap();
156        rem /= &radix;
157    }
158
159    res
160}