github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/rollup/circuitcapacitychecker/libzkp/src/lib.rs (about) 1 #![feature(once_cell)] 2 3 pub mod checker { 4 use crate::utils::{c_char_to_str, c_char_to_vec, vec_to_c_char}; 5 use anyhow::{anyhow, bail, Error}; 6 use libc::c_char; 7 use prover::{ 8 zkevm::{CircuitCapacityChecker, RowUsage}, 9 BlockTrace, 10 }; 11 use serde_derive::{Deserialize, Serialize}; 12 use std::cell::OnceCell; 13 use std::collections::HashMap; 14 use std::panic; 15 use std::ptr::null; 16 17 #[derive(Debug, Clone, Deserialize, Serialize)] 18 pub struct CommonResult { 19 pub error: Option<String>, 20 } 21 22 #[derive(Debug, Clone, Deserialize, Serialize)] 23 pub struct RowUsageResult { 24 pub acc_row_usage: Option<RowUsage>, 25 pub error: Option<String>, 26 } 27 28 #[derive(Debug, Clone, Deserialize, Serialize)] 29 pub struct TxNumResult { 30 pub tx_num: u64, 31 pub error: Option<String>, 32 } 33 34 static mut CHECKERS: OnceCell<HashMap<u64, CircuitCapacityChecker>> = OnceCell::new(); 35 36 /// # Safety 37 #[no_mangle] 38 pub unsafe extern "C" fn init() { 39 env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")) 40 .format_timestamp_millis() 41 .init(); 42 let checkers = HashMap::new(); 43 CHECKERS 44 .set(checkers) 45 .expect("circuit capacity checker initialized twice"); 46 } 47 48 /// # Safety 49 #[no_mangle] 50 pub unsafe extern "C" fn new_circuit_capacity_checker() -> u64 { 51 let checkers = CHECKERS 52 .get_mut() 53 .expect("fail to get circuit capacity checkers map in new_circuit_capacity_checker"); 54 let id = checkers.len() as u64; 55 let checker = CircuitCapacityChecker::new(); 56 checkers.insert(id, checker); 57 id 58 } 59 60 /// # Safety 61 #[no_mangle] 62 pub unsafe extern "C" fn reset_circuit_capacity_checker(id: u64) { 63 CHECKERS 64 .get_mut() 65 .expect("fail to get circuit capacity checkers map in reset_circuit_capacity_checker") 66 .get_mut(&id) 67 .unwrap_or_else(|| panic!("fail to get circuit capacity checker (id: {id:?}) in reset_circuit_capacity_checker")) 68 .reset() 69 } 70 71 /// # Safety 72 #[no_mangle] 73 pub unsafe extern "C" fn apply_tx(id: u64, tx_traces: *const c_char) -> *const c_char { 74 let result = apply_tx_inner(id, tx_traces); 75 let r = match result { 76 Ok(acc_row_usage) => { 77 log::debug!( 78 "id: {:?}, acc_row_usage: {:?}", 79 id, 80 acc_row_usage.row_number, 81 ); 82 RowUsageResult { 83 acc_row_usage: Some(acc_row_usage), 84 error: None, 85 } 86 } 87 Err(e) => RowUsageResult { 88 acc_row_usage: None, 89 error: Some(format!("{e:?}")), 90 }, 91 }; 92 serde_json::to_vec(&r).map_or(null(), vec_to_c_char) 93 } 94 95 unsafe fn apply_tx_inner(id: u64, tx_traces: *const c_char) -> Result<RowUsage, Error> { 96 log::debug!( 97 "ccc apply_tx raw input, id: {:?}, tx_traces: {:?}", 98 id, 99 c_char_to_str(tx_traces)? 100 ); 101 let tx_traces_vec = c_char_to_vec(tx_traces); 102 let traces = serde_json::from_slice::<BlockTrace>(&tx_traces_vec)?; 103 104 if traces.transactions.len() != 1 { 105 bail!("traces.transactions.len() != 1"); 106 } 107 if traces.execution_results.len() != 1 { 108 bail!("traces.execution_results.len() != 1"); 109 } 110 if traces.tx_storage_trace.len() != 1 { 111 bail!("traces.tx_storage_trace.len() != 1"); 112 } 113 114 let r = panic::catch_unwind(|| { 115 CHECKERS 116 .get_mut() 117 .ok_or(anyhow!( 118 "fail to get circuit capacity checkers map in apply_tx" 119 ))? 120 .get_mut(&id) 121 .ok_or(anyhow!( 122 "fail to get circuit capacity checker (id: {id:?}) in apply_tx" 123 ))? 124 .estimate_circuit_capacity(&[traces]) 125 }); 126 match r { 127 Ok(result) => result, 128 Err(e) => { 129 bail!("estimate_circuit_capacity (id: {id:?}) error in apply_tx, error: {e:?}") 130 } 131 } 132 } 133 134 /// # Safety 135 #[no_mangle] 136 pub unsafe extern "C" fn apply_block(id: u64, block_trace: *const c_char) -> *const c_char { 137 let result = apply_block_inner(id, block_trace); 138 let r = match result { 139 Ok(acc_row_usage) => { 140 log::debug!( 141 "id: {:?}, acc_row_usage: {:?}", 142 id, 143 acc_row_usage.row_number, 144 ); 145 RowUsageResult { 146 acc_row_usage: Some(acc_row_usage), 147 error: None, 148 } 149 } 150 Err(e) => RowUsageResult { 151 acc_row_usage: None, 152 error: Some(format!("{e:?}")), 153 }, 154 }; 155 serde_json::to_vec(&r).map_or(null(), vec_to_c_char) 156 } 157 158 unsafe fn apply_block_inner(id: u64, block_trace: *const c_char) -> Result<RowUsage, Error> { 159 log::debug!( 160 "ccc apply_block raw input, id: {:?}, block_trace: {:?}", 161 id, 162 c_char_to_str(block_trace)? 163 ); 164 let block_trace = c_char_to_vec(block_trace); 165 let traces = serde_json::from_slice::<BlockTrace>(&block_trace)?; 166 167 let r = panic::catch_unwind(|| { 168 CHECKERS 169 .get_mut() 170 .ok_or(anyhow!( 171 "fail to get circuit capacity checkers map in apply_block" 172 ))? 173 .get_mut(&id) 174 .ok_or(anyhow!( 175 "fail to get circuit capacity checker (id: {id:?}) in apply_block" 176 ))? 177 .estimate_circuit_capacity(&[traces]) 178 }); 179 match r { 180 Ok(result) => result, 181 Err(e) => { 182 bail!("estimate_circuit_capacity (id: {id:?}) error in apply_block, error: {e:?}") 183 } 184 } 185 } 186 187 /// # Safety 188 #[no_mangle] 189 pub unsafe extern "C" fn get_tx_num(id: u64) -> *const c_char { 190 let result = get_tx_num_inner(id); 191 let r = match result { 192 Ok(tx_num) => { 193 log::debug!("id: {id}, tx_num: {tx_num}"); 194 TxNumResult { 195 tx_num, 196 error: None, 197 } 198 } 199 Err(e) => TxNumResult { 200 tx_num: 0, 201 error: Some(format!("{e:?}")), 202 }, 203 }; 204 serde_json::to_vec(&r).map_or(null(), vec_to_c_char) 205 } 206 207 unsafe fn get_tx_num_inner(id: u64) -> Result<u64, Error> { 208 log::debug!("ccc get_tx_num raw input, id: {id}"); 209 panic::catch_unwind(|| { 210 Ok(CHECKERS 211 .get_mut() 212 .ok_or(anyhow!( 213 "fail to get circuit capacity checkers map in get_tx_num" 214 ))? 215 .get_mut(&id) 216 .ok_or(anyhow!( 217 "fail to get circuit capacity checker (id: {id}) in get_tx_num" 218 ))? 219 .get_tx_num() as u64) 220 }) 221 .map_or_else( 222 |e| bail!("circuit capacity checker (id: {id}) error in get_tx_num: {e:?}"), 223 |result| result, 224 ) 225 } 226 227 /// # Safety 228 #[no_mangle] 229 pub unsafe extern "C" fn set_light_mode(id: u64, light_mode: bool) -> *const c_char { 230 let result = set_light_mode_inner(id, light_mode); 231 let r = match result { 232 Ok(()) => CommonResult { error: None }, 233 Err(e) => CommonResult { 234 error: Some(format!("{e:?}")), 235 }, 236 }; 237 serde_json::to_vec(&r).map_or(null(), vec_to_c_char) 238 } 239 240 unsafe fn set_light_mode_inner(id: u64, light_mode: bool) -> Result<(), Error> { 241 log::debug!("ccc set_light_mode raw input, id: {id}"); 242 panic::catch_unwind(|| { 243 CHECKERS 244 .get_mut() 245 .ok_or(anyhow!( 246 "fail to get circuit capacity checkers map in set_light_mode" 247 ))? 248 .get_mut(&id) 249 .ok_or(anyhow!( 250 "fail to get circuit capacity checker (id: {id}) in set_light_mode" 251 ))? 252 .set_light_mode(light_mode); 253 Ok(()) 254 }) 255 .map_or_else( 256 |e| bail!("circuit capacity checker (id: {id}) error in set_light_mode: {e:?}"), 257 |result| result, 258 ) 259 } 260 } 261 262 pub mod utils { 263 use std::ffi::{CStr, CString}; 264 use std::os::raw::c_char; 265 use std::str::Utf8Error; 266 267 /// # Safety 268 #[no_mangle] 269 pub unsafe extern "C" fn free_c_chars(ptr: *mut c_char) { 270 if ptr.is_null() { 271 log::warn!("Try to free an empty pointer!"); 272 return; 273 } 274 275 let _ = CString::from_raw(ptr); 276 } 277 278 #[allow(dead_code)] 279 pub(crate) fn c_char_to_str(c: *const c_char) -> Result<&'static str, Utf8Error> { 280 let cstr = unsafe { CStr::from_ptr(c) }; 281 cstr.to_str() 282 } 283 284 #[allow(dead_code)] 285 pub(crate) fn c_char_to_vec(c: *const c_char) -> Vec<u8> { 286 let cstr = unsafe { CStr::from_ptr(c) }; 287 cstr.to_bytes().to_vec() 288 } 289 290 #[allow(dead_code)] 291 pub(crate) fn vec_to_c_char(bytes: Vec<u8>) -> *const c_char { 292 CString::new(bytes) 293 .expect("fail to create new CString from bytes") 294 .into_raw() 295 } 296 297 #[allow(dead_code)] 298 pub(crate) fn bool_to_int(b: bool) -> u8 { 299 match b { 300 true => 1, 301 false => 0, 302 } 303 } 304 }