From 23824321ba4e936e3f96471b589577fbe74e38c8 Mon Sep 17 00:00:00 2001 From: Daniela Brozzoni Date: Sat, 31 Oct 2020 16:28:12 +0100 Subject: [PATCH] [wallet] Add tests for BranchAndBoundCoinSelection::bnb --- src/wallet/coin_selection.rs | 131 +++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/src/wallet/coin_selection.rs b/src/wallet/coin_selection.rs index 8f3b9241..45bbe300 100644 --- a/src/wallet/coin_selection.rs +++ b/src/wallet/coin_selection.rs @@ -856,4 +856,135 @@ mod test { } } + #[test] + #[should_panic(expected = "BnBNoExactMatch")] + fn test_bnb_function_no_exact_match() { + let fee_rate = FeeRate::from_sat_per_vb(10.0); + let utxos: Vec = get_test_utxos() + .into_iter() + .map(|u| OutputGroup::new(u.0, u.1, fee_rate)) + .collect(); + + let curr_available_value = utxos + .iter() + .fold(0, |acc, x| acc + x.effective_value as u64); + + let size_of_change = 31; + let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb(); + BranchAndBoundCoinSelection::new(size_of_change) + .bnb( + vec![], + utxos, + 0, + curr_available_value, + 20_000, + 50.0, + cost_of_change, + ) + .unwrap(); + } + + #[test] + #[should_panic(expected = "BnBTotalTriesExceeded")] + fn test_bnb_function_tries_exceeded() { + let fee_rate = FeeRate::from_sat_per_vb(10.0); + let utxos: Vec = generate_same_value_utxos(100_000, 100_000) + .into_iter() + .map(|u| OutputGroup::new(u.0, u.1, fee_rate)) + .collect(); + + let curr_available_value = utxos + .iter() + .fold(0, |acc, x| acc + x.effective_value as u64); + + let size_of_change = 31; + let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb(); + + BranchAndBoundCoinSelection::new(size_of_change) + .bnb( + vec![], + utxos, + 0, + curr_available_value, + 20_000, + 50.0, + cost_of_change, + ) + .unwrap(); + } + + // The match won't be exact but still in the range + #[test] + fn test_bnb_function_almost_exact_match_with_fees() { + let fee_rate = FeeRate::from_sat_per_vb(1.0); + let size_of_change = 31; + let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb(); + let fee_amount = 50.0; + + let utxos: Vec<_> = generate_same_value_utxos(50_000, 10) + .into_iter() + .map(|u| OutputGroup::new(u.0, u.1, fee_rate)) + .collect(); + + let curr_value = 0; + + let curr_available_value = utxos + .iter() + .fold(0, |acc, x| acc + x.effective_value as u64); + + // 2*(value of 1 utxo) - 2*(1 utxo fees with 1.0sat/vbyte fee rate) - + // cost_of_change + 5. + let target_amount = 2 * 50_000 - 2 * 67 - cost_of_change.ceil() as u64 + 5; + + let result = BranchAndBoundCoinSelection::new(size_of_change) + .bnb( + vec![], + utxos, + curr_value, + curr_available_value, + target_amount, + fee_amount, + cost_of_change, + ) + .unwrap(); + assert_eq!(result.fee_amount, 186.0); + assert_eq!(result.selected_amount, 100_000); + } + + // TODO: bnb() function should be optimized, and this test should be done with more utxos + #[test] + fn test_bnb_function_exact_match_more_utxos() { + let seed = [0; 32]; + let mut rng: StdRng = SeedableRng::from_seed(seed); + let fee_rate = FeeRate::from_sat_per_vb(0.0); + + for _ in 0..200 { + let optional_utxos: Vec<_> = generate_random_utxos(&mut rng, 40) + .into_iter() + .map(|u| OutputGroup::new(u.0, u.1, fee_rate)) + .collect(); + + let curr_value = 0; + + let curr_available_value = optional_utxos + .iter() + .fold(0, |acc, x| acc + x.effective_value as u64); + + let target_amount = optional_utxos[3].effective_value as u64 + + optional_utxos[23].effective_value as u64; + + let result = BranchAndBoundCoinSelection::new(0) + .bnb( + vec![], + optional_utxos, + curr_value, + curr_available_value, + target_amount, + 0.0, + 0.0, + ) + .unwrap(); + assert_eq!(result.selected_amount, target_amount); + } + } }