Skip to content

Commit

Permalink
test(wallet): check there are no duplicates across required and optio…
Browse files Browse the repository at this point in the history
…nal utxos

This test replaces the one used to test
`coin_selection::filter_duplicates` introduced in
5299db3.

As the code changed and there is not a single point to verificate the
following properties:
- there are no duplicates in required utxos
- there are no duplicates in optional utxos
- there are no duplicates across optional and required utxos
anymore, test have been prefixed with `not_duplicated_utxos*` to allow
its joint execution by using the following command:
cargo test -- not_duplicated_utxos
  • Loading branch information
nymius committed Jan 23, 2025
1 parent 0bbf8f0 commit 05d94f3
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 0 deletions.
134 changes: 134 additions & 0 deletions crates/wallet/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2557,3 +2557,137 @@ macro_rules! doctest_wallet {
wallet
}}
}

#[cfg(test)]
mod test {
use super::*;
use crate::test_utils::get_test_tr_single_sig_xprv_and_change_desc;
use crate::test_utils::insert_anchor;
use crate::test_utils::insert_tx;

#[test]
fn not_duplicated_utxos_across_optional_and_required() {
let (external_desc, internal_desc) = get_test_tr_single_sig_xprv_and_change_desc();

// create new wallet
let mut wallet = Wallet::create(external_desc, internal_desc)
.network(Network::Testnet)
.create_wallet_no_persist()
.unwrap();

let two_output_tx = Transaction {
input: vec![],
output: vec![
TxOut {
script_pubkey: wallet
.next_unused_address(KeychainKind::External)
.script_pubkey(),
value: Amount::from_sat(25_000),
},
TxOut {
script_pubkey: wallet
.next_unused_address(KeychainKind::External)
.script_pubkey(),
value: Amount::from_sat(75_000),
},
],
version: transaction::Version::non_standard(0),
lock_time: absolute::LockTime::ZERO,
};

let txid = two_output_tx.compute_txid();
insert_tx(&mut wallet, two_output_tx);

let expected_anchor = ConfirmationBlockTime {
block_id: wallet.latest_checkpoint().block_id(),
confirmation_time: 200,
};

insert_anchor(&mut wallet, txid, expected_anchor);

let mut params = TxParams::default();
wallet
.get_utxo(OutPoint { txid, vout: 0 })
.map(|outpoint| {
params.utxos.insert(outpoint);
})
.unwrap();
// enforce selection of first output in transaction
let received = wallet.filter_utxos(&params, wallet.latest_checkpoint().block_id().height);
// notice expected doesn't include the first output from two_output_tx as it should be
// filtered out
let expected = vec![wallet
.get_utxo(OutPoint { txid, vout: 1 })
.map(|utxo| WeightedUtxo {
satisfaction_weight: wallet
.public_descriptor(utxo.keychain)
.max_weight_to_satisfy()
.unwrap(),
utxo: Utxo::Local(utxo),
})
.unwrap()];

assert_eq!(expected, received);
}

#[test]
fn not_duplicated_utxos_in_optional_list() {
let (external_desc, internal_desc) = get_test_tr_single_sig_xprv_and_change_desc();

// create new wallet
let mut wallet = Wallet::create(external_desc, internal_desc)
.network(Network::Testnet)
.create_wallet_no_persist()
.unwrap();

let two_output_tx = Transaction {
input: vec![],
output: vec![
TxOut {
script_pubkey: wallet
.next_unused_address(KeychainKind::External)
.script_pubkey(),
value: Amount::from_sat(25_000),
},
TxOut {
script_pubkey: wallet
.next_unused_address(KeychainKind::External)
.script_pubkey(),
value: Amount::from_sat(75_000),
},
],
version: transaction::Version::non_standard(0),
lock_time: absolute::LockTime::ZERO,
};

let txid = two_output_tx.compute_txid();

for _ in 0..3 {
insert_tx(&mut wallet, two_output_tx.clone());
}

let expected_anchor = ConfirmationBlockTime {
block_id: wallet.latest_checkpoint().block_id(),
confirmation_time: 200,
};

insert_anchor(&mut wallet, txid, expected_anchor);

// enforce selection of first output in transaction
let received = wallet
.indexed_graph
.graph()
.filter_chain_unspents(
&wallet.chain,
wallet.chain.tip().block_id(),
wallet.indexed_graph.index.outpoints().iter().cloned(),
)
.map(|(_, full_txout)| full_txout.outpoint)
.collect::<Vec<_>>();
// notice expected doesn't include the first output from two_output_tx as it should be
// filtered out
let expected = vec![OutPoint { txid, vout: 0 }, OutPoint { txid, vout: 1 }];

assert_eq!(expected, received);
}
}
13 changes: 13 additions & 0 deletions crates/wallet/src/wallet/tx_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1041,4 +1041,17 @@ mod test {
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0].keychain, KeychainKind::Internal);
}

#[test]
fn not_duplicated_utxos_in_required_list() {
let mut params = TxParams::default();
let test_utxos = get_test_utxos();
for _ in 0..3 {
params.utxos.insert(test_utxos[0].clone());
}
assert_eq!(
vec![test_utxos[0].clone()],
params.utxos.into_iter().collect::<Vec<_>>()
);
}
}

0 comments on commit 05d94f3

Please sign in to comment.