290 lines
7.9 KiB
Rust
290 lines
7.9 KiB
Rust
// lib.rs
|
||
//
|
||
// 此部分代码主要负责Rust-C两侧的数据内存结构转换,提供了C侧的函数接口。注意命名规范:
|
||
// 在C侧使用时,凡是函数名带有 '_cwallet'的,调用过之后都必须用'free_cwallet'释放内存,
|
||
// 否则导致内存泄漏
|
||
//
|
||
|
||
use std::ffi::{CStr, CString};
|
||
use std::os::raw::c_char;
|
||
use wasm_bindgen::prelude::*;
|
||
|
||
mod wallet;
|
||
use wallet_impl::Wallet;
|
||
|
||
use crate::wallet::*;
|
||
|
||
// #[cfg(target_os = "android")]
|
||
// mod android;
|
||
macro_rules! cchar_to_str {
|
||
($p1:expr) => {{
|
||
let s = CStr::from_ptr($p1);
|
||
let ps = s.to_str().unwrap();
|
||
ps
|
||
}};
|
||
}
|
||
|
||
macro_rules! cchar_to_string {
|
||
($p1:expr) => {{
|
||
let s = CStr::from_ptr($p1);
|
||
let ps = s.to_str().unwrap();
|
||
ps.to_string()
|
||
}};
|
||
}
|
||
|
||
macro_rules! cchar_to_ostring {
|
||
($p1:expr) => {{
|
||
let s = CStr::from_ptr($p1);
|
||
let pb = s.to_str().unwrap();
|
||
let result = if pb.is_empty() {
|
||
None
|
||
} else {
|
||
Some(pb.to_string())
|
||
};
|
||
result
|
||
}};
|
||
}
|
||
|
||
macro_rules! str_to_cchar {
|
||
($p1:expr) => {{
|
||
let msgkey = CString::new($p1).unwrap();
|
||
let c_msgkey: *mut c_char = msgkey.into_raw();
|
||
c_msgkey
|
||
}};
|
||
}
|
||
|
||
macro_rules! ostr_to_cchar {
|
||
($p1:expr) => {{
|
||
let key = match $p1 {
|
||
Some(val) => CString::new(val).unwrap(),
|
||
None => CString::new("").unwrap(),
|
||
};
|
||
let c_key: *mut c_char = key.into_raw();
|
||
c_key
|
||
}};
|
||
}
|
||
|
||
#[repr(C)]
|
||
pub struct CWallet {
|
||
pub msg_key: *mut c_char,
|
||
pub master_key: *mut c_char,
|
||
pub second_key: *mut c_char,
|
||
pub backup_key: *mut c_char,
|
||
}
|
||
|
||
#[wasm_bindgen]
|
||
extern "C" {
|
||
// Use `js_namespace` here to bind `console.log(..)` instead of just
|
||
// `log(..)`
|
||
#[wasm_bindgen(js_namespace = console)]
|
||
fn log(s: &str);
|
||
|
||
// The `console.log` is quite polymorphic, so we can bind it with multiple
|
||
// signatures. Note that we need to use `js_name` to ensure we always call
|
||
// `log` in JS.
|
||
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
||
fn log_u32(a: u32);
|
||
|
||
// Multiple arguments too!
|
||
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
||
fn log_many(a: &str, b: &str);
|
||
}
|
||
|
||
macro_rules! console_log {
|
||
// Note that this is using the `log` function imported above during
|
||
// `bare_bones`
|
||
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
|
||
}
|
||
|
||
#[no_mangle]
|
||
pub unsafe extern "C" fn new_wallet(msg: *const c_char) -> CWallet {
|
||
let str = cchar_to_str!(msg);
|
||
let rust_wallet = wallet_impl::Wallet::new(str);
|
||
convert_to_cwallet(rust_wallet)
|
||
}
|
||
|
||
#[no_mangle]
|
||
pub unsafe extern "C" fn reset_wallet(
|
||
msg_key: *const c_char,
|
||
master_key: *const c_char,
|
||
second_key: *const c_char,
|
||
backup_key: *const c_char,
|
||
) -> CWallet {
|
||
let rust_wallet = generate_rwallet(msg_key, master_key, second_key, backup_key);
|
||
let rust_wallet2 = rust_wallet.reset_wallet();
|
||
convert_to_cwallet(rust_wallet2)
|
||
}
|
||
|
||
#[no_mangle]
|
||
pub unsafe extern "C" fn free_cwallet(cw: CWallet) {
|
||
drop(CString::from_raw(cw.msg_key));
|
||
drop(CString::from_raw(cw.master_key));
|
||
drop(CString::from_raw(cw.second_key));
|
||
drop(CString::from_raw(cw.backup_key));
|
||
}
|
||
|
||
#[no_mangle]
|
||
pub unsafe extern "C" fn get_address(
|
||
msg_key: *const c_char,
|
||
master_key: *const c_char,
|
||
second_key: *const c_char,
|
||
backup_key: *const c_char,
|
||
) -> *mut c_char {
|
||
let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key);
|
||
let address = rwallet.get_address();
|
||
let address_str = format!("{:?}", address);
|
||
let c_address = CString::new(address_str).unwrap();
|
||
c_address.into_raw()
|
||
}
|
||
|
||
#[wasm_bindgen]
|
||
pub fn wget_address(
|
||
msg_key: String,
|
||
master_key: String,
|
||
second_key: Option<String>,
|
||
backup_key: Option<String>,
|
||
) -> String {
|
||
console_log!("wget_address: {}, {}!", msg_key, master_key);
|
||
let rwallet = Wallet {
|
||
msg_key,
|
||
master_key,
|
||
second_key,
|
||
backup_key,
|
||
};
|
||
console_log!("wallet: {:?}", rwallet);
|
||
let address = rwallet.get_address();
|
||
let address_str = format!("{:?}", address);
|
||
address_str
|
||
}
|
||
|
||
#[no_mangle]
|
||
pub unsafe extern "C" fn generate_sec_key(
|
||
msg_key: *const c_char,
|
||
master_key: *const c_char,
|
||
second_key: *const c_char,
|
||
backup_key: *const c_char,
|
||
) -> *mut c_char {
|
||
let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key);
|
||
let s_key = rwallet.generate_sec_key();
|
||
let cs_key = CString::new(s_key).unwrap();
|
||
cs_key.into_raw()
|
||
}
|
||
|
||
#[no_mangle]
|
||
pub unsafe extern "C" fn sign(
|
||
msg_key: *const c_char,
|
||
master_key: *const c_char,
|
||
second_key: *const c_char,
|
||
backup_key: *const c_char,
|
||
msg: *const c_char,
|
||
) -> *mut c_char {
|
||
let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key);
|
||
let msg_str = cchar_to_str!(msg);
|
||
let signature = rwallet.sign(msg_str);
|
||
let r = match signature {
|
||
Ok(v) => v,
|
||
Err(err) => panic!("Problem sign: {:?}", err),
|
||
};
|
||
str_to_cchar!(r)
|
||
}
|
||
|
||
#[no_mangle]
|
||
pub unsafe extern "C" fn sign_for_tran(
|
||
msg_key: *const c_char,
|
||
master_key: *const c_char,
|
||
second_key: *const c_char,
|
||
backup_key: *const c_char,
|
||
msg: *const c_char,
|
||
) -> *mut c_char {
|
||
let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key);
|
||
let msg_str = cchar_to_str!(msg);
|
||
let signature = rwallet.sign_for_tran(msg_str);
|
||
let (r, recid) = match signature {
|
||
Ok((v, _recid)) => (v, _recid),
|
||
Err(err) => panic!("Problem sign: {:?}", err),
|
||
};
|
||
let result = format!("{}|{}", r, recid);
|
||
str_to_cchar!(result)
|
||
}
|
||
|
||
#[no_mangle]
|
||
pub unsafe extern "C" fn encrypt(
|
||
msg_key: *const c_char,
|
||
master_key: *const c_char,
|
||
second_key: *const c_char,
|
||
backup_key: *const c_char,
|
||
msg: *const c_char,
|
||
) -> *mut c_char {
|
||
let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key);
|
||
let msg_str = cchar_to_str!(msg);
|
||
let r = match rwallet.zencrypt(msg_str) {
|
||
Ok(v) => v,
|
||
Err(err) => panic!("Problem encrypt: {:?}", err),
|
||
};
|
||
str_to_cchar!(r)
|
||
}
|
||
|
||
#[no_mangle]
|
||
pub unsafe extern "C" fn decrypt(
|
||
msg_key: *const c_char,
|
||
master_key: *const c_char,
|
||
second_key: *const c_char,
|
||
backup_key: *const c_char,
|
||
msg: *const c_char,
|
||
) -> *mut c_char {
|
||
let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key);
|
||
let msg_str = cchar_to_str!(msg);
|
||
println!("{}", msg_str);
|
||
let r = match rwallet.zdecrypt(msg_str) {
|
||
Ok(v) => v,
|
||
Err(err) => panic!("Problem encrypt: {:?}", err),
|
||
};
|
||
str_to_cchar!(r)
|
||
}
|
||
|
||
unsafe fn convert_to_cwallet(rwallet: Wallet) -> CWallet {
|
||
let c_msgkey: *mut c_char = str_to_cchar!(rwallet.msg_key);
|
||
let c_masterkey: *mut c_char = str_to_cchar!(rwallet.master_key);
|
||
let c_secondkey = ostr_to_cchar!(rwallet.second_key);
|
||
let c_backupkey = ostr_to_cchar!(rwallet.backup_key);
|
||
|
||
let cw = CWallet {
|
||
msg_key: c_msgkey,
|
||
master_key: c_masterkey,
|
||
second_key: c_secondkey,
|
||
backup_key: c_backupkey,
|
||
};
|
||
cw
|
||
}
|
||
|
||
// unsafe fn convert_to_rwallet(cwallet: &CWallet) -> Wallet {
|
||
// let pmsg = cchar_to_string!(cwallet.msg_key);
|
||
// let pm = cchar_to_string!(cwallet.master_key);
|
||
// let second_key = cchar_to_ostring!(cwallet.second_key);
|
||
// let backup_key = cchar_to_ostring!(cwallet.backup_key);
|
||
// Wallet {
|
||
// msg_key: pmsg,
|
||
// master_key: pm,
|
||
// second_key: second_key,
|
||
// backup_key: backup_key
|
||
// }
|
||
// }
|
||
|
||
unsafe fn generate_rwallet(
|
||
msg_key: *const c_char,
|
||
master_key: *const c_char,
|
||
second_key: *const c_char,
|
||
backup_key: *const c_char,
|
||
) -> Wallet {
|
||
let pmsg = cchar_to_string!(msg_key);
|
||
let pm = cchar_to_string!(master_key);
|
||
let second_key = cchar_to_ostring!(second_key);
|
||
let backup_key = cchar_to_ostring!(backup_key);
|
||
Wallet {
|
||
msg_key: pmsg,
|
||
master_key: pm,
|
||
second_key: second_key,
|
||
backup_key: backup_key,
|
||
}
|
||
}
|