From 2db24fb8c5645111de008cd621fa6408e723d96e Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Fri, 23 Jul 2021 10:27:16 +1000 Subject: [PATCH] Add unit test required not enough Add a unit test that passes a required utxo to the coin selection algorithm that is less than the required spend. This tests that we get that utxo included as well as tests that the rest of the coin selection algorithm code also executes (i.e., that we do not short circuit incorrectly). --- src/wallet/coin_selection.rs | 96 ++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/src/wallet/coin_selection.rs b/src/wallet/coin_selection.rs index 1dcc2c9e..41e83da9 100644 --- a/src/wallet/coin_selection.rs +++ b/src/wallet/coin_selection.rs @@ -557,50 +557,31 @@ mod test { const FEE_AMOUNT: f32 = 50.0; + fn utxo(value: u64, index: u32) -> WeightedUtxo { + assert!(index < 10); + let outpoint = OutPoint::from_str(&format!( + "000000000000000000000000000000000000000000000000000000000000000{}:0", + index + )) + .unwrap(); + WeightedUtxo { + satisfaction_weight: P2WPKH_WITNESS_SIZE, + utxo: Utxo::Local(LocalUtxo { + outpoint, + txout: TxOut { + value, + script_pubkey: Script::new(), + }, + keychain: KeychainKind::External, + }), + } + } + fn get_test_utxos() -> Vec { vec![ - WeightedUtxo { - satisfaction_weight: P2WPKH_WITNESS_SIZE, - utxo: Utxo::Local(LocalUtxo { - outpoint: OutPoint::from_str( - "0000000000000000000000000000000000000000000000000000000000000000:0", - ) - .unwrap(), - txout: TxOut { - value: 100_000, - script_pubkey: Script::new(), - }, - keychain: KeychainKind::External, - }), - }, - WeightedUtxo { - satisfaction_weight: P2WPKH_WITNESS_SIZE, - utxo: Utxo::Local(LocalUtxo { - outpoint: OutPoint::from_str( - "0000000000000000000000000000000000000000000000000000000000000001:0", - ) - .unwrap(), - txout: TxOut { - value: FEE_AMOUNT as u64 - 40, - script_pubkey: Script::new(), - }, - keychain: KeychainKind::External, - }), - }, - WeightedUtxo { - satisfaction_weight: P2WPKH_WITNESS_SIZE, - utxo: Utxo::Local(LocalUtxo { - outpoint: OutPoint::from_str( - "0000000000000000000000000000000000000000000000000000000000000002:0", - ) - .unwrap(), - txout: TxOut { - value: 200_000, - script_pubkey: Script::new(), - }, - keychain: KeychainKind::Internal, - }), - }, + utxo(100_000, 0), + utxo(FEE_AMOUNT as u64 - 40, 1), + utxo(200_000, 2), ] } @@ -817,6 +798,37 @@ mod test { assert!((result.fee_amount - 254.0).abs() < f32::EPSILON); } + #[test] + fn test_bnb_coin_selection_required_not_enough() { + let utxos = get_test_utxos(); + let database = MemoryDatabase::default(); + + let required = vec![utxos[0].clone()]; + let mut optional = utxos[1..].to_vec(); + optional.push(utxo(500_000, 3)); + + // Defensive assertions, for sanity and in case someone changes the test utxos vector. + let amount: u64 = required.iter().map(|u| u.utxo.txout().value).sum(); + assert_eq!(amount, 100_000); + let amount: u64 = optional.iter().map(|u| u.utxo.txout().value).sum(); + assert!(amount > 150_000); + + let result = BranchAndBoundCoinSelection::default() + .coin_select( + &database, + required, + optional, + FeeRate::from_sat_per_vb(1.0), + 150_000, + FEE_AMOUNT, + ) + .unwrap(); + + assert_eq!(result.selected.len(), 3); + assert_eq!(result.selected_amount(), 300_010); + assert!((result.fee_amount - 254.0).abs() < f32::EPSILON); + } + #[test] #[should_panic(expected = "InsufficientFunds")] fn test_bnb_coin_selection_insufficient_funds() {