Skip to content

Commit

Permalink
feat!: tell an FFI client that a recovery is in progress on `wallet_c…
Browse files Browse the repository at this point in the history
…reate` (#3249)

Description
---
### Note: This is a breaking change to LibWallet FFI

Currently if a wallet recovery was in progress and the wallet was shutdown the next time that wallet is start by an FFI client using the ‘wallet_create’ method there is no way for the FFI client to know that the recovery should be continued.

The wallet is able to resume the recovery from where it left off and it should so as not to lose funds but the FFI client must restart the recovery process with the same seed words. The FFI client has to do the restarting so that it can provide the callback through which the process is monitored.

Furthermore, the wallet does not respond to P2P transaction negotiation message if a recovery process is in progress so it is important that an FFI client completes any outstanding recoveries ASAP.

How Has This Been Tested?
---
untested in the backend.
  • Loading branch information
philipr-za committed Aug 27, 2021
1 parent 6970230 commit 1368d59
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 2 deletions.
34 changes: 32 additions & 2 deletions base_layer/wallet_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ use tari_wallet::{
},
types::ValidationRetryStrategy,
util::emoji::{emoji_set, EmojiId, EmojiIdError},
utxo_scanner_service::utxo_scanning::UtxoScannerService,
utxo_scanner_service::utxo_scanning::{UtxoScannerService, RECOVERY_KEY},
Wallet,
WalletConfig,
WalletSqlite,
Expand Down Expand Up @@ -2792,6 +2792,8 @@ unsafe fn init_logging(log_path: *const c_char, num_rolling_log_files: c_uint, s
/// `callback_saf_message_received` - The callback function pointer that will be called when the Dht has determined that
/// is has connected to enough of its neighbours to be confident that it has received any SAF messages that were waiting
/// for it.
/// `recovery_in_progress` - Pointer to an bool which will be modified to indicate if there is an outstanding recovery
/// that should be completed or not to an error code should one occur, may not be null. Functions as an out parameter.
/// `error_out` - Pointer to an int which will be modified
/// to an error code should one occur, may not be null. Functions as an out parameter.
/// ## Returns
Expand Down Expand Up @@ -2823,6 +2825,7 @@ pub unsafe extern "C" fn wallet_create(
callback_invalid_txo_validation_complete: unsafe extern "C" fn(u64, u8),
callback_transaction_validation_complete: unsafe extern "C" fn(u64, u8),
callback_saf_messages_received: unsafe extern "C" fn(),
recovery_in_progress: *mut bool,
error_out: *mut c_int,
) -> *mut TariWallet {
use tari_key_manager::mnemonic::Mnemonic;
Expand Down Expand Up @@ -2922,6 +2925,13 @@ pub unsafe extern "C" fn wallet_create(
None,
);

let mut recovery_lookup = match runtime.block_on(wallet_database.get_client_key_value(RECOVERY_KEY.to_owned())) {
Err(_) => false,
Ok(None) => false,
Ok(Some(_)) => true,
};
ptr::swap(recovery_in_progress, &mut recovery_lookup as *mut bool);

w = runtime.block_on(Wallet::start(
wallet_config,
wallet_database,
Expand Down Expand Up @@ -5737,6 +5747,8 @@ mod test {
unsafe {
let mut error = 0;
let error_ptr = &mut error as *mut c_int;
let mut recovery_in_progress = true;
let recovery_in_progress_ptr = &mut recovery_in_progress as *mut bool;

let secret_key_alice = private_key_generate();
let public_key_alice = public_key_from_private_key(secret_key_alice, error_ptr);
Expand Down Expand Up @@ -5800,9 +5812,10 @@ mod test {
invalid_txo_validation_complete_callback,
transaction_validation_complete_callback,
saf_messages_received_callback,
recovery_in_progress_ptr,
error_ptr,
);

assert!(!(*recovery_in_progress_ptr), "no recovery in progress");
assert_eq!(*error_ptr, 0, "No error expected");
wallet_destroy(alice_wallet);

Expand Down Expand Up @@ -5839,8 +5852,10 @@ mod test {
invalid_txo_validation_complete_callback,
transaction_validation_complete_callback,
saf_messages_received_callback,
recovery_in_progress_ptr,
error_ptr,
);
assert!(!(*recovery_in_progress_ptr), "no recovery in progress");

assert_eq!(*error_ptr, 0, "No error expected");
wallet_destroy(alice_wallet2);
Expand Down Expand Up @@ -5894,6 +5909,8 @@ mod test {
unsafe {
let mut error = 0;
let error_ptr = &mut error as *mut c_int;
let mut recovery_in_progress = true;
let recovery_in_progress_ptr = &mut recovery_in_progress as *mut bool;

let secret_key_alice = private_key_generate();
let public_key_alice = public_key_from_private_key(secret_key_alice, error_ptr);
Expand Down Expand Up @@ -5941,6 +5958,7 @@ mod test {
invalid_txo_validation_complete_callback,
transaction_validation_complete_callback,
saf_messages_received_callback,
recovery_in_progress_ptr,
error_ptr,
);

Expand Down Expand Up @@ -5988,6 +6006,7 @@ mod test {
invalid_txo_validation_complete_callback,
transaction_validation_complete_callback,
saf_messages_received_callback,
recovery_in_progress_ptr,
error_ptr,
);

Expand Down Expand Up @@ -6018,6 +6037,7 @@ mod test {
invalid_txo_validation_complete_callback,
transaction_validation_complete_callback,
saf_messages_received_callback,
recovery_in_progress_ptr,
error_ptr,
);
assert_eq!(error, 428);
Expand All @@ -6043,6 +6063,7 @@ mod test {
invalid_txo_validation_complete_callback,
transaction_validation_complete_callback,
saf_messages_received_callback,
recovery_in_progress_ptr,
error_ptr,
);

Expand Down Expand Up @@ -6089,8 +6110,10 @@ mod test {
invalid_txo_validation_complete_callback,
transaction_validation_complete_callback,
saf_messages_received_callback,
recovery_in_progress_ptr,
error_ptr,
);
assert!(!(*recovery_in_progress_ptr), "no recovery in progress");

assert_eq!(error, 0);
string_destroy(alice_network_str as *mut c_char);
Expand All @@ -6114,6 +6137,8 @@ mod test {
unsafe {
let mut error = 0;
let error_ptr = &mut error as *mut c_int;
let mut recovery_in_progress = true;
let recovery_in_progress_ptr = &mut recovery_in_progress as *mut bool;

let secret_key_alice = private_key_generate();
let db_name_alice = CString::new(random::string(8).as_str()).unwrap();
Expand Down Expand Up @@ -6161,6 +6186,7 @@ mod test {
invalid_txo_validation_complete_callback,
transaction_validation_complete_callback,
saf_messages_received_callback,
recovery_in_progress_ptr,
error_ptr,
);

Expand Down Expand Up @@ -6229,6 +6255,8 @@ mod test {
unsafe {
let mut error = 0;
let error_ptr = &mut error as *mut c_int;
let mut recovery_in_progress = true;
let recovery_in_progress_ptr = &mut recovery_in_progress as *mut bool;

let mnemonic = vec![
"clever", "jaguar", "bus", "engage", "oil", "august", "media", "high", "trick", "remove", "tiny",
Expand Down Expand Up @@ -6309,6 +6337,7 @@ mod test {
invalid_txo_validation_complete_callback,
transaction_validation_complete_callback,
saf_messages_received_callback,
recovery_in_progress_ptr,
error_ptr,
);

Expand Down Expand Up @@ -6363,6 +6392,7 @@ mod test {
invalid_txo_validation_complete_callback,
transaction_validation_complete_callback,
saf_messages_received_callback,
recovery_in_progress_ptr,
error_ptr,
);
assert_eq!(error, 0);
Expand Down
3 changes: 3 additions & 0 deletions base_layer/wallet_ffi/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,8 @@ void comms_config_destroy(struct TariCommsConfig *wc);
/// `callback_saf_message_received` - The callback function pointer that will be called when the Dht has determined that
/// is has connected to enough of its neighbours to be confident that it has received any SAF messages that were waiting
/// for it.
/// `recovery_in_progress` - Pointer to an bool which will be modified to indicate if there is an outstanding recovery
/// that should be completed or not to an error code should one occur, may not be null. Functions as an out parameter.
/// `error_out` - Pointer to an int which will be modified
/// to an error code should one occur, may not be null. Functions as an out parameter.
/// ## Returns
Expand Down Expand Up @@ -477,6 +479,7 @@ struct TariWallet *wallet_create(struct TariCommsConfig *config,
void (*callback_invalid_txo_validation_complete)(unsigned long long, unsigned char),
void (*callback_transaction_validation_complete)(unsigned long long, unsigned char),
void (*callback_saf_message_received)(),
bool *recovery_in_progress,
int *error_out);

// Signs a message
Expand Down
3 changes: 3 additions & 0 deletions integration_tests/helpers/ffi/walletFFI.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class WalletFFI {

static #fn;
static error = ref.alloc(ref.types.int);
static recovery_in_progress = ref.alloc(ref.types.bool);
static NULL = ref.NULL;
static #loaded = false;
static #ps = null;
Expand Down Expand Up @@ -432,6 +433,7 @@ class WalletFFI {
"pointer",
"pointer",
"pointer",
"bool*",
"int*",
],
],
Expand Down Expand Up @@ -1519,6 +1521,7 @@ class WalletFFI {
callback_invalid_txo_validation_complete,
callback_transaction_validation_complete,
callback_saf_message_received,
this.recovery_in_progress,
this.error,
this.checkAsyncRes(resolve, reject, "walletCreate")
)
Expand Down

0 comments on commit 1368d59

Please sign in to comment.