2018-11-28 09:19:43 -08:00
#[ macro_use ]
extern crate log ;
2019-02-11 07:44:49 -08:00
mod utils ;
2018-11-21 08:40:18 -08:00
2019-02-07 04:58:33 -08:00
use android_logger ::Filter ;
2019-02-11 18:56:17 -08:00
use failure ::format_err ;
2019-02-07 04:58:33 -08:00
use jni ::{
objects ::{ JClass , JString } ,
2019-02-11 08:20:11 -08:00
sys ::{ jboolean , jbyteArray , jint , jlong , jobjectArray , jstring , JNI_FALSE , JNI_TRUE } ,
2019-02-07 04:58:33 -08:00
JNIEnv ,
} ;
2019-02-07 04:56:04 -08:00
use log ::Level ;
2020-06-09 19:14:22 -07:00
use std ::convert ::TryFrom ;
2019-02-11 18:56:17 -08:00
use std ::panic ;
2019-02-07 04:56:04 -08:00
use std ::path ::Path ;
2019-02-11 18:56:17 -08:00
use std ::ptr ;
2019-02-07 04:56:04 -08:00
use zcash_client_backend ::{
2019-11-17 20:45:05 -08:00
encoding ::{
2020-07-27 11:39:43 -07:00
decode_extended_full_viewing_key , decode_extended_spending_key ,
encode_extended_full_viewing_key , encode_extended_spending_key , encode_payment_address ,
2019-11-17 20:45:05 -08:00
} ,
2019-04-10 10:39:06 -07:00
keys ::spending_key ,
2019-02-07 04:56:04 -08:00
} ;
2019-04-10 10:39:06 -07:00
use zcash_client_sqlite ::{
2019-05-24 08:06:19 -07:00
address ::RecipientAddress ,
2019-05-02 15:40:58 -07:00
chain ::{ rewind_to_height , validate_combined_chain } ,
2019-08-29 10:04:53 -07:00
error ::ErrorKind ,
init ::{ init_accounts_table , init_blocks_table , init_data_database } ,
query ::{
get_address , get_balance , get_received_memo_as_utf8 , get_sent_memo_as_utf8 ,
get_verified_balance ,
} ,
2020-03-12 21:41:17 -07:00
scan ::{ decrypt_and_store_transaction , scan_cached_blocks } ,
2019-08-29 10:04:53 -07:00
transact ::create_to_address ,
2019-04-10 10:39:06 -07:00
} ;
2020-02-11 16:57:57 -08:00
2019-04-10 10:39:06 -07:00
use zcash_primitives ::{
2019-11-17 20:45:05 -08:00
block ::BlockHash ,
2019-12-13 07:58:20 -08:00
consensus ::BranchId ,
2019-11-17 20:45:05 -08:00
note_encryption ::Memo ,
2020-03-12 21:41:17 -07:00
transaction ::{ components ::Amount , Transaction } ,
2019-11-17 20:45:05 -08:00
zip32 ::{ ExtendedFullViewingKey , ExtendedSpendingKey } ,
2019-04-10 10:39:06 -07:00
} ;
use zcash_proofs ::prover ::LocalTxProver ;
2019-02-07 04:56:04 -08:00
2019-03-08 19:47:49 -08:00
use crate ::utils ::exception ::unwrap_exc_or ;
2019-02-07 04:56:04 -08:00
2020-06-09 19:14:22 -07:00
#[ cfg(feature = " mainnet " ) ]
use zcash_primitives ::consensus ::MainNetwork as Network ;
#[ cfg(not(feature = " mainnet " )) ]
use zcash_primitives ::consensus ::TestNetwork as Network ;
2019-04-10 10:43:24 -07:00
#[ cfg(feature = " mainnet " ) ]
2019-11-17 20:45:05 -08:00
use zcash_client_backend ::constants ::mainnet ::{
2020-02-12 05:39:30 -08:00
COIN_TYPE , HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY , HRP_SAPLING_EXTENDED_SPENDING_KEY ,
HRP_SAPLING_PAYMENT_ADDRESS ,
2019-11-17 20:45:05 -08:00
} ;
2019-04-10 10:43:24 -07:00
#[ cfg(not(feature = " mainnet " )) ]
2019-11-17 20:45:05 -08:00
use zcash_client_backend ::constants ::testnet ::{
2020-02-12 05:39:30 -08:00
COIN_TYPE , HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY , HRP_SAPLING_EXTENDED_SPENDING_KEY ,
HRP_SAPLING_PAYMENT_ADDRESS ,
2019-11-17 20:45:05 -08:00
} ;
2020-02-11 16:57:57 -08:00
use zcash_client_backend ::encoding ::decode_extended_full_viewing_key ;
2019-04-10 10:43:24 -07:00
2019-02-07 04:56:04 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_initLogs (
2019-02-11 07:11:09 -08:00
_env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
) {
2019-02-07 04:56:04 -08:00
android_logger ::init_once (
2019-11-17 20:45:05 -08:00
Filter ::default ( ) . with_min_level ( Level ::Debug ) ,
2019-02-07 04:56:04 -08:00
Some ( " cash.z.rust.logs " ) ,
) ;
log_panics ::init ( ) ;
debug! ( " logs have been initialized successfully " ) ;
}
2018-11-28 09:19:43 -08:00
2019-02-07 04:56:04 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_initDataDb (
2019-02-11 07:11:09 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
2019-02-07 04:56:04 -08:00
) -> jboolean {
2019-02-11 18:56:17 -08:00
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
init_data_database ( & db_data )
. map ( | ( ) | JNI_TRUE )
. map_err ( | e | format_err! ( " Error while initializing data DB: {} " , e ) )
} ) ;
unwrap_exc_or ( & env , res , JNI_FALSE )
2019-02-07 04:56:04 -08:00
}
2018-11-28 09:19:43 -08:00
2019-02-07 04:56:04 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_initAccountsTable (
2019-02-11 07:11:09 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
2019-02-07 04:56:04 -08:00
seed : jbyteArray ,
accounts : jint ,
) -> jobjectArray {
2019-02-11 18:56:17 -08:00
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
let seed = env . convert_byte_array ( seed ) . unwrap ( ) ;
let accounts = if accounts > = 0 {
accounts as u32
} else {
return Err ( format_err! ( " accounts argument must be positive " ) ) ;
} ;
let extsks : Vec < _ > = ( 0 .. accounts )
2019-12-18 20:30:19 -08:00
. map ( | account | spending_key ( & seed , COIN_TYPE , account ) )
2019-02-07 04:56:04 -08:00
. collect ( ) ;
2019-02-07 05:01:54 -08:00
let extfvks : Vec < _ > = extsks . iter ( ) . map ( ExtendedFullViewingKey ::from ) . collect ( ) ;
2019-02-07 04:56:04 -08:00
match init_accounts_table ( & db_data , & extfvks ) {
Ok ( ( ) ) = > {
// Return the ExtendedSpendingKeys for the created accounts
2019-02-11 18:56:17 -08:00
Ok ( utils ::rust_vec_to_java (
& env ,
extsks ,
" java/lang/String " ,
| env , extsk | {
env . new_string ( encode_extended_spending_key (
2019-04-10 10:39:06 -07:00
HRP_SAPLING_EXTENDED_SPENDING_KEY ,
2019-02-11 18:56:17 -08:00
& extsk ,
) )
} ,
| env | env . new_string ( " " ) ,
) )
2019-01-28 05:05:12 -08:00
}
2019-02-11 18:56:17 -08:00
Err ( e ) = > Err ( format_err! ( " Error while initializing accounts: {} " , e ) ) ,
2019-01-28 05:05:12 -08:00
}
2019-02-11 18:56:17 -08:00
} ) ;
unwrap_exc_or ( & env , res , ptr ::null_mut ( ) )
2019-02-07 04:56:04 -08:00
}
2019-01-29 17:41:50 -08:00
2019-11-17 20:45:05 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_deriveExtendedSpendingKeys (
2019-11-17 20:45:05 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
seed : jbyteArray ,
accounts : jint ,
) -> jobjectArray {
let res = panic ::catch_unwind ( | | {
let seed = env . convert_byte_array ( seed ) . unwrap ( ) ;
let accounts = if accounts > 0 {
accounts as u32
} else {
return Err ( format_err! ( " accounts argument must be greater than zero " ) ) ;
} ;
let extsks : Vec < _ > = ( 0 .. accounts )
2019-12-18 20:30:19 -08:00
. map ( | account | spending_key ( & seed , COIN_TYPE , account ) )
2019-11-17 20:45:05 -08:00
. collect ( ) ;
Ok ( utils ::rust_vec_to_java (
& env ,
extsks ,
" java/lang/String " ,
| env , extsk | {
env . new_string ( encode_extended_spending_key (
HRP_SAPLING_EXTENDED_SPENDING_KEY ,
& extsk ,
) )
} ,
| env | env . new_string ( " " ) ,
) )
} ) ;
unwrap_exc_or ( & env , res , ptr ::null_mut ( ) )
}
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_deriveExtendedFullViewingKeys (
2019-11-17 20:45:05 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
seed : jbyteArray ,
accounts : jint ,
) -> jobjectArray {
let res = panic ::catch_unwind ( | | {
let seed = env . convert_byte_array ( seed ) . unwrap ( ) ;
let accounts = if accounts > 0 {
accounts as u32
} else {
return Err ( format_err! ( " accounts argument must be greater than zero " ) ) ;
} ;
let extfvks : Vec < _ > = ( 0 .. accounts )
2019-12-18 20:30:19 -08:00
. map ( | account | ExtendedFullViewingKey ::from ( & spending_key ( & seed , COIN_TYPE , account ) ) )
2019-11-17 20:45:05 -08:00
. collect ( ) ;
Ok ( utils ::rust_vec_to_java (
& env ,
extfvks ,
" java/lang/String " ,
| env , extfvk | {
env . new_string ( encode_extended_full_viewing_key (
HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY ,
& extfvk ,
) )
} ,
| env | env . new_string ( " " ) ,
) )
} ) ;
unwrap_exc_or ( & env , res , ptr ::null_mut ( ) )
}
2020-02-11 16:57:57 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_deriveAddressFromSeed (
2020-02-11 16:57:57 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
seed : jbyteArray ,
account_index : jint ,
) -> jstring {
let res = panic ::catch_unwind ( | | {
let seed = env . convert_byte_array ( seed ) . unwrap ( ) ;
let account_index = if account_index > = 0 {
account_index as u32
} else {
return Err ( format_err! ( " accountIndex argument must be positive " ) ) ;
} ;
2020-02-12 05:39:30 -08:00
let address = spending_key ( & seed , COIN_TYPE , account_index )
. default_address ( )
. unwrap ( )
. 1 ;
let address_str = encode_payment_address ( HRP_SAPLING_PAYMENT_ADDRESS , & address ) ;
let output = env
. new_string ( address_str )
. expect ( " Couldn't create Java string! " ) ;
2020-02-11 16:57:57 -08:00
Ok ( output . into_inner ( ) )
} ) ;
unwrap_exc_or ( & env , res , ptr ::null_mut ( ) )
}
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_deriveAddressFromViewingKey (
2020-02-11 16:57:57 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
extfvk_string : JString < '_ > ,
) -> jstring {
let res = panic ::catch_unwind ( | | {
let extfvk_string = utils ::java_string_to_rust ( & env , extfvk_string ) ;
let extfvk = match decode_extended_full_viewing_key (
2020-07-27 11:39:43 -07:00
HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY ,
2020-02-11 16:57:57 -08:00
& extfvk_string ,
) {
Ok ( Some ( extfvk ) ) = > extfvk ,
Ok ( None ) = > {
2020-07-27 11:39:43 -07:00
return Err ( format_err! ( " Failed to parse viewing key string in order to derive the address. Deriving a viewing key from the string returned no results. Encoding was valid but type was incorrect. " ) ) ;
2020-02-11 16:57:57 -08:00
}
Err ( e ) = > {
return Err ( format_err! (
" Error while deriving viewing key from string input: {} " ,
e
) ) ;
}
} ;
2020-02-12 05:39:30 -08:00
let address = extfvk . default_address ( ) . unwrap ( ) . 1 ;
let address_str = encode_payment_address ( HRP_SAPLING_PAYMENT_ADDRESS , & address ) ;
let output = env
. new_string ( address_str )
. expect ( " Couldn't create Java string! " ) ;
2020-02-11 16:57:57 -08:00
Ok ( output . into_inner ( ) )
} ) ;
unwrap_exc_or ( & env , res , ptr ::null_mut ( ) )
}
2019-11-17 20:45:05 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_deriveExtendedFullViewingKey (
2019-11-17 20:45:05 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
extsk_string : JString < '_ > ,
) -> jobjectArray {
let res = panic ::catch_unwind ( | | {
let extsk_string = utils ::java_string_to_rust ( & env , extsk_string ) ;
let extfvk = match decode_extended_spending_key (
HRP_SAPLING_EXTENDED_SPENDING_KEY ,
& extsk_string ,
) {
Ok ( Some ( extsk ) ) = > ExtendedFullViewingKey ::from ( & extsk ) ,
Ok ( None ) = > {
return Err ( format_err! ( " Deriving viewing key from spending key returned no results. Encoding was valid but type was incorrect. " ) ) ;
}
Err ( e ) = > {
return Err ( format_err! (
" Error while deriving viewing key from spending key: {} " ,
e
) ) ;
}
} ;
let output = env
. new_string ( encode_extended_full_viewing_key (
HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY ,
& extfvk ,
) )
. expect ( " Couldn't create Java string! " ) ;
Ok ( output . into_inner ( ) )
} ) ;
unwrap_exc_or ( & env , res , ptr ::null_mut ( ) )
}
2019-02-07 04:56:04 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_initBlocksTable (
2019-02-11 07:11:09 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
2019-02-07 04:56:04 -08:00
height : jint ,
2019-05-02 15:40:58 -07:00
hash_string : JString < '_ > ,
2019-02-07 04:56:04 -08:00
time : jlong ,
2019-02-22 06:52:03 -08:00
sapling_tree_string : JString < '_ > ,
2019-02-07 04:56:04 -08:00
) -> jboolean {
2019-02-11 18:56:17 -08:00
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
2019-05-02 15:40:58 -07:00
let hash = {
let mut hash = hex ::decode ( utils ::java_string_to_rust ( & env , hash_string ) ) . unwrap ( ) ;
hash . reverse ( ) ;
BlockHash ::from_slice ( & hash )
} ;
2019-02-11 18:56:17 -08:00
let time = if time > = 0 & & time < = jlong ::from ( u32 ::max_value ( ) ) {
time as u32
} else {
return Err ( format_err! ( " time argument must fit in a u32 " ) ) ;
} ;
2019-02-22 06:52:03 -08:00
let sapling_tree =
hex ::decode ( utils ::java_string_to_rust ( & env , sapling_tree_string ) ) . unwrap ( ) ;
2019-02-11 18:56:17 -08:00
2019-11-17 20:45:05 -08:00
debug! ( " initializing blocks table with height {} " , height ) ;
2019-05-02 15:40:58 -07:00
match init_blocks_table ( & db_data , height , hash , time , & sapling_tree ) {
2019-02-11 18:56:17 -08:00
Ok ( ( ) ) = > Ok ( JNI_TRUE ) ,
Err ( e ) = > Err ( format_err! ( " Error while initializing blocks table: {} " , e ) ) ,
2019-01-14 16:31:26 -08:00
}
2019-02-11 18:56:17 -08:00
} ) ;
unwrap_exc_or ( & env , res , JNI_FALSE )
2019-02-07 04:56:04 -08:00
}
2019-01-14 16:31:26 -08:00
2019-02-07 04:56:04 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_getAddress (
2019-02-11 07:11:09 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
2019-02-07 04:56:04 -08:00
account : jint ,
) -> jstring {
2019-02-11 18:56:17 -08:00
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
let account = if account > = 0 {
account as u32
} else {
return Err ( format_err! ( " account argument must be positive " ) ) ;
} ;
match get_address ( & db_data , account ) {
Ok ( addr ) = > {
let output = env . new_string ( addr ) . expect ( " Couldn't create Java string! " ) ;
Ok ( output . into_inner ( ) )
2019-01-29 18:20:53 -08:00
}
2019-02-11 18:56:17 -08:00
Err ( e ) = > Err ( format_err! ( " Error while fetching address: {} " , e ) ) ,
2019-02-07 04:56:04 -08:00
}
2019-02-11 18:56:17 -08:00
} ) ;
unwrap_exc_or ( & env , res , ptr ::null_mut ( ) )
2019-02-07 04:56:04 -08:00
}
2018-11-22 05:54:25 -08:00
2019-06-04 07:15:19 -07:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_isValidShieldedAddress (
2019-06-04 07:15:19 -07:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
addr : JString < '_ > ,
) -> jboolean {
let res = panic ::catch_unwind ( | | {
let addr = utils ::java_string_to_rust ( & env , addr ) ;
match RecipientAddress ::from_str ( & addr ) {
2019-07-10 11:55:38 -07:00
Some ( addr ) = > match addr {
2019-06-04 07:15:19 -07:00
RecipientAddress ::Shielded ( _ ) = > Ok ( JNI_TRUE ) ,
RecipientAddress ::Transparent ( _ ) = > Ok ( JNI_FALSE ) ,
2019-08-29 10:04:53 -07:00
} ,
None = > Err ( format_err! ( " Address is for the wrong network " ) ) ,
2019-06-04 07:15:19 -07:00
}
} ) ;
unwrap_exc_or ( & env , res , JNI_FALSE )
}
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_isValidTransparentAddress (
2019-06-04 07:15:19 -07:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
addr : JString < '_ > ,
) -> jboolean {
let res = panic ::catch_unwind ( | | {
let addr = utils ::java_string_to_rust ( & env , addr ) ;
match RecipientAddress ::from_str ( & addr ) {
2019-07-10 11:55:38 -07:00
Some ( addr ) = > match addr {
2019-06-04 07:15:19 -07:00
RecipientAddress ::Shielded ( _ ) = > Ok ( JNI_FALSE ) ,
RecipientAddress ::Transparent ( _ ) = > Ok ( JNI_TRUE ) ,
2019-08-29 10:04:53 -07:00
} ,
None = > Err ( format_err! ( " Address is for the wrong network " ) ) ,
2019-06-04 07:15:19 -07:00
}
} ) ;
unwrap_exc_or ( & env , res , JNI_FALSE )
}
2019-02-07 04:56:04 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_getBalance (
2019-02-11 07:11:09 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
2019-02-07 04:56:04 -08:00
account : jint ,
) -> jlong {
2019-02-11 18:56:17 -08:00
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
let account = if account > = 0 {
account as u32
} else {
return Err ( format_err! ( " account argument must be positive " ) ) ;
} ;
match get_balance ( & db_data , account ) {
2019-08-29 10:04:53 -07:00
Ok ( balance ) = > Ok ( balance . into ( ) ) ,
2019-02-11 18:56:17 -08:00
Err ( e ) = > Err ( format_err! ( " Error while fetching balance: {} " , e ) ) ,
2018-12-04 08:46:24 -08:00
}
2019-02-11 18:56:17 -08:00
} ) ;
unwrap_exc_or ( & env , res , - 1 )
2019-02-07 04:56:04 -08:00
}
2018-12-04 08:46:24 -08:00
2019-02-18 17:45:38 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_getVerifiedBalance (
2019-02-18 17:45:38 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
account : jint ,
) -> jlong {
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
let account = if account > = 0 {
account as u32
} else {
return Err ( format_err! ( " account argument must be positive " ) ) ;
} ;
match get_verified_balance ( & db_data , account ) {
2019-08-29 10:04:53 -07:00
Ok ( balance ) = > Ok ( balance . into ( ) ) ,
2019-02-18 17:45:38 -08:00
Err ( e ) = > Err ( format_err! ( " Error while fetching verified balance: {} " , e ) ) ,
}
} ) ;
unwrap_exc_or ( & env , res , - 1 )
}
2019-02-08 07:23:21 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_getReceivedMemoAsUtf8 (
2019-02-11 07:11:09 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
2019-02-08 07:23:21 -08:00
id_note : jlong ,
) -> jstring {
2019-02-11 18:56:17 -08:00
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
2019-03-08 19:47:49 -08:00
let memo = match get_received_memo_as_utf8 ( db_data , id_note ) {
2019-02-11 18:56:17 -08:00
Ok ( memo ) = > memo . unwrap_or_default ( ) ,
Err ( e ) = > return Err ( format_err! ( " Error while fetching memo: {} " , e ) ) ,
} ;
let output = env . new_string ( memo ) . expect ( " Couldn't create Java string! " ) ;
Ok ( output . into_inner ( ) )
} ) ;
unwrap_exc_or ( & env , res , ptr ::null_mut ( ) )
2019-02-08 07:23:21 -08:00
}
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_getSentMemoAsUtf8 (
2019-02-11 07:11:09 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
2019-02-08 07:23:21 -08:00
id_note : jlong ,
) -> jstring {
2019-02-11 18:56:17 -08:00
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
2019-03-08 19:47:49 -08:00
let memo = match get_sent_memo_as_utf8 ( db_data , id_note ) {
2019-02-11 18:56:17 -08:00
Ok ( memo ) = > memo . unwrap_or_default ( ) ,
Err ( e ) = > return Err ( format_err! ( " Error while fetching memo: {} " , e ) ) ,
} ;
let output = env . new_string ( memo ) . expect ( " Couldn't create Java string! " ) ;
Ok ( output . into_inner ( ) )
} ) ;
unwrap_exc_or ( & env , res , ptr ::null_mut ( ) )
2019-02-08 07:23:21 -08:00
}
2019-05-02 15:40:58 -07:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_validateCombinedChain (
2019-05-02 15:40:58 -07:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_cache : JString < '_ > ,
db_data : JString < '_ > ,
) -> jint {
let res = panic ::catch_unwind ( | | {
let db_cache = utils ::java_string_to_rust ( & env , db_cache ) ;
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
if let Err ( e ) = validate_combined_chain ( & db_cache , & db_data ) {
match e . kind ( ) {
ErrorKind ::InvalidChain ( upper_bound , _ ) = > Ok ( * upper_bound ) ,
_ = > Err ( format_err! ( " Error while validating chain: {} " , e ) ) ,
}
} else {
// All blocks are valid, so "highest invalid block height" is below genesis.
Ok ( - 1 )
}
} ) ;
unwrap_exc_or ( & env , res , 0 )
}
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_rewindToHeight (
2019-05-02 15:40:58 -07:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
height : jint ,
) -> jboolean {
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
match rewind_to_height ( & db_data , height ) {
Ok ( ( ) ) = > Ok ( JNI_TRUE ) ,
Err ( e ) = > Err ( format_err! (
" Error while rewinding data DB to height {}: {} " ,
height ,
e
) ) ,
}
} ) ;
unwrap_exc_or ( & env , res , JNI_FALSE )
}
2019-02-07 04:56:04 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_scanBlocks (
2019-02-11 07:11:09 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_cache : JString < '_ > ,
db_data : JString < '_ > ,
2019-02-07 04:56:04 -08:00
) -> jboolean {
2019-02-11 18:56:17 -08:00
let res = panic ::catch_unwind ( | | {
let db_cache = utils ::java_string_to_rust ( & env , db_cache ) ;
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
2020-02-11 16:57:57 -08:00
match scan_cached_blocks ( & db_cache , & db_data , None ) {
2019-02-11 18:56:17 -08:00
Ok ( ( ) ) = > Ok ( JNI_TRUE ) ,
Err ( e ) = > Err ( format_err! ( " Error while scanning blocks: {} " , e ) ) ,
2018-11-22 05:54:25 -08:00
}
2019-02-11 18:56:17 -08:00
} ) ;
unwrap_exc_or ( & env , res , JNI_FALSE )
2019-02-07 04:56:04 -08:00
}
2018-12-04 08:36:47 -08:00
2020-01-14 09:56:03 -08:00
// ADDED BY ANDROID
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_scanBlockBatch (
2020-01-14 09:56:03 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_cache : JString < '_ > ,
db_data : JString < '_ > ,
2020-02-12 05:39:30 -08:00
limit : jint ,
2020-01-14 09:56:03 -08:00
) -> jboolean {
let res = panic ::catch_unwind ( | | {
let db_cache = utils ::java_string_to_rust ( & env , db_cache ) ;
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
2020-02-11 16:57:57 -08:00
match scan_cached_blocks ( & db_cache , & db_data , Some ( limit ) ) {
2020-01-14 09:56:03 -08:00
Ok ( ( ) ) = > Ok ( JNI_TRUE ) ,
Err ( e ) = > Err ( format_err! ( " Error while scanning blocks: {} " , e ) ) ,
}
} ) ;
unwrap_exc_or ( & env , res , JNI_FALSE )
}
2020-03-12 21:41:17 -07:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_decryptAndStoreTransaction (
2020-03-12 21:41:17 -07:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
tx : jbyteArray ,
) -> jboolean {
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
let tx_bytes = env . convert_byte_array ( tx ) . unwrap ( ) ;
let tx = Transaction ::read ( & tx_bytes [ .. ] ) ? ;
match decrypt_and_store_transaction ( & db_data , & tx ) {
Ok ( ( ) ) = > Ok ( JNI_TRUE ) ,
Err ( e ) = > Err ( format_err! ( " Error while decrypting transaction: {} " , e ) ) ,
}
} ) ;
unwrap_exc_or ( & env , res , JNI_FALSE )
}
2019-02-07 04:56:04 -08:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_createToAddress (
2019-02-11 07:11:09 -08:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
db_data : JString < '_ > ,
2020-06-09 19:14:22 -07:00
consensus_branch_id : jlong ,
2019-02-07 04:56:04 -08:00
account : jint ,
2019-02-11 07:11:09 -08:00
extsk : JString < '_ > ,
to : JString < '_ > ,
2019-02-07 04:56:04 -08:00
value : jlong ,
2019-11-12 08:58:15 -08:00
memo : jbyteArray ,
2019-02-11 07:11:09 -08:00
spend_params : JString < '_ > ,
output_params : JString < '_ > ,
2019-02-07 04:56:04 -08:00
) -> jlong {
2019-02-11 18:56:17 -08:00
let res = panic ::catch_unwind ( | | {
let db_data = utils ::java_string_to_rust ( & env , db_data ) ;
let account = if account > = 0 {
account as u32
} else {
return Err ( format_err! ( " account argument must be positive " ) ) ;
} ;
let extsk = utils ::java_string_to_rust ( & env , extsk ) ;
let to = utils ::java_string_to_rust ( & env , to ) ;
2019-11-17 20:45:05 -08:00
let value =
Amount ::from_i64 ( value ) . map_err ( | ( ) | format_err! ( " Invalid amount, out of range " ) ) ? ;
2019-08-29 10:57:05 -07:00
if value . is_negative ( ) {
2019-08-30 10:05:02 -07:00
return Err ( format_err! ( " Amount is negative " ) ) ;
2019-08-29 10:57:05 -07:00
}
2019-11-12 08:58:15 -08:00
let memo_bytes = env . convert_byte_array ( memo ) . unwrap ( ) ;
2019-02-11 18:56:17 -08:00
let spend_params = utils ::java_string_to_rust ( & env , spend_params ) ;
let output_params = utils ::java_string_to_rust ( & env , output_params ) ;
2019-04-10 10:39:06 -07:00
let extsk = match decode_extended_spending_key ( HRP_SAPLING_EXTENDED_SPENDING_KEY , & extsk ) {
Ok ( Some ( extsk ) ) = > extsk ,
Ok ( None ) = > {
return Err ( format_err! ( " ExtendedSpendingKey is for the wrong network " ) ) ;
}
Err ( e ) = > {
return Err ( format_err! ( " Invalid ExtendedSpendingKey: {} " , e ) ) ;
}
} ;
2019-05-24 08:06:19 -07:00
let to = match RecipientAddress ::from_str ( & to ) {
2019-07-10 11:55:38 -07:00
Some ( to ) = > to ,
None = > {
2019-05-24 08:06:19 -07:00
return Err ( format_err! ( " Address is for the wrong network " ) ) ;
2019-03-08 19:47:49 -08:00
}
2019-02-11 18:56:17 -08:00
} ;
2019-11-12 08:58:15 -08:00
let memo = Memo ::from_bytes ( & memo_bytes ) ;
2019-02-11 18:56:17 -08:00
2019-04-10 10:39:06 -07:00
let prover = LocalTxProver ::new ( Path ::new ( & spend_params ) , Path ::new ( & output_params ) ) ;
2019-02-11 18:56:17 -08:00
2020-06-09 19:14:22 -07:00
let branch_id = match BranchId ::try_from ( consensus_branch_id as u32 ) {
Ok ( branch ) = > branch ,
Err ( e ) = > {
return Err ( format_err! ( " Invalid consensus branch id: {} " , e ) ) ;
}
} ;
// let branch = if
2019-08-29 10:04:53 -07:00
create_to_address (
2019-02-11 18:56:17 -08:00
& db_data ,
2020-06-09 19:14:22 -07:00
branch_id ,
2019-02-11 18:56:17 -08:00
prover ,
( account , & extsk ) ,
& to ,
value ,
memo ,
)
2019-12-13 07:58:20 -08:00
. map_err ( | e | format_err! ( " Error while creating transaction: {} " , e ) )
2019-02-11 18:56:17 -08:00
} ) ;
unwrap_exc_or ( & env , res , - 1 )
2018-11-20 09:59:08 -08:00
}
2020-06-09 19:14:22 -07:00
#[ no_mangle ]
2020-06-10 00:08:19 -07:00
pub unsafe extern " C " fn Java_cash_z_ecc_android_sdk_jni_RustBackend_branchIdForHeight (
2020-06-09 19:14:22 -07:00
env : JNIEnv < '_ > ,
_ : JClass < '_ > ,
height : jint ,
) -> jint {
let res = panic ::catch_unwind ( | | {
let branch : BranchId = BranchId ::for_height ::< Network > ( height as u32 ) ;
let branch_id :u32 = u32 ::from ( branch ) ;
debug! ( " For height {} found consensus branch {:?} " , height , branch ) ;
Ok ( branch_id as i32 )
} ) ;
unwrap_exc_or ( & env , res , - 1 )
2020-06-09 20:28:21 -07:00
}