From 6931d0bd1f044bf73c0cb760c0eb0be19aea8de1 Mon Sep 17 00:00:00 2001 From: KaFai Choi Date: Tue, 8 Mar 2022 17:12:46 +0700 Subject: [PATCH] add private function select_sorted_utxso to be resued by multiple CoinSelection impl --- src/wallet/coin_selection.rs | 126 +++++++++++++---------------------- 1 file changed, 48 insertions(+), 78 deletions(-) diff --git a/src/wallet/coin_selection.rs b/src/wallet/coin_selection.rs index 1538346a..7b4a4833 100644 --- a/src/wallet/coin_selection.rs +++ b/src/wallet/coin_selection.rs @@ -183,7 +183,7 @@ impl CoinSelectionAlgorithm for LargestFirstCoinSelection { mut optional_utxos: Vec, fee_rate: FeeRate, amount_needed: u64, - mut fee_amount: u64, + fee_amount: u64, ) -> Result { log::debug!( "amount_needed = `{}`, fee_amount = `{}`, fee_rate = `{:?}`", @@ -202,44 +202,7 @@ impl CoinSelectionAlgorithm for LargestFirstCoinSelection { .chain(optional_utxos.into_iter().rev().map(|utxo| (false, utxo))) }; - // Keep including inputs until we've got enough. - // Store the total input value in selected_amount and the total fee being paid in fee_amount - let mut selected_amount = 0; - let selected = utxos - .scan( - (&mut selected_amount, &mut fee_amount), - |(selected_amount, fee_amount), (must_use, weighted_utxo)| { - if must_use || **selected_amount < amount_needed + **fee_amount { - **fee_amount += - fee_rate.fee_wu(TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight); - **selected_amount += weighted_utxo.utxo.txout().value; - - log::debug!( - "Selected {}, updated fee_amount = `{}`", - weighted_utxo.utxo.outpoint(), - fee_amount - ); - - Some(weighted_utxo.utxo) - } else { - None - } - }, - ) - .collect::>(); - - let amount_needed_with_fees = amount_needed + fee_amount; - if selected_amount < amount_needed_with_fees { - return Err(Error::InsufficientFunds { - needed: amount_needed_with_fees, - available: selected_amount, - }); - } - - Ok(CoinSelectionResult { - selected, - fee_amount, - }) + select_sorted_utxos(utxos, fee_rate, amount_needed, fee_amount) } } @@ -258,7 +221,7 @@ impl CoinSelectionAlgorithm for OldestFirstCoinSelection { mut optional_utxos: Vec, fee_rate: FeeRate, amount_needed: u64, - mut fee_amount: u64, + fee_amount: u64, ) -> Result { // query db and create a blockheight lookup table let blockheights = optional_utxos @@ -298,47 +261,54 @@ impl CoinSelectionAlgorithm for OldestFirstCoinSelection { .chain(optional_utxos.into_iter().map(|utxo| (false, utxo))) }; - // Keep including inputs until we've got enough. - // Store the total input value in selected_amount and the total fee being paid in fee_amount - let mut selected_amount = 0; - let selected = utxos - .scan( - (&mut selected_amount, &mut fee_amount), - |(selected_amount, fee_amount), (must_use, weighted_utxo)| { - if must_use || **selected_amount < amount_needed + **fee_amount { - **fee_amount += - fee_rate.fee_wu(TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight); - **selected_amount += weighted_utxo.utxo.txout().value; - - log::debug!( - "Selected {}, updated fee_amount = `{}`", - weighted_utxo.utxo.outpoint(), - fee_amount - ); - - Some(weighted_utxo.utxo) - } else { - None - } - }, - ) - .collect::>(); - - let amount_needed_with_fees = amount_needed + fee_amount; - if selected_amount < amount_needed_with_fees { - return Err(Error::InsufficientFunds { - needed: amount_needed_with_fees, - available: selected_amount, - }); - } - - Ok(CoinSelectionResult { - selected, - fee_amount, - }) + select_sorted_utxos(utxos, fee_rate, amount_needed, fee_amount) } } +fn select_sorted_utxos( + utxos: impl Iterator, + fee_rate: FeeRate, + amount_needed: u64, + mut fee_amount: u64, +) -> Result { + let mut selected_amount = 0; + let selected = utxos + .scan( + (&mut selected_amount, &mut fee_amount), + |(selected_amount, fee_amount), (must_use, weighted_utxo)| { + if must_use || **selected_amount < amount_needed + **fee_amount { + **fee_amount += + fee_rate.fee_wu(TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight); + **selected_amount += weighted_utxo.utxo.txout().value; + + log::debug!( + "Selected {}, updated fee_amount = `{}`", + weighted_utxo.utxo.outpoint(), + fee_amount + ); + + Some(weighted_utxo.utxo) + } else { + None + } + }, + ) + .collect::>(); + + let amount_needed_with_fees = amount_needed + fee_amount; + if selected_amount < amount_needed_with_fees { + return Err(Error::InsufficientFunds { + needed: amount_needed_with_fees, + available: selected_amount, + }); + } + + Ok(CoinSelectionResult { + selected, + fee_amount, + }) +} + #[derive(Debug, Clone)] // Adds fee information to an UTXO. struct OutputGroup {