diff --git a/.gitignore b/.gitignore index 30226da..9d55bb8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ Cargo.lock /local.properties .gradle wallet_db +bdk_ffi_test diff --git a/bdk_ffi_test.c b/bdk_ffi_test.c new file mode 100644 index 0000000..7c2d492 --- /dev/null +++ b/bdk_ffi_test.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include "bdk_ffi.h" + +int main (int argc, char const * const argv[]) +{ + // test print_string + print_string("hello 123"); + + // test concat_string + char const * string1 = "string1"; + char const * string2 = "string2"; + char * string3 = concat_string(string1, string2); + print_string(string3); + free_string(string3); + // verify free_string after free_string fails + ////free_string(string3); + + // test print_config with c created config + Config_t config1 = { .name = "test", .count = 101 }; + print_config(&config1); + + // test new_config + Config_t * config2 = new_config("test test", 202); + print_config(config2); + + // test free_config + free_config(config2); + // verify print_config after free_config fails (invalid data) + ////print_config(config2); + // verify free_config after free_config fails (double free detected, core dumped) + ////free_config(config2); + + char const * name = "test_wallet"; + char const * desc = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"; + char const * change = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"; + //char const * change = NULL; + + // test new_wallet + { + WalletPtr_t * wallet = new_wallet(name, desc, change); + + // test sync_wallet + sync_wallet(wallet); + printf("after sync_wallet\n"); + sync_wallet(wallet); + printf("after sync_wallet\n"); + + // test new_address + char * address1 = new_address(wallet); + printf("address1: %s\n", address1); + free_string(address1); + assert(address1 != NULL); + char * address2 = new_address(wallet); + printf("address2: %s\n", address2); + assert(address2 != NULL); + free_string(address2); + + // test free_wallet + free_wallet(wallet); + printf("after free_wallet\n"); + + // test free_wallet NULL doesn't crash + free_wallet(NULL); + + // verify sync_wallet after sync_wallet fails (double free detected, core dumped) + ////sync_wallet(&wallet); + } + + return EXIT_SUCCESS; +} diff --git a/build.sh b/build.sh index d80153a..5e9eab6 100755 --- a/build.sh +++ b/build.sh @@ -1,9 +1,13 @@ +# rust cargo build cargo test --features c-headers -- generate_headers -cc main.c -o main -L target/debug -l bdk_ffi -l pthread -l dl -l m -./main +export LD_LIBRARY_PATH=`pwd`/target/debug + +# cc +cc bdk_ffi_test.c -o bdk_ffi_test -L target/debug -l bdk_ffi -l pthread -l dl -l m +#valgrind --leak-check=full ./bdk_ffi_test +./bdk_ffi_test # jvm mkdir -p jvm/build/jniLibs/x86_64_linux cp target/debug/libbdk_ffi.so jvm/build/jniLibs/x86_64_linux -export LD_LIBRARY_PATH=`pwd`/target/debug diff --git a/main.c b/main.c deleted file mode 100644 index 6d133e4..0000000 --- a/main.c +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include -#include "bdk_ffi.h" - -int main (int argc, char const * const argv[]) -{ - // test print_string - print_string("hello 123"); - - // test concat_string - char const * string1 = "string1"; - char const * string2 = "string2"; - char * string3 = concat_string(string1, string2); - print_string(string3); - free_string(string3); - // verify free_string after free_string fails - ////free_string(string3); - - // test print_config with c created config - Config_t config1 = { .name = "test", .count = 101 }; - print_config(&config1); - - // test new_config - Config_t * config2 = new_config("test test", 202); - print_config(config2); - - // test free_config - free_config(config2); - // verify print_config after free_config fails (invalid data) - ////print_config(config2); - // verify free_config after free_config fails (double free detected, core dumped) - ////free_config(config2); - - //char const * name = "test_wallet"; - //char const * desc = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"; - //char const * change = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"; - - ////printf("wallet name: %s\n", name); - ////printf("descriptor: %s\n", desc); - ////printf("change descriptor: %s\n", change); - //WalletPtr_t * wallet = new_wallet(name, desc, change); - - //sync_wallet(&wallet); - //sync_wallet(&wallet); - - //char const * address1 = new_address(&wallet); - //printf("address1: %s\n", address1); - //char const * address2 = new_address(&wallet); - //printf("address: %s\n", address2); - - //free_wallet(wallet); - ////sync_wallet(&wallet); - - return EXIT_SUCCESS; -} diff --git a/src/lib.rs b/src/lib.rs index 714fe9f..7776e47 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,73 +64,68 @@ fn free_config(config: Box) { drop(config) } -//#[derive_ReprC] -//#[ReprC::opaque] -//pub struct WalletPtr { -// raw: Wallet, -//} +#[derive_ReprC] +#[ReprC::opaque] +pub struct WalletPtr { + raw: Wallet, +} -//impl From> for WalletPtr { -// fn from(wallet: Wallet) -> Self { -// WalletPtr { -// raw: wallet, -// } -// } -//} +impl From> for WalletPtr { + fn from(wallet: Wallet) -> Self { + WalletPtr { + raw: wallet, + } + } +} -//#[ffi_export] -//fn new_wallet<'a>( -// name: char_p_ref<'a>, -// descriptor: char_p_ref<'a>, -// change_descriptor: Option>, -//) -> Box { -// let name = name.to_string(); -// let descriptor = descriptor.to_string(); -// let change_descriptor = change_descriptor.map(|s| s.to_string()); -// -// let database = sled::open("./wallet_db").unwrap(); -// let tree = database.open_tree(name.clone()).unwrap(); -// -// let descriptor: &str = descriptor.as_str(); -// let change_descriptor: Option<&str> = change_descriptor.as_deref(); -// -// let electrum_url = "ssl://electrum.blockstream.info:60002"; -// let client = Client::new(&electrum_url).unwrap(); -// -// let wallet = Wallet::new( -// descriptor, -// change_descriptor, -// Testnet, -// tree, -// ElectrumBlockchain::from(client), -// ) -// .unwrap(); -// -// Box::new(WalletPtr::from(wallet)) -//} +#[ffi_export] +fn new_wallet( + name: char_p_ref, + descriptor: char_p_ref, + change_descriptor: Option, +) -> Box { + let name = name.to_string(); + let descriptor = descriptor.to_string(); + let change_descriptor = change_descriptor.map(|s| s.to_string()); -//#[ffi_export] -//fn sync_wallet( wallet: &Box) { -// println!("before sync"); -// let _r = wallet.raw.sync(log_progress(), Some(100)); -// println!("after sync"); -//} + let database = sled::open("./wallet_db").unwrap(); + let tree = database.open_tree(name.clone()).unwrap(); -//#[ffi_export] -//fn new_address( wallet: &Box) -> char_p_boxed { -// println!("before new_address"); -// let new_address = wallet.raw.get_address(New); -// println!("after new_address: {:?}", new_address); -// let new_address = new_address.unwrap(); -// let new_address = new_address.to_string(); -// println!("new address: ${}", new_address); -// new_address.try_into().unwrap() -//} + let descriptor: &str = descriptor.as_str(); + let change_descriptor: Option<&str> = change_descriptor.as_deref(); -//#[ffi_export] -//fn free_wallet( wallet: Box) { -// drop(wallet) -//} + let electrum_url = "ssl://electrum.blockstream.info:60002"; + let client = Client::new(&electrum_url).unwrap(); + + let wallet = Wallet::new( + descriptor, + change_descriptor, + Testnet, + tree, + ElectrumBlockchain::from(client), + ) + .unwrap(); + println!("created wallet"); + Box::new(WalletPtr::from(wallet)) +} + +#[ffi_export] +fn sync_wallet( wallet: &WalletPtr) { + let _r = wallet.raw.sync(log_progress(), Some(100)); +} + +#[ffi_export] +fn new_address( wallet: &WalletPtr) -> char_p_boxed { + let new_address = wallet.raw.get_address(New); + let new_address = new_address.unwrap(); + let new_address = new_address.to_string(); + new_address.try_into().unwrap() +} + +#[ffi_export] +fn free_wallet( wallet: Option>) { + drop(wallet) +} /// The following test function is necessary for the header generation. #[::safer_ffi::cfg_headers]