rust_witness/
lib.rs

1use fnv::FnvHasher;
2pub use 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            mod [<$x _witness_c>] {
14                extern "C" {
15                    pub fn witness_c_init() -> *mut std::ffi::c_void;
16                    pub fn witness_c_resolver() -> *mut std::ffi::c_void;
17                    pub fn witness_c_cleanup(instance: *mut std::ffi::c_void);
18                }
19            }
20            extern "C" {
21                pub fn [<$x Instantiate>](i: *mut std::ffi::c_void, resolveImports: *mut std::ffi::c_void);
22                pub fn [<$x FreeInstance>](i: *mut std::ffi::c_void);
23                pub fn [<$x _getFieldNumLen32>](i: *mut std::ffi::c_void) -> u32;
24                pub fn [<$x _getRawPrime>](i: *mut std::ffi::c_void);
25                pub fn [<$x _getWitnessSize>](i: *mut std::ffi::c_void) -> u32;
26                pub fn [<$x _readSharedRWMemory>](i: *mut std::ffi::c_void, l0: u32) -> u32;
27                pub fn [<$x _writeSharedRWMemory>](i: *mut std::ffi::c_void, l0: u32, l1: u32);
28                pub fn [<$x _setInputSignal>](i: *mut std::ffi::c_void, l0: u32, l1: u32, l2: u32);
29                pub fn [<$x _getWitness>](i: *mut std::ffi::c_void, l0: u32);
30                pub fn [<$x _init>](i: *mut std::ffi::c_void, l0: u32);
31            }
32
33            // Public functions to make the above functions accessible
34            // in the crate namespace
35            pub unsafe fn [<$x _c_init>]() -> *mut std::ffi::c_void {
36                unsafe { [<$x _witness_c>]::witness_c_init() }
37            }
38
39            pub unsafe fn [<$x _c_resolver>]() -> *mut std::ffi::c_void {
40                unsafe { [<$x _witness_c>]::witness_c_resolver() }
41            }
42
43            pub unsafe fn [<$x _c_cleanup>](v: *mut std::ffi::c_void) {
44                unsafe {
45                    [<$x _witness_c>]::witness_c_cleanup(v);
46                }
47            }
48        }
49        rust_witness::paste::item! {
50            pub fn [<$x _witness>]<I: IntoIterator<Item = (String, Vec<rust_witness::BigInt>)>>(inputs: I) -> Vec<rust_witness::BigInt> {
51                // used for keying the values to signals
52                unsafe {
53                    let instance = [<$x _c_init>]();
54                    let resolver = [<$x _c_resolver>]();
55                    // instantiate the memory structures
56
57                    [<$x Instantiate>](instance, resolver);
58
59                    // ready to build the witness
60
61                    let n32 = [<$x _getFieldNumLen32>](instance);
62                    [<$x _getRawPrime>](instance);
63                    let mut arr = vec![0; n32 as usize];
64                    for x in 0..n32 {
65                        let res = [<$x _readSharedRWMemory>](instance, x);
66                        arr[(n32 as usize) - (x as usize) - 1] = res;
67                    }
68                    // let prime = from_array32(arr);
69                    // let n64 = ((prime.bits() - 1) / 64 + 1) as u32;
70
71                    // prepare for building the witness
72                    [<$x _init>](instance, 0);
73
74                    // allocate the inputs
75                    for (name, values) in inputs.into_iter() {
76                        let (msb, lsb) = rust_witness::fnv(&name);
77
78                        for (i, value) in values.into_iter().enumerate() {
79                            let f_arr = rust_witness::to_array32(&value, n32 as usize);
80                            for j in 0..n32 {
81                                [<$x _writeSharedRWMemory>](
82                                    instance,
83                                    j,
84                                    f_arr[(n32 as usize) - 1 - (j as usize)],
85                                );
86                            }
87                            [<$x _setInputSignal>](instance, msb, lsb, i as u32);
88                        }
89                    }
90
91                    let mut w = Vec::new();
92
93                    let witness_size = [<$x _getWitnessSize>](instance);
94                    for i in 0..witness_size {
95                        [<$x _getWitness>](instance, i);
96                        let mut arr = vec![0; n32 as usize];
97                        for j in 0..n32 {
98                            arr[(n32 as usize) - 1 - (j as usize)] =
99                                [<$x _readSharedRWMemory>](instance, j);
100                        }
101                        w.push(rust_witness::from_array32(arr));
102                    }
103
104                    // cleanup the c memory
105                    [<$x FreeInstance>](instance);
106                    [<$x _c_cleanup>](instance);
107
108                    w
109
110                    // If the witness program produces negative values or values above the prime we should
111                    // bring the values into range like below
112
113                    // // convert it to field elements
114                    // w.into_iter()
115                    //     .map(|w| {
116                    //         let w = if w.sign() == num_bigint::Sign::Minus {
117                    //             // Need to negate the witness element if negative
118                    //             prime.to_biguint().unwrap() - w.abs().to_biguint().unwrap()
119                    //         } else {
120                    //             w.to_biguint().unwrap()
121                    //         };
122                    //         w
123                    //     })
124                    //     .collect::<Vec<_>>()
125                }
126            }
127        }
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}