From 4714a0386a1ac637fdcad2e3f2fd76fa652c133a Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Tue, 17 Jan 2023 14:49:52 +0200 Subject: [PATCH 1/4] add tx_id_to export --- .../src/automation/commands.rs | 2 + .../src/grpc/wallet_grpc_server.rs | 2 +- .../src/output_manager_service/handle.rs | 4 +- .../src/output_manager_service/service.rs | 8 +- .../storage/database/mod.rs | 7 +- .../storage/sqlite_db/mod.rs | 12 +- .../wallet/src/storage/sqlite_db/wallet.rs | 2 +- .../output_manager_service_tests/service.rs | 14 +- base_layer/wallet_ffi/src/lib.rs | 137 +++++++++++++++++- base_layer/wallet_ffi/wallet.h | 55 +++++++ 10 files changed, 221 insertions(+), 22 deletions(-) diff --git a/applications/tari_console_wallet/src/automation/commands.rs b/applications/tari_console_wallet/src/automation/commands.rs index ff69a0ee4c..a90ff3ac3b 100644 --- a/applications/tari_console_wallet/src/automation/commands.rs +++ b/applications/tari_console_wallet/src/automation/commands.rs @@ -765,6 +765,7 @@ pub async fn command_runner( }, ExportUtxos(args) => match output_service.get_unspent_outputs().await { Ok(utxos) => { + let utxos: Vec = utxos.into_iter().map(|v| v.0).collect(); let count = utxos.len(); let sum: MicroTari = utxos.iter().map(|utxo| utxo.value).sum(); if let Some(file) = args.output_file { @@ -801,6 +802,7 @@ pub async fn command_runner( }, CountUtxos => match output_service.get_unspent_outputs().await { Ok(utxos) => { + let utxos: Vec = utxos.into_iter().map(|v| v.0).collect(); let count = utxos.len(); let values: Vec = utxos.iter().map(|utxo| utxo.value).collect(); let sum: MicroTari = values.iter().sum(); 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 c3b5c1b3dd..5be7985081 100644 --- a/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs +++ b/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs @@ -274,7 +274,7 @@ impl wallet_server::Wallet for WalletGrpcServer { Ok(Response::new(GetUnspentAmountsResponse { amount: unspent_amounts .into_iter() - .map(|o| o.value.as_u64()) + .map(|o| o.0.value.as_u64()) .filter(|&a| a > 0) .collect(), })) diff --git a/base_layer/wallet/src/output_manager_service/handle.rs b/base_layer/wallet/src/output_manager_service/handle.rs index cac04bbdad..13db403255 100644 --- a/base_layer/wallet/src/output_manager_service/handle.rs +++ b/base_layer/wallet/src/output_manager_service/handle.rs @@ -252,7 +252,7 @@ pub enum OutputManagerResponse { TransactionToSend(SenderTransactionProtocol), TransactionCancelled, SpentOutputs(Vec), - UnspentOutputs(Vec), + UnspentOutputs(Vec<(UnblindedOutput, u64)>), Outputs(Vec), InvalidOutputs(Vec), BaseNodePublicKeySet, @@ -625,7 +625,7 @@ impl OutputManagerHandle { } /// Sorted from lowest value to highest - pub async fn get_unspent_outputs(&mut self) -> Result, OutputManagerError> { + pub async fn get_unspent_outputs(&mut self) -> Result, OutputManagerError> { match self.handle.call(OutputManagerRequest::GetUnspentOutputs).await?? { OutputManagerResponse::UnspentOutputs(s) => Ok(s), _ => Err(OutputManagerError::UnexpectedApiResponse), diff --git a/base_layer/wallet/src/output_manager_service/service.rs b/base_layer/wallet/src/output_manager_service/service.rs index 7499735f93..f628fe910e 100644 --- a/base_layer/wallet/src/output_manager_service/service.rs +++ b/base_layer/wallet/src/output_manager_service/service.rs @@ -351,7 +351,11 @@ where Ok(OutputManagerResponse::SpentOutputs(outputs)) }, OutputManagerRequest::GetUnspentOutputs => { - let outputs = self.fetch_unspent_outputs()?.into_iter().map(|v| v.into()).collect(); + let outputs = self + .fetch_unspent_outputs()? + .into_iter() + .map(|(output, tx_id)| (output.into(), tx_id)) + .collect(); Ok(OutputManagerResponse::UnspentOutputs(outputs)) }, OutputManagerRequest::GetOutputsBy(q) => { @@ -1533,7 +1537,7 @@ where Ok(self.resources.db.fetch_spent_outputs()?) } - pub fn fetch_unspent_outputs(&self) -> Result, OutputManagerError> { + pub fn fetch_unspent_outputs(&self) -> Result, OutputManagerError> { Ok(self.resources.db.fetch_all_unspent_outputs()?) } diff --git a/base_layer/wallet/src/output_manager_service/storage/database/mod.rs b/base_layer/wallet/src/output_manager_service/storage/database/mod.rs index fcfd689bca..1741557a4b 100644 --- a/base_layer/wallet/src/output_manager_service/storage/database/mod.rs +++ b/base_layer/wallet/src/output_manager_service/storage/database/mod.rs @@ -99,7 +99,7 @@ pub enum DbKey { pub enum DbValue { SpentOutput(Box), UnspentOutput(Box), - UnspentOutputs(Vec), + UnspentOutputs(Vec<(DbUnblindedOutput, u64)>), SpentOutputs(Vec), InvalidOutputs(Vec), KnownOneSidedPaymentScripts(Vec), @@ -218,7 +218,7 @@ where T: OutputManagerBackend + 'static self.db.cancel_pending_transaction(tx_id) } - pub fn fetch_all_unspent_outputs(&self) -> Result, OutputManagerStorageError> { + pub fn fetch_all_unspent_outputs(&self) -> Result, OutputManagerStorageError> { let result = match self.db.fetch(&DbKey::UnspentOutputs)? { Some(DbValue::UnspentOutputs(outputs)) => outputs, Some(other) => return unexpected_result(DbKey::UnspentOutputs, other), @@ -300,7 +300,8 @@ where T: OutputManagerBackend + 'static Ok(Some(other)) => unexpected_result(DbKey::UnspentOutputs, other), Err(e) => log_error(DbKey::UnspentOutputs, e), }?; - Ok(uo) + let outputs = uo.into_iter().map(|(output, _)| (output)).collect(); + Ok(outputs) } pub fn get_invalid_outputs(&self) -> Result, OutputManagerStorageError> { diff --git a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs index 9144c889c1..591d5d8715 100644 --- a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs +++ b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs @@ -202,7 +202,11 @@ impl OutputManagerBackend for OutputManagerSqliteDatabase { Some(DbValue::UnspentOutputs( outputs .iter() - .map(|o| o.clone().to_db_unblinded_output(&cipher)) + .map(|o| { + o.clone() + .to_db_unblinded_output(&cipher) + .map(|v| (v, o.received_in_tx_id.unwrap_or_default() as u64)) + }) .collect::, _>>()?, )) }, @@ -222,7 +226,11 @@ impl OutputManagerBackend for OutputManagerSqliteDatabase { Some(DbValue::UnspentOutputs( outputs .iter() - .map(|o| o.clone().to_db_unblinded_output(&cipher)) + .map(|o| { + o.clone() + .to_db_unblinded_output(&cipher) + .map(|v| (v, o.received_in_tx_id.unwrap_or_default() as u64)) + }) .collect::, _>>()?, )) }, diff --git a/base_layer/wallet/src/storage/sqlite_db/wallet.rs b/base_layer/wallet/src/storage/sqlite_db/wallet.rs index 935a266d11..805878814d 100644 --- a/base_layer/wallet/src/storage/sqlite_db/wallet.rs +++ b/base_layer/wallet/src/storage/sqlite_db/wallet.rs @@ -866,7 +866,7 @@ mod test { let value2 = "value2".to_string(); let passphrase = "a very very secret key example.".to_string().into(); - let db = WalletSqliteDatabase::new(connection.clone(), passphrase).unwrap(); + let db = WalletSqliteDatabase::new(connection, passphrase).unwrap(); let cipher = db.cipher(); ClientKeyValueSql::new(key1.clone(), value1.clone(), &cipher) 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 97384f27dd..f48752923f 100644 --- a/base_layer/wallet/tests/output_manager_service_tests/service.rs +++ b/base_layer/wallet/tests/output_manager_service_tests/service.rs @@ -495,8 +495,8 @@ async fn test_utxo_selection_no_chain_metadata() { assert_eq!(utxos.len(), 8); for (index, utxo) in utxos.iter().enumerate() { let i = index as u64 + 3; - assert_eq!(utxo.features.maturity, i); - assert_eq!(utxo.value, i * amount); + assert_eq!(utxo.0.features.maturity, i); + assert_eq!(utxo.0.value, i * amount); } // test that we can get a fee estimate with no chain metadata @@ -530,7 +530,7 @@ async fn test_utxo_selection_no_chain_metadata() { // test that largest utxo was encumbered let utxos = oms.get_unspent_outputs().await.unwrap(); assert_eq!(utxos.len(), 7); - for (index, utxo) in utxos.iter().enumerate() { + for (index, (utxo, _)) in utxos.iter().enumerate() { let i = index as u64 + 3; assert_eq!(utxo.features.maturity, i); assert_eq!(utxo.value, i * amount); @@ -621,7 +621,7 @@ async fn test_utxo_selection_with_chain_metadata() { // test that largest spendable utxo was encumbered let utxos = oms.get_unspent_outputs().await.unwrap(); assert_eq!(utxos.len(), 9); - let found = utxos.iter().any(|u| u.value == 6 * amount); + let found = utxos.iter().any(|u| u.0.value == 6 * amount); assert!(!found, "An unspendable utxo was selected"); // test transactions @@ -645,7 +645,7 @@ async fn test_utxo_selection_with_chain_metadata() { // test that utxos with the lowest 2 maturities were encumbered let utxos = oms.get_unspent_outputs().await.unwrap(); assert_eq!(utxos.len(), 7); - for utxo in &utxos { + for (utxo, _) in &utxos { assert_ne!(utxo.features.maturity, 1); assert_ne!(utxo.value, amount); assert_ne!(utxo.features.maturity, 2); @@ -673,7 +673,7 @@ async fn test_utxo_selection_with_chain_metadata() { // test that utxos with the highest spendable 2 maturities were encumbered let utxos = oms.get_unspent_outputs().await.unwrap(); assert_eq!(utxos.len(), 5); - for utxo in &utxos { + for (utxo, _) in &utxos { assert_ne!(utxo.features.maturity, 4); assert_ne!(utxo.value, 4 * amount); assert_ne!(utxo.features.maturity, 5); @@ -752,7 +752,7 @@ async fn test_utxo_selection_with_tx_priority() { let utxos = oms.get_unspent_outputs().await.unwrap(); assert_eq!(utxos.len(), 1); - assert_ne!(utxos[0].features.output_type, OutputType::Coinbase); + assert_ne!(utxos[0].0.features.output_type, OutputType::Coinbase); } #[tokio::test] diff --git a/base_layer/wallet_ffi/src/lib.rs b/base_layer/wallet_ffi/src/lib.rs index d16d221a1c..7eedb49aa9 100644 --- a/base_layer/wallet_ffi/src/lib.rs +++ b/base_layer/wallet_ffi/src/lib.rs @@ -203,7 +203,7 @@ pub type TariEncryptedValue = tari_core::transactions::transaction_components::E pub type TariComAndPubSignature = tari_common_types::types::ComAndPubSignature; pub type TariUnblindedOutput = tari_core::transactions::transaction_components::UnblindedOutput; -pub struct TariUnblindedOutputs(Vec); +pub struct TariUnblindedOutputs(Vec<(TariUnblindedOutput, u64)>); pub struct TariContacts(Vec); @@ -1613,10 +1613,10 @@ pub unsafe extern "C" fn tari_unblinded_output_to_json( ptr::swap(error_out, &mut error as *mut c_int); } else { match serde_json::to_string(&*output) { - Ok(json_string) => match CString::new(json_string.to_string()) { + Ok(json_string) => match CString::new(json_string) { Ok(v) => hex_bytes = v, _ => { - error = LibWalletError::from(InterfaceError::PointerError("contact".to_string())).code; + error = LibWalletError::from(InterfaceError::PointerError("output".to_string())).code; ptr::swap(error_out, &mut error as *mut c_int); }, }, @@ -1747,7 +1747,43 @@ pub unsafe extern "C" fn unblinded_outputs_get_at( ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } - Box::into_raw(Box::new((*outputs).0[position as usize].clone())) + Box::into_raw(Box::new((*outputs).0[position as usize].0.clone())) +} + +/// Gets a TariUnblindedOutput from TariUnblindedOutputs at position +/// +/// ## Arguments +/// `outputs` - The pointer to a TariUnblindedOutputs +/// `position` - The integer position +/// `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 TariUnblindedOutput` - Returns a TariUnblindedOutput, note that it returns ptr::null_mut() if +/// TariUnblindedOutputs is null or position is invalid +/// +/// # Safety +/// The ```contact_destroy``` method must be called when finished with a TariContact to prevent a memory leak +#[no_mangle] +pub unsafe extern "C" fn unblinded_outputs_tx_id_get_at( + outputs: *mut TariUnblindedOutputs, + position: c_uint, + error_out: *mut c_int, +) -> *mut c_ulonglong { + let mut error = 0; + ptr::swap(error_out, &mut error as *mut c_int); + if outputs.is_null() { + error = LibWalletError::from(InterfaceError::NullError("outputs".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + } + let len = unblinded_outputs_get_length(outputs, error_out) as c_int - 1; + if len < 0 || position > len as c_uint { + error = LibWalletError::from(InterfaceError::PositionInvalidError).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + } + Box::into_raw(Box::new((*outputs).0[position as usize].1)) } /// Frees memory for a TariUnblindedOutputs @@ -3679,6 +3715,99 @@ pub unsafe extern "C" fn completed_transaction_get_cancellation_reason( } } +/// returns the TariCompletedTransaction as a json string +/// +/// ## Arguments +/// `tx` - The pointer to a TariCompletedTransaction +/// +/// ## Returns +/// `*mut c_char` - Returns a pointer to a char array. Note that it returns an empty char array if +/// TariCompletedTransaction is null or the position is invalid +/// +/// # Safety +/// The ```completed_transaction_destroy``` function must be called when finished with a TariCompletedTransaction to +/// prevent a memory leak +#[no_mangle] +pub unsafe extern "C" fn tari_completed_transaction_to_json( + tx: *mut TariCompletedTransaction, + error_out: *mut c_int, +) -> *mut c_char { + let mut error = 0; + ptr::swap(error_out, &mut error as *mut c_int); + let mut hex_bytes = CString::new("").expect("Blank CString will not fail."); + if tx.is_null() { + error = LibWalletError::from(InterfaceError::NullError("transaction".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + } else { + match serde_json::to_string(&*tx) { + Ok(json_string) => match CString::new(json_string) { + Ok(v) => hex_bytes = v, + _ => { + error = LibWalletError::from(InterfaceError::PointerError("transaction".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + }, + }, + Err(_) => { + error = LibWalletError::from(HexError::HexConversionError).code; + ptr::swap(error_out, &mut error as *mut c_int); + }, + } + } + CString::into_raw(hex_bytes) +} + +/// Creates a TariUnblindedOutput from a char array +/// +/// ## Arguments +/// `tx_json` - The pointer to a char array which is json of the TariCompletedTransaction +/// `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 TariCompletedTransaction` - Returns a pointer to a TariCompletedTransaction. Note that it returns +/// ptr::null_mut() if key is null or if there was an error creating the TariCompletedTransaction from key +/// +/// # Safety +/// The ```completed_transaction_destroy``` function must be called when finished with a TariCompletedTransaction to +// /// prevent a memory leak +#[no_mangle] +pub unsafe extern "C" fn create_tari_completed_transaction_from_json( + tx_json: *const c_char, + error_out: *mut c_int, +) -> *mut TariCompletedTransaction { + let mut error = 0; + ptr::swap(error_out, &mut error as *mut c_int); + let tx_json_str; + if tx_json.is_null() { + error = LibWalletError::from(InterfaceError::NullError("tx_json".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + } else { + match CStr::from_ptr(tx_json).to_str() { + Ok(v) => { + tx_json_str = v.to_owned(); + }, + _ => { + error = LibWalletError::from(InterfaceError::PointerError("tx_json".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + }, + }; + } + let tx: Result = serde_json::from_str(&tx_json_str); + + match tx { + Ok(tx) => Box::into_raw(Box::new(tx)), + Err(e) => { + error!(target: LOG_TARGET, "Error creating a transaction from json: {:?}", e); + + error = LibWalletError::from(HexError::HexConversionError).code; + ptr::swap(error_out, &mut error as *mut c_int); + ptr::null_mut() + }, + } +} + /// Frees memory for a TariCompletedTransaction /// /// ## Arguments diff --git a/base_layer/wallet_ffi/wallet.h b/base_layer/wallet_ffi/wallet.h index 8b180c1c57..0fba497067 100644 --- a/base_layer/wallet_ffi/wallet.h +++ b/base_layer/wallet_ffi/wallet.h @@ -944,6 +944,26 @@ TariUnblindedOutput *unblinded_outputs_get_at(struct TariUnblindedOutputs *outpu unsigned int position, int *error_out); +/** + * Gets a TariUnblindedOutput from TariUnblindedOutputs at position + * + * ## Arguments + * `outputs` - The pointer to a TariUnblindedOutputs + * `position` - The integer position + * `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 TariUnblindedOutput` - Returns a TariUnblindedOutput, note that it returns ptr::null_mut() if + * TariUnblindedOutputs is null or position is invalid + * + * # Safety + * The ```contact_destroy``` method must be called when finished with a TariContact to prevent a memory leak + */ +unsigned long long *unblinded_outputs_tx_id_get_at(struct TariUnblindedOutputs *outputs, + unsigned int position, + int *error_out); + /** * Frees memory for a TariUnblindedOutputs * @@ -1972,6 +1992,41 @@ unsigned long long completed_transaction_get_confirmations(TariCompletedTransact int completed_transaction_get_cancellation_reason(TariCompletedTransaction *tx, int *error_out); +/** + * returns the TariCompletedTransaction as a json string + * + * ## Arguments + * `tx` - The pointer to a TariCompletedTransaction + * + * ## Returns + * `*mut c_char` - Returns a pointer to a char array. Note that it returns an empty char array if + * TariCompletedTransaction is null or the position is invalid + * + * # Safety + * The ```completed_transaction_destroy``` function must be called when finished with a TariCompletedTransaction to + * prevent a memory leak + */ +char *tari_completed_transaction_to_json(TariCompletedTransaction *tx, + int *error_out); + +/** + * Creates a TariUnblindedOutput from a char array + * + * ## Arguments + * `tx_json` - The pointer to a char array which is json of the TariCompletedTransaction + * `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 TariCompletedTransaction` - Returns a pointer to a TariCompletedTransaction. Note that it returns ptr::null_mut() + * if key is null or if there was an error creating the TariCompletedTransaction from key + * + * # Safety + * The ```completed_transaction_destroy``` function must be called when finished with a TariCompletedTransaction to + */ +TariCompletedTransaction *create_tari_completed_transaction_from_json(const char *tx_json, + int *error_out); + /** * Frees memory for a TariCompletedTransaction * From 3ebb47bbb3747a8e48528268f71217db8b906c0a Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Wed, 18 Jan 2023 11:48:23 +0200 Subject: [PATCH 2/4] code review changes --- .../src/automation/commands.rs | 4 +- .../src/grpc/wallet_grpc_server.rs | 2 +- .../src/output_manager_service/handle.rs | 6 +-- .../recovery/standard_outputs_recoverer.rs | 2 + .../src/output_manager_service/service.rs | 47 +++++++++++++++---- .../storage/database/mod.rs | 7 ++- .../output_manager_service/storage/models.rs | 15 +++++- .../storage/sqlite_db/mod.rs | 12 +---- .../storage/sqlite_db/output_sql.rs | 2 + base_layer/wallet_ffi/src/lib.rs | 13 +++-- base_layer/wallet_ffi/wallet.h | 10 ++-- 11 files changed, 81 insertions(+), 39 deletions(-) diff --git a/applications/tari_console_wallet/src/automation/commands.rs b/applications/tari_console_wallet/src/automation/commands.rs index a90ff3ac3b..e10468eaae 100644 --- a/applications/tari_console_wallet/src/automation/commands.rs +++ b/applications/tari_console_wallet/src/automation/commands.rs @@ -765,7 +765,7 @@ pub async fn command_runner( }, ExportUtxos(args) => match output_service.get_unspent_outputs().await { Ok(utxos) => { - let utxos: Vec = utxos.into_iter().map(|v| v.0).collect(); + let utxos: Vec = utxos.into_iter().map(|v| v.unblinded_output).collect(); let count = utxos.len(); let sum: MicroTari = utxos.iter().map(|utxo| utxo.value).sum(); if let Some(file) = args.output_file { @@ -802,7 +802,7 @@ pub async fn command_runner( }, CountUtxos => match output_service.get_unspent_outputs().await { Ok(utxos) => { - let utxos: Vec = utxos.into_iter().map(|v| v.0).collect(); + let utxos: Vec = utxos.into_iter().map(|v| v.unblinded_output).collect(); let count = utxos.len(); let values: Vec = utxos.iter().map(|utxo| utxo.value).collect(); let sum: MicroTari = values.iter().sum(); 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 5be7985081..ce9427df1c 100644 --- a/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs +++ b/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs @@ -274,7 +274,7 @@ impl wallet_server::Wallet for WalletGrpcServer { Ok(Response::new(GetUnspentAmountsResponse { amount: unspent_amounts .into_iter() - .map(|o| o.0.value.as_u64()) + .map(|o| o.unblinded_output.value.as_u64()) .filter(|&a| a > 0) .collect(), })) diff --git a/base_layer/wallet/src/output_manager_service/handle.rs b/base_layer/wallet/src/output_manager_service/handle.rs index 13db403255..4a6624b2f0 100644 --- a/base_layer/wallet/src/output_manager_service/handle.rs +++ b/base_layer/wallet/src/output_manager_service/handle.rs @@ -53,7 +53,7 @@ use crate::output_manager_service::{ service::{Balance, OutputStatusesByTxId}, storage::{ database::OutputBackendQuery, - models::{KnownOneSidedPaymentScript, SpendingPriority}, + models::{DbUnblindedOutput, KnownOneSidedPaymentScript, SpendingPriority}, }, UtxoSelectionCriteria, }; @@ -252,7 +252,7 @@ pub enum OutputManagerResponse { TransactionToSend(SenderTransactionProtocol), TransactionCancelled, SpentOutputs(Vec), - UnspentOutputs(Vec<(UnblindedOutput, u64)>), + UnspentOutputs(Vec), Outputs(Vec), InvalidOutputs(Vec), BaseNodePublicKeySet, @@ -625,7 +625,7 @@ impl OutputManagerHandle { } /// Sorted from lowest value to highest - pub async fn get_unspent_outputs(&mut self) -> Result, OutputManagerError> { + pub async fn get_unspent_outputs(&mut self) -> Result, OutputManagerError> { match self.handle.call(OutputManagerRequest::GetUnspentOutputs).await?? { OutputManagerResponse::UnspentOutputs(s) => Ok(s), _ => Err(OutputManagerError::UnexpectedApiResponse), diff --git a/base_layer/wallet/src/output_manager_service/recovery/standard_outputs_recoverer.rs b/base_layer/wallet/src/output_manager_service/recovery/standard_outputs_recoverer.rs index 00d81a9334..27215a546c 100644 --- a/base_layer/wallet/src/output_manager_service/recovery/standard_outputs_recoverer.rs +++ b/base_layer/wallet/src/output_manager_service/recovery/standard_outputs_recoverer.rs @@ -161,6 +161,8 @@ where None, Some(proof), output_source, + None, + None, )?; let tx_id = TxId::new_random(); let output_hex = db_output.commitment.to_hex(); diff --git a/base_layer/wallet/src/output_manager_service/service.rs b/base_layer/wallet/src/output_manager_service/service.rs index f628fe910e..01da07f21b 100644 --- a/base_layer/wallet/src/output_manager_service/service.rs +++ b/base_layer/wallet/src/output_manager_service/service.rs @@ -351,11 +351,7 @@ where Ok(OutputManagerResponse::SpentOutputs(outputs)) }, OutputManagerRequest::GetUnspentOutputs => { - let outputs = self - .fetch_unspent_outputs()? - .into_iter() - .map(|(output, tx_id)| (output.into(), tx_id)) - .collect(); + let outputs = self.fetch_unspent_outputs()?; Ok(OutputManagerResponse::UnspentOutputs(outputs)) }, OutputManagerRequest::GetOutputsBy(q) => { @@ -654,6 +650,8 @@ where &self.resources.factories, spend_priority, OutputSource::default(), + tx_id, + None, )?; debug!( target: LOG_TARGET, @@ -692,6 +690,8 @@ where spend_priority, None, OutputSource::default(), + tx_id, + None, )?; debug!( target: LOG_TARGET, @@ -732,6 +732,8 @@ where &self.resources.factories, spend_priority, OutputSource::default(), + Some(tx_id), + None, )?; self.resources.db.add_unvalidated_output(tx_id, output)?; @@ -848,6 +850,8 @@ where None, None, OutputSource::default(), + Some(single_round_sender_data.tx_id), + None, )?; self.resources @@ -1050,6 +1054,8 @@ where None, None, OutputSource::default(), + Some(tx_id), + None, )?); } @@ -1114,6 +1120,8 @@ where None, None, OutputSource::Coinbase, + Some(tx_id), + None, )?; // If there is no existing output available, we store the one we produced. @@ -1207,13 +1215,15 @@ where None, None, OutputSource::default(), + None, + None, )?) } let mut stp = builder .build(&self.resources.factories, None, u64::MAX) .map_err(|e| OutputManagerError::BuildError(e.message))?; - + let tx_id = stp.get_tx_id()?; if let Some(unblinded_output) = stp.get_change_unblinded_output()? { db_outputs.push(DbUnblindedOutput::rewindable_from_unblinded_output( unblinded_output, @@ -1222,9 +1232,10 @@ where None, None, OutputSource::default(), + Some(tx_id), + None, )?); } - let tx_id = stp.get_tx_id()?; self.resources .db @@ -1329,6 +1340,8 @@ where None, None, OutputSource::default(), + Some(tx_id), + None, )?; builder .with_output(utxo.unblinded_output.clone(), sender_offset_private_key.clone()) @@ -1369,6 +1382,8 @@ where None, None, OutputSource::default(), + Some(tx_id), + None, )?; outputs.push(change_output); } @@ -1537,7 +1552,7 @@ where Ok(self.resources.db.fetch_spent_outputs()?) } - pub fn fetch_unspent_outputs(&self) -> Result, OutputManagerError> { + pub fn fetch_unspent_outputs(&self) -> Result, OutputManagerError> { Ok(self.resources.db.fetch_all_unspent_outputs()?) } @@ -1824,6 +1839,8 @@ where None, None, OutputSource::default(), + None, + None, )?; tx_builder @@ -2043,6 +2060,8 @@ where None, None, OutputSource::default(), + None, + None, )?; tx_builder @@ -2101,6 +2120,8 @@ where None, None, OutputSource::default(), + Some(tx_id), + None, )?); } @@ -2250,6 +2271,8 @@ where None, None, OutputSource::default(), + None, + None, )?; tx_builder @@ -2412,6 +2435,8 @@ where None, None, OutputSource::AtomicSwap, + Some(tx_id), + None, )?; outputs.push(change_output); @@ -2499,6 +2524,8 @@ where None, None, OutputSource::Refund, + Some(tx_id), + None, )?; outputs.push(change_output); @@ -2649,6 +2676,7 @@ where output.minimum_value_promise, ); + let tx_id = TxId::new_random(); let db_output = DbUnblindedOutput::rewindable_from_unblinded_output( rewound_output.clone(), &self.resources.factories, @@ -2659,10 +2687,11 @@ where None, Some(&output.proof), output_source, + Some(tx_id), + None, )?; let output_hex = output.commitment.to_hex(); - let tx_id = TxId::new_random(); match self.resources.db.add_unspent_output_with_tx_id(tx_id, db_output) { Ok(_) => { diff --git a/base_layer/wallet/src/output_manager_service/storage/database/mod.rs b/base_layer/wallet/src/output_manager_service/storage/database/mod.rs index 1741557a4b..fcfd689bca 100644 --- a/base_layer/wallet/src/output_manager_service/storage/database/mod.rs +++ b/base_layer/wallet/src/output_manager_service/storage/database/mod.rs @@ -99,7 +99,7 @@ pub enum DbKey { pub enum DbValue { SpentOutput(Box), UnspentOutput(Box), - UnspentOutputs(Vec<(DbUnblindedOutput, u64)>), + UnspentOutputs(Vec), SpentOutputs(Vec), InvalidOutputs(Vec), KnownOneSidedPaymentScripts(Vec), @@ -218,7 +218,7 @@ where T: OutputManagerBackend + 'static self.db.cancel_pending_transaction(tx_id) } - pub fn fetch_all_unspent_outputs(&self) -> Result, OutputManagerStorageError> { + pub fn fetch_all_unspent_outputs(&self) -> Result, OutputManagerStorageError> { let result = match self.db.fetch(&DbKey::UnspentOutputs)? { Some(DbValue::UnspentOutputs(outputs)) => outputs, Some(other) => return unexpected_result(DbKey::UnspentOutputs, other), @@ -300,8 +300,7 @@ where T: OutputManagerBackend + 'static Ok(Some(other)) => unexpected_result(DbKey::UnspentOutputs, other), Err(e) => log_error(DbKey::UnspentOutputs, e), }?; - let outputs = uo.into_iter().map(|(output, _)| (output)).collect(); - Ok(outputs) + Ok(uo) } pub fn get_invalid_outputs(&self) -> Result, OutputManagerStorageError> { diff --git a/base_layer/wallet/src/output_manager_service/storage/models.rs b/base_layer/wallet/src/output_manager_service/storage/models.rs index 45ad665a7d..16ee1e0c4c 100644 --- a/base_layer/wallet/src/output_manager_service/storage/models.rs +++ b/base_layer/wallet/src/output_manager_service/storage/models.rs @@ -24,7 +24,10 @@ use std::cmp::Ordering; use chrono::NaiveDateTime; use derivative::Derivative; -use tari_common_types::types::{BlockHash, BulletRangeProof, Commitment, HashOutput, PrivateKey}; +use tari_common_types::{ + transaction::TxId, + types::{BlockHash, BulletRangeProof, Commitment, HashOutput, PrivateKey}, +}; use tari_core::transactions::{ transaction_components::UnblindedOutput, transaction_protocol::RewindData, @@ -51,6 +54,8 @@ pub struct DbUnblindedOutput { pub marked_deleted_in_block: Option, pub spending_priority: SpendingPriority, pub source: OutputSource, + pub received_in_tx_id: Option, + pub spent_in_tx_id: Option, } impl DbUnblindedOutput { @@ -59,6 +64,8 @@ impl DbUnblindedOutput { factory: &CryptoFactories, spend_priority: Option, source: OutputSource, + received_in_tx_id: Option, + spent_in_tx_id: Option, ) -> Result { let tx_out = output.as_transaction_output(factory)?; Ok(DbUnblindedOutput { @@ -74,6 +81,8 @@ impl DbUnblindedOutput { marked_deleted_in_block: None, spending_priority: spend_priority.unwrap_or(SpendingPriority::Normal), source, + received_in_tx_id, + spent_in_tx_id, }) } @@ -84,6 +93,8 @@ impl DbUnblindedOutput { spending_priority: Option, proof: Option<&BulletRangeProof>, source: OutputSource, + received_in_tx_id: Option, + spent_in_tx_id: Option, ) -> Result { let tx_out = output.as_rewindable_transaction_output(factory, rewind_data, proof)?; Ok(DbUnblindedOutput { @@ -99,6 +110,8 @@ impl DbUnblindedOutput { marked_deleted_in_block: None, spending_priority: spending_priority.unwrap_or(SpendingPriority::Normal), source, + received_in_tx_id, + spent_in_tx_id, }) } } diff --git a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs index 591d5d8715..9144c889c1 100644 --- a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs +++ b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs @@ -202,11 +202,7 @@ impl OutputManagerBackend for OutputManagerSqliteDatabase { Some(DbValue::UnspentOutputs( outputs .iter() - .map(|o| { - o.clone() - .to_db_unblinded_output(&cipher) - .map(|v| (v, o.received_in_tx_id.unwrap_or_default() as u64)) - }) + .map(|o| o.clone().to_db_unblinded_output(&cipher)) .collect::, _>>()?, )) }, @@ -226,11 +222,7 @@ impl OutputManagerBackend for OutputManagerSqliteDatabase { Some(DbValue::UnspentOutputs( outputs .iter() - .map(|o| { - o.clone() - .to_db_unblinded_output(&cipher) - .map(|v| (v, o.received_in_tx_id.unwrap_or_default() as u64)) - }) + .map(|o| o.clone().to_db_unblinded_output(&cipher)) .collect::, _>>()?, )) }, diff --git a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/output_sql.rs b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/output_sql.rs index def955fc6a..b0a60d4552 100644 --- a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/output_sql.rs +++ b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/output_sql.rs @@ -795,6 +795,8 @@ impl OutputSql { marked_deleted_in_block, spending_priority, source: o.source.try_into()?, + received_in_tx_id: o.received_in_tx_id.map(|d| (d as u64).into()), + spent_in_tx_id: o.spent_in_tx_id.map(|d| (d as u64).into()), }) } } diff --git a/base_layer/wallet_ffi/src/lib.rs b/base_layer/wallet_ffi/src/lib.rs index 7eedb49aa9..fd8e83431f 100644 --- a/base_layer/wallet_ffi/src/lib.rs +++ b/base_layer/wallet_ffi/src/lib.rs @@ -203,7 +203,7 @@ pub type TariEncryptedValue = tari_core::transactions::transaction_components::E pub type TariComAndPubSignature = tari_common_types::types::ComAndPubSignature; pub type TariUnblindedOutput = tari_core::transactions::transaction_components::UnblindedOutput; -pub struct TariUnblindedOutputs(Vec<(TariUnblindedOutput, u64)>); +pub struct TariUnblindedOutputs(Vec); pub struct TariContacts(Vec); @@ -1747,7 +1747,7 @@ pub unsafe extern "C" fn unblinded_outputs_get_at( ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } - Box::into_raw(Box::new((*outputs).0[position as usize].0.clone())) + Box::into_raw(Box::new((*outputs).0[position as usize].unblinded_output.clone())) } /// Gets a TariUnblindedOutput from TariUnblindedOutputs at position @@ -1765,7 +1765,7 @@ pub unsafe extern "C" fn unblinded_outputs_get_at( /// # Safety /// The ```contact_destroy``` method must be called when finished with a TariContact to prevent a memory leak #[no_mangle] -pub unsafe extern "C" fn unblinded_outputs_tx_id_get_at( +pub unsafe extern "C" fn unblinded_outputs_received_tx_id_get_at( outputs: *mut TariUnblindedOutputs, position: c_uint, error_out: *mut c_int, @@ -1783,7 +1783,12 @@ pub unsafe extern "C" fn unblinded_outputs_tx_id_get_at( ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } - Box::into_raw(Box::new((*outputs).0[position as usize].1)) + Box::into_raw(Box::new( + (*outputs).0[position as usize] + .received_in_tx_id + .unwrap_or_default() + .as_u64(), + )) } /// Frees memory for a TariUnblindedOutputs diff --git a/base_layer/wallet_ffi/wallet.h b/base_layer/wallet_ffi/wallet.h index 0fba497067..573ad59ba3 100644 --- a/base_layer/wallet_ffi/wallet.h +++ b/base_layer/wallet_ffi/wallet.h @@ -960,9 +960,9 @@ TariUnblindedOutput *unblinded_outputs_get_at(struct TariUnblindedOutputs *outpu * # Safety * The ```contact_destroy``` method must be called when finished with a TariContact to prevent a memory leak */ -unsigned long long *unblinded_outputs_tx_id_get_at(struct TariUnblindedOutputs *outputs, - unsigned int position, - int *error_out); +unsigned long long *unblinded_outputs_received_tx_id_get_at(struct TariUnblindedOutputs *outputs, + unsigned int position, + int *error_out); /** * Frees memory for a TariUnblindedOutputs @@ -2018,8 +2018,8 @@ char *tari_completed_transaction_to_json(TariCompletedTransaction *tx, * as an out parameter. * * ## Returns - * `*mut TariCompletedTransaction` - Returns a pointer to a TariCompletedTransaction. Note that it returns ptr::null_mut() - * if key is null or if there was an error creating the TariCompletedTransaction from key + * `*mut TariCompletedTransaction` - Returns a pointer to a TariCompletedTransaction. Note that it returns + * ptr::null_mut() if key is null or if there was an error creating the TariCompletedTransaction from key * * # Safety * The ```completed_transaction_destroy``` function must be called when finished with a TariCompletedTransaction to From df14afa314419e37155c11d29159aaee10861cd7 Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Wed, 18 Jan 2023 12:18:54 +0200 Subject: [PATCH 3/4] fix tests --- .../storage/sqlite_db/mod.rs | 6 ++-- .../output_manager_service_tests/service.rs | 34 +++++++++---------- .../output_manager_service_tests/storage.rs | 14 ++++---- base_layer/wallet/tests/utxo_scanner.rs | 12 +++---- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs index 9144c889c1..c3cb0a20d9 100644 --- a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs +++ b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs @@ -1439,7 +1439,7 @@ mod test { for _i in 0..2 { let (_, uo) = make_input(MicroTari::from(100 + OsRng.next_u64() % 1000)); - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); let o = NewOutputSql::new(uo, OutputStatus::Unspent, None, None, &cipher).unwrap(); outputs.push(o.clone()); outputs_unspent.push(o.clone()); @@ -1448,7 +1448,7 @@ mod test { for _i in 0..3 { let (_, uo) = make_input(MicroTari::from(100 + OsRng.next_u64() % 1000)); - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); let o = NewOutputSql::new(uo, OutputStatus::Spent, None, None, &cipher).unwrap(); outputs.push(o.clone()); outputs_spent.push(o.clone()); @@ -1556,7 +1556,7 @@ mod test { let (_, uo) = make_input(MicroTari::from(100 + OsRng.next_u64() % 1000)); let decrypted_spending_key = uo.spending_key.to_vec(); - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); let output = NewOutputSql::new(uo, OutputStatus::Unspent, None, None, &cipher).unwrap(); 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 f48752923f..e3922727d8 100644 --- a/base_layer/wallet/tests/output_manager_service_tests/service.rs +++ b/base_layer/wallet/tests/output_manager_service_tests/service.rs @@ -495,8 +495,8 @@ async fn test_utxo_selection_no_chain_metadata() { assert_eq!(utxos.len(), 8); for (index, utxo) in utxos.iter().enumerate() { let i = index as u64 + 3; - assert_eq!(utxo.0.features.maturity, i); - assert_eq!(utxo.0.value, i * amount); + assert_eq!(utxo.unblinded_output.features.maturity, i); + assert_eq!(utxo.unblinded_output.value, i * amount); } // test that we can get a fee estimate with no chain metadata @@ -530,10 +530,10 @@ async fn test_utxo_selection_no_chain_metadata() { // test that largest utxo was encumbered let utxos = oms.get_unspent_outputs().await.unwrap(); assert_eq!(utxos.len(), 7); - for (index, (utxo, _)) in utxos.iter().enumerate() { + for (index, utxo) in utxos.iter().enumerate() { let i = index as u64 + 3; - assert_eq!(utxo.features.maturity, i); - assert_eq!(utxo.value, i * amount); + assert_eq!(utxo.unblinded_output.features.maturity, i); + assert_eq!(utxo.unblinded_output.value, i * amount); } } @@ -621,7 +621,7 @@ async fn test_utxo_selection_with_chain_metadata() { // test that largest spendable utxo was encumbered let utxos = oms.get_unspent_outputs().await.unwrap(); assert_eq!(utxos.len(), 9); - let found = utxos.iter().any(|u| u.0.value == 6 * amount); + let found = utxos.iter().any(|u| u.unblinded_output.value == 6 * amount); assert!(!found, "An unspendable utxo was selected"); // test transactions @@ -645,11 +645,11 @@ async fn test_utxo_selection_with_chain_metadata() { // test that utxos with the lowest 2 maturities were encumbered let utxos = oms.get_unspent_outputs().await.unwrap(); assert_eq!(utxos.len(), 7); - for (utxo, _) in &utxos { - assert_ne!(utxo.features.maturity, 1); - assert_ne!(utxo.value, amount); - assert_ne!(utxo.features.maturity, 2); - assert_ne!(utxo.value, 2 * amount); + for utxo in &utxos { + assert_ne!(utxo.unblinded_output.features.maturity, 1); + assert_ne!(utxo.unblinded_output.value, amount); + assert_ne!(utxo.unblinded_output.features.maturity, 2); + assert_ne!(utxo.unblinded_output.value, 2 * amount); } // when the amount is greater than the largest utxo, then "Largest" selection strategy is used @@ -673,11 +673,11 @@ async fn test_utxo_selection_with_chain_metadata() { // test that utxos with the highest spendable 2 maturities were encumbered let utxos = oms.get_unspent_outputs().await.unwrap(); assert_eq!(utxos.len(), 5); - for (utxo, _) in &utxos { - assert_ne!(utxo.features.maturity, 4); - assert_ne!(utxo.value, 4 * amount); - assert_ne!(utxo.features.maturity, 5); - assert_ne!(utxo.value, 5 * amount); + for utxo in &utxos { + assert_ne!(utxo.unblinded_output.features.maturity, 4); + assert_ne!(utxo.unblinded_output.value, 4 * amount); + assert_ne!(utxo.unblinded_output.features.maturity, 5); + assert_ne!(utxo.unblinded_output.value, 5 * amount); } } @@ -752,7 +752,7 @@ async fn test_utxo_selection_with_tx_priority() { let utxos = oms.get_unspent_outputs().await.unwrap(); assert_eq!(utxos.len(), 1); - assert_ne!(utxos[0].0.features.output_type, OutputType::Coinbase); + assert_ne!(utxos[0].unblinded_output.features.output_type, OutputType::Coinbase); } #[tokio::test] diff --git a/base_layer/wallet/tests/output_manager_service_tests/storage.rs b/base_layer/wallet/tests/output_manager_service_tests/storage.rs index cbec793036..82a200e720 100644 --- a/base_layer/wallet/tests/output_manager_service_tests/storage.rs +++ b/base_layer/wallet/tests/output_manager_service_tests/storage.rs @@ -55,7 +55,7 @@ pub fn test_db_backend(backend: T) { MicroTari::from(100 + OsRng.next_u64() % 1000), &factories.commitment, )); - let mut uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap(); + let mut uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); uo.unblinded_output.features.maturity = i; db.add_unspent_output(uo.clone()).unwrap(); unspent_outputs.push(uo); @@ -102,7 +102,7 @@ pub fn test_db_backend(backend: T) { MicroTari::from(100 + OsRng.next_u64() % 1000), &factories.commitment, )); - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); db.add_unspent_output(uo.clone()).unwrap(); pending_tx.outputs_to_be_spent.push(uo); } @@ -112,7 +112,7 @@ pub fn test_db_backend(backend: T) { MicroTari::from(100 + OsRng.next_u64() % 1000), &factories.commitment, )); - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); pending_tx.outputs_to_be_received.push(uo); } db.encumber_outputs( @@ -248,7 +248,7 @@ pub fn test_db_backend(backend: T) { &factories.commitment, )); let output_to_be_received = - DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap(); + DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); db.add_output_to_be_received(TxId::from(11u64), output_to_be_received.clone(), None) .unwrap(); pending_incoming_balance += output_to_be_received.unblinded_output.value; @@ -360,7 +360,7 @@ pub async fn test_short_term_encumberance() { &factories.commitment, ) .await; - let mut uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap(); + let mut uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); uo.unblinded_output.features.maturity = i; db.add_unspent_output(uo.clone()).unwrap(); unspent_outputs.push(uo); @@ -417,7 +417,7 @@ pub async fn test_no_duplicate_outputs() { // create an output let (_ti, uo) = make_input(&mut OsRng, MicroTari::from(1000), &factories.commitment).await; - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); // add it to the database let result = db.add_unspent_output(uo.clone()); @@ -457,7 +457,7 @@ pub async fn test_mark_as_unmined() { // create an output let (_ti, uo) = make_input(&mut OsRng, MicroTari::from(1000), &factories.commitment).await; - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); // add it to the database db.add_unspent_output(uo.clone()).unwrap(); diff --git a/base_layer/wallet/tests/utxo_scanner.rs b/base_layer/wallet/tests/utxo_scanner.rs index ddca1f3151..57496ee24d 100644 --- a/base_layer/wallet/tests/utxo_scanner.rs +++ b/base_layer/wallet/tests/utxo_scanner.rs @@ -325,7 +325,7 @@ async fn test_utxo_scanner_recovery() { let mut total_amount_to_recover = MicroTari::from(0); for (h, outputs) in &unblinded_outputs { for output in outputs.iter().skip(outputs.len() / 2) { - let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown) + let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown, None, None) .unwrap(); // Only the outputs in blocks after the birthday should be included in the recovered total if *h >= NUM_BLOCKS.saturating_sub(BIRTHDAY_OFFSET).saturating_sub(2) { @@ -417,7 +417,7 @@ async fn test_utxo_scanner_recovery_with_restart() { let mut total_amount_to_recover = MicroTari::from(0); for (h, outputs) in &unblinded_outputs { for output in outputs.iter().skip(outputs.len() / 2) { - let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown) + let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown, None, None) .unwrap(); // Only the outputs in blocks after the birthday should be included in the recovered total if *h >= NUM_BLOCKS.saturating_sub(BIRTHDAY_OFFSET).saturating_sub(2) { @@ -573,7 +573,7 @@ async fn test_utxo_scanner_recovery_with_restart_and_reorg() { let mut db_unblinded_outputs = Vec::new(); for outputs in unblinded_outputs.values() { for output in outputs.iter().skip(outputs.len() / 2) { - let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown) + let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown, None, None) .unwrap(); db_unblinded_outputs.push(dbo); } @@ -642,7 +642,7 @@ async fn test_utxo_scanner_recovery_with_restart_and_reorg() { let mut total_amount_to_recover = MicroTari::from(0); for (h, outputs) in &unblinded_outputs { for output in outputs.iter().skip(outputs.len() / 2) { - let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown) + let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown, None, None) .unwrap(); // Only the outputs in blocks after the birthday should be included in the recovered total if *h >= 4 { @@ -847,7 +847,7 @@ async fn test_utxo_scanner_one_sided_payments() { let mut total_amount_to_recover = MicroTari::from(0); for (h, outputs) in &unblinded_outputs { for output in outputs.iter().skip(outputs.len() / 2) { - let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown) + let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown, None, None) .unwrap(); // Only the outputs in blocks after the birthday should be included in the recovered total if *h >= NUM_BLOCKS.saturating_sub(BIRTHDAY_OFFSET).saturating_sub(2) { @@ -922,7 +922,7 @@ async fn test_utxo_scanner_one_sided_payments() { block_headers.insert(NUM_BLOCKS, block_header11); db_unblinded_outputs - .push(DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown).unwrap()); + .push(DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap()); test_interface .oms_mock_state .set_one_sided_payments(db_unblinded_outputs); From 96a871353f1ec7e19b952f64cd3e063f6476d00d Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Wed, 18 Jan 2023 18:04:06 +0200 Subject: [PATCH 4/4] fmt --- .../storage/sqlite_db/mod.rs | 10 +++- .../output_manager_service_tests/storage.rs | 12 ++-- base_layer/wallet/tests/utxo_scanner.rs | 60 +++++++++++++++---- 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs index c3cb0a20d9..1d75bed0af 100644 --- a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs +++ b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs @@ -1412,6 +1412,7 @@ mod test { (input, unblinded_output) } + #[allow(clippy::too_many_lines)] #[test] fn test_crud() { let db_name = format!("{}.sqlite3", random::string(8).as_str()); @@ -1439,7 +1440,8 @@ mod test { for _i in 0..2 { let (_, uo) = make_input(MicroTari::from(100 + OsRng.next_u64() % 1000)); - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None) + .unwrap(); let o = NewOutputSql::new(uo, OutputStatus::Unspent, None, None, &cipher).unwrap(); outputs.push(o.clone()); outputs_unspent.push(o.clone()); @@ -1448,7 +1450,8 @@ mod test { for _i in 0..3 { let (_, uo) = make_input(MicroTari::from(100 + OsRng.next_u64() % 1000)); - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None) + .unwrap(); let o = NewOutputSql::new(uo, OutputStatus::Spent, None, None, &cipher).unwrap(); outputs.push(o.clone()); outputs_spent.push(o.clone()); @@ -1556,7 +1559,8 @@ mod test { let (_, uo) = make_input(MicroTari::from(100 + OsRng.next_u64() % 1000)); let decrypted_spending_key = uo.spending_key.to_vec(); - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); + let uo = + DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); let output = NewOutputSql::new(uo, OutputStatus::Unspent, None, None, &cipher).unwrap(); diff --git a/base_layer/wallet/tests/output_manager_service_tests/storage.rs b/base_layer/wallet/tests/output_manager_service_tests/storage.rs index 82a200e720..80df47485d 100644 --- a/base_layer/wallet/tests/output_manager_service_tests/storage.rs +++ b/base_layer/wallet/tests/output_manager_service_tests/storage.rs @@ -55,7 +55,8 @@ pub fn test_db_backend(backend: T) { MicroTari::from(100 + OsRng.next_u64() % 1000), &factories.commitment, )); - let mut uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); + let mut uo = + DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); uo.unblinded_output.features.maturity = i; db.add_unspent_output(uo.clone()).unwrap(); unspent_outputs.push(uo); @@ -102,7 +103,8 @@ pub fn test_db_backend(backend: T) { MicroTari::from(100 + OsRng.next_u64() % 1000), &factories.commitment, )); - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None) + .unwrap(); db.add_unspent_output(uo.clone()).unwrap(); pending_tx.outputs_to_be_spent.push(uo); } @@ -112,7 +114,8 @@ pub fn test_db_backend(backend: T) { MicroTari::from(100 + OsRng.next_u64() % 1000), &factories.commitment, )); - let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); + let uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None) + .unwrap(); pending_tx.outputs_to_be_received.push(uo); } db.encumber_outputs( @@ -360,7 +363,8 @@ pub async fn test_short_term_encumberance() { &factories.commitment, ) .await; - let mut uo = DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); + let mut uo = + DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(); uo.unblinded_output.features.maturity = i; db.add_unspent_output(uo.clone()).unwrap(); unspent_outputs.push(uo); diff --git a/base_layer/wallet/tests/utxo_scanner.rs b/base_layer/wallet/tests/utxo_scanner.rs index 57496ee24d..05711a13d4 100644 --- a/base_layer/wallet/tests/utxo_scanner.rs +++ b/base_layer/wallet/tests/utxo_scanner.rs @@ -325,8 +325,15 @@ async fn test_utxo_scanner_recovery() { let mut total_amount_to_recover = MicroTari::from(0); for (h, outputs) in &unblinded_outputs { for output in outputs.iter().skip(outputs.len() / 2) { - let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown, None, None) - .unwrap(); + let dbo = DbUnblindedOutput::from_unblinded_output( + output.clone(), + &factories, + None, + OutputSource::Unknown, + None, + None, + ) + .unwrap(); // Only the outputs in blocks after the birthday should be included in the recovered total if *h >= NUM_BLOCKS.saturating_sub(BIRTHDAY_OFFSET).saturating_sub(2) { total_outputs_to_recover += 1; @@ -417,8 +424,15 @@ async fn test_utxo_scanner_recovery_with_restart() { let mut total_amount_to_recover = MicroTari::from(0); for (h, outputs) in &unblinded_outputs { for output in outputs.iter().skip(outputs.len() / 2) { - let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown, None, None) - .unwrap(); + let dbo = DbUnblindedOutput::from_unblinded_output( + output.clone(), + &factories, + None, + OutputSource::Unknown, + None, + None, + ) + .unwrap(); // Only the outputs in blocks after the birthday should be included in the recovered total if *h >= NUM_BLOCKS.saturating_sub(BIRTHDAY_OFFSET).saturating_sub(2) { total_outputs_to_recover += 1; @@ -573,8 +587,15 @@ async fn test_utxo_scanner_recovery_with_restart_and_reorg() { let mut db_unblinded_outputs = Vec::new(); for outputs in unblinded_outputs.values() { for output in outputs.iter().skip(outputs.len() / 2) { - let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown, None, None) - .unwrap(); + let dbo = DbUnblindedOutput::from_unblinded_output( + output.clone(), + &factories, + None, + OutputSource::Unknown, + None, + None, + ) + .unwrap(); db_unblinded_outputs.push(dbo); } } @@ -642,8 +663,15 @@ async fn test_utxo_scanner_recovery_with_restart_and_reorg() { let mut total_amount_to_recover = MicroTari::from(0); for (h, outputs) in &unblinded_outputs { for output in outputs.iter().skip(outputs.len() / 2) { - let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown, None, None) - .unwrap(); + let dbo = DbUnblindedOutput::from_unblinded_output( + output.clone(), + &factories, + None, + OutputSource::Unknown, + None, + None, + ) + .unwrap(); // Only the outputs in blocks after the birthday should be included in the recovered total if *h >= 4 { total_outputs_to_recover += 1; @@ -847,8 +875,15 @@ async fn test_utxo_scanner_one_sided_payments() { let mut total_amount_to_recover = MicroTari::from(0); for (h, outputs) in &unblinded_outputs { for output in outputs.iter().skip(outputs.len() / 2) { - let dbo = DbUnblindedOutput::from_unblinded_output(output.clone(), &factories, None, OutputSource::Unknown, None, None) - .unwrap(); + let dbo = DbUnblindedOutput::from_unblinded_output( + output.clone(), + &factories, + None, + OutputSource::Unknown, + None, + None, + ) + .unwrap(); // Only the outputs in blocks after the birthday should be included in the recovered total if *h >= NUM_BLOCKS.saturating_sub(BIRTHDAY_OFFSET).saturating_sub(2) { total_outputs_to_recover += 1; @@ -921,8 +956,9 @@ async fn test_utxo_scanner_one_sided_payments() { utxos_by_block.push(block11); block_headers.insert(NUM_BLOCKS, block_header11); - db_unblinded_outputs - .push(DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap()); + db_unblinded_outputs.push( + DbUnblindedOutput::from_unblinded_output(uo, &factories, None, OutputSource::Unknown, None, None).unwrap(), + ); test_interface .oms_mock_state .set_one_sided_payments(db_unblinded_outputs);