@@ -126,7 +126,7 @@ pub(crate) struct TxParams {
126126 pub ( crate ) internal_policy_path : Option < BTreeMap < String , Vec < usize > > > ,
127127 pub ( crate ) external_policy_path : Option < BTreeMap < String , Vec < usize > > > ,
128128 pub ( crate ) utxos : HashSet < LocalOutput > ,
129- pub ( crate ) foreign_utxos : Vec < WeightedUtxo > ,
129+ pub ( crate ) foreign_utxos : HashSet < WeightedUtxo > ,
130130 pub ( crate ) unspendable : HashSet < OutPoint > ,
131131 pub ( crate ) manually_selected_only : bool ,
132132 pub ( crate ) sighash : Option < psbt:: PsbtSighashType > ,
@@ -382,7 +382,7 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
382382 }
383383 }
384384
385- self . params . foreign_utxos . push ( WeightedUtxo {
385+ self . params . foreign_utxos . insert ( WeightedUtxo {
386386 satisfaction_weight,
387387 utxo : Utxo :: Foreign {
388388 outpoint,
@@ -1100,4 +1100,34 @@ mod test {
11001100 params. utxos. into_iter( ) . collect:: <Vec <_>>( )
11011101 ) ;
11021102 }
1103+
1104+ #[ test]
1105+ fn not_duplicated_foreign_utxos ( ) {
1106+ use crate :: test_utils:: get_funded_wallet_wpkh;
1107+ // Use two different wallets to avoid adding local utxos
1108+ let ( wallet1, txid1) = get_funded_wallet_wpkh ( ) ;
1109+ let ( mut wallet2, _) = get_funded_wallet_wpkh ( ) ;
1110+
1111+ let utxo1 = wallet1. list_unspent ( ) . next ( ) . unwrap ( ) ;
1112+ let tx1 = wallet1. get_tx ( txid1) . unwrap ( ) . tx_node . tx . clone ( ) ;
1113+
1114+ let satisfaction_weight = wallet1
1115+ . public_descriptor ( KeychainKind :: External )
1116+ . max_weight_to_satisfy ( )
1117+ . unwrap ( ) ;
1118+
1119+ let mut builder = wallet2. build_tx ( ) ;
1120+ for _ in 0 ..2 {
1121+ let _ = builder. add_foreign_utxo (
1122+ utxo1. outpoint ,
1123+ psbt:: Input {
1124+ non_witness_utxo : Some ( tx1. as_ref ( ) . clone ( ) ) ,
1125+ ..Default :: default ( )
1126+ } ,
1127+ satisfaction_weight,
1128+ ) ;
1129+ }
1130+
1131+ assert_eq ! ( builder. params. foreign_utxos. len( ) , 1 ) ;
1132+ }
11031133}
0 commit comments