diff --git a/Cargo.lock b/Cargo.lock index 08c8fceebf..c91e4af3b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -480,6 +480,12 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cast5" version = "0.10.0" @@ -887,7 +893,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0363053954f3e679645fc443321ca128b7b950a6fe288cf5f9335cc22ee58394" dependencies = [ "atty", - "cast", + "cast 0.2.7", "clap 2.34.0", "criterion-plot 0.3.1", "csv", @@ -909,12 +915,12 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" dependencies = [ "atty", - "cast", + "cast 0.3.0", "clap 2.34.0", "criterion-plot 0.4.4", "csv", @@ -940,7 +946,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76f9212ddf2f4a9eb2d401635190600656a1f88a932ef53d06e7fa4c7e02fb8e" dependencies = [ "byteorder", - "cast", + "cast 0.2.7", "itertools 0.8.2", ] @@ -950,7 +956,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" dependencies = [ - "cast", + "cast 0.2.7", "itertools 0.10.3", ] @@ -4966,7 +4972,7 @@ dependencies = [ "chacha20poly1305 0.9.1", "chrono", "config", - "criterion 0.3.5", + "criterion 0.3.6", "croaring", "decimal-rs", "derivative", diff --git a/applications/tari_console_wallet/src/automation/commands.rs b/applications/tari_console_wallet/src/automation/commands.rs index 46b2784276..cd75b73f24 100644 --- a/applications/tari_console_wallet/src/automation/commands.rs +++ b/applications/tari_console_wallet/src/automation/commands.rs @@ -58,7 +58,7 @@ use tari_wallet::{ connectivity_service::WalletConnectivityInterface, error::WalletError, key_manager_service::NextKeyResult, - output_manager_service::handle::OutputManagerHandle, + output_manager_service::{handle::OutputManagerHandle, UtxoSelectionCriteria}, transaction_service::handle::{TransactionEvent, TransactionServiceHandle}, TransactionStage, WalletConfig, @@ -118,6 +118,7 @@ pub async fn send_tari( .send_transaction( dest_pubkey, amount, + UtxoSelectionCriteria::default(), OutputFeatures::default(), fee_per_gram * uT, message, @@ -131,11 +132,12 @@ pub async fn init_sha_atomic_swap( mut wallet_transaction_service: TransactionServiceHandle, fee_per_gram: u64, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, dest_pubkey: PublicKey, message: String, ) -> Result<(TxId, PublicKey, TransactionOutput), CommandError> { let (tx_id, pre_image, output) = wallet_transaction_service - .send_sha_atomic_swap_transaction(dest_pubkey, amount, fee_per_gram * uT, message) + .send_sha_atomic_swap_transaction(dest_pubkey, amount, selection_criteria, fee_per_gram * uT, message) .await .map_err(CommandError::TransactionServiceError)?; Ok((tx_id, pre_image, output)) @@ -181,6 +183,7 @@ pub async fn send_one_sided( mut wallet_transaction_service: TransactionServiceHandle, fee_per_gram: u64, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, dest_pubkey: PublicKey, message: String, ) -> Result { @@ -188,6 +191,7 @@ pub async fn send_one_sided( .send_one_sided_transaction( dest_pubkey, amount, + selection_criteria, OutputFeatures::default(), fee_per_gram * uT, message, @@ -200,6 +204,7 @@ pub async fn send_one_sided_to_stealth_address( mut wallet_transaction_service: TransactionServiceHandle, fee_per_gram: u64, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, dest_pubkey: PublicKey, message: String, ) -> Result { @@ -207,6 +212,7 @@ pub async fn send_one_sided_to_stealth_address( .send_one_sided_to_stealth_address_transaction( dest_pubkey, amount, + selection_criteria, OutputFeatures::default(), fee_per_gram * uT, message, @@ -374,10 +380,26 @@ pub async fn make_it_rain( send_tari(tx_service, fee, amount, pk.clone(), msg.clone()).await }, MakeItRainTransactionType::OneSided => { - send_one_sided(tx_service, fee, amount, pk.clone(), msg.clone()).await + send_one_sided( + tx_service, + fee, + amount, + UtxoSelectionCriteria::default(), + pk.clone(), + msg.clone(), + ) + .await }, MakeItRainTransactionType::StealthOneSided => { - send_one_sided_to_stealth_address(tx_service, fee, amount, pk.clone(), msg.clone()).await + send_one_sided_to_stealth_address( + tx_service, + fee, + amount, + UtxoSelectionCriteria::default(), + pk.clone(), + msg.clone(), + ) + .await }, }; let submit_time = Instant::now(); @@ -594,6 +616,7 @@ pub async fn command_runner( transaction_service.clone(), config.fee_per_gram, args.amount, + UtxoSelectionCriteria::default(), args.destination.into(), args.message, ) @@ -606,6 +629,7 @@ pub async fn command_runner( transaction_service.clone(), config.fee_per_gram, args.amount, + UtxoSelectionCriteria::default(), args.destination.into(), args.message, ) @@ -722,6 +746,7 @@ pub async fn command_runner( transaction_service.clone(), config.fee_per_gram, args.amount, + UtxoSelectionCriteria::default(), args.destination.into(), args.message, ) diff --git a/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs b/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs index 1af3c6311a..43aa77c19e 100644 --- a/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs +++ b/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs @@ -88,7 +88,7 @@ use tari_core::transactions::{ use tari_utilities::{hex::Hex, ByteArray}; use tari_wallet::{ connectivity_service::{OnlineStatus, WalletConnectivityInterface}, - output_manager_service::handle::OutputManagerHandle, + output_manager_service::{handle::OutputManagerHandle, UtxoSelectionCriteria}, transaction_service::{ handle::TransactionServiceHandle, storage::models::{self, WalletTransaction}, @@ -301,6 +301,7 @@ impl wallet_server::Wallet for WalletGrpcServer { .send_sha_atomic_swap_transaction( address.clone(), message.amount.into(), + UtxoSelectionCriteria::default(), message.fee_per_gram.into(), message.message, ) @@ -478,6 +479,7 @@ impl wallet_server::Wallet for WalletGrpcServer { .send_transaction( pk, amount.into(), + UtxoSelectionCriteria::default(), OutputFeatures::default(), fee_per_gram.into(), message, @@ -488,6 +490,7 @@ impl wallet_server::Wallet for WalletGrpcServer { .send_one_sided_transaction( pk, amount.into(), + UtxoSelectionCriteria::default(), OutputFeatures::default(), fee_per_gram.into(), message, @@ -498,6 +501,7 @@ impl wallet_server::Wallet for WalletGrpcServer { .send_one_sided_to_stealth_address_transaction( pk, amount.into(), + UtxoSelectionCriteria::default(), OutputFeatures::default(), fee_per_gram.into(), message, @@ -546,7 +550,12 @@ impl wallet_server::Wallet for WalletGrpcServer { let mut transaction_service = self.get_transaction_service(); debug!(target: LOG_TARGET, "Trying to burn {} Tari", message.amount); let response = match transaction_service - .burn_tari(message.amount.into(), message.fee_per_gram.into(), message.message) + .burn_tari( + message.amount.into(), + UtxoSelectionCriteria::default(), + message.fee_per_gram.into(), + message.message, + ) .await { Ok(tx_id) => { diff --git a/applications/tari_console_wallet/src/ui/components/send_tab.rs b/applications/tari_console_wallet/src/ui/components/send_tab.rs index 734f6cd229..cffad8bd69 100644 --- a/applications/tari_console_wallet/src/ui/components/send_tab.rs +++ b/applications/tari_console_wallet/src/ui/components/send_tab.rs @@ -4,6 +4,7 @@ use log::*; use tari_core::transactions::tari_amount::MicroTari; use tari_utilities::hex::Hex; +use tari_wallet::output_manager_service::UtxoSelectionCriteria; use tokio::{runtime::Handle, sync::watch}; use tui::{ backend::Backend, @@ -268,6 +269,7 @@ impl SendTab { match Handle::current().block_on(app_state.send_one_sided_transaction( self.to_field.clone(), amount.into(), + UtxoSelectionCriteria::default(), fee_per_gram, self.message_field.clone(), tx, @@ -286,6 +288,7 @@ impl SendTab { app_state.send_one_sided_to_stealth_address_transaction( self.to_field.clone(), amount.into(), + UtxoSelectionCriteria::default(), fee_per_gram, self.message_field.clone(), tx, @@ -305,6 +308,7 @@ impl SendTab { match Handle::current().block_on(app_state.send_transaction( self.to_field.clone(), amount.into(), + UtxoSelectionCriteria::default(), fee_per_gram, self.message_field.clone(), tx, diff --git a/applications/tari_console_wallet/src/ui/state/app_state.rs b/applications/tari_console_wallet/src/ui/state/app_state.rs index 8d3a22b6bd..0c775bc646 100644 --- a/applications/tari_console_wallet/src/ui/state/app_state.rs +++ b/applications/tari_console_wallet/src/ui/state/app_state.rs @@ -55,7 +55,7 @@ use tari_wallet::{ base_node_service::{handle::BaseNodeEventReceiver, service::BaseNodeState}, connectivity_service::{OnlineStatus, WalletConnectivityHandle, WalletConnectivityInterface}, contacts_service::{handle::ContactsLivenessEvent, storage::database::Contact}, - output_manager_service::{handle::OutputManagerEventReceiver, service::Balance}, + output_manager_service::{handle::OutputManagerEventReceiver, service::Balance, UtxoSelectionCriteria}, transaction_service::{ handle::TransactionEventReceiver, storage::models::{CompletedTransaction, TxCancellationReason}, @@ -265,6 +265,7 @@ impl AppState { &mut self, public_key: String, amount: u64, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: u64, message: String, result_tx: watch::Sender, @@ -282,6 +283,7 @@ impl AppState { tokio::spawn(send_transaction_task( public_key, MicroTari::from(amount), + selection_criteria, output_features, message, fee_per_gram, @@ -296,6 +298,7 @@ impl AppState { &mut self, public_key: String, amount: u64, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: u64, message: String, result_tx: watch::Sender, @@ -313,6 +316,7 @@ impl AppState { tokio::spawn(send_one_sided_transaction_task( public_key, MicroTari::from(amount), + selection_criteria, output_features, message, fee_per_gram, @@ -327,6 +331,7 @@ impl AppState { &mut self, dest_pubkey: String, amount: u64, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: u64, message: String, result_tx: watch::Sender, @@ -344,6 +349,7 @@ impl AppState { tokio::spawn(send_one_sided_to_stealth_address_transaction( dest_pubkey, MicroTari::from(amount), + selection_criteria, output_features, message, fee_per_gram, diff --git a/applications/tari_console_wallet/src/ui/state/tasks.rs b/applications/tari_console_wallet/src/ui/state/tasks.rs index e7a8d2a368..be18a312f9 100644 --- a/applications/tari_console_wallet/src/ui/state/tasks.rs +++ b/applications/tari_console_wallet/src/ui/state/tasks.rs @@ -22,7 +22,10 @@ use tari_comms::types::CommsPublicKey; use tari_core::transactions::{tari_amount::MicroTari, transaction_components::OutputFeatures}; -use tari_wallet::transaction_service::handle::{TransactionEvent, TransactionSendStatus, TransactionServiceHandle}; +use tari_wallet::{ + output_manager_service::UtxoSelectionCriteria, + transaction_service::handle::{TransactionEvent, TransactionSendStatus, TransactionServiceHandle}, +}; use tokio::sync::{broadcast, watch}; use crate::ui::{state::UiTransactionSendStatus, UiError}; @@ -32,6 +35,7 @@ const LOG_TARGET: &str = "wallet::console_wallet::tasks "; pub async fn send_transaction_task( public_key: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, message: String, fee_per_gram: MicroTari, @@ -42,7 +46,14 @@ pub async fn send_transaction_task( let mut event_stream = transaction_service_handle.get_event_stream(); let mut send_status = TransactionSendStatus::default(); match transaction_service_handle - .send_transaction(public_key, amount, output_features, fee_per_gram, message) + .send_transaction( + public_key, + amount, + selection_criteria, + output_features, + fee_per_gram, + message, + ) .await { Err(e) => { @@ -100,6 +111,7 @@ pub async fn send_transaction_task( pub async fn send_one_sided_transaction_task( public_key: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, message: String, fee_per_gram: MicroTari, @@ -109,7 +121,14 @@ pub async fn send_one_sided_transaction_task( let _result = result_tx.send(UiTransactionSendStatus::Initiated); let mut event_stream = transaction_service_handle.get_event_stream(); match transaction_service_handle - .send_one_sided_transaction(public_key, amount, output_features, fee_per_gram, message) + .send_one_sided_transaction( + public_key, + amount, + selection_criteria, + output_features, + fee_per_gram, + message, + ) .await { Err(e) => { @@ -146,6 +165,7 @@ pub async fn send_one_sided_transaction_task( pub async fn send_one_sided_to_stealth_address_transaction( dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, message: String, fee_per_gram: MicroTari, @@ -155,7 +175,14 @@ pub async fn send_one_sided_to_stealth_address_transaction( let _result = result_tx.send(UiTransactionSendStatus::Initiated); let mut event_stream = transaction_service_handle.get_event_stream(); match transaction_service_handle - .send_one_sided_to_stealth_address_transaction(dest_pubkey, amount, output_features, fee_per_gram, message) + .send_one_sided_to_stealth_address_transaction( + dest_pubkey, + amount, + selection_criteria, + output_features, + fee_per_gram, + message, + ) .await { Err(e) => { diff --git a/base_layer/wallet/src/output_manager_service/handle.rs b/base_layer/wallet/src/output_manager_service/handle.rs index 3403678213..45923b6f93 100644 --- a/base_layer/wallet/src/output_manager_service/handle.rs +++ b/base_layer/wallet/src/output_manager_service/handle.rs @@ -78,7 +78,7 @@ pub enum OutputManagerRequest { PrepareToSendTransaction { tx_id: TxId, amount: MicroTari, - utxo_selection: UtxoSelectionCriteria, + selection_criteria: UtxoSelectionCriteria, output_features: Box, fee_per_gram: MicroTari, tx_meta: TransactionMetadata, @@ -90,7 +90,7 @@ pub enum OutputManagerRequest { CreatePayToSelfTransaction { tx_id: TxId, amount: MicroTari, - utxo_selection: UtxoSelectionCriteria, + selection_criteria: UtxoSelectionCriteria, output_features: Box, fee_per_gram: MicroTari, lock_height: Option, @@ -99,7 +99,7 @@ pub enum OutputManagerRequest { CreatePayToSelfWithOutputs { outputs: Vec, fee_per_gram: MicroTari, - input_selection: UtxoSelectionCriteria, + selection_criteria: UtxoSelectionCriteria, }, CancelTransaction(TxId), GetSpentOutputs, @@ -120,6 +120,7 @@ pub enum OutputManagerRequest { RemoveEncryption, FeeEstimate { amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, num_kernels: usize, num_outputs: usize, @@ -197,13 +198,14 @@ impl fmt::Display for OutputManagerRequest { GetCoinbaseTransaction(_) => write!(f, "GetCoinbaseTransaction"), FeeEstimate { amount, + selection_criteria, fee_per_gram, num_kernels, num_outputs, } => write!( f, - "FeeEstimate(amount: {}, fee_per_gram: {}, num_kernels: {}, num_outputs: {})", - amount, fee_per_gram, num_kernels, num_outputs + "FeeEstimate(amount: {}, fee_per_gram: {}, num_kernels: {}, num_outputs: {}, selection_criteria: {:?})", + amount, fee_per_gram, num_kernels, num_outputs, selection_criteria ), ScanForRecoverableOutputs(_) => write!(f, "ScanForRecoverableOutputs"), ScanOutputs(_) => write!(f, "ScanOutputs"), @@ -545,7 +547,7 @@ impl OutputManagerHandle { .call(OutputManagerRequest::PrepareToSendTransaction { tx_id, amount, - utxo_selection, + selection_criteria: utxo_selection, output_features: Box::new(output_features), fee_per_gram, tx_meta, @@ -566,6 +568,7 @@ impl OutputManagerHandle { pub async fn fee_estimate( &mut self, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, num_kernels: usize, num_outputs: usize, @@ -574,6 +577,7 @@ impl OutputManagerHandle { .handle .call(OutputManagerRequest::FeeEstimate { amount, + selection_criteria, fee_per_gram, num_kernels, num_outputs, @@ -833,7 +837,7 @@ impl OutputManagerHandle { .call(OutputManagerRequest::CreatePayToSelfWithOutputs { outputs, fee_per_gram, - input_selection, + selection_criteria: input_selection, }) .await?? { @@ -857,7 +861,7 @@ impl OutputManagerHandle { .call(OutputManagerRequest::CreatePayToSelfTransaction { tx_id, amount, - utxo_selection, + selection_criteria: utxo_selection, output_features: Box::new(output_features), fee_per_gram, lock_height, diff --git a/base_layer/wallet/src/output_manager_service/service.rs b/base_layer/wallet/src/output_manager_service/service.rs index 1ee1ce9788..409616c90d 100644 --- a/base_layer/wallet/src/output_manager_service/service.rs +++ b/base_layer/wallet/src/output_manager_service/service.rs @@ -279,7 +279,7 @@ where OutputManagerRequest::PrepareToSendTransaction { tx_id, amount, - utxo_selection, + selection_criteria, output_features, fee_per_gram, tx_meta, @@ -291,7 +291,7 @@ where .prepare_transaction_to_send( tx_id, amount, - utxo_selection, + selection_criteria, fee_per_gram, tx_meta, message, @@ -305,7 +305,7 @@ where OutputManagerRequest::CreatePayToSelfTransaction { tx_id, amount, - utxo_selection, + selection_criteria, output_features, fee_per_gram, lock_height, @@ -314,7 +314,7 @@ where .create_pay_to_self_transaction( tx_id, amount, - utxo_selection, + selection_criteria, *output_features, fee_per_gram, lock_height, @@ -324,11 +324,12 @@ where .map(OutputManagerResponse::PayToSelfTransaction), OutputManagerRequest::FeeEstimate { amount, + selection_criteria, fee_per_gram, num_kernels, num_outputs, } => self - .fee_estimate(amount, fee_per_gram, num_kernels, num_outputs) + .fee_estimate(amount, selection_criteria, fee_per_gram, num_kernels, num_outputs) .await .map(OutputManagerResponse::FeeEstimate), OutputManagerRequest::ConfirmPendingTransaction(tx_id) => self @@ -445,10 +446,10 @@ where OutputManagerRequest::CreatePayToSelfWithOutputs { outputs, fee_per_gram, - input_selection, + selection_criteria, } => { let (tx_id, transaction) = self - .create_pay_to_self_containing_outputs(outputs, fee_per_gram, input_selection) + .create_pay_to_self_containing_outputs(outputs, selection_criteria, fee_per_gram) .await?; Ok(OutputManagerResponse::CreatePayToSelfWithOutputs { transaction: Box::new(transaction), @@ -809,6 +810,7 @@ where async fn fee_estimate( &mut self, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, num_kernels: usize, num_outputs: usize, @@ -836,10 +838,10 @@ where let utxo_selection = self .select_utxos( amount, + selection_criteria, fee_per_gram, num_outputs, metadata_byte_size * num_outputs, - UtxoSelectionCriteria::default(), ) .await?; @@ -858,7 +860,7 @@ where &mut self, tx_id: TxId, amount: MicroTari, - utxo_selection: UtxoSelectionCriteria, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, tx_meta: TransactionMetadata, message: String, @@ -871,7 +873,7 @@ where target: LOG_TARGET, "Preparing to send transaction. Amount: {}. UTXO Selection: {}. Fee per gram: {}. ", amount, - utxo_selection, + selection_criteria, fee_per_gram, ); let metadata_byte_size = self @@ -885,7 +887,7 @@ where ); let input_selection = self - .select_utxos(amount, fee_per_gram, 1, metadata_byte_size, utxo_selection) + .select_utxos(amount, selection_criteria, fee_per_gram, 1, metadata_byte_size) .await?; let offset = PrivateKey::random(&mut OsRng); @@ -1051,8 +1053,8 @@ where async fn create_pay_to_self_containing_outputs( &mut self, outputs: Vec, - fee_per_gram: MicroTari, selection_criteria: UtxoSelectionCriteria, + fee_per_gram: MicroTari, ) -> Result<(TxId, Transaction), OutputManagerError> { let total_value = outputs.iter().map(|o| o.value()).sum(); let nop_script = script![Nop]; @@ -1069,10 +1071,10 @@ where let input_selection = self .select_utxos( total_value, + selection_criteria, fee_per_gram, outputs.len(), metadata_byte_size, - selection_criteria, ) .await?; let offset = PrivateKey::random(&mut OsRng); @@ -1208,7 +1210,7 @@ where &mut self, tx_id: TxId, amount: MicroTari, - utxo_selection: UtxoSelectionCriteria, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, fee_per_gram: MicroTari, lock_height: Option, @@ -1227,7 +1229,7 @@ where ); let input_selection = self - .select_utxos(amount, fee_per_gram, 1, metadata_byte_size, utxo_selection) + .select_utxos(amount, selection_criteria, fee_per_gram, 1, metadata_byte_size) .await?; let offset = PrivateKey::random(&mut OsRng); @@ -1387,10 +1389,10 @@ where async fn select_utxos( &mut self, amount: MicroTari, + mut selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, num_outputs: usize, total_output_metadata_byte_size: usize, - mut selection_criteria: UtxoSelectionCriteria, ) -> Result { debug!( target: LOG_TARGET, @@ -1644,10 +1646,10 @@ where let selection = self .select_utxos( amount_per_split * MicroTari(number_of_splits as u64), + UtxoSelectionCriteria::largest_first(), fee_per_gram, number_of_splits, self.default_metadata_size() * number_of_splits, - UtxoSelectionCriteria::largest_first(), ) .await?; diff --git a/base_layer/wallet/src/transaction_service/handle.rs b/base_layer/wallet/src/transaction_service/handle.rs index 9a68c97690..fda68fc370 100644 --- a/base_layer/wallet/src/transaction_service/handle.rs +++ b/base_layer/wallet/src/transaction_service/handle.rs @@ -48,6 +48,7 @@ use tokio::sync::broadcast; use tower::Service; use crate::{ + output_manager_service::UtxoSelectionCriteria, transaction_service::{ error::TransactionServiceError, storage::models::{ @@ -76,18 +77,21 @@ pub enum TransactionServiceRequest { SendTransaction { dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: Box, fee_per_gram: MicroTari, message: String, }, BurnTari { amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, message: String, }, SendOneSidedTransaction { dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: Box, fee_per_gram: MicroTari, message: String, @@ -95,11 +99,12 @@ pub enum TransactionServiceRequest { SendOneSidedToStealthAddressTransaction { dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: Box, fee_per_gram: MicroTari, message: String, }, - SendShaAtomicSwapTransaction(CommsPublicKey, MicroTari, MicroTari, String), + SendShaAtomicSwapTransaction(CommsPublicKey, MicroTari, UtxoSelectionCriteria, MicroTari, String), CancelTransaction(TxId), ImportUtxoWithStatus { amount: MicroTari, @@ -173,7 +178,7 @@ impl fmt::Display for TransactionServiceRequest { amount, message )), - Self::SendShaAtomicSwapTransaction(k, v, _, msg) => { + Self::SendShaAtomicSwapTransaction(k, _, v, _, msg) => { f.write_str(&format!("SendShaAtomicSwapTransaction (to {}, {}, {})", k, v, msg)) }, Self::CancelTransaction(t) => f.write_str(&format!("CancelTransaction ({})", t)), @@ -428,6 +433,7 @@ impl TransactionServiceHandle { &mut self, dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, fee_per_gram: MicroTari, message: String, @@ -437,6 +443,7 @@ impl TransactionServiceHandle { .call(TransactionServiceRequest::SendTransaction { dest_pubkey, amount, + selection_criteria, output_features: Box::new(output_features), fee_per_gram, message, @@ -452,6 +459,7 @@ impl TransactionServiceHandle { &mut self, dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, fee_per_gram: MicroTari, message: String, @@ -461,6 +469,7 @@ impl TransactionServiceHandle { .call(TransactionServiceRequest::SendOneSidedTransaction { dest_pubkey, amount, + selection_criteria, output_features: Box::new(output_features), fee_per_gram, message, @@ -476,6 +485,7 @@ impl TransactionServiceHandle { pub async fn burn_tari( &mut self, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, message: String, ) -> Result { @@ -483,6 +493,7 @@ impl TransactionServiceHandle { .handle .call(TransactionServiceRequest::BurnTari { amount, + selection_criteria, fee_per_gram, message, }) @@ -497,6 +508,7 @@ impl TransactionServiceHandle { &mut self, dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, fee_per_gram: MicroTari, message: String, @@ -506,6 +518,7 @@ impl TransactionServiceHandle { .call(TransactionServiceRequest::SendOneSidedToStealthAddressTransaction { dest_pubkey, amount, + selection_criteria, output_features: Box::new(output_features), fee_per_gram, message, @@ -810,6 +823,7 @@ impl TransactionServiceHandle { &mut self, dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, message: String, ) -> Result<(TxId, PublicKey, TransactionOutput), TransactionServiceError> { @@ -818,6 +832,7 @@ impl TransactionServiceHandle { .call(TransactionServiceRequest::SendShaAtomicSwapTransaction( dest_pubkey, amount, + selection_criteria, fee_per_gram, message, )) diff --git a/base_layer/wallet/src/transaction_service/service.rs b/base_layer/wallet/src/transaction_service/service.rs index bba16e7217..a159e800a3 100644 --- a/base_layer/wallet/src/transaction_service/service.rs +++ b/base_layer/wallet/src/transaction_service/service.rs @@ -573,6 +573,7 @@ where TransactionServiceRequest::SendTransaction { dest_pubkey, amount, + selection_criteria, output_features, fee_per_gram, message, @@ -581,6 +582,7 @@ where self.send_transaction( dest_pubkey, amount, + selection_criteria, *output_features, fee_per_gram, message, @@ -595,6 +597,7 @@ where TransactionServiceRequest::SendOneSidedTransaction { dest_pubkey, amount, + selection_criteria, output_features, fee_per_gram, message, @@ -602,6 +605,7 @@ where .send_one_sided_transaction( dest_pubkey, amount, + selection_criteria, *output_features, fee_per_gram, message, @@ -612,6 +616,7 @@ where TransactionServiceRequest::SendOneSidedToStealthAddressTransaction { dest_pubkey, amount, + selection_criteria, output_features, fee_per_gram, message, @@ -619,6 +624,7 @@ where .send_one_sided_to_stealth_address_transaction( dest_pubkey, amount, + selection_criteria, *output_features, fee_per_gram, message, @@ -628,24 +634,36 @@ where .map(TransactionServiceResponse::TransactionSent), TransactionServiceRequest::BurnTari { amount, + selection_criteria, fee_per_gram, message, } => self - .burn_tari(amount, fee_per_gram, message, transaction_broadcast_join_handles) + .burn_tari( + amount, + selection_criteria, + fee_per_gram, + message, + transaction_broadcast_join_handles, + ) .await .map(TransactionServiceResponse::TransactionSent), - TransactionServiceRequest::SendShaAtomicSwapTransaction(dest_pubkey, amount, fee_per_gram, message) => { - Ok(TransactionServiceResponse::ShaAtomicSwapTransactionSent( - self.send_sha_atomic_swap_transaction( - dest_pubkey, - amount, - fee_per_gram, - message, - transaction_broadcast_join_handles, - ) - .await?, - )) - }, + TransactionServiceRequest::SendShaAtomicSwapTransaction( + dest_pubkey, + amount, + selection_criteria, + fee_per_gram, + message, + ) => Ok(TransactionServiceResponse::ShaAtomicSwapTransactionSent( + self.send_sha_atomic_swap_transaction( + dest_pubkey, + amount, + selection_criteria, + fee_per_gram, + message, + transaction_broadcast_join_handles, + ) + .await?, + )), TransactionServiceRequest::CancelTransaction(tx_id) => self .cancel_pending_transaction(tx_id) .await @@ -869,6 +887,7 @@ where &mut self, dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, fee_per_gram: MicroTari, message: String, @@ -895,8 +914,7 @@ where .create_pay_to_self_transaction( tx_id, amount, - // TODO: allow customization of selected inputs and outputs - UtxoSelectionCriteria::default(), + selection_criteria, output_features, fee_per_gram, None, @@ -976,6 +994,7 @@ where &mut self, dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, message: String, transaction_broadcast_join_handles: &mut FuturesUnordered< @@ -1011,7 +1030,7 @@ where .prepare_transaction_to_send( tx_id, amount, - UtxoSelectionCriteria::default(), + selection_criteria, OutputFeatures::default(), fee_per_gram, TransactionMetadata::default(), @@ -1156,6 +1175,7 @@ where &mut self, dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, fee_per_gram: MicroTari, message: String, @@ -1172,7 +1192,7 @@ where .prepare_transaction_to_send( tx_id, amount, - UtxoSelectionCriteria::default(), + selection_criteria, output_features, fee_per_gram, TransactionMetadata::default(), @@ -1290,6 +1310,7 @@ where &mut self, dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, fee_per_gram: MicroTari, message: String, @@ -1306,6 +1327,7 @@ where self.send_one_sided_or_stealth( dest_pubkey.clone(), amount, + selection_criteria, output_features, fee_per_gram, message, @@ -1322,6 +1344,7 @@ where pub async fn burn_tari( &mut self, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, message: String, transaction_broadcast_join_handles: &mut FuturesUnordered< @@ -1337,7 +1360,7 @@ where .prepare_transaction_to_send( tx_id, amount, - UtxoSelectionCriteria::default(), + selection_criteria, output_features, fee_per_gram, tx_meta, @@ -1435,6 +1458,7 @@ where &mut self, dest_pubkey: CommsPublicKey, amount: MicroTari, + selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, fee_per_gram: MicroTari, message: String, @@ -1461,6 +1485,7 @@ where self.send_one_sided_or_stealth( dest_pubkey, amount, + selection_criteria, output_features, fee_per_gram, message, diff --git a/base_layer/wallet/tests/output_manager_service_tests/service.rs b/base_layer/wallet/tests/output_manager_service_tests/service.rs index 43b64159bd..e7dd4237d3 100644 --- a/base_layer/wallet/tests/output_manager_service_tests/service.rs +++ b/base_layer/wallet/tests/output_manager_service_tests/service.rs @@ -353,7 +353,13 @@ async fn fee_estimate() { let fee_per_gram = MicroTari::from(1); let fee = oms .output_manager_handle - .fee_estimate(MicroTari::from(100), fee_per_gram, 1, 1) + .fee_estimate( + MicroTari::from(100), + UtxoSelectionCriteria::default(), + fee_per_gram, + 1, + 1, + ) .await .unwrap(); assert_eq!( @@ -365,7 +371,13 @@ async fn fee_estimate() { for outputs in 1..5 { let fee = oms .output_manager_handle - .fee_estimate(MicroTari::from(100), fee_per_gram, 1, outputs) + .fee_estimate( + MicroTari::from(100), + UtxoSelectionCriteria::default(), + fee_per_gram, + 1, + outputs, + ) .await .unwrap(); @@ -384,7 +396,13 @@ async fn fee_estimate() { // not enough funds let err = oms .output_manager_handle - .fee_estimate(MicroTari::from(2750), fee_per_gram, 1, 1) + .fee_estimate( + MicroTari::from(2750), + UtxoSelectionCriteria::default(), + fee_per_gram, + 1, + 1, + ) .await .unwrap_err(); assert!(matches!(err, OutputManagerError::NotEnoughFunds)); @@ -468,7 +486,10 @@ async fn test_utxo_selection_no_chain_metadata() { } // test that we can get a fee estimate with no chain metadata - let fee = oms.fee_estimate(amount, fee_per_gram, 1, 2).await.unwrap(); + let fee = oms + .fee_estimate(amount, UtxoSelectionCriteria::default(), fee_per_gram, 1, 2) + .await + .unwrap(); let expected_fee = fee_calc.calculate(fee_per_gram, 1, 1, 3, default_metadata_byte_size() * 3); assert_eq!(fee, expected_fee); @@ -477,14 +498,17 @@ async fn test_utxo_selection_no_chain_metadata() { // so instead of returning "not enough funds".to_string(), return "funds pending" let spendable_amount = (3..=10).sum::() * amount; let err = oms - .fee_estimate(spendable_amount, fee_per_gram, 1, 2) + .fee_estimate(spendable_amount, UtxoSelectionCriteria::default(), fee_per_gram, 1, 2) .await .unwrap_err(); assert!(matches!(err, OutputManagerError::FundsPending)); // test not enough funds let broke_amount = spendable_amount + MicroTari::from(2000); - let err = oms.fee_estimate(broke_amount, fee_per_gram, 1, 2).await.unwrap_err(); + let err = oms + .fee_estimate(broke_amount, UtxoSelectionCriteria::default(), fee_per_gram, 1, 2) + .await + .unwrap_err(); assert!(matches!(err, OutputManagerError::NotEnoughFunds)); // coin split uses the "Largest" selection strategy @@ -559,7 +583,10 @@ async fn test_utxo_selection_with_chain_metadata() { assert_eq!(utxos.len(), 10); // test fee estimates - let fee = oms.fee_estimate(amount, fee_per_gram, 1, 2).await.unwrap(); + let fee = oms + .fee_estimate(amount, UtxoSelectionCriteria::default(), fee_per_gram, 1, 2) + .await + .unwrap(); let expected_fee = fee_calc.calculate(fee_per_gram, 1, 2, 3, default_metadata_byte_size() * 3); assert_eq!(fee, expected_fee); @@ -567,7 +594,7 @@ async fn test_utxo_selection_with_chain_metadata() { // even though we have utxos for the fee, they can't be spent because they are not mature yet let spendable_amount = (1..=6).sum::() * amount; let err = oms - .fee_estimate(spendable_amount, fee_per_gram, 1, 2) + .fee_estimate(spendable_amount, UtxoSelectionCriteria::default(), fee_per_gram, 1, 2) .await .unwrap_err(); assert!(matches!(err, OutputManagerError::NotEnoughFunds)); diff --git a/base_layer/wallet/tests/transaction_service_tests/service.rs b/base_layer/wallet/tests/transaction_service_tests/service.rs index faa064a0af..a03dcf9a28 100644 --- a/base_layer/wallet/tests/transaction_service_tests/service.rs +++ b/base_layer/wallet/tests/transaction_service_tests/service.rs @@ -522,6 +522,7 @@ async fn manage_single_transaction() { .send_transaction( bob_node_identity.public_key().clone(), value, + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(4), "".to_string() @@ -535,6 +536,7 @@ async fn manage_single_transaction() { .send_transaction( bob_node_identity.public_key().clone(), value, + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(4), message, @@ -641,6 +643,7 @@ async fn single_transaction_to_self() { .send_transaction( alice_node_identity.public_key().clone(), value, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 20.into(), message.clone(), @@ -724,6 +727,7 @@ async fn send_one_sided_transaction_to_other() { .send_one_sided_transaction( bob_node_identity.public_key().clone(), value, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 20.into(), message.clone(), @@ -849,6 +853,7 @@ async fn recover_one_sided_transaction() { .send_one_sided_transaction( bob_node_identity.public_key().clone(), value, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 20.into(), message.clone(), @@ -940,7 +945,13 @@ async fn test_htlc_send_and_claim() { let mut alice_ts_clone = alice_ts.clone(); let bob_pubkey = bob_ts_interface.base_node_identity.public_key().clone(); let (tx_id, pre_image, output) = alice_ts_clone - .send_sha_atomic_swap_transaction(bob_pubkey, value, 20.into(), message.clone()) + .send_sha_atomic_swap_transaction( + bob_pubkey, + value, + UtxoSelectionCriteria::default(), + 20.into(), + message.clone(), + ) .await .expect("Alice sending HTLC transaction"); @@ -1049,6 +1060,7 @@ async fn send_one_sided_transaction_to_self() { .send_one_sided_transaction( alice_node_identity.public_key().clone(), value, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 20.into(), message.clone(), @@ -1187,6 +1199,7 @@ async fn manage_multiple_transactions() { .send_transaction( bob_node_identity.public_key().clone(), value_a_to_b_1, + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(20), "a to b 1".to_string(), @@ -1199,6 +1212,7 @@ async fn manage_multiple_transactions() { .send_transaction( carol_node_identity.public_key().clone(), value_a_to_c_1, + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(20), "a to c 1".to_string(), @@ -1213,6 +1227,7 @@ async fn manage_multiple_transactions() { .send_transaction( alice_node_identity.public_key().clone(), value_b_to_a_1, + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(20), "b to a 1".to_string(), @@ -1223,6 +1238,7 @@ async fn manage_multiple_transactions() { .send_transaction( bob_node_identity.public_key().clone(), value_a_to_b_2, + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(20), "a to b 2".to_string(), @@ -1349,6 +1365,7 @@ async fn test_accepting_unknown_tx_id_and_malformed_reply() { .send_transaction( bob_node_identity.public_key().clone(), MicroTari::from(5000), + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(20), "".to_string(), @@ -1732,6 +1749,7 @@ async fn discovery_async_return_test() { .send_transaction( bob_node_identity.public_key().clone(), value_a_to_c_1, + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(20), "Discovery Tx!".to_string(), @@ -1768,6 +1786,7 @@ async fn discovery_async_return_test() { .send_transaction( carol_node_identity.public_key().clone(), value_a_to_c_1, + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(20), "Discovery Tx2!".to_string(), @@ -2037,6 +2056,7 @@ async fn test_transaction_cancellation() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 100 * uT, "Testing Message".to_string(), @@ -2358,6 +2378,7 @@ async fn test_direct_vs_saf_send_of_tx_reply_and_finalize() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 100 * uT, "Testing Message".to_string(), @@ -2542,6 +2563,7 @@ async fn test_direct_vs_saf_send_of_tx_reply_and_finalize() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 100 * uT, "Testing Message".to_string(), @@ -2674,6 +2696,7 @@ async fn test_tx_direct_send_behaviour() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 100 * uT, "Testing Message1".to_string(), @@ -2717,6 +2740,7 @@ async fn test_tx_direct_send_behaviour() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 100 * uT, "Testing Message2".to_string(), @@ -2765,6 +2789,7 @@ async fn test_tx_direct_send_behaviour() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 100 * uT, "Testing Message3".to_string(), @@ -2813,6 +2838,7 @@ async fn test_tx_direct_send_behaviour() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 100 * uT, "Testing Message4".to_string(), @@ -4054,6 +4080,7 @@ async fn test_transaction_resending() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 100 * uT, "Testing Message".to_string(), @@ -4541,6 +4568,7 @@ async fn test_replying_to_cancelled_tx() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 100 * uT, "Testing Message".to_string(), @@ -4663,6 +4691,7 @@ async fn test_transaction_timeout_cancellation() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 20 * uT, "Testing Message".to_string(), @@ -4917,6 +4946,7 @@ async fn transaction_service_tx_broadcast() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent1, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 100 * uT, "Testing Message".to_string(), @@ -4977,6 +5007,7 @@ async fn transaction_service_tx_broadcast() { .send_transaction( bob_node_identity.public_key().clone(), amount_sent2, + UtxoSelectionCriteria::default(), OutputFeatures::default(), 20 * uT, "Testing Message2".to_string(), diff --git a/base_layer/wallet/tests/wallet.rs b/base_layer/wallet/tests/wallet.rs index e75d5dd0f9..9206f435fe 100644 --- a/base_layer/wallet/tests/wallet.rs +++ b/base_layer/wallet/tests/wallet.rs @@ -95,7 +95,7 @@ use tempfile::tempdir; use tokio::{sync::mpsc, time::sleep}; pub mod support; -use tari_wallet::output_manager_service::storage::database::OutputManagerDatabase; +use tari_wallet::output_manager_service::{storage::database::OutputManagerDatabase, UtxoSelectionCriteria}; fn create_peer(public_key: CommsPublicKey, net_address: Multiaddr) -> Peer { Peer::new( @@ -274,6 +274,7 @@ async fn test_wallet() { .send_transaction( bob_identity.public_key().clone(), value, + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(5), "".to_string(), @@ -589,6 +590,7 @@ async fn test_store_and_forward_send_tx() { .send_transaction( carol_identity.public_key().clone(), value, + UtxoSelectionCriteria::default(), OutputFeatures::default(), MicroTari::from(3), "Store and Forward!".to_string(), diff --git a/base_layer/wallet_ffi/src/lib.rs b/base_layer/wallet_ffi/src/lib.rs index 436b8608b9..5ec00576ca 100644 --- a/base_layer/wallet_ffi/src/lib.rs +++ b/base_layer/wallet_ffi/src/lib.rs @@ -135,6 +135,7 @@ use tari_wallet::{ models::DbUnblindedOutput, OutputStatus, }, + UtxoSelectionCriteria, }, storage::{ database::WalletDatabase, @@ -2243,6 +2244,7 @@ pub unsafe extern "C" fn liveness_data_get_message_type( /// | 0 | Online | /// | 1 | Offline | /// | 2 | NeverSeen | +/// | 3 | Banned | /// /// # Safety /// The ```liveness_data_destroy``` method must be called when finished with a TariContactsLivenessData to prevent a @@ -5395,6 +5397,8 @@ pub unsafe extern "C" fn balance_destroy(balance: *mut TariBalance) { /// `wallet` - The TariWallet pointer /// `dest_public_key` - The TariPublicKey pointer of the peer /// `amount` - The amount +/// `commitments` - A `TariVector` of "strings", tagged as `TariTypeTag::String`, containing commitment's hex values +/// (see `Commitment::to_hex()`) /// `fee_per_gram` - The transaction fee /// `message` - The pointer to a char array /// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions @@ -5410,6 +5414,7 @@ pub unsafe extern "C" fn wallet_send_transaction( wallet: *mut TariWallet, dest_public_key: *mut TariPublicKey, amount: c_ulonglong, + commitments: *mut TariVector, fee_per_gram: c_ulonglong, message: *const c_char, one_sided: bool, @@ -5429,6 +5434,18 @@ pub unsafe extern "C" fn wallet_send_transaction( return 0; } + let selection_criteria = match commitments.as_ref() { + None => UtxoSelectionCriteria::default(), + Some(cs) => match cs.to_commitment_vec() { + Ok(cs) => UtxoSelectionCriteria::specific(cs), + Err(e) => { + error!(target: LOG_TARGET, "failed to convert from tari vector: {:?}", e); + ptr::replace(error_out, LibWalletError::from(e).code as c_int); + return 0; + }, + }, + }; + let message_string; if message.is_null() { error = LibWalletError::from(InterfaceError::NullError("message".to_string())).code; @@ -5463,6 +5480,7 @@ pub unsafe extern "C" fn wallet_send_transaction( .send_one_sided_to_stealth_address_transaction( (*dest_public_key).clone(), MicroTari::from(amount), + selection_criteria, OutputFeatures::default(), MicroTari::from(fee_per_gram), message_string, @@ -5481,6 +5499,7 @@ pub unsafe extern "C" fn wallet_send_transaction( .block_on((*wallet).wallet.transaction_service.send_transaction( (*dest_public_key).clone(), MicroTari::from(amount), + selection_criteria, OutputFeatures::default(), MicroTari::from(fee_per_gram), message_string, @@ -5500,6 +5519,8 @@ pub unsafe extern "C" fn wallet_send_transaction( /// ## Arguments /// `wallet` - The TariWallet pointer /// `amount` - The amount +/// `commitments` - A `TariVector` of "strings", tagged as `TariTypeTag::String`, containing commitment's hex values +/// (see `Commitment::to_hex()`) /// `fee_per_gram` - The fee per gram /// `num_kernels` - The number of transaction kernels /// `num_outputs` - The number of outputs @@ -5515,6 +5536,7 @@ pub unsafe extern "C" fn wallet_send_transaction( pub unsafe extern "C" fn wallet_get_fee_estimate( wallet: *mut TariWallet, amount: c_ulonglong, + commitments: *mut TariVector, fee_per_gram: c_ulonglong, num_kernels: c_ulonglong, num_outputs: c_ulonglong, @@ -5528,10 +5550,23 @@ pub unsafe extern "C" fn wallet_get_fee_estimate( return 0; } + let selection_criteria = match commitments.as_ref() { + None => UtxoSelectionCriteria::default(), + Some(cs) => match cs.to_commitment_vec() { + Ok(cs) => UtxoSelectionCriteria::specific(cs), + Err(e) => { + error!(target: LOG_TARGET, "failed to convert from tari vector: {:?}", e); + ptr::replace(error_out, LibWalletError::from(e).code as c_int); + return 0; + }, + }, + }; + match (*wallet) .runtime .block_on((*wallet).wallet.output_manager_service.fee_estimate( MicroTari::from(amount), + selection_criteria, MicroTari::from(fee_per_gram), num_kernels as usize, num_outputs as usize, diff --git a/base_layer/wallet_ffi/wallet.h b/base_layer/wallet_ffi/wallet.h index cf3b054424..362d617c7d 100644 --- a/base_layer/wallet_ffi/wallet.h +++ b/base_layer/wallet_ffi/wallet.h @@ -1258,6 +1258,7 @@ int liveness_data_get_message_type(TariContactsLivenessData *liveness_data, * | 0 | Online | * | 1 | Offline | * | 2 | NeverSeen | + * | 3 | Banned | * * # Safety * The ```liveness_data_destroy``` method must be called when finished with a TariContactsLivenessData to prevent a @@ -2652,6 +2653,8 @@ void balance_destroy(TariBalance *balance); * `wallet` - The TariWallet pointer * `dest_public_key` - The TariPublicKey pointer of the peer * `amount` - The amount + * `commitments` - A `TariVector` of "strings", tagged as `TariTypeTag::String`, containing commitment's hex values + * (see `Commitment::to_hex()`) * `fee_per_gram` - The transaction fee * `message` - The pointer to a char array * `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions @@ -2666,6 +2669,7 @@ void balance_destroy(TariBalance *balance); unsigned long long wallet_send_transaction(struct TariWallet *wallet, TariPublicKey *dest_public_key, unsigned long long amount, + struct TariVector *commitments, unsigned long long fee_per_gram, const char *message, bool one_sided, @@ -2677,6 +2681,8 @@ unsigned long long wallet_send_transaction(struct TariWallet *wallet, * ## Arguments * `wallet` - The TariWallet pointer * `amount` - The amount + * `commitments` - A `TariVector` of "strings", tagged as `TariTypeTag::String`, containing commitment's hex values + * (see `Commitment::to_hex()`) * `fee_per_gram` - The fee per gram * `num_kernels` - The number of transaction kernels * `num_outputs` - The number of outputs @@ -2691,6 +2697,7 @@ unsigned long long wallet_send_transaction(struct TariWallet *wallet, */ unsigned long long wallet_get_fee_estimate(struct TariWallet *wallet, unsigned long long amount, + struct TariVector *commitments, unsigned long long fee_per_gram, unsigned long long num_kernels, unsigned long long num_outputs, diff --git a/integration_tests/helpers/ffi/ffiInterface.js b/integration_tests/helpers/ffi/ffiInterface.js index 51b75cb814..475908159b 100644 --- a/integration_tests/helpers/ffi/ffiInterface.js +++ b/integration_tests/helpers/ffi/ffiInterface.js @@ -361,6 +361,7 @@ class InterfaceFFI { this.ptr, this.ptr, this.ulonglong, + this.ptr, this.ulonglong, this.string, this.bool, @@ -1460,6 +1461,7 @@ class InterfaceFFI { ptr, destination, amount, + null, fee_per_gram, message, one_sided,