add wallet code
This commit is contained in:
parent
0381fd1d76
commit
8c78a366cc
1954
Cargo.lock
generated
Normal file
1954
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
Cargo.toml
17
Cargo.toml
@ -4,5 +4,22 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[lib]
|
||||
name = "rustywallet"
|
||||
# this is needed to build for iOS and Android.
|
||||
crate-type = ["staticlib", "dylib"]
|
||||
|
||||
# this dependency is only needed for Android.
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
jni = { version = "0.19.0", default-features = false }
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.65"
|
||||
openssl = { version = "0.10.41", features = ["vendored"] }
|
||||
secp256k1 = { version = "0.24.0", features = ["rand"] }
|
||||
serde = { version = "1.0.145", features = ["derive"]}
|
||||
serde_json = "1.0.85"
|
||||
shamir_secret_sharing = "0.1.1"
|
||||
tiny-keccak = "1.5"
|
||||
web3 = "0.18.0"
|
||||
|
||||
|
20
scripts/android_build.sh
Executable file
20
scripts/android_build.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# set the version to use the library
|
||||
min_ver=22
|
||||
# verify before executing this that you have the proper targets installed
|
||||
cargo ndk -t armeabi-v7a -t arm64-v8a -t x86_64 -p ${min_ver} build --release
|
||||
|
||||
# moving libraries to the android project
|
||||
jniLibs=./android/rusty-android-lib/src/main/jniLibs
|
||||
libName=librustywallet.so
|
||||
|
||||
rm -rf ${jniLibs}
|
||||
|
||||
mkdir ${jniLibs}
|
||||
mkdir ${jniLibs}/arm64-v8a
|
||||
mkdir ${jniLibs}/armeabi-v7a
|
||||
mkdir ${jniLibs}/x86_64
|
||||
|
||||
cp target/aarch64-linux-android/release/${libName} ${jniLibs}/arm64-v8a/${libName}
|
||||
cp target/armv7-linux-androideabi/release/${libName} ${jniLibs}/armeabi-v7a/${libName}
|
||||
cp target/x86_64-linux-android/release/${libName} ${jniLibs}/x86_64/${libName}
|
7
scripts/install_targets.sh
Executable file
7
scripts/install_targets.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Android targets
|
||||
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
|
||||
|
||||
# iOS targets
|
||||
rustup target add aarch64-apple-ios armv7-apple-ios armv7s-apple-ios x86_64-apple-ios i386-apple-ios
|
17
scripts/ios_build.sh
Executable file
17
scripts/ios_build.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# building
|
||||
cbindgen src/lib.rs -l c > rustywallet.h
|
||||
cargo lipo --release
|
||||
|
||||
# moving files to the ios project
|
||||
proj=ios
|
||||
inc=../${proj}/include
|
||||
libs=../${proj}/libs
|
||||
|
||||
rm -rf ${inc} ${libs}
|
||||
|
||||
mkdir ${inc}
|
||||
mkdir ${libs}
|
||||
|
||||
cp rustywallet.h ${inc}
|
||||
cp target/universal/release/librustywallet.a ${libs}
|
107
src/lib.rs
Normal file
107
src/lib.rs
Normal file
@ -0,0 +1,107 @@
|
||||
// lib.rs
|
||||
//
|
||||
// 此部分代码主要负责Rust-C两侧的数据内存结构转换,提供了C侧的函数接口。注意命名规范:
|
||||
// 在C侧使用时,凡是函数名带有 '_cwallet'的,调用过之后都必须用'free_cwallet'释放内存,
|
||||
// 否则导致内存泄漏
|
||||
//
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::c_char;
|
||||
|
||||
mod wallet;
|
||||
|
||||
use wallet_impl::Wallet;
|
||||
|
||||
use crate::wallet::*;
|
||||
|
||||
// #[cfg(target_os = "android")]
|
||||
// mod android;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CWallet {
|
||||
pub public_key: *mut c_char,
|
||||
pub private_key: *mut c_char,
|
||||
pub public_addr: *mut c_char,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn generate_cwallet() -> CWallet {
|
||||
println!("generating wallet");
|
||||
let (secret_key, pub_key) = wallet_impl::generate_keypair();
|
||||
|
||||
// println!("secret key: {}", &secret_key.to_string());
|
||||
// println!("public key: {}", &pub_key.to_string());
|
||||
|
||||
//let pub_address = eth_wallet::public_key_address(&pub_key);
|
||||
//println!("public address: {:?}", pub_address);
|
||||
|
||||
let rust_wallet = wallet_impl::Wallet::new(&secret_key, &pub_key);
|
||||
println!("rust_wallet: {:?}", &rust_wallet);
|
||||
convert_to_cwallet(rust_wallet)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn free_cwallet(cw: CWallet) {
|
||||
drop(CString::from_raw(cw.public_key));
|
||||
drop(CString::from_raw(cw.private_key));
|
||||
drop(CString::from_raw(cw.public_addr));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn save_wallet(cw: &CWallet) {
|
||||
let rwallet = convert_to_rwallet(cw);
|
||||
wallet_impl::Wallet::save_keys(&rwallet, "wallet.json").unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn fetch_cwallet() -> CWallet {
|
||||
match wallet_impl::Wallet::retrieve_keys("wallet.json") {
|
||||
Err(_) => {
|
||||
let wallet = wallet_impl::Wallet {
|
||||
secret_key: "".to_string(),
|
||||
public_key: "".to_string(),
|
||||
public_address: "".to_string(),
|
||||
};
|
||||
return convert_to_cwallet(wallet);
|
||||
}
|
||||
Ok(w) => return convert_to_cwallet(w),
|
||||
};
|
||||
}
|
||||
|
||||
unsafe fn convert_to_cwallet(rwallet: Wallet) -> CWallet {
|
||||
// 转换Rust字符串数据为C的字符串并移交ownership
|
||||
let pubkey = CString::new(rwallet.public_key).unwrap();
|
||||
let c_pubkey: *mut c_char = pubkey.into_raw();
|
||||
let seckey = CString::new(rwallet.secret_key).unwrap();
|
||||
let c_seckey: *mut c_char = seckey.into_raw();
|
||||
let pubaddr = CString::new(rwallet.public_address).unwrap();
|
||||
let c_pubaddr: *mut c_char = pubaddr.into_raw();
|
||||
|
||||
//println!("crypto wallet address: {}", CStr::from_ptr(c_pubaddr).to_str().unwrap());
|
||||
|
||||
let cw = CWallet {
|
||||
public_key: c_pubkey,
|
||||
private_key: c_seckey,
|
||||
public_addr: c_pubaddr,
|
||||
};
|
||||
|
||||
//println!("crypto_wallet addr: {}", CStr::from_ptr(cw.public_addr).to_str().unwrap());
|
||||
|
||||
cw
|
||||
}
|
||||
|
||||
unsafe fn convert_to_rwallet(cwallet: &CWallet) -> Wallet {
|
||||
let a = CStr::from_ptr(cwallet.public_addr);
|
||||
let pa = a.to_str().unwrap();
|
||||
|
||||
let pk = CStr::from_ptr(cwallet.public_key);
|
||||
let ppk = pk.to_str().unwrap();
|
||||
|
||||
let sk = CStr::from_ptr(cwallet.private_key);
|
||||
let psk = sk.to_str().unwrap();
|
||||
Wallet {
|
||||
secret_key: psk.to_string(),
|
||||
public_key: ppk.to_string(),
|
||||
public_address: pa.to_string(),
|
||||
}
|
||||
}
|
1
src/wallet/mod.rs
Normal file
1
src/wallet/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod wallet_impl;
|
59
src/wallet/wallet_impl.rs
Normal file
59
src/wallet/wallet_impl.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use anyhow::Result;
|
||||
use secp256k1::rand::rngs::OsRng;
|
||||
use secp256k1::{PublicKey, SecretKey};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::BufWriter;
|
||||
use std::{fs::OpenOptions, io::BufReader};
|
||||
use tiny_keccak::keccak256;
|
||||
use web3::types::Address;
|
||||
|
||||
pub fn generate_keypair() -> (SecretKey, PublicKey) {
|
||||
let secp = secp256k1::Secp256k1::new();
|
||||
secp.generate_keypair(&mut OsRng)
|
||||
}
|
||||
|
||||
pub fn public_key_address(public_key: &PublicKey) -> Address {
|
||||
let public_key = public_key.serialize_uncompressed();
|
||||
debug_assert_eq!(public_key[0], 0x04);
|
||||
let hash = keccak256(&public_key[1..]);
|
||||
|
||||
Address::from_slice(&hash[12..])
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Wallet {
|
||||
pub secret_key: String,
|
||||
pub public_key: String,
|
||||
pub public_address: String,
|
||||
}
|
||||
|
||||
impl Wallet {
|
||||
pub fn new(secret_key: &SecretKey, public_key: &PublicKey) -> Self {
|
||||
let addr: Address = public_key_address(&public_key);
|
||||
Wallet {
|
||||
secret_key: format!("{:?}", secret_key),
|
||||
public_key: public_key.to_string(),
|
||||
public_address: format!("{:?}", addr),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_keys(&self, file_path: &str) -> Result<()> {
|
||||
let file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(file_path)?;
|
||||
let buf_writer = BufWriter::new(file);
|
||||
|
||||
serde_json::to_writer_pretty(buf_writer, self)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn retrieve_keys(file_path: &str) -> Result<Wallet> {
|
||||
let file = OpenOptions::new().read(true).open(file_path)?;
|
||||
let buf_reader = BufReader::new(file);
|
||||
|
||||
let wallet: Wallet = serde_json::from_reader(buf_reader)?;
|
||||
Ok(wallet)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user