diff --git a/README.md b/README.md index 172866d1..d294377c 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,10 @@ The current interface is provided via `select_coins()` function. The required p As discussed in the literature above, ideally we want to choose a selection from the existing UTXO set available to the wallet. However, if there is no combination that efficiently matches the target spend amount, then creating a change output by splitting a UTXO is the next best option. Therefore, the algorithm takes into account the current cost of creating a new output (cost_of_change). +## Benchmarks + +To run the bench marks use: RUSTFLAGS='--cfg=bench' cargo +nightly bench. + ## Minimum Supported Rust Version (MSRV) This library should always compile with any combination of features on **Rust 1.48**. diff --git a/src/branch_and_bound.rs b/src/branch_and_bound.rs index a76ca73b..ed440dde 100644 --- a/src/branch_and_bound.rs +++ b/src/branch_and_bound.rs @@ -544,3 +544,49 @@ mod tests { assert_eq!(list, expected_list(expected_i_list, &mut weighted_utxos)); } } + +#[cfg(bench)] +mod benches { + use super::*; + use crate::select_coins_bnb; + use bitcoin::ScriptBuf; + use bitcoin::TxOut; + use bitcoin::Weight; + use core::str::FromStr; + use test::Bencher; + + #[bench] + /// Creates a UTXO pool of 1,000 coins that do not match and one coin + /// that will be a match when combined with any of the other 1,000 coins. + /// + /// Matching benchmark of Bitcoin core coin-selection benchmark. + // https://github.com/bitcoin/bitcoin/blob/f3bc1a72825fe2b51f4bc20e004cef464f05b965/src/bench/coin_selection.cpp#L44 + fn bench_select_coins_bnb(bh: &mut Bencher) { + // https://github.com/bitcoin/bitcoin/blob/f3bc1a72825fe2b51f4bc20e004cef464f05b965/src/wallet/coinselection.h#L18 + /// lower bound for randomly-chosen target change amount + let cost_of_change = Amount::from_sat(50_000); + + let one = WeightedUtxo { + satisfaction_weight: Weight::ZERO, + utxo: TxOut { value: Amount::from_sat(1_000), script_pubkey: ScriptBuf::new() }, + }; + + let two = WeightedUtxo { + satisfaction_weight: Weight::ZERO, + utxo: TxOut { value: Amount::from_sat(3), script_pubkey: ScriptBuf::new() }, + }; + + let target = Amount::from_sat(1_003); + let mut utxo_pool = vec![one; 1000]; + utxo_pool.push(two); + + bh.iter(|| { + let result = + select_coins_bnb(target, cost_of_change, FeeRate::ZERO, &mut utxo_pool.clone()) + .unwrap(); + assert_eq!(2, result.len()); + assert_eq!(Amount::from_sat(1_000), result[0].utxo.value); + assert_eq!(Amount::from_sat(3), result[1].utxo.value); + }); + } +} diff --git a/src/lib.rs b/src/lib.rs index c700cbf5..96493d6d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,49 +72,3 @@ pub fn select_coins( coins } } - -#[cfg(bench)] -mod benches { - use crate::select_coins_bnb; - use crate::Utxo; - use test::Bencher; - - #[derive(Clone, Debug, Eq, PartialEq)] - struct MinimalUtxo { - value: u64, - } - - impl Utxo for MinimalUtxo { - fn get_value(&self) -> u64 { - self.value - } - } - - #[bench] - /// Creates a UTXO pool of 1,000 coins that do not match and one coin - /// that will be a match when combined with any of the other 1,000 coins. - /// - /// Matching benchmark of Bitcoin core coin-selection benchmark. - // https://github.com/bitcoin/bitcoin/blob/f3bc1a72825fe2b51f4bc20e004cef464f05b965/src/bench/coin_selection.cpp#L44 - fn bench_select_coins_bnb(bh: &mut Bencher) { - // https://github.com/bitcoin/bitcoin/blob/f3bc1a72825fe2b51f4bc20e004cef464f05b965/src/consensus/amount.h#L15 - /// The amount of satoshis in one BTC. - const COIN: u64 = 100_000_000; - - // https://github.com/bitcoin/bitcoin/blob/f3bc1a72825fe2b51f4bc20e004cef464f05b965/src/wallet/coinselection.h#L18 - /// lower bound for randomly-chosen target change amount - const CHANGE_LOWER: u64 = 50_000; - - let u = MinimalUtxo { value: 1000 * COIN }; - let mut utxo_pool = vec![u; 1000]; - utxo_pool.push(MinimalUtxo { value: 3 * COIN }); - - bh.iter(|| { - let result = - select_coins_bnb(1003 * COIN, CHANGE_LOWER, &mut utxo_pool.clone()).unwrap(); - assert_eq!(2, result.len()); - assert_eq!(1000 * COIN, result[0].value); - assert_eq!(3 * COIN, result[1].value); - }); - } -}