diff --git a/clients/tests/rust/src/main.rs b/clients/tests/rust/src/main.rs index 79b77d31..90556314 100644 --- a/clients/tests/rust/src/main.rs +++ b/clients/tests/rust/src/main.rs @@ -15,14 +15,14 @@ use anyhow::{Result, Ok}; #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { - /* tb01_simple_transfer::execute().await?; + tb01_simple_transfer::execute().await?; tb02_transfer_address_reuse::execute().await?; tb03_simple_atomic_transfer::execute().await?; tb04_simple_lightning_latch::execute().await?; tm01_sender_double_spends::execute().await?; ta01_sign_second_not_called::execute().await?; ta02_duplicate_deposits::execute().await?; - tv05::execute().await?; */ + tv05::execute().await?; ta03_multiple_deposits::execute().await?; diff --git a/clients/tests/rust/src/ta03_multiple_deposits.rs b/clients/tests/rust/src/ta03_multiple_deposits.rs index e3e10267..7aa7c8ab 100644 --- a/clients/tests/rust/src/ta03_multiple_deposits.rs +++ b/clients/tests/rust/src/ta03_multiple_deposits.rs @@ -2,7 +2,6 @@ use std::{env, process::Command, thread, time::Duration}; use anyhow::{Result, Ok}; use mercuryrustlib::{client_config::ClientConfig, BackupTx, CoinStatus, Wallet}; -use serde_json::json; use crate::{bitcoin_core, electrs}; @@ -85,9 +84,6 @@ async fn basic_workflow(client_config: &ClientConfig, wallet1: &Wallet, wallet2: assert!(duplicated_coin_3.is_some()); let new_coin = new_coin.unwrap(); - // let duplicated_coin_1 = duplicated_coin_1.unwrap(); - // let duplicated_coin_2 = duplicated_coin_2.unwrap(); - // let duplicated_coin_3 = duplicated_coin_3.unwrap(); let statechain_id = new_coin.statechain_id.as_ref().unwrap(); @@ -101,7 +97,6 @@ async fn basic_workflow(client_config: &ClientConfig, wallet1: &Wallet, wallet2: let result = mercuryrustlib::transfer_sender::execute(&client_config, &wallet2_transfer_adress, &wallet1.name, &statechain_id, Some(duplicated_indexes), force_send, batch_id).await; - // result.unwrap(); assert!(result.is_ok()); let wallet1 = mercuryrustlib::sqlite_manager::get_wallet(&client_config.pool, &wallet1.name).await?; @@ -146,38 +141,6 @@ async fn basic_workflow(client_config: &ClientConfig, wallet1: &Wallet, wallet2: validate_backup_transactions(&bk_txs, info_config.interval)?; } - /* println!("Grouped Backup Transactions:"); - - for backup_txs in grouped_backup_transactions.iter() { - for backup_tx in backup_txs.iter() { - let tx_outpoint = mercuryrustlib::get_previous_outpoint(&backup_tx)?; - println!("statechain_id: {}", statechain_id); - println!("txid: {} vout: {}", tx_outpoint.txid, tx_outpoint.vout); - println!("tx_n: {}", backup_tx.tx_n); - // println!("client_public_nonce: {}", backup_tx.client_public_nonce); - // println!("server_public_nonce: {}", backup_tx.server_public_nonce); - // println!("client_public_key: {}", backup_tx.client_public_key); - // println!("server_public_key: {}", backup_tx.server_public_key); - // println!("blinding_factor: {}", backup_tx.blinding_factor); - println!("----------------------"); - } - } */ - - - - - // for backup_tx in backup_transactions.iter() { - // let tx_outpoint = mercuryrustlib::get_previous_outpoint(&backup_tx)?; - // println!("txid: {} vout: {}", tx_outpoint.txid, tx_outpoint.vout); - // println!("tx_n: {}", backup_tx.tx_n); - // println!("client_public_nonce: {}", backup_tx.client_public_nonce); - // println!("server_public_nonce: {}", backup_tx.server_public_nonce); - // println!("client_public_key: {}", backup_tx.client_public_key); - // println!("server_public_key: {}", backup_tx.server_public_key); - // println!("blinding_factor: {}", backup_tx.blinding_factor); - // println!("----------------------"); - // } - let transfer_receive_result = mercuryrustlib::transfer_receiver::execute(&client_config, &wallet2.name).await?; let received_statechain_ids = transfer_receive_result.received_statechain_ids; @@ -363,6 +326,141 @@ async fn resend_workflow(client_config: &ClientConfig, wallet1: &Wallet, wallet2 Ok(()) } +async fn multiple_sends_workflow(client_config: &ClientConfig, wallet1: &Wallet, wallet2: &Wallet, wallet3: &Wallet) -> Result<()> { + + let amount = 1000; + + let token_id = mercuryrustlib::deposit::get_token(client_config).await?; + + let deposit_address = mercuryrustlib::deposit::get_deposit_bitcoin_address(&client_config, &wallet1.name, &token_id, amount).await?; + + deposit(amount, &client_config, &deposit_address).await?; + + let amount = 2000; + + deposit(amount, &client_config, &deposit_address).await?; + + deposit(amount, &client_config, &deposit_address).await?; + + let amount = 1000; + + deposit(amount, &client_config, &deposit_address).await?; + + mercuryrustlib::coin_status::update_coins(&client_config, &wallet1.name).await?; + let wallet1: mercuryrustlib::Wallet = mercuryrustlib::sqlite_manager::get_wallet(&client_config.pool, &wallet1.name).await?; + + let new_coin = wallet1.coins.iter().find(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 0 && coin.status == CoinStatus::CONFIRMED); + let duplicated_coin_1 = wallet1.coins.iter().find(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 1 && coin.status == CoinStatus::DUPLICATED); + let duplicated_coin_2 = wallet1.coins.iter().find(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 2 && coin.status == CoinStatus::DUPLICATED); + let duplicated_coin_3 = wallet1.coins.iter().find(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 3 && coin.status == CoinStatus::DUPLICATED); + + assert!(new_coin.is_some()); + assert!(duplicated_coin_1.is_some()); + assert!(duplicated_coin_2.is_some()); + assert!(duplicated_coin_3.is_some()); + + let new_coin = new_coin.unwrap(); + + let statechain_id = new_coin.statechain_id.as_ref().unwrap(); + + let wallet2_transfer_adress = mercuryrustlib::transfer_receiver::new_transfer_address(&client_config, &wallet2.name).await?; + + let batch_id = None; + + let force_send = true; + + let duplicated_indexes = vec![1, 2, 3]; + + let result = mercuryrustlib::transfer_sender::execute(&client_config, &wallet2_transfer_adress, &wallet1.name, &statechain_id, Some(duplicated_indexes), force_send, batch_id).await; + + assert!(result.is_ok()); + + let wallet1 = mercuryrustlib::sqlite_manager::get_wallet(&client_config.pool, &wallet1.name).await?; + + let new_coin = wallet1.coins.iter().find(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 0 && coin.status == CoinStatus::IN_TRANSFER); + let duplicated_coin_1 = wallet1.coins.iter().find(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 1 && coin.status == CoinStatus::IN_TRANSFER); + let duplicated_coin_2 = wallet1.coins.iter().find(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 2 && coin.status == CoinStatus::IN_TRANSFER); + let duplicated_coin_3 = wallet1.coins.iter().find(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 3 && coin.status == CoinStatus::IN_TRANSFER); + + assert!(new_coin.is_some()); + assert!(duplicated_coin_1.is_some()); + assert!(duplicated_coin_2.is_some()); + assert!(duplicated_coin_3.is_some()); + + let transfer_receive_result = mercuryrustlib::transfer_receiver::execute(&client_config, &wallet2.name).await?; + + let received_statechain_ids = transfer_receive_result.received_statechain_ids; + + assert!(received_statechain_ids.contains(&statechain_id.to_string())); + assert!(received_statechain_ids.len() == 1); + + let wallet2: mercuryrustlib::Wallet = mercuryrustlib::sqlite_manager::get_wallet(&client_config.pool, &wallet2.name).await?; + + let w2_new_coin = wallet2.coins.iter().find(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 0 && coin.status == CoinStatus::CONFIRMED); + let w2_duplicated_coin_1 = wallet2.coins.iter().find(|&coin| coin.statechain_id == Some(statechain_id.to_string()) && coin.duplicate_index == 1 && coin.status == CoinStatus::DUPLICATED); + let w2_duplicated_coin_2 = wallet2.coins.iter().find(|&coin| coin.statechain_id == Some(statechain_id.to_string()) && coin.duplicate_index == 2 && coin.status == CoinStatus::DUPLICATED); + let w2_duplicated_coin_3 = wallet2.coins.iter().find(|&coin| coin.statechain_id == Some(statechain_id.to_string()) && coin.duplicate_index == 3 && coin.status == CoinStatus::DUPLICATED); + + assert!(w2_new_coin.is_some()); + assert!(w2_duplicated_coin_1.is_some()); + assert!(w2_duplicated_coin_2.is_some()); + assert!(w2_duplicated_coin_3.is_some()); + + let wallet3_transfer_adress = mercuryrustlib::transfer_receiver::new_transfer_address(&client_config, &wallet3.name).await?; + + let batch_id = None; + + let force_send = true; + + let duplicated_indexes = vec![1, 2, 3]; + + let result = mercuryrustlib::transfer_sender::execute(&client_config, &wallet3_transfer_adress, &wallet2.name, &statechain_id, Some(duplicated_indexes), force_send, batch_id).await; + + assert!(result.is_ok()); + + let transfer_receive_result = mercuryrustlib::transfer_receiver::execute(&client_config, &wallet3.name).await?; + + let received_statechain_ids = transfer_receive_result.received_statechain_ids; + + assert!(received_statechain_ids.contains(&statechain_id.to_string())); + assert!(received_statechain_ids.len() == 1); + + let wallet3: mercuryrustlib::Wallet = mercuryrustlib::sqlite_manager::get_wallet(&client_config.pool, &wallet3.name).await?; + + let w3_new_coin = wallet3.coins.iter().find(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 0 && coin.status == CoinStatus::CONFIRMED); + let w3_duplicated_coin_1 = wallet3.coins.iter().find(|&coin| coin.statechain_id == Some(statechain_id.to_string()) && coin.duplicate_index == 1 && coin.status == CoinStatus::DUPLICATED); + let w3_duplicated_coin_2 = wallet3.coins.iter().find(|&coin| coin.statechain_id == Some(statechain_id.to_string()) && coin.duplicate_index == 2 && coin.status == CoinStatus::DUPLICATED); + let w3_duplicated_coin_3 = wallet3.coins.iter().find(|&coin| coin.statechain_id == Some(statechain_id.to_string()) && coin.duplicate_index == 3 && coin.status == CoinStatus::DUPLICATED); + + assert!(w3_new_coin.is_some()); + assert!(w3_duplicated_coin_1.is_some()); + assert!(w3_duplicated_coin_2.is_some()); + assert!(w3_duplicated_coin_3.is_some()); + + let core_wallet_address = bitcoin_core::getnewaddress()?; + + let fee_rate = None; + + let result = mercuryrustlib::withdraw::execute(&client_config, &wallet3.name, statechain_id, &core_wallet_address, fee_rate, Some(3)).await; + assert!(result.is_ok()); + + let wallet1_transfer_adress = mercuryrustlib::transfer_receiver::new_transfer_address(&client_config, &wallet1.name).await?; + + let batch_id = None; + + let force_send = true; + + let duplicated_indexes = vec![1, 2, 3]; + + let result = mercuryrustlib::transfer_sender::execute(&client_config, &wallet1_transfer_adress, &wallet3.name, &statechain_id, Some(duplicated_indexes), force_send, batch_id).await; + + assert!(result.is_err()); + + assert!(result.err().unwrap().to_string().contains("There have been withdrawals of other coins with this same statechain_id (possibly duplicates).This transfer cannot be performed because the recipient would reject it due to the difference in signature count.This coin can be withdrawn, however.")); + + Ok(()) +} + pub async fn execute() -> Result<()> { let _ = Command::new("rm").arg("wallet.db").arg("wallet.db-shm").arg("wallet.db-wal").output().expect("failed to execute process"); @@ -387,6 +485,14 @@ pub async fn execute() -> Result<()> { resend_workflow(&client_config, &wallet1, &wallet2).await?; + let wallet3 = mercuryrustlib::wallet::create_wallet( + "wallet3", + &client_config).await?; + + mercuryrustlib::sqlite_manager::insert_wallet(&client_config.pool, &wallet3).await?; + + multiple_sends_workflow(&client_config, &wallet1, &wallet2, &wallet3).await?; + println!("TA03 - Test \"Multiple Deposits in the Same Adress\" completed successfully"); Ok(())