Skip to content

Commit

Permalink
Fix sending error (when user sends to themselves)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssantos21 committed Oct 29, 2024
1 parent e176b13 commit f155df1
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 3 deletions.
3 changes: 2 additions & 1 deletion clients/libs/rust/src/coin_status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ pub async fn update_coins(client_config: &ClientConfig, wallet_name: &str) -> Re
if wallet.coins[i].status == CoinStatus::DUPLICATED {
let is_transferred = (0..wallet.coins.len()).any(|j|
i != j && // Skip comparing with self
wallet.coins[j].statechain_id == wallet.coins[i].statechain_id &&
wallet.coins[j].statechain_id == wallet.coins[i].statechain_id &&
wallet.coins[j].locktime == wallet.coins[i].locktime &&
wallet.coins[j].status == CoinStatus::TRANSFERRED
);
if is_transferred {
Expand Down
8 changes: 6 additions & 2 deletions clients/libs/rust/src/transfer_sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,15 @@ pub async fn create_backup_transactions(

// Get coins that already have a backup transaction
for coin in wallet.coins.iter_mut() {
// Check if coin matches any backup transaction
// Check if coin matches any backup transaction and has one of the specified statuses
let has_matching_tx = backup_transactions.iter().any(|backup_tx| {
if let Ok(tx_outpoint) = get_previous_outpoint(backup_tx) {
if let (Some(utxo_txid), Some(utxo_vout)) = (coin.utxo_txid.clone(), coin.utxo_vout) {
tx_outpoint.txid == utxo_txid && tx_outpoint.vout == utxo_vout
(coin.status == CoinStatus::DUPLICATED ||
coin.status == CoinStatus::CONFIRMED ||
coin.status == CoinStatus::IN_TRANSFER) &&
tx_outpoint.txid == utxo_txid &&
tx_outpoint.vout == utxo_vout
} else {
false
}
Expand Down
157 changes: 157 additions & 0 deletions clients/tests/rust/src/ta03_multiple_deposits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,161 @@ async fn multiple_sends_workflow(client_config: &ClientConfig, wallet1: &Wallet,
Ok(())
}

async fn send_to_itself_workflow(client_config: &ClientConfig, wallet1: &Wallet, wallet2: &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 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, 3];

let result = mercuryrustlib::transfer_sender::execute(&client_config, &wallet1_transfer_adress, &wallet1.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, &wallet1.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);

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 transferred_coin_0 = wallet1.coins.iter().filter(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 0 && coin.status == CoinStatus::TRANSFERRED);
let transferred_coin_1 = wallet1.coins.iter().filter(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 1 && coin.status == CoinStatus::TRANSFERRED);
let invalidated_coin_2 = wallet1.coins.iter().filter(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 2 && coin.status == CoinStatus::INVALIDATED);
let transferred_coin_3 = wallet1.coins.iter().filter(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 3 && coin.status == CoinStatus::TRANSFERRED);

assert!(transferred_coin_0.count() == 1);
assert!(transferred_coin_1.count() == 1);
assert!(invalidated_coin_2.count() == 1);
assert!(transferred_coin_3.count() == 1);

let confirmed_coin_0 = wallet1.coins.iter().filter(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 0 && coin.status == CoinStatus::CONFIRMED);
let duplicated_coin_1 = wallet1.coins.iter().filter(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 1 && coin.status == CoinStatus::DUPLICATED);
let duplicated_coin_2 = wallet1.coins.iter().filter(|&coin| coin.aggregated_address == Some(deposit_address.clone()) && coin.duplicate_index == 2 && coin.status == CoinStatus::DUPLICATED);

assert!(confirmed_coin_0.count() == 1);
assert!(duplicated_coin_1.count() == 1);
assert!(duplicated_coin_2.count() == 1);

// now send the coins to another wallet.

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];

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::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::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 mut coins_json = Vec::new();
for coin in wallet1.coins.iter() {
let obj = json!({
"coin.user_pubkey": coin.user_pubkey,
"coin.aggregated_address": coin.aggregated_address.as_ref().unwrap_or(&"".to_string()),
"coin.address": coin.address,
"coin.statechain_id": coin.statechain_id.as_ref().unwrap_or(&"".to_string()),
"coin.amount": coin.amount.unwrap_or(0),
"coin.status": coin.status,
"coin.locktime": coin.locktime.unwrap_or(0),
"coin.duplicate_index": coin.duplicate_index,
});
coins_json.push(obj);
}
let coins_json_string = serde_json::to_string_pretty(&coins_json).unwrap();
println!("{}", coins_json_string); */

assert!(new_coin.is_some());
assert!(duplicated_coin_1.is_some());
assert!(duplicated_coin_2.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);

assert!(w2_new_coin.is_some());
assert!(w2_duplicated_coin_1.is_some());
assert!(w2_duplicated_coin_2.is_some());

let core_wallet_address = bitcoin_core::getnewaddress()?;

let fee_rate = None;

let result = mercuryrustlib::withdraw::execute(&client_config, &wallet2.name, statechain_id, &core_wallet_address, fee_rate, Some(1)).await;
assert!(result.is_ok());

let result = mercuryrustlib::withdraw::execute(&client_config, &wallet2.name, statechain_id, &core_wallet_address, fee_rate, Some(2)).await;
assert!(result.is_ok());

let result = mercuryrustlib::withdraw::execute(&client_config, &wallet2.name, statechain_id, &core_wallet_address, fee_rate, None).await;
assert!(result.is_ok());

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");
Expand Down Expand Up @@ -493,6 +648,8 @@ pub async fn execute() -> Result<()> {

multiple_sends_workflow(&client_config, &wallet1, &wallet2, &wallet3).await?;

send_to_itself_workflow(&client_config, &wallet1, &wallet2).await?;

println!("TA03 - Test \"Multiple Deposits in the Same Adress\" completed successfully");

Ok(())
Expand Down

0 comments on commit f155df1

Please sign in to comment.