arnaucube
arnaucube/circom-compatPublic Self-hosted repository
circom-compat/src/witness/circom.rs
src/witness/circom.rsRaw
  1use color_eyre::Result;
  2use wasmer::{Function, Instance, Value};
  3
  4#[derive(Clone, Debug)]
  5pub struct Wasm(Instance);
  6
  7pub trait CircomBase {
  8    fn init(&self, sanity_check: bool) -> Result<()>;
  9    fn func(&self, name: &str) -> &Function;
 10    fn get_ptr_witness_buffer(&self) -> Result<u32>;
 11    fn get_ptr_witness(&self, w: u32) -> Result<u32>;
 12    fn get_n_vars(&self) -> Result<u32>;
 13    fn get_signal_offset32(
 14        &self,
 15        p_sig_offset: u32,
 16        component: u32,
 17        hash_msb: u32,
 18        hash_lsb: u32,
 19    ) -> Result<()>;
 20    fn set_signal(&self, c_idx: u32, component: u32, signal: u32, p_val: u32) -> Result<()>;
 21    fn get_u32(&self, name: &str) -> Result<u32>;
 22    // Only exists natively in Circom2, hardcoded for Circom
 23    fn get_version(&self) -> Result<u32>;
 24}
 25
 26pub trait Circom {
 27    fn get_fr_len(&self) -> Result<u32>;
 28    fn get_ptr_raw_prime(&self) -> Result<u32>;
 29}
 30
 31#[cfg(feature = "circom-2")]
 32pub trait Circom2 {
 33    fn get_field_num_len32(&self) -> Result<u32>;
 34    fn get_raw_prime(&self) -> Result<()>;
 35    fn read_shared_rw_memory(&self, i: u32) -> Result<u32>;
 36    fn write_shared_rw_memory(&self, i: u32, v: u32) -> Result<()>;
 37    fn set_input_signal(&self, hmsb: u32, hlsb: u32, pos: u32) -> Result<()>;
 38    fn get_witness(&self, i: u32) -> Result<()>;
 39    fn get_witness_size(&self) -> Result<u32>;
 40}
 41
 42impl Circom for Wasm {
 43    fn get_fr_len(&self) -> Result<u32> {
 44        self.get_u32("getFrLen")
 45    }
 46
 47    fn get_ptr_raw_prime(&self) -> Result<u32> {
 48        self.get_u32("getPRawPrime")
 49    }
 50}
 51
 52#[cfg(feature = "circom-2")]
 53impl Circom2 for Wasm {
 54    fn get_field_num_len32(&self) -> Result<u32> {
 55        self.get_u32("getFieldNumLen32")
 56    }
 57
 58    fn get_raw_prime(&self) -> Result<()> {
 59        let func = self.func("getRawPrime");
 60        func.call(&[])?;
 61        Ok(())
 62    }
 63
 64    fn read_shared_rw_memory(&self, i: u32) -> Result<u32> {
 65        let func = self.func("readSharedRWMemory");
 66        let result = func.call(&[i.into()])?;
 67        Ok(result[0].unwrap_i32() as u32)
 68    }
 69
 70    fn write_shared_rw_memory(&self, i: u32, v: u32) -> Result<()> {
 71        let func = self.func("writeSharedRWMemory");
 72        func.call(&[i.into(), v.into()])?;
 73        Ok(())
 74    }
 75
 76    fn set_input_signal(&self, hmsb: u32, hlsb: u32, pos: u32) -> Result<()> {
 77        let func = self.func("setInputSignal");
 78        func.call(&[hmsb.into(), hlsb.into(), pos.into()])?;
 79        Ok(())
 80    }
 81
 82    fn get_witness(&self, i: u32) -> Result<()> {
 83        let func = self.func("getWitness");
 84        func.call(&[i.into()])?;
 85        Ok(())
 86    }
 87
 88    fn get_witness_size(&self) -> Result<u32> {
 89        self.get_u32("getWitnessSize")
 90    }
 91}
 92
 93impl CircomBase for Wasm {
 94    fn init(&self, sanity_check: bool) -> Result<()> {
 95        let func = self.func("init");
 96        func.call(&[Value::I32(sanity_check as i32)])?;
 97        Ok(())
 98    }
 99
100    fn get_ptr_witness_buffer(&self) -> Result<u32> {
101        self.get_u32("getWitnessBuffer")
102    }
103
104    fn get_ptr_witness(&self, w: u32) -> Result<u32> {
105        let func = self.func("getPWitness");
106        let res = func.call(&[w.into()])?;
107
108        Ok(res[0].unwrap_i32() as u32)
109    }
110
111    fn get_n_vars(&self) -> Result<u32> {
112        self.get_u32("getNVars")
113    }
114
115    fn get_signal_offset32(
116        &self,
117        p_sig_offset: u32,
118        component: u32,
119        hash_msb: u32,
120        hash_lsb: u32,
121    ) -> Result<()> {
122        let func = self.func("getSignalOffset32");
123        func.call(&[
124            p_sig_offset.into(),
125            component.into(),
126            hash_msb.into(),
127            hash_lsb.into(),
128        ])?;
129
130        Ok(())
131    }
132
133    fn set_signal(&self, c_idx: u32, component: u32, signal: u32, p_val: u32) -> Result<()> {
134        let func = self.func("setSignal");
135        func.call(&[c_idx.into(), component.into(), signal.into(), p_val.into()])?;
136
137        Ok(())
138    }
139
140    // Default to version 1 if it isn't explicitly defined
141    fn get_version(&self) -> Result<u32> {
142        match self.0.exports.get_function("getVersion") {
143            Ok(func) => Ok(func.call(&[])?[0].unwrap_i32() as u32),
144            Err(_) => Ok(1),
145        }
146    }
147
148    fn get_u32(&self, name: &str) -> Result<u32> {
149        let func = self.func(name);
150        let result = func.call(&[])?;
151        Ok(result[0].unwrap_i32() as u32)
152    }
153
154    fn func(&self, name: &str) -> &Function {
155        self.0
156            .exports
157            .get_function(name)
158            .unwrap_or_else(|_| panic!("function {} not found", name))
159    }
160}
161
162impl Wasm {
163    pub fn new(instance: Instance) -> Self {
164        Self(instance)
165    }
166}