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  }