@@ -375,28 +375,34 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
375375 satisfaction_weight : Weight ,
376376 sequence : Sequence ,
377377 ) -> Result < & mut Self , AddForeignUtxoError > {
378+ let script_pubkey = if let Some ( ref txout) = psbt_input. witness_utxo {
379+ txout. script_pubkey . clone ( )
380+ } else if let Some ( tx) = psbt_input. non_witness_utxo . as_ref ( ) {
381+ if tx. compute_txid ( ) != outpoint. txid {
382+ return Err ( AddForeignUtxoError :: InvalidTxid {
383+ input_txid : tx. compute_txid ( ) ,
384+ foreign_utxo : outpoint,
385+ } ) ;
386+ }
387+ if tx. output . len ( ) <= outpoint. vout as usize {
388+ return Err ( AddForeignUtxoError :: InvalidOutpoint ( outpoint) ) ;
389+ }
390+
391+ if let Ok ( txout) = tx. tx_out ( outpoint. vout as usize ) {
392+ txout. script_pubkey . clone ( )
393+ } else {
394+ return Err ( AddForeignUtxoError :: InvalidOutpoint ( outpoint) ) ;
395+ }
396+ } else {
397+ return Err ( AddForeignUtxoError :: MissingUtxo ) ;
398+ } ;
399+
378400 // Avoid the inclusion of local utxos as foreign utxos
379- if self . wallet . tx_graph ( ) . get_txout ( outpoint) . is_some ( ) {
380- return Err ( AddForeignUtxoError :: NotForeignUtxo ) ;
401+ if self . wallet . is_mine ( script_pubkey) {
402+ // TODO(2.0.0): return Err(AddForeignUtxoError::NotForeignUtxo);
403+ // No-op to avoid breaking changes until next major release
404+ return Ok ( self ) ;
381405 } ;
382- if psbt_input. witness_utxo . is_none ( ) {
383- match psbt_input. non_witness_utxo . as_ref ( ) {
384- Some ( tx) => {
385- if tx. compute_txid ( ) != outpoint. txid {
386- return Err ( AddForeignUtxoError :: InvalidTxid {
387- input_txid : tx. compute_txid ( ) ,
388- foreign_utxo : outpoint,
389- } ) ;
390- }
391- if tx. output . len ( ) <= outpoint. vout as usize {
392- return Err ( AddForeignUtxoError :: InvalidOutpoint ( outpoint) ) ;
393- }
394- }
395- None => {
396- return Err ( AddForeignUtxoError :: MissingUtxo ) ;
397- }
398- }
399- }
400406
401407 self . params . utxos . push ( WeightedUtxo {
402408 satisfaction_weight,
@@ -716,8 +722,8 @@ pub enum AddForeignUtxoError {
716722 InvalidOutpoint ( OutPoint ) ,
717723 /// Foreign utxo missing witness_utxo or non_witness_utxo
718724 MissingUtxo ,
719- /// UTxO is owned by wallet
720- NotForeignUtxo ,
725+ // Avoid breaking changes until next major release
726+ // TODO(2.0.0): NotForeignUtxo,
721727}
722728
723729impl fmt:: Display for AddForeignUtxoError {
@@ -737,7 +743,8 @@ impl fmt::Display for AddForeignUtxoError {
737743 outpoint. txid, outpoint. vout,
738744 ) ,
739745 Self :: MissingUtxo => write ! ( f, "Foreign utxo missing witness_utxo or non_witness_utxo" ) ,
740- Self :: NotForeignUtxo => write ! ( f, "UTxO is owned by wallet" ) ,
746+ // Avoid breaking changes until next major release
747+ // TODO(2.0.0): Self::NotForeignUtxo => write!(f, "UTxO is owned by wallet"),
741748 }
742749 }
743750}
@@ -1106,4 +1113,21 @@ mod test {
11061113 builder. fee_rate ( FeeRate :: from_sat_per_kwu ( feerate + 250 ) ) ;
11071114 let _ = builder. finish ( ) . unwrap ( ) ;
11081115 }
1116+
1117+ #[ test]
1118+ fn test_add_foreign_utxo_fails_when_utxo_is_owned_by_wallet ( ) {
1119+ use crate :: test_utils:: get_funded_wallet_wpkh;
1120+ let ( mut wallet, _) = get_funded_wallet_wpkh ( ) ;
1121+ let outpoint = wallet. list_unspent ( ) . next ( ) . expect ( "must exist" ) . outpoint ;
1122+ let foreign_utxo_satisfaction = wallet
1123+ . public_descriptor ( KeychainKind :: External )
1124+ . max_weight_to_satisfy ( )
1125+ . unwrap ( ) ;
1126+
1127+ let mut builder = wallet. build_tx ( ) ;
1128+ let _ =
1129+ builder. add_foreign_utxo ( outpoint, psbt:: Input :: default ( ) , foreign_utxo_satisfaction) ;
1130+ // TODO(2.0.0): assert!(matches!(result, Err(AddForeignUtxoError::NotForeignUtxo)));
1131+ assert ! ( builder. params. utxos. is_empty( ) ) ;
1132+ }
11091133}
0 commit comments