101101//! # Ok::<(), anyhow::Error>(())
102102//! ```
103103
104- use crate :: chain:: collections:: HashSet ;
105104use crate :: wallet:: utils:: IsDust ;
106105use crate :: Utxo ;
107106use crate :: WeightedUtxo ;
108107use bitcoin:: { Amount , FeeRate , SignedAmount } ;
109108
110109use alloc:: vec:: Vec ;
111110use bitcoin:: consensus:: encode:: serialize;
112- use bitcoin:: OutPoint ;
113111use bitcoin:: TxIn ;
114112use bitcoin:: { Script , Weight } ;
115113
@@ -720,25 +718,6 @@ fn calculate_cs_result(
720718 }
721719}
722720
723- /// Remove duplicate UTXOs.
724- ///
725- /// If a UTXO appears in both `required` and `optional`, the appearance in `required` is kept.
726- pub ( crate ) fn filter_duplicates < I > ( required : I , optional : I ) -> ( I , I )
727- where
728- I : IntoIterator < Item = WeightedUtxo > + FromIterator < WeightedUtxo > ,
729- {
730- let mut visited = HashSet :: < OutPoint > :: new ( ) ;
731- let required = required
732- . into_iter ( )
733- . filter ( |utxo| visited. insert ( utxo. utxo . outpoint ( ) ) )
734- . collect :: < I > ( ) ;
735- let optional = optional
736- . into_iter ( )
737- . filter ( |utxo| visited. insert ( utxo. utxo . outpoint ( ) ) )
738- . collect :: < I > ( ) ;
739- ( required, optional)
740- }
741-
742721#[ cfg( test) ]
743722mod test {
744723 use assert_matches:: assert_matches;
@@ -751,7 +730,6 @@ mod test {
751730
752731 use super :: * ;
753732 use crate :: types:: * ;
754- use crate :: wallet:: coin_selection:: filter_duplicates;
755733
756734 use rand:: prelude:: SliceRandom ;
757735 use rand:: { thread_rng, Rng , RngCore , SeedableRng } ;
@@ -1618,102 +1596,6 @@ mod test {
16181596 assert_eq ! ( res. selected_amount( ) , Amount :: from_sat( 200_000 ) ) ;
16191597 }
16201598
1621- #[ test]
1622- fn test_filter_duplicates ( ) {
1623- fn utxo ( txid : & str , value : u64 ) -> WeightedUtxo {
1624- WeightedUtxo {
1625- satisfaction_weight : Weight :: ZERO ,
1626- utxo : Utxo :: Local ( LocalOutput {
1627- outpoint : OutPoint :: new ( bitcoin:: hashes:: Hash :: hash ( txid. as_bytes ( ) ) , 0 ) ,
1628- txout : TxOut {
1629- value : Amount :: from_sat ( value) ,
1630- script_pubkey : ScriptBuf :: new ( ) ,
1631- } ,
1632- keychain : KeychainKind :: External ,
1633- is_spent : false ,
1634- derivation_index : 0 ,
1635- chain_position : ChainPosition :: Confirmed {
1636- anchor : ConfirmationBlockTime {
1637- block_id : BlockId {
1638- height : 12345 ,
1639- hash : BlockHash :: all_zeros ( ) ,
1640- } ,
1641- confirmation_time : 12345 ,
1642- } ,
1643- transitively : None ,
1644- } ,
1645- } ) ,
1646- }
1647- }
1648-
1649- fn to_utxo_vec ( utxos : & [ ( & str , u64 ) ] ) -> Vec < WeightedUtxo > {
1650- let mut v = utxos
1651- . iter ( )
1652- . map ( |& ( txid, value) | utxo ( txid, value) )
1653- . collect :: < Vec < _ > > ( ) ;
1654- v. sort_by_key ( |u| u. utxo . outpoint ( ) ) ;
1655- v
1656- }
1657-
1658- struct TestCase < ' a > {
1659- name : & ' a str ,
1660- required : & ' a [ ( & ' a str , u64 ) ] ,
1661- optional : & ' a [ ( & ' a str , u64 ) ] ,
1662- exp_required : & ' a [ ( & ' a str , u64 ) ] ,
1663- exp_optional : & ' a [ ( & ' a str , u64 ) ] ,
1664- }
1665-
1666- let test_cases = [
1667- TestCase {
1668- name : "no_duplicates" ,
1669- required : & [ ( "A" , 1000 ) , ( "B" , 2100 ) ] ,
1670- optional : & [ ( "C" , 1000 ) ] ,
1671- exp_required : & [ ( "A" , 1000 ) , ( "B" , 2100 ) ] ,
1672- exp_optional : & [ ( "C" , 1000 ) ] ,
1673- } ,
1674- TestCase {
1675- name : "duplicate_required_utxos" ,
1676- required : & [ ( "A" , 3000 ) , ( "B" , 1200 ) , ( "C" , 1234 ) , ( "A" , 3000 ) ] ,
1677- optional : & [ ( "D" , 2100 ) ] ,
1678- exp_required : & [ ( "A" , 3000 ) , ( "B" , 1200 ) , ( "C" , 1234 ) ] ,
1679- exp_optional : & [ ( "D" , 2100 ) ] ,
1680- } ,
1681- TestCase {
1682- name : "duplicate_optional_utxos" ,
1683- required : & [ ( "A" , 3000 ) , ( "B" , 1200 ) ] ,
1684- optional : & [ ( "C" , 5000 ) , ( "D" , 1300 ) , ( "C" , 5000 ) ] ,
1685- exp_required : & [ ( "A" , 3000 ) , ( "B" , 1200 ) ] ,
1686- exp_optional : & [ ( "C" , 5000 ) , ( "D" , 1300 ) ] ,
1687- } ,
1688- TestCase {
1689- name : "duplicate_across_required_and_optional_utxos" ,
1690- required : & [ ( "A" , 3000 ) , ( "B" , 1200 ) , ( "C" , 2100 ) ] ,
1691- optional : & [ ( "A" , 3000 ) , ( "D" , 1200 ) , ( "E" , 5000 ) ] ,
1692- exp_required : & [ ( "A" , 3000 ) , ( "B" , 1200 ) , ( "C" , 2100 ) ] ,
1693- exp_optional : & [ ( "D" , 1200 ) , ( "E" , 5000 ) ] ,
1694- } ,
1695- ] ;
1696-
1697- for ( i, t) in test_cases. into_iter ( ) . enumerate ( ) {
1698- let ( required, optional) =
1699- filter_duplicates ( to_utxo_vec ( t. required ) , to_utxo_vec ( t. optional ) ) ;
1700- assert_eq ! (
1701- required,
1702- to_utxo_vec( t. exp_required) ,
1703- "[{}:{}] unexpected `required` result" ,
1704- i,
1705- t. name
1706- ) ;
1707- assert_eq ! (
1708- optional,
1709- to_utxo_vec( t. exp_optional) ,
1710- "[{}:{}] unexpected `optional` result" ,
1711- i,
1712- t. name
1713- ) ;
1714- }
1715- }
1716-
17171599 #[ test]
17181600 fn test_deterministic_coin_selection_picks_same_utxos ( ) {
17191601 enum CoinSelectionAlgo {
0 commit comments