diff --git a/base_layer/core/src/blocks/genesis_block.rs b/base_layer/core/src/blocks/genesis_block.rs index 7d1c98b06e..6c069800e9 100644 --- a/base_layer/core/src/blocks/genesis_block.rs +++ b/base_layer/core/src/blocks/genesis_block.rs @@ -93,7 +93,6 @@ fn print_mr_values(block: &mut Block, print: bool) { let mut kernel_mmr = KernelMmr::new(Vec::new()); for k in block.body.kernels() { - println!("k: {}", k); kernel_mmr.push(k.hash().to_vec()).unwrap(); } diff --git a/base_layer/core/src/blocks/pre_mine/mod.rs b/base_layer/core/src/blocks/pre_mine/mod.rs index 54f5264f2c..7009dc70b8 100644 --- a/base_layer/core/src/blocks/pre_mine/mod.rs +++ b/base_layer/core/src/blocks/pre_mine/mod.rs @@ -981,7 +981,6 @@ mod test { Vec, ) { let threshold_addresses_for_index = vec![ - // This wil be public keys TariAddress::from_base58( "f4bYsv3sEMroDGKMMjhgm7cp1jDShdRWQzmV8wZiD6sJPpAEuezkiHtVhn7akK3YqswH5t3sUASW7rbvPSqMBDSCSp", ) @@ -1404,6 +1403,7 @@ mod test { ); } + #[ignore] #[tokio::test] async fn test_create_genesis_block_info() { for network in [ diff --git a/base_layer/wallet_ffi/src/callback_handler.rs b/base_layer/wallet_ffi/src/callback_handler.rs index b25d12b05c..9f6dc4f21c 100644 --- a/base_layer/wallet_ffi/src/callback_handler.rs +++ b/base_layer/wallet_ffi/src/callback_handler.rs @@ -35,7 +35,7 @@ //! request_key is used to identify which request this callback references and a result of true means it was successful //! and false that the process timed out and new one will be started -use std::{ops::Deref, sync::Arc}; +use std::{ffi::c_void, ops::Deref, sync::Arc}; use log::*; use minotari_wallet::{ @@ -65,29 +65,35 @@ use tokio::sync::{broadcast, watch}; use crate::ffi_basenode_state::TariBaseNodeState; +#[derive(Clone, Copy)] +pub struct Context(pub *mut c_void); + +unsafe impl Send for Context {} + const LOG_TARGET: &str = "wallet::transaction_service::callback_handler"; pub struct CallbackHandler where TBackend: TransactionBackend + 'static { - callback_received_transaction: unsafe extern "C" fn(*mut InboundTransaction), - callback_received_transaction_reply: unsafe extern "C" fn(*mut CompletedTransaction), - callback_received_finalized_transaction: unsafe extern "C" fn(*mut CompletedTransaction), - callback_transaction_broadcast: unsafe extern "C" fn(*mut CompletedTransaction), - callback_transaction_mined: unsafe extern "C" fn(*mut CompletedTransaction), - callback_transaction_mined_unconfirmed: unsafe extern "C" fn(*mut CompletedTransaction, u64), - callback_faux_transaction_confirmed: unsafe extern "C" fn(*mut CompletedTransaction), - callback_faux_transaction_unconfirmed: unsafe extern "C" fn(*mut CompletedTransaction, u64), - callback_transaction_send_result: unsafe extern "C" fn(u64, *mut TransactionSendStatus), - callback_transaction_cancellation: unsafe extern "C" fn(*mut CompletedTransaction, u64), - callback_txo_validation_complete: unsafe extern "C" fn(u64, u64), - callback_contacts_liveness_data_updated: unsafe extern "C" fn(*mut ContactsLivenessData), - callback_balance_updated: unsafe extern "C" fn(*mut Balance), - callback_transaction_validation_complete: unsafe extern "C" fn(u64, u64), - callback_saf_messages_received: unsafe extern "C" fn(), - callback_connectivity_status: unsafe extern "C" fn(u64), - callback_wallet_scanned_height: unsafe extern "C" fn(u64), - callback_base_node_state: unsafe extern "C" fn(*mut TariBaseNodeState), + pub context: Context, + callback_received_transaction: unsafe extern "C" fn(context: *mut c_void, *mut InboundTransaction), + callback_received_transaction_reply: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction), + callback_received_finalized_transaction: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction), + callback_transaction_broadcast: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction), + callback_transaction_mined: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction), + callback_transaction_mined_unconfirmed: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction, u64), + callback_faux_transaction_confirmed: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction), + callback_faux_transaction_unconfirmed: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction, u64), + callback_transaction_send_result: unsafe extern "C" fn(context: *mut c_void, u64, *mut TransactionSendStatus), + callback_transaction_cancellation: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction, u64), + callback_txo_validation_complete: unsafe extern "C" fn(context: *mut c_void, u64, u64), + callback_contacts_liveness_data_updated: unsafe extern "C" fn(context: *mut c_void, *mut ContactsLivenessData), + callback_balance_updated: unsafe extern "C" fn(context: *mut c_void, *mut Balance), + callback_transaction_validation_complete: unsafe extern "C" fn(context: *mut c_void, u64, u64), + callback_saf_messages_received: unsafe extern "C" fn(context: *mut c_void), + callback_connectivity_status: unsafe extern "C" fn(context: *mut c_void, u64), + callback_wallet_scanned_height: unsafe extern "C" fn(context: *mut c_void, u64), + callback_base_node_state: unsafe extern "C" fn(context: *mut c_void, *mut TariBaseNodeState), db: TransactionDatabase, base_node_service_event_stream: BaseNodeEventReceiver, transaction_service_event_stream: TransactionEventReceiver, @@ -106,7 +112,9 @@ impl CallbackHandler where TBackend: TransactionBackend + 'static { #[allow(clippy::too_many_arguments)] + #[allow(clippy::too_many_lines)] pub fn new( + context: Context, db: TransactionDatabase, base_node_service_event_stream: BaseNodeEventReceiver, transaction_service_event_stream: TransactionEventReceiver, @@ -118,24 +126,32 @@ where TBackend: TransactionBackend + 'static comms_address: TariAddress, connectivity_status_watch: watch::Receiver, contacts_liveness_events: broadcast::Receiver>, - callback_received_transaction: unsafe extern "C" fn(*mut InboundTransaction), - callback_received_transaction_reply: unsafe extern "C" fn(*mut CompletedTransaction), - callback_received_finalized_transaction: unsafe extern "C" fn(*mut CompletedTransaction), - callback_transaction_broadcast: unsafe extern "C" fn(*mut CompletedTransaction), - callback_transaction_mined: unsafe extern "C" fn(*mut CompletedTransaction), - callback_transaction_mined_unconfirmed: unsafe extern "C" fn(*mut CompletedTransaction, u64), - callback_faux_transaction_confirmed: unsafe extern "C" fn(*mut CompletedTransaction), - callback_faux_transaction_unconfirmed: unsafe extern "C" fn(*mut CompletedTransaction, u64), - callback_transaction_send_result: unsafe extern "C" fn(u64, *mut TransactionSendStatus), - callback_transaction_cancellation: unsafe extern "C" fn(*mut CompletedTransaction, u64), - callback_txo_validation_complete: unsafe extern "C" fn(u64, u64), - callback_contacts_liveness_data_updated: unsafe extern "C" fn(*mut ContactsLivenessData), - callback_balance_updated: unsafe extern "C" fn(*mut Balance), - callback_transaction_validation_complete: unsafe extern "C" fn(u64, u64), - callback_saf_messages_received: unsafe extern "C" fn(), - callback_connectivity_status: unsafe extern "C" fn(u64), - callback_wallet_scanned_height: unsafe extern "C" fn(u64), - callback_base_node_state: unsafe extern "C" fn(*mut TariBaseNodeState), + callback_received_transaction: unsafe extern "C" fn(context: *mut c_void, *mut InboundTransaction), + callback_received_transaction_reply: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction), + callback_received_finalized_transaction: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction), + callback_transaction_broadcast: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction), + callback_transaction_mined: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction), + callback_transaction_mined_unconfirmed: unsafe extern "C" fn( + context: *mut c_void, + *mut CompletedTransaction, + u64, + ), + callback_faux_transaction_confirmed: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction), + callback_faux_transaction_unconfirmed: unsafe extern "C" fn( + context: *mut c_void, + *mut CompletedTransaction, + u64, + ), + callback_transaction_send_result: unsafe extern "C" fn(context: *mut c_void, u64, *mut TransactionSendStatus), + callback_transaction_cancellation: unsafe extern "C" fn(context: *mut c_void, *mut CompletedTransaction, u64), + callback_txo_validation_complete: unsafe extern "C" fn(context: *mut c_void, u64, u64), + callback_contacts_liveness_data_updated: unsafe extern "C" fn(context: *mut c_void, *mut ContactsLivenessData), + callback_balance_updated: unsafe extern "C" fn(context: *mut c_void, *mut Balance), + callback_transaction_validation_complete: unsafe extern "C" fn(context: *mut c_void, u64, u64), + callback_saf_messages_received: unsafe extern "C" fn(context: *mut c_void), + callback_connectivity_status: unsafe extern "C" fn(context: *mut c_void, u64), + callback_wallet_scanned_height: unsafe extern "C" fn(context: *mut c_void, u64), + callback_base_node_state: unsafe extern "C" fn(context: *mut c_void, *mut TariBaseNodeState), ) -> Self { info!( target: LOG_TARGET, @@ -207,6 +223,7 @@ where TBackend: TransactionBackend + 'static ); Self { + context, callback_received_transaction, callback_received_transaction_reply, callback_received_finalized_transaction, @@ -440,7 +457,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(tx)); unsafe { - (self.callback_received_transaction)(boxing); + (self.callback_received_transaction)(self.context.0, boxing); } }, Err(e) => error!( @@ -459,7 +476,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(tx)); unsafe { - (self.callback_received_transaction_reply)(boxing); + (self.callback_received_transaction_reply)(self.context.0, boxing); } }, Err(e) => error!(target: LOG_TARGET, "Error retrieving Completed Transaction: {:?}", e), @@ -475,7 +492,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(tx)); unsafe { - (self.callback_received_finalized_transaction)(boxing); + (self.callback_received_finalized_transaction)(self.context.0, boxing); } }, Err(e) => error!(target: LOG_TARGET, "Error retrieving Completed Transaction: {:?}", e), @@ -498,7 +515,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(balance)); unsafe { - (self.callback_balance_updated)(boxing); + (self.callback_balance_updated)(self.context.0, boxing); } } }, @@ -516,7 +533,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(data)); unsafe { - (self.callback_contacts_liveness_data_updated)(boxing); + (self.callback_contacts_liveness_data_updated)(self.context.0, boxing); } } @@ -527,7 +544,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(status)); unsafe { - (self.callback_transaction_send_result)(tx_id.as_u64(), boxing); + (self.callback_transaction_send_result)(self.context.0, tx_id.as_u64(), boxing); } } @@ -559,7 +576,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(tx)); unsafe { - (self.callback_transaction_cancellation)(boxing, reason); + (self.callback_transaction_cancellation)(self.context.0, boxing, reason); } }, } @@ -574,7 +591,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(tx)); unsafe { - (self.callback_transaction_broadcast)(boxing); + (self.callback_transaction_broadcast)(self.context.0, boxing); } }, Err(e) => error!(target: LOG_TARGET, "Error retrieving Completed Transaction: {:?}", e), @@ -590,7 +607,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(tx)); unsafe { - (self.callback_transaction_mined)(boxing); + (self.callback_transaction_mined)(self.context.0, boxing); } }, Err(e) => error!(target: LOG_TARGET, "Error retrieving Completed Transaction: {:?}", e), @@ -606,7 +623,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(tx)); unsafe { - (self.callback_transaction_mined_unconfirmed)(boxing, confirmations); + (self.callback_transaction_mined_unconfirmed)(self.context.0, boxing, confirmations); } }, Err(e) => error!(target: LOG_TARGET, "Error retrieving Completed Transaction: {:?}", e), @@ -622,7 +639,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(tx)); unsafe { - (self.callback_faux_transaction_confirmed)(boxing); + (self.callback_faux_transaction_confirmed)(self.context.0, boxing); } }, Err(e) => error!(target: LOG_TARGET, "Error retrieving Completed Transaction: {:?}", e), @@ -638,7 +655,7 @@ where TBackend: TransactionBackend + 'static ); let boxing = Box::into_raw(Box::new(tx)); unsafe { - (self.callback_faux_transaction_unconfirmed)(boxing, confirmations); + (self.callback_faux_transaction_unconfirmed)(self.context.0, boxing, confirmations); } }, Err(e) => error!(target: LOG_TARGET, "Error retrieving Completed Transaction: {:?}", e), @@ -651,7 +668,7 @@ where TBackend: TransactionBackend + 'static "Calling Transaction Validation Complete callback function for Request Key: {}", request_key, ); unsafe { - (self.callback_transaction_validation_complete)(request_key, success); + (self.callback_transaction_validation_complete)(self.context.0, request_key, success); } } @@ -664,14 +681,14 @@ where TBackend: TransactionBackend + 'static ); unsafe { - (self.callback_txo_validation_complete)(request_key, success); + (self.callback_txo_validation_complete)(self.context.0, request_key, success); } } fn saf_messages_received_event(&mut self) { debug!(target: LOG_TARGET, "Calling SAF Messages Received callback function"); unsafe { - (self.callback_saf_messages_received)(); + (self.callback_saf_messages_received)(self.context.0); } } @@ -681,7 +698,7 @@ where TBackend: TransactionBackend + 'static "Calling Connectivity Status changed callback function" ); unsafe { - (self.callback_connectivity_status)(status as u64); + (self.callback_connectivity_status)(self.context.0, status as u64); } } @@ -691,7 +708,7 @@ where TBackend: TransactionBackend + 'static "Calling Scanned height changed callback function" ); unsafe { - (self.callback_wallet_scanned_height)(height); + (self.callback_wallet_scanned_height)(self.context.0, height); } } @@ -727,7 +744,7 @@ where TBackend: TransactionBackend + 'static }; unsafe { - (self.callback_base_node_state)(Box::into_raw(Box::new(state))); + (self.callback_base_node_state)(self.context.0, Box::into_raw(Box::new(state))); } } } diff --git a/base_layer/wallet_ffi/src/callback_handler_tests.rs b/base_layer/wallet_ffi/src/callback_handler_tests.rs index a381137a0c..c913d985b3 100644 --- a/base_layer/wallet_ffi/src/callback_handler_tests.rs +++ b/base_layer/wallet_ffi/src/callback_handler_tests.rs @@ -4,6 +4,7 @@ #[cfg(test)] mod test { use std::{ + ffi::c_void, mem::size_of, sync::{Arc, Mutex}, thread, @@ -62,7 +63,7 @@ mod test { }; use crate::{ - callback_handler::CallbackHandler, + callback_handler::{CallbackHandler, Context}, ffi_basenode_state::TariBaseNodeState, output_manager_service_mock::MockOutputManagerService, }; @@ -131,63 +132,75 @@ mod test { static CALLBACK_STATE: Lazy> = Lazy::new(|| Mutex::new(CallbackState::new())); - unsafe extern "C" fn received_tx_callback(tx: *mut InboundTransaction) { + unsafe extern "C" fn received_tx_callback(_context: *mut c_void, tx: *mut InboundTransaction) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.received_tx_callback_called = true; drop(lock); drop(Box::from_raw(tx)) } - unsafe extern "C" fn received_tx_reply_callback(tx: *mut CompletedTransaction) { + unsafe extern "C" fn received_tx_reply_callback(_context: *mut c_void, tx: *mut CompletedTransaction) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.received_tx_reply_callback_called = true; drop(lock); drop(Box::from_raw(tx)) } - unsafe extern "C" fn received_tx_finalized_callback(tx: *mut CompletedTransaction) { + unsafe extern "C" fn received_tx_finalized_callback(_context: *mut c_void, tx: *mut CompletedTransaction) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.received_finalized_tx_callback_called = true; drop(lock); drop(Box::from_raw(tx)) } - unsafe extern "C" fn broadcast_callback(tx: *mut CompletedTransaction) { + unsafe extern "C" fn broadcast_callback(_context: *mut c_void, tx: *mut CompletedTransaction) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.broadcast_tx_callback_called = true; drop(lock); drop(Box::from_raw(tx)) } - unsafe extern "C" fn mined_callback(tx: *mut CompletedTransaction) { + unsafe extern "C" fn mined_callback(_context: *mut c_void, tx: *mut CompletedTransaction) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.mined_tx_callback_called = true; drop(lock); drop(Box::from_raw(tx)) } - unsafe extern "C" fn mined_unconfirmed_callback(tx: *mut CompletedTransaction, confirmations: u64) { + unsafe extern "C" fn mined_unconfirmed_callback( + _context: *mut c_void, + tx: *mut CompletedTransaction, + confirmations: u64, + ) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.mined_tx_unconfirmed_callback_called = confirmations; drop(lock); drop(Box::from_raw(tx)) } - unsafe extern "C" fn faux_confirmed_callback(tx: *mut CompletedTransaction) { + unsafe extern "C" fn faux_confirmed_callback(_context: *mut c_void, tx: *mut CompletedTransaction) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.faux_tx_confirmed_callback_called = true; drop(lock); drop(Box::from_raw(tx)) } - unsafe extern "C" fn faux_unconfirmed_callback(tx: *mut CompletedTransaction, confirmations: u64) { + unsafe extern "C" fn faux_unconfirmed_callback( + _context: *mut c_void, + tx: *mut CompletedTransaction, + confirmations: u64, + ) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.faux_tx_unconfirmed_callback_called = confirmations; drop(lock); drop(Box::from_raw(tx)) } - unsafe extern "C" fn transaction_send_result_callback(_tx_id: u64, status: *mut TransactionSendStatus) { + unsafe extern "C" fn transaction_send_result_callback( + _context: *mut c_void, + _tx_id: u64, + status: *mut TransactionSendStatus, + ) { let mut lock = CALLBACK_STATE.lock().unwrap(); if (*status).direct_send_result { lock.direct_send_callback_called += 1; @@ -201,13 +214,13 @@ mod test { drop(lock); } - unsafe extern "C" fn saf_messages_received_callback() { + unsafe extern "C" fn saf_messages_received_callback(_context: *mut c_void) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.saf_messages_received = true; drop(lock); } - unsafe extern "C" fn tx_cancellation_callback(tx: *mut CompletedTransaction, _reason: u64) { + unsafe extern "C" fn tx_cancellation_callback(_context: *mut c_void, tx: *mut CompletedTransaction, _reason: u64) { let mut lock = CALLBACK_STATE.lock().unwrap(); match (*tx).tx_id.as_u64() { 3 => lock.tx_cancellation_callback_called_inbound = true, @@ -219,7 +232,7 @@ mod test { drop(Box::from_raw(tx)) } - unsafe extern "C" fn txo_validation_complete_callback(_tx_id: u64, result: u64) { + unsafe extern "C" fn txo_validation_complete_callback(_context: *mut c_void, _tx_id: u64, result: u64) { let mut lock = CALLBACK_STATE.lock().unwrap(); match result { 0 => lock.callback_txo_validation_completed = true, @@ -231,13 +244,16 @@ mod test { drop(lock); } - unsafe extern "C" fn contacts_liveness_data_updated_callback(_data: *mut ContactsLivenessData) { + unsafe extern "C" fn contacts_liveness_data_updated_callback( + _context: *mut c_void, + _data: *mut ContactsLivenessData, + ) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.callback_contacts_liveness_data_updated += 1; drop(lock); } - unsafe extern "C" fn balance_updated_callback(balance: *mut Balance) { + unsafe extern "C" fn balance_updated_callback(_context: *mut c_void, balance: *mut Balance) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.callback_balance_updated += 1; drop(lock); @@ -246,25 +262,29 @@ mod test { // casting is okay in tests #[allow(clippy::cast_possible_truncation)] - unsafe extern "C" fn transaction_validation_complete_callback(request_key: u64, result: u64) { + unsafe extern "C" fn transaction_validation_complete_callback( + _context: *mut c_void, + request_key: u64, + result: u64, + ) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.callback_transaction_validation_complete += request_key as u32 + result as u32; drop(lock); } - unsafe extern "C" fn connectivity_status_callback(status: u64) { + unsafe extern "C" fn connectivity_status_callback(_context: *mut c_void, status: u64) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.connectivity_status_callback_called += status + 1; drop(lock); } - unsafe extern "C" fn wallet_scanner_height_callback(height: u64) { + unsafe extern "C" fn wallet_scanner_height_callback(_context: *mut c_void, height: u64) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.wallet_scanner_height_callback_called += height; drop(lock); } - unsafe extern "C" fn base_node_state_changed_callback(state: *mut TariBaseNodeState) { + unsafe extern "C" fn base_node_state_changed_callback(_context: *mut c_void, state: *mut TariBaseNodeState) { let mut lock = CALLBACK_STATE.lock().unwrap(); lock.base_node_state_changed_callback_invoked = true; drop(lock); @@ -482,8 +502,9 @@ mod test { PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), Network::LocalNet, ); - + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let callback_handler = CallbackHandler::new( + Context(void_ptr), db, base_node_event_receiver, transaction_event_receiver, diff --git a/base_layer/wallet_ffi/src/lib.rs b/base_layer/wallet_ffi/src/lib.rs index 47d11ee255..1da0f997ac 100644 --- a/base_layer/wallet_ffi/src/lib.rs +++ b/base_layer/wallet_ffi/src/lib.rs @@ -185,7 +185,7 @@ use tokio::runtime::Runtime; use zeroize::Zeroize; use crate::{ - callback_handler::CallbackHandler, + callback_handler::{CallbackHandler, Context}, enums::SeedWordPushResult, error::{InterfaceError, TransactionError}, tasks::recovery_event_monitoring, @@ -259,6 +259,7 @@ pub struct TariWallet { wallet: WalletSqlite, runtime: Runtime, shutdown: Shutdown, + context: Context, } #[derive(Debug)] @@ -5659,6 +5660,7 @@ unsafe fn init_logging( /// Creates a TariWallet /// /// ## Arguments +/// Context - a pointer to some context used by all the callbacks /// `config` - The TariCommsConfig pointer /// `log_path` - An optional file path to the file where the logs will be written. If no log is required pass *null* /// pointer. @@ -5760,6 +5762,7 @@ unsafe fn init_logging( #[allow(clippy::cognitive_complexity)] #[allow(clippy::too_many_lines)] pub unsafe extern "C" fn wallet_create( + context: *mut c_void, config: *mut TariCommsConfig, log_path: *const c_char, log_verbosity: c_int, @@ -5772,24 +5775,36 @@ pub unsafe extern "C" fn wallet_create( peer_seed_str: *const c_char, dns_sec: bool, - callback_received_transaction: unsafe extern "C" fn(*mut TariPendingInboundTransaction), - callback_received_transaction_reply: unsafe extern "C" fn(*mut TariCompletedTransaction), - callback_received_finalized_transaction: unsafe extern "C" fn(*mut TariCompletedTransaction), - callback_transaction_broadcast: unsafe extern "C" fn(*mut TariCompletedTransaction), - callback_transaction_mined: unsafe extern "C" fn(*mut TariCompletedTransaction), - callback_transaction_mined_unconfirmed: unsafe extern "C" fn(*mut TariCompletedTransaction, u64), - callback_faux_transaction_confirmed: unsafe extern "C" fn(*mut TariCompletedTransaction), - callback_faux_transaction_unconfirmed: unsafe extern "C" fn(*mut TariCompletedTransaction, u64), - callback_transaction_send_result: unsafe extern "C" fn(c_ulonglong, *mut TariTransactionSendStatus), - callback_transaction_cancellation: unsafe extern "C" fn(*mut TariCompletedTransaction, u64), - callback_txo_validation_complete: unsafe extern "C" fn(u64, u64), - callback_contacts_liveness_data_updated: unsafe extern "C" fn(*mut TariContactsLivenessData), - callback_balance_updated: unsafe extern "C" fn(*mut TariBalance), - callback_transaction_validation_complete: unsafe extern "C" fn(u64, u64), - callback_saf_messages_received: unsafe extern "C" fn(), - callback_connectivity_status: unsafe extern "C" fn(u64), - callback_wallet_scanned_height: unsafe extern "C" fn(u64), - callback_base_node_state: unsafe extern "C" fn(*mut TariBaseNodeState), + callback_received_transaction: unsafe extern "C" fn(context: *mut c_void, *mut TariPendingInboundTransaction), + callback_received_transaction_reply: unsafe extern "C" fn(context: *mut c_void, *mut TariCompletedTransaction), + callback_received_finalized_transaction: unsafe extern "C" fn(context: *mut c_void, *mut TariCompletedTransaction), + callback_transaction_broadcast: unsafe extern "C" fn(context: *mut c_void, *mut TariCompletedTransaction), + callback_transaction_mined: unsafe extern "C" fn(context: *mut c_void, *mut TariCompletedTransaction), + callback_transaction_mined_unconfirmed: unsafe extern "C" fn( + context: *mut c_void, + *mut TariCompletedTransaction, + u64, + ), + callback_faux_transaction_confirmed: unsafe extern "C" fn(context: *mut c_void, *mut TariCompletedTransaction), + callback_faux_transaction_unconfirmed: unsafe extern "C" fn( + context: *mut c_void, + *mut TariCompletedTransaction, + u64, + ), + callback_transaction_send_result: unsafe extern "C" fn( + context: *mut c_void, + c_ulonglong, + *mut TariTransactionSendStatus, + ), + callback_transaction_cancellation: unsafe extern "C" fn(context: *mut c_void, *mut TariCompletedTransaction, u64), + callback_txo_validation_complete: unsafe extern "C" fn(context: *mut c_void, u64, u64), + callback_contacts_liveness_data_updated: unsafe extern "C" fn(context: *mut c_void, *mut TariContactsLivenessData), + callback_balance_updated: unsafe extern "C" fn(context: *mut c_void, *mut TariBalance), + callback_transaction_validation_complete: unsafe extern "C" fn(context: *mut c_void, u64, u64), + callback_saf_messages_received: unsafe extern "C" fn(context: *mut c_void), + callback_connectivity_status: unsafe extern "C" fn(context: *mut c_void, u64), + callback_wallet_scanned_height: unsafe extern "C" fn(context: *mut c_void, u64), + callback_base_node_state: unsafe extern "C" fn(context: *mut c_void, *mut TariBaseNodeState), recovery_in_progress: *mut bool, error_out: *mut c_int, ) -> *mut TariWallet { @@ -6086,9 +6101,10 @@ pub unsafe extern "C" fn wallet_create( } let mut utxo_scanner = w.utxo_scanner_service.clone(); - + let context = Context(context); // Start Callback Handler let callback_handler = CallbackHandler::new( + context, TransactionDatabase::new(transaction_backend), w.base_node_service.get_event_stream(), w.transaction_service.get_event_stream(), @@ -6126,6 +6142,7 @@ pub unsafe extern "C" fn wallet_create( wallet: w, runtime, shutdown, + context, }; Box::into_raw(Box::new(tari_wallet)) @@ -8179,7 +8196,7 @@ pub unsafe extern "C" fn wallet_get_cancelled_transaction_by_id( ptr::null_mut() } -/// Get the TariWalletAddress from a TariWallet +/// Get the interactive TariWalletAddress from a TariWallet /// /// ## Arguments /// `wallet` - The TariWallet pointer @@ -8193,7 +8210,7 @@ pub unsafe extern "C" fn wallet_get_cancelled_transaction_by_id( /// # Safety /// The ```tari_address_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak #[no_mangle] -pub unsafe extern "C" fn wallet_get_tari_address( +pub unsafe extern "C" fn wallet_get_tari_interactive_address( wallet: *mut TariWallet, error_out: *mut c_int, ) -> *mut TariWalletAddress { @@ -8223,6 +8240,50 @@ pub unsafe extern "C" fn wallet_get_tari_address( Box::into_raw(Box::new(address)) } +/// Get the one_sided only TariWalletAddress from a TariWallet +/// +/// ## Arguments +/// `wallet` - The TariWallet pointer +/// `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 +/// `*mut TariWalletAddress` - returns the address, note that ptr::null_mut() is returned +/// if wc is null +/// +/// # Safety +/// The ```tari_address_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak +#[no_mangle] +pub unsafe extern "C" fn wallet_get_tari_one_sided_address( + wallet: *mut TariWallet, + error_out: *mut c_int, +) -> *mut TariWalletAddress { + let mut error = 0; + ptr::swap(error_out, &mut error as *mut c_int); + if wallet.is_null() { + error = LibWalletError::from(InterfaceError::NullError("wallet".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + } + let runtime = match Runtime::new() { + Ok(r) => r, + Err(e) => { + error = LibWalletError::from(InterfaceError::TokioError(e.to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + }, + }; + let address = match runtime.block_on(async { (*wallet).wallet.get_wallet_one_sided_address().await }) { + Ok(address) => address, + Err(e) => { + error = LibWalletError::from(e).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + }, + }; + Box::into_raw(Box::new(address)) +} + /// Cancel a Pending Transaction /// /// ## Arguments @@ -8793,7 +8854,7 @@ pub unsafe extern "C" fn wallet_is_recovery_in_progress(wallet: *mut TariWallet, pub unsafe extern "C" fn wallet_start_recovery( wallet: *mut TariWallet, base_node_public_key: *mut TariPublicKey, - recovery_progress_callback: unsafe extern "C" fn(u8, u64, u64), + recovery_progress_callback: unsafe extern "C" fn(context: *mut c_void, u8, u64, u64), recovered_output_message: *const c_char, error_out: *mut c_int, ) -> bool { @@ -8852,6 +8913,7 @@ pub unsafe extern "C" fn wallet_start_recovery( event_stream, recovery_join_handle, recovery_progress_callback, + (*wallet).context, )); true @@ -9396,7 +9458,7 @@ pub unsafe extern "C" fn contacts_handle_destroy(contacts_handle: *mut ContactsS /// ------------------------------------------------------------------------------------------ /// #[cfg(test)] mod test { - use std::{path::Path, str::from_utf8, sync::Mutex}; + use std::{ffi::c_void, path::Path, str::from_utf8, sync::Mutex}; use minotari_wallet::{ storage::sqlite_utilities::run_migration_and_create_sqlite_connection, @@ -9470,7 +9532,7 @@ mod test { static CALLBACK_STATE_FFI: Lazy> = Lazy::new(|| Mutex::new(CallbackState::new())); - unsafe extern "C" fn received_tx_callback(tx: *mut TariPendingInboundTransaction) { + unsafe extern "C" fn received_tx_callback(_context: *mut c_void, tx: *mut TariPendingInboundTransaction) { assert!(!tx.is_null()); assert_eq!( type_of((*tx).clone()), @@ -9482,7 +9544,7 @@ mod test { pending_inbound_transaction_destroy(tx); } - unsafe extern "C" fn received_tx_reply_callback(tx: *mut TariCompletedTransaction) { + unsafe extern "C" fn received_tx_reply_callback(_context: *mut c_void, tx: *mut TariCompletedTransaction) { assert!(!tx.is_null()); assert_eq!( type_of((*tx).clone()), @@ -9495,7 +9557,7 @@ mod test { completed_transaction_destroy(tx); } - unsafe extern "C" fn received_tx_finalized_callback(tx: *mut TariCompletedTransaction) { + unsafe extern "C" fn received_tx_finalized_callback(_context: *mut c_void, tx: *mut TariCompletedTransaction) { assert!(!tx.is_null()); assert_eq!( type_of((*tx).clone()), @@ -9508,7 +9570,7 @@ mod test { completed_transaction_destroy(tx); } - unsafe extern "C" fn broadcast_callback(tx: *mut TariCompletedTransaction) { + unsafe extern "C" fn broadcast_callback(_context: *mut c_void, tx: *mut TariCompletedTransaction) { assert!(!tx.is_null()); assert_eq!( type_of((*tx).clone()), @@ -9521,7 +9583,7 @@ mod test { completed_transaction_destroy(tx); } - unsafe extern "C" fn mined_callback(tx: *mut TariCompletedTransaction) { + unsafe extern "C" fn mined_callback(_context: *mut c_void, tx: *mut TariCompletedTransaction) { assert!(!tx.is_null()); assert_eq!( type_of((*tx).clone()), @@ -9534,7 +9596,11 @@ mod test { completed_transaction_destroy(tx); } - unsafe extern "C" fn mined_unconfirmed_callback(tx: *mut TariCompletedTransaction, _confirmations: u64) { + unsafe extern "C" fn mined_unconfirmed_callback( + _context: *mut c_void, + tx: *mut TariCompletedTransaction, + _confirmations: u64, + ) { assert!(!tx.is_null()); assert_eq!( type_of((*tx).clone()), @@ -9563,7 +9629,7 @@ mod test { completed_transaction_destroy(tx); } - unsafe extern "C" fn scanned_callback(tx: *mut TariCompletedTransaction) { + unsafe extern "C" fn scanned_callback(_context: *mut c_void, tx: *mut TariCompletedTransaction) { assert!(!tx.is_null()); assert_eq!( type_of((*tx).clone()), @@ -9576,7 +9642,11 @@ mod test { completed_transaction_destroy(tx); } - unsafe extern "C" fn scanned_unconfirmed_callback(tx: *mut TariCompletedTransaction, _confirmations: u64) { + unsafe extern "C" fn scanned_unconfirmed_callback( + _context: *mut c_void, + tx: *mut TariCompletedTransaction, + _confirmations: u64, + ) { assert!(!tx.is_null()); assert_eq!( type_of((*tx).clone()), @@ -9610,7 +9680,11 @@ mod test { } } - unsafe extern "C" fn transaction_send_result_callback(_tx_id: c_ulonglong, status: *mut TransactionSendStatus) { + unsafe extern "C" fn transaction_send_result_callback( + _context: *mut c_void, + _tx_id: c_ulonglong, + status: *mut TransactionSendStatus, + ) { assert!(!status.is_null()); assert_eq!( type_of((*status).clone()), @@ -9619,7 +9693,11 @@ mod test { transaction_send_status_destroy(status); } - unsafe extern "C" fn tx_cancellation_callback(tx: *mut TariCompletedTransaction, _reason: u64) { + unsafe extern "C" fn tx_cancellation_callback( + _context: *mut c_void, + tx: *mut TariCompletedTransaction, + _reason: u64, + ) { assert!(!tx.is_null()); assert_eq!( type_of((*tx).clone()), @@ -9628,35 +9706,42 @@ mod test { completed_transaction_destroy(tx); } - unsafe extern "C" fn txo_validation_complete_callback(_tx_id: c_ulonglong, _result: u64) { + unsafe extern "C" fn txo_validation_complete_callback(_context: *mut c_void, _tx_id: c_ulonglong, _result: u64) { // assert!(true); //optimized out by compiler } - unsafe extern "C" fn contacts_liveness_data_updated_callback(_balance: *mut TariContactsLivenessData) { + unsafe extern "C" fn contacts_liveness_data_updated_callback( + _context: *mut c_void, + _balance: *mut TariContactsLivenessData, + ) { // assert!(true); //optimized out by compiler } - unsafe extern "C" fn balance_updated_callback(_balance: *mut TariBalance) { + unsafe extern "C" fn balance_updated_callback(_context: *mut c_void, _balance: *mut TariBalance) { // assert!(true); //optimized out by compiler } - unsafe extern "C" fn transaction_validation_complete_callback(_tx_id: c_ulonglong, _result: u64) { + unsafe extern "C" fn transaction_validation_complete_callback( + _context: *mut c_void, + _tx_id: c_ulonglong, + _result: u64, + ) { // assert!(true); //optimized out by compiler } - unsafe extern "C" fn saf_messages_received_callback() { + unsafe extern "C" fn saf_messages_received_callback(_context: *mut c_void) { // assert!(true); //optimized out by compiler } - unsafe extern "C" fn connectivity_status_callback(_status: u64) { + unsafe extern "C" fn connectivity_status_callback(_context: *mut c_void, _status: u64) { // assert!(true); //optimized out by compiler } - unsafe extern "C" fn wallet_scanned_height_callback(_height: u64) { + unsafe extern "C" fn wallet_scanned_height_callback(_context: *mut c_void, _height: u64) { // assert!(true); //optimized out by compiler } - unsafe extern "C" fn base_node_state_callback(_state: *mut TariBaseNodeState) { + unsafe extern "C" fn base_node_state_callback(_context: *mut c_void, _state: *mut TariBaseNodeState) { // assert!(true); //optimized out by compiler } @@ -10316,7 +10401,10 @@ mod test { CString::into_raw(CString::new("Hello from Alasca").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let alice_wallet = wallet_create( + void_ptr, alice_config, ptr::null(), 0, @@ -10364,7 +10452,9 @@ mod test { drop(wallet_backend); // Check that the same key is returned when the wallet is started a second time + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let alice_wallet2 = wallet_create( + void_ptr, alice_config, ptr::null(), 0, @@ -10482,7 +10572,9 @@ mod test { let passphrase: *const c_char = CString::into_raw(CString::new("dolphis dancing in the coastal waters").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let alice_wallet = wallet_create( + void_ptr, alice_config, ptr::null(), 0, @@ -10711,7 +10803,9 @@ mod test { let passphrase: *const c_char = CString::into_raw(CString::new("a cat outside in Istanbul").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let wallet = wallet_create( + void_ptr, config, ptr::null(), 0, @@ -10748,7 +10842,7 @@ mod test { assert_eq!(error, 0); let seed_words = wallet_get_seed_words(wallet, error_ptr); assert_eq!(error, 0); - let public_address = wallet_get_tari_address(wallet, error_ptr); + let public_address = wallet_get_tari_interactive_address(wallet, error_ptr); assert_eq!(error, 0); // use seed words to create recovery wallet @@ -10780,7 +10874,10 @@ mod test { CString::into_raw(CString::new(temp_dir.path().join("asdf").to_str().unwrap()).unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let recovered_wallet = wallet_create( + void_ptr, config, log_path, 0, @@ -10817,7 +10914,7 @@ mod test { let recovered_seed_words = wallet_get_seed_words(recovered_wallet, error_ptr); assert_eq!(error, 0); - let recovered_address = wallet_get_tari_address(recovered_wallet, error_ptr); + let recovered_address = wallet_get_tari_interactive_address(recovered_wallet, error_ptr); assert_eq!(error, 0); assert_eq!(*seed_words, *recovered_seed_words); @@ -10861,7 +10958,9 @@ mod test { let passphrase: *const c_char = CString::into_raw(CString::new("Satoshi Nakamoto").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let alice_wallet = wallet_create( + void_ptr, alice_config, ptr::null(), 0, @@ -11040,7 +11139,9 @@ mod test { let passphrase: *const c_char = CString::into_raw(CString::new("J-bay open corona").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let alice_wallet = wallet_create( + void_ptr, alice_config, ptr::null(), 0, @@ -11180,7 +11281,9 @@ mod test { let passphrase: *const c_char = CString::into_raw(CString::new("The master and margarita").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let alice_wallet = wallet_create( + void_ptr, alice_config, ptr::null(), 0, @@ -11400,7 +11503,10 @@ mod test { let passphrase: *const c_char = CString::into_raw(CString::new("niao").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let alice_wallet = wallet_create( + void_ptr, alice_config, ptr::null(), 0, @@ -11628,7 +11734,9 @@ mod test { let passphrase: *const c_char = CString::into_raw(CString::new("niao").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let alice_wallet = wallet_create( + void_ptr, alice_config, ptr::null(), 0, @@ -11890,7 +11998,9 @@ mod test { ); let passphrase: *const c_char = CString::into_raw(CString::new("niao").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let wallet_ptr = wallet_create( + void_ptr, config, ptr::null(), 0, @@ -12272,7 +12382,9 @@ mod test { ); let passphrase: *const c_char = CString::into_raw(CString::new("niao").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let alice_wallet_ptr = wallet_create( + void_ptr, alice_config, ptr::null(), 0, @@ -12338,7 +12450,9 @@ mod test { ); let passphrase: *const c_char = CString::into_raw(CString::new("niao").unwrap()) as *const c_char; let dns_string: *const c_char = CString::into_raw(CString::new("").unwrap()) as *const c_char; + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; let bob_wallet_ptr = wallet_create( + void_ptr, bob_config, ptr::null(), 0, diff --git a/base_layer/wallet_ffi/src/tasks.rs b/base_layer/wallet_ffi/src/tasks.rs index c173d2d2ee..6ce805679b 100644 --- a/base_layer/wallet_ffi/src/tasks.rs +++ b/base_layer/wallet_ffi/src/tasks.rs @@ -20,11 +20,15 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +use std::ffi::c_void; + use log::*; use minotari_wallet::{error::WalletError, utxo_scanner_service::handle::UtxoScannerEvent}; use tari_utilities::hex::Hex; use tokio::{sync::broadcast, task::JoinHandle}; +use crate::callback_handler::Context; + const LOG_TARGET: &str = "wallet_ffi"; /// Events that the recovery process will report via the callback @@ -42,13 +46,14 @@ enum RecoveryEvent { pub async fn recovery_event_monitoring( mut event_stream: broadcast::Receiver, recovery_join_handle: JoinHandle>, - recovery_progress_callback: unsafe extern "C" fn(u8, u64, u64), + recovery_progress_callback: unsafe extern "C" fn(context: *mut c_void, u8, u64, u64), + context: Context, ) { loop { match event_stream.recv().await { Ok(UtxoScannerEvent::ConnectingToBaseNode(peer)) => { unsafe { - (recovery_progress_callback)(RecoveryEvent::ConnectingToBaseNode as u8, 0u64, 0u64); + (recovery_progress_callback)(context.0, RecoveryEvent::ConnectingToBaseNode as u8, 0u64, 0u64); } info!( target: LOG_TARGET, @@ -58,7 +63,7 @@ pub async fn recovery_event_monitoring( }, Ok(UtxoScannerEvent::ConnectedToBaseNode(pk, elapsed)) => { unsafe { - (recovery_progress_callback)(RecoveryEvent::ConnectedToBaseNode as u8, 0u64, 1u64); + (recovery_progress_callback)(context.0, RecoveryEvent::ConnectedToBaseNode as u8, 0u64, 1u64); } info!( target: LOG_TARGET, @@ -75,6 +80,7 @@ pub async fn recovery_event_monitoring( }) => { unsafe { (recovery_progress_callback)( + context.0, RecoveryEvent::ConnectionToBaseNodeFailed as u8, num_retries as u64, retry_limit as u64, @@ -92,7 +98,7 @@ pub async fn recovery_event_monitoring( tip_height: total, }) => { unsafe { - (recovery_progress_callback)(RecoveryEvent::Progress as u8, current, total); + (recovery_progress_callback)(context.0, RecoveryEvent::Progress as u8, current, total); } info!(target: LOG_TARGET, "Recovery progress: {}/{}", current, total); }, @@ -114,6 +120,7 @@ pub async fn recovery_event_monitoring( ); unsafe { (recovery_progress_callback)( + context.0, RecoveryEvent::Completed as u8, num_recovered, u64::from(value_recovered), @@ -128,6 +135,7 @@ pub async fn recovery_event_monitoring( }) => { unsafe { (recovery_progress_callback)( + context.0, RecoveryEvent::ScanningRoundFailed as u8, num_retries as u64, retry_limit as u64, @@ -140,7 +148,7 @@ pub async fn recovery_event_monitoring( }, Ok(UtxoScannerEvent::ScanningFailed) => { unsafe { - (recovery_progress_callback)(RecoveryEvent::RecoveryFailed as u8, 0u64, 0u64); + (recovery_progress_callback)(context.0, RecoveryEvent::RecoveryFailed as u8, 0u64, 0u64); } warn!(target: LOG_TARGET, "UTXO Scanner failed and exited",); }, @@ -159,13 +167,13 @@ pub async fn recovery_event_monitoring( Ok(Ok(_)) => {}, Ok(Err(e)) => { unsafe { - (recovery_progress_callback)(RecoveryEvent::RecoveryFailed as u8, 0u64, 1u64); + (recovery_progress_callback)(context.0, RecoveryEvent::RecoveryFailed as u8, 0u64, 1u64); } error!(target: LOG_TARGET, "Recovery error: {:?}", e); }, Err(e) => { unsafe { - (recovery_progress_callback)(RecoveryEvent::RecoveryFailed as u8, 1u64, 0u64); + (recovery_progress_callback)(context.0, RecoveryEvent::RecoveryFailed as u8, 1u64, 0u64); } error!(target: LOG_TARGET, "Recovery error: {}", e); }, diff --git a/base_layer/wallet_ffi/wallet.h b/base_layer/wallet_ffi/wallet.h index b629000b10..c3f4124c13 100644 --- a/base_layer/wallet_ffi/wallet.h +++ b/base_layer/wallet_ffi/wallet.h @@ -2849,6 +2849,7 @@ TariPublicKey *public_keys_get_at(const struct TariPublicKeys *public_keys, * Creates a TariWallet * * ## Arguments + * Context - a pointer to some context used by all the callbacks * `config` - The TariCommsConfig pointer * `log_path` - An optional file path to the file where the logs will be written. If no log is required pass *null* * pointer. @@ -2947,7 +2948,8 @@ TariPublicKey *public_keys_get_at(const struct TariPublicKeys *public_keys, * # Safety * The ```wallet_destroy``` method must be called when finished with a TariWallet to prevent a memory leak */ -struct TariWallet *wallet_create(TariCommsConfig *config, +struct TariWallet *wallet_create(void *context, + TariCommsConfig *config, const char *log_path, int log_verbosity, unsigned int num_rolling_log_files, @@ -2958,28 +2960,44 @@ struct TariWallet *wallet_create(TariCommsConfig *config, const char *network_str, const char *peer_seed_str, bool dns_sec, - void (*callback_received_transaction)(TariPendingInboundTransaction*), - void (*callback_received_transaction_reply)(TariCompletedTransaction*), - void (*callback_received_finalized_transaction)(TariCompletedTransaction*), - void (*callback_transaction_broadcast)(TariCompletedTransaction*), - void (*callback_transaction_mined)(TariCompletedTransaction*), - void (*callback_transaction_mined_unconfirmed)(TariCompletedTransaction*, + void (*callback_received_transaction)(void *context, + TariPendingInboundTransaction*), + void (*callback_received_transaction_reply)(void *context, + TariCompletedTransaction*), + void (*callback_received_finalized_transaction)(void *context, + TariCompletedTransaction*), + void (*callback_transaction_broadcast)(void *context, + TariCompletedTransaction*), + void (*callback_transaction_mined)(void *context, + TariCompletedTransaction*), + void (*callback_transaction_mined_unconfirmed)(void *context, + TariCompletedTransaction*, uint64_t), - void (*callback_faux_transaction_confirmed)(TariCompletedTransaction*), - void (*callback_faux_transaction_unconfirmed)(TariCompletedTransaction*, + void (*callback_faux_transaction_confirmed)(void *context, + TariCompletedTransaction*), + void (*callback_faux_transaction_unconfirmed)(void *context, + TariCompletedTransaction*, uint64_t), - void (*callback_transaction_send_result)(unsigned long long, + void (*callback_transaction_send_result)(void *context, + unsigned long long, TariTransactionSendStatus*), - void (*callback_transaction_cancellation)(TariCompletedTransaction*, + void (*callback_transaction_cancellation)(void *context, + TariCompletedTransaction*, uint64_t), - void (*callback_txo_validation_complete)(uint64_t, uint64_t), - void (*callback_contacts_liveness_data_updated)(TariContactsLivenessData*), - void (*callback_balance_updated)(TariBalance*), - void (*callback_transaction_validation_complete)(uint64_t, uint64_t), - void (*callback_saf_messages_received)(void), - void (*callback_connectivity_status)(uint64_t), - void (*callback_wallet_scanned_height)(uint64_t), - void (*callback_base_node_state)(struct TariBaseNodeState*), + void (*callback_txo_validation_complete)(void *context, + uint64_t, + uint64_t), + void (*callback_contacts_liveness_data_updated)(void *context, + TariContactsLivenessData*), + void (*callback_balance_updated)(void *context, TariBalance*), + void (*callback_transaction_validation_complete)(void *context, + uint64_t, + uint64_t), + void (*callback_saf_messages_received)(void *context), + void (*callback_connectivity_status)(void *context, uint64_t), + void (*callback_wallet_scanned_height)(void *context, uint64_t), + void (*callback_base_node_state)(void *context, + struct TariBaseNodeState*), bool *recovery_in_progress, int *error_out); @@ -3689,7 +3707,7 @@ TariCompletedTransaction *wallet_get_cancelled_transaction_by_id(struct TariWall int *error_out); /** - * Get the TariWalletAddress from a TariWallet + * Get the interactive TariWalletAddress from a TariWallet * * ## Arguments * `wallet` - The TariWallet pointer @@ -3703,8 +3721,26 @@ TariCompletedTransaction *wallet_get_cancelled_transaction_by_id(struct TariWall * # Safety * The ```tari_address_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak */ -TariWalletAddress *wallet_get_tari_address(struct TariWallet *wallet, - int *error_out); +TariWalletAddress *wallet_get_tari_interactive_address(struct TariWallet *wallet, + int *error_out); + +/** + * Get the one_sided only TariWalletAddress from a TariWallet + * + * ## Arguments + * `wallet` - The TariWallet pointer + * `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 + * `*mut TariWalletAddress` - returns the address, note that ptr::null_mut() is returned + * if wc is null + * + * # Safety + * The ```tari_address_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak + */ +TariWalletAddress *wallet_get_tari_one_sided_address(struct TariWallet *wallet, + int *error_out); /** * Cancel a Pending Transaction @@ -3964,7 +4000,10 @@ bool wallet_is_recovery_in_progress(struct TariWallet *wallet, */ bool wallet_start_recovery(struct TariWallet *wallet, TariPublicKey *base_node_public_key, - void (*recovery_progress_callback)(uint8_t, uint64_t, uint64_t), + void (*recovery_progress_callback)(void *context, + uint8_t, + uint64_t, + uint64_t), const char *recovered_output_message, int *error_out); diff --git a/integration_tests/src/ffi/ffi_import.rs b/integration_tests/src/ffi/ffi_import.rs index 25d9e68418..8509946839 100644 --- a/integration_tests/src/ffi/ffi_import.rs +++ b/integration_tests/src/ffi/ffi_import.rs @@ -379,6 +379,7 @@ extern "C" { error_out: *mut c_int, ) -> *mut TariPublicKey; pub fn wallet_create( + context: *mut c_void, config: *mut TariCommsConfig, log_path: *const c_char, log_level: c_int, @@ -390,24 +391,46 @@ extern "C" { network_str: *const c_char, peer_seed_str: *const c_char, dns_sec: bool, - callback_received_transaction: unsafe extern "C" fn(*mut TariPendingInboundTransaction), - callback_received_transaction_reply: unsafe extern "C" fn(*mut TariCompletedTransaction), - callback_received_finalized_transaction: unsafe extern "C" fn(*mut TariCompletedTransaction), - callback_transaction_broadcast: unsafe extern "C" fn(*mut TariCompletedTransaction), - callback_transaction_mined: unsafe extern "C" fn(*mut TariCompletedTransaction), - callback_transaction_mined_unconfirmed: unsafe extern "C" fn(*mut TariCompletedTransaction, u64), - callback_faux_transaction_confirmed: unsafe extern "C" fn(*mut TariCompletedTransaction), - callback_faux_transaction_unconfirmed: unsafe extern "C" fn(*mut TariCompletedTransaction, u64), - callback_transaction_send_result: unsafe extern "C" fn(c_ulonglong, *mut TariTransactionSendStatus), - callback_transaction_cancellation: unsafe extern "C" fn(*mut TariCompletedTransaction, u64), - callback_txo_validation_complete: unsafe extern "C" fn(u64, u64), - callback_contacts_liveness_data_updated: unsafe extern "C" fn(*mut TariContactsLivenessData), - callback_balance_updated: unsafe extern "C" fn(*mut TariBalance), - callback_transaction_validation_complete: unsafe extern "C" fn(u64, u64), - callback_saf_messages_received: unsafe extern "C" fn(), - callback_connectivity_status: unsafe extern "C" fn(u64), - callback_wallet_scanned_height: unsafe extern "C" fn(u64), - callback_base_node_state_updated: unsafe extern "C" fn(*mut TariBaseNodeState), + callback_received_transaction: unsafe extern "C" fn(context: *mut c_void, *mut TariPendingInboundTransaction), + callback_received_transaction_reply: unsafe extern "C" fn(context: *mut c_void, *mut TariCompletedTransaction), + callback_received_finalized_transaction: unsafe extern "C" fn( + context: *mut c_void, + *mut TariCompletedTransaction, + ), + callback_transaction_broadcast: unsafe extern "C" fn(context: *mut c_void, *mut TariCompletedTransaction), + callback_transaction_mined: unsafe extern "C" fn(context: *mut c_void, *mut TariCompletedTransaction), + callback_transaction_mined_unconfirmed: unsafe extern "C" fn( + context: *mut c_void, + *mut TariCompletedTransaction, + u64, + ), + callback_faux_transaction_confirmed: unsafe extern "C" fn(context: *mut c_void, *mut TariCompletedTransaction), + callback_faux_transaction_unconfirmed: unsafe extern "C" fn( + context: *mut c_void, + *mut TariCompletedTransaction, + u64, + ), + callback_transaction_send_result: unsafe extern "C" fn( + context: *mut c_void, + c_ulonglong, + *mut TariTransactionSendStatus, + ), + callback_transaction_cancellation: unsafe extern "C" fn( + context: *mut c_void, + *mut TariCompletedTransaction, + u64, + ), + callback_txo_validation_complete: unsafe extern "C" fn(context: *mut c_void, u64, u64), + callback_contacts_liveness_data_updated: unsafe extern "C" fn( + context: *mut c_void, + *mut TariContactsLivenessData, + ), + callback_balance_updated: unsafe extern "C" fn(context: *mut c_void, *mut TariBalance), + callback_transaction_validation_complete: unsafe extern "C" fn(context: *mut c_void, u64, u64), + callback_saf_messages_received: unsafe extern "C" fn(context: *mut c_void), + callback_connectivity_status: unsafe extern "C" fn(context: *mut c_void, u64), + callback_wallet_scanned_height: unsafe extern "C" fn(context: *mut c_void, u64), + callback_base_node_state_updated: unsafe extern "C" fn(context: *mut c_void, *mut TariBaseNodeState), recovery_in_progress: *mut bool, error_out: *mut c_int, ) -> *mut TariWallet; @@ -528,7 +551,11 @@ extern "C" { transaction_id: c_ulonglong, error_out: *mut c_int, ) -> *mut TariCompletedTransaction; - pub fn wallet_get_tari_address(wallet: *mut TariWallet, error_out: *mut c_int) -> *mut TariWalletAddress; + pub fn wallet_get_tari_interactive_address( + wallet: *mut TariWallet, + error_out: *mut c_int, + ) -> *mut TariWalletAddress; + pub fn wallet_get_tari_one_sided_address(wallet: *mut TariWallet, error_out: *mut c_int) -> *mut TariWalletAddress; pub fn wallet_cancel_pending_transaction( wallet: *mut TariWallet, transaction_id: c_ulonglong, @@ -552,7 +579,7 @@ extern "C" { pub fn wallet_start_recovery( wallet: *mut TariWallet, base_node_public_key: *mut TariPublicKey, - recovery_progress_callback: unsafe extern "C" fn(u8, u64, u64), + recovery_progress_callback: unsafe extern "C" fn(context: *mut c_void, u8, u64, u64), recovered_output_message: *const c_char, error_out: *mut c_int, ) -> bool; diff --git a/integration_tests/src/ffi/wallet.rs b/integration_tests/src/ffi/wallet.rs index 6be02d5b0a..3e8c69b3f7 100644 --- a/integration_tests/src/ffi/wallet.rs +++ b/integration_tests/src/ffi/wallet.rs @@ -58,94 +58,114 @@ use super::{ }; use crate::ffi::{callbacks, ffi_import::TariBaseNodeState}; -extern "C" fn callback_received_transaction(ptr: *mut TariPendingInboundTransaction) { +extern "C" fn callback_received_transaction(_context: *mut c_void, ptr: *mut TariPendingInboundTransaction) { let callbacks = Callbacks::instance(); callbacks.on_received_transaction(ptr); // println!("callback_received_transaction"); } -extern "C" fn callback_received_transaction_reply(ptr: *mut TariCompletedTransaction) { +extern "C" fn callback_received_transaction_reply(_context: *mut c_void, ptr: *mut TariCompletedTransaction) { let callbacks = Callbacks::instance(); callbacks.on_received_transaction_reply(ptr); // println!("callback_received_transaction_reply"); } -extern "C" fn callback_received_finalized_transaction(ptr: *mut TariCompletedTransaction) { +extern "C" fn callback_received_finalized_transaction(_context: *mut c_void, ptr: *mut TariCompletedTransaction) { let callbacks = Callbacks::instance(); callbacks.on_received_finalized_transaction(ptr); // println!("callback_received_finalized_transaction"); } -extern "C" fn callback_transaction_broadcast(ptr: *mut TariCompletedTransaction) { +extern "C" fn callback_transaction_broadcast(_context: *mut c_void, ptr: *mut TariCompletedTransaction) { let callbacks = Callbacks::instance(); callbacks.on_transaction_broadcast(ptr); // println!("callback_transaction_broadcast"); } -extern "C" fn callback_transaction_mined(ptr: *mut TariCompletedTransaction) { +extern "C" fn callback_transaction_mined(_context: *mut c_void, ptr: *mut TariCompletedTransaction) { let callbacks = Callbacks::instance(); callbacks.on_transaction_mined(ptr); // println!("callback_transaction_mined"); } -extern "C" fn callback_transaction_mined_unconfirmed(ptr: *mut TariCompletedTransaction, confirmations: u64) { +extern "C" fn callback_transaction_mined_unconfirmed( + _context: *mut c_void, + ptr: *mut TariCompletedTransaction, + confirmations: u64, +) { let callbacks = Callbacks::instance(); callbacks.on_transaction_mined_unconfirmed(ptr, confirmations); // println!("callback_transaction_mined_unconfirmed"); } -extern "C" fn callback_faux_transaction_confirmed(ptr: *mut TariCompletedTransaction) { +extern "C" fn callback_faux_transaction_confirmed(_context: *mut c_void, ptr: *mut TariCompletedTransaction) { let callbacks = Callbacks::instance(); callbacks.on_faux_transaction_confirmed(ptr); // println!("callback_faux_transaction_confirmed"); } -extern "C" fn callback_faux_transaction_unconfirmed(ptr: *mut TariCompletedTransaction, confirmations: u64) { +extern "C" fn callback_faux_transaction_unconfirmed( + _context: *mut c_void, + ptr: *mut TariCompletedTransaction, + confirmations: u64, +) { let callbacks = Callbacks::instance(); callbacks.on_faux_transaction_mined_unconfirmed(ptr, confirmations); // println!("callback_faux_transaction_unconfirmed"); } -extern "C" fn callback_transaction_send_result(tx_id: c_ulonglong, ptr: *mut TariTransactionSendStatus) { +extern "C" fn callback_transaction_send_result( + _context: *mut c_void, + tx_id: c_ulonglong, + ptr: *mut TariTransactionSendStatus, +) { let callbacks = Callbacks::instance(); callbacks.on_transaction_send_result(tx_id, ptr); // println!("callback_transaction_send_result"); } -extern "C" fn callback_transaction_cancellation(ptr: *mut TariCompletedTransaction, reason: u64) { +extern "C" fn callback_transaction_cancellation( + _context: *mut c_void, + ptr: *mut TariCompletedTransaction, + reason: u64, +) { let callbacks = Callbacks::instance(); callbacks.on_transaction_cancellation(ptr, reason); // println!("callback_transaction_cancellation"); } -extern "C" fn callback_txo_validation_complete(request_key: u64, validation_results: u64) { +extern "C" fn callback_txo_validation_complete(_context: *mut c_void, request_key: u64, validation_results: u64) { let callbacks = Callbacks::instance(); callbacks.on_txo_validation_complete(request_key, validation_results); // println!("callback_txo_validation_complete"); } -extern "C" fn callback_contacts_liveness_data_updated(ptr: *mut TariContactsLivenessData) { +extern "C" fn callback_contacts_liveness_data_updated(_context: *mut c_void, ptr: *mut TariContactsLivenessData) { let callbacks = Callbacks::instance(); callbacks.on_contacts_liveness_data_updated(ptr); // println!("callback_contacts_liveness_data_updated"); } -extern "C" fn callback_balance_updated(ptr: *mut TariBalance) { +extern "C" fn callback_balance_updated(_context: *mut c_void, ptr: *mut TariBalance) { let callbacks = Callbacks::instance(); callbacks.on_balance_updated(ptr); // println!("callback_balance_updated"); } -extern "C" fn callback_transaction_validation_complete(request_key: u64, validation_results: u64) { +extern "C" fn callback_transaction_validation_complete( + _context: *mut c_void, + request_key: u64, + validation_results: u64, +) { let callbacks = Callbacks::instance(); callbacks.on_transaction_validation_complete(request_key, validation_results); // println!("callback_transaction_validation_complete"); } -extern "C" fn callback_saf_messages_received() { +extern "C" fn callback_saf_messages_received(_context: *mut c_void) { let callbacks = Callbacks::instance(); callbacks.on_saf_messages_received(); // println!("callback_saf_messages_received"); } -extern "C" fn callback_connectivity_status(status: u64) { +extern "C" fn callback_connectivity_status(_context: *mut c_void, status: u64) { let callbacks = Callbacks::instance(); callbacks.on_connectivity_status(status); // println!("callback_connectivity_status"); } -extern "C" fn callback_wallet_scanned_height(height: u64) { +extern "C" fn callback_wallet_scanned_height(_context: *mut c_void, height: u64) { let callbacks = Callbacks::instance(); callbacks.callback_wallet_scanned_height(height); // println!("callback_wallet_scanned_height"); } -extern "C" fn callback_base_node_state(state: *mut TariBaseNodeState) { +extern "C" fn callback_base_node_state(_context: *mut c_void, state: *mut TariBaseNodeState) { let callbacks = Callbacks::instance(); callbacks.on_basenode_state_update(state); } @@ -177,9 +197,10 @@ impl Wallet { let mut recovery_in_progress: bool = false; let mut error = 0; let ptr; - + let void_ptr: *mut c_void = &mut (5) as *mut _ as *mut c_void; unsafe { ptr = wallet_create( + void_ptr, comms_config.get_ptr(), CString::new(log_path).unwrap().into_raw(), 11, @@ -270,10 +291,10 @@ impl Wallet { let ptr; let mut error = 0; unsafe { - ptr = ffi_import::wallet_get_tari_address(self.ptr, &mut error); + ptr = ffi_import::wallet_get_tari_interactive_address(self.ptr, &mut error); if error > 0 { - println!("wallet_get_tari_address error {}", error); - panic!("wallet_get_tari_address error"); + println!("wallet_get_tari_interactive_address error {}", error); + panic!("wallet_get_tari_interactive_address error"); } } WalletAddress::from_ptr(ptr) diff --git a/integration_tests/src/ffi/wallet_address.rs b/integration_tests/src/ffi/wallet_address.rs index 05c1707ca4..a7ae222723 100644 --- a/integration_tests/src/ffi/wallet_address.rs +++ b/integration_tests/src/ffi/wallet_address.rs @@ -48,8 +48,8 @@ impl WalletAddress { unsafe { ptr = ffi_import::tari_address_from_base58(CString::new(address).unwrap().into_raw(), &mut error); if error > 0 { - println!("wallet_get_tari_address error {}", error); - panic!("wallet_get_tari_address error"); + println!("wallet_get_tari_interactive_address error {}", error); + panic!("wallet_get_tari_interactive_address error"); } } Self { ptr } @@ -62,8 +62,8 @@ impl WalletAddress { unsafe { ptr = ffi_import::emoji_id_to_tari_address(CString::new(emoji_id).unwrap().into_raw(), &mut error); if error > 0 { - println!("wallet_get_tari_address error {}", error); - panic!("wallet_get_tari_address error"); + println!("wallet_get_tari_interactive_address error {}", error); + panic!("wallet_get_tari_interactive_address error"); } } Self { ptr } @@ -75,8 +75,8 @@ impl WalletAddress { unsafe { ptr = ffi_import::tari_address_get_bytes(self.ptr, &mut error); if error > 0 { - println!("wallet_get_tari_address error {}", error); - panic!("wallet_get_tari_address error"); + println!("wallet_get_tari_interactive_address error {}", error); + panic!("wallet_get_tari_interactive_address error"); } } FFIBytes::from_ptr(ptr)