@@ -1644,18 +1644,121 @@ fn test_calculate_fee_with_missing_foreign_utxo() {
16441644}
16451645
16461646#[ test]
1647- fn test_add_foreign_utxo_invalid_psbt_input ( ) {
1647+ fn test_add_foreign_utxo_fails_without_psbt_input_prev_tx_data ( ) {
16481648 let ( mut wallet, _) = get_funded_wallet_wpkh ( ) ;
1649- let outpoint = wallet. list_unspent ( ) . next ( ) . expect ( "must exist" ) . outpoint ;
1649+ let address = Address :: from_str ( "bcrt1q3qtze4ys45tgdvguj66zrk4fu6hq3a3v9pfly5" )
1650+ . expect ( "address" )
1651+ . require_network ( Network :: Regtest )
1652+ . unwrap ( ) ;
1653+ let tx0 = Transaction {
1654+ output : vec ! [ TxOut {
1655+ value: Amount :: from_sat( 76_000 ) ,
1656+ script_pubkey: address. script_pubkey( ) ,
1657+ } ] ,
1658+ ..new_tx ( 0 )
1659+ } ;
1660+ let external_outpoint = OutPoint {
1661+ txid : tx0. compute_txid ( ) ,
1662+ vout : 0 ,
1663+ } ;
16501664 let foreign_utxo_satisfaction = wallet
16511665 . public_descriptor ( KeychainKind :: External )
16521666 . max_weight_to_satisfy ( )
16531667 . unwrap ( ) ;
16541668
16551669 let mut builder = wallet. build_tx ( ) ;
1656- let result =
1657- builder. add_foreign_utxo ( outpoint, psbt:: Input :: default ( ) , foreign_utxo_satisfaction) ;
1658- assert ! ( matches!( result, Err ( AddForeignUtxoError :: MissingUtxo ) ) ) ;
1670+ let result = builder. add_foreign_utxo (
1671+ external_outpoint,
1672+ psbt:: Input :: default ( ) ,
1673+ foreign_utxo_satisfaction,
1674+ ) ;
1675+ assert ! (
1676+ matches!( result, Err ( AddForeignUtxoError :: MissingUtxo ) ) ,
1677+ "should fail when there is no data about the transaction creating the input"
1678+ ) ;
1679+ }
1680+
1681+ #[ test]
1682+ fn test_add_foreign_utxo_fails_when_utxo_is_owned_by_wallet_with_prev_txout ( ) {
1683+ let ( mut wallet1, _) =
1684+ get_funded_wallet_single ( "wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)" ) ;
1685+
1686+ let utxo = wallet1. list_unspent ( ) . next ( ) . expect ( "must take!" ) ;
1687+ let foreign_utxo_satisfaction = wallet1
1688+ . public_descriptor ( KeychainKind :: External )
1689+ . max_weight_to_satisfy ( )
1690+ . unwrap ( ) ;
1691+
1692+ let psbt_input = psbt:: Input {
1693+ // Add txout
1694+ witness_utxo : Some ( utxo. txout . clone ( ) ) ,
1695+ ..Default :: default ( )
1696+ } ;
1697+
1698+ let mut builder = wallet1. build_tx ( ) ;
1699+ let result = builder. add_foreign_utxo ( utxo. outpoint , psbt_input, foreign_utxo_satisfaction) ;
1700+ assert ! (
1701+ matches!( result, Err ( AddForeignUtxoError :: NotForeignUtxo ) ) ,
1702+ "should fail when the outpoint provided is not foreign to the wallet"
1703+ ) ;
1704+ }
1705+
1706+ #[ test]
1707+ fn test_add_foreign_utxo_fails_when_utxo_is_owned_by_wallet_with_full_prev_tx ( ) {
1708+ let ( mut wallet1, txid1) =
1709+ get_funded_wallet_single ( "wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)" ) ;
1710+
1711+ let utxo = wallet1. list_unspent ( ) . next ( ) . expect ( "must take!" ) ;
1712+ let full_tx = wallet1. get_tx ( txid1) . unwrap ( ) . tx_node . tx . clone ( ) ;
1713+ let foreign_utxo_satisfaction = wallet1
1714+ . public_descriptor ( KeychainKind :: External )
1715+ . max_weight_to_satisfy ( )
1716+ . unwrap ( ) ;
1717+
1718+ let psbt_input = psbt:: Input {
1719+ // Add full transaction
1720+ non_witness_utxo : Some ( full_tx. as_ref ( ) . clone ( ) ) ,
1721+ ..Default :: default ( )
1722+ } ;
1723+
1724+ let mut builder = wallet1. build_tx ( ) ;
1725+ let result = builder. add_foreign_utxo ( utxo. outpoint , psbt_input, foreign_utxo_satisfaction) ;
1726+ assert ! (
1727+ matches!( result, Err ( AddForeignUtxoError :: NotForeignUtxo ) ) ,
1728+ "should fail when the outpoint provided is not foreign to the wallet"
1729+ ) ;
1730+ }
1731+
1732+ #[ test]
1733+ fn test_add_foreign_utxo_fails_with_invalid_outpoint_vout ( ) {
1734+ let ( mut wallet1, txid1) =
1735+ get_funded_wallet_single ( "wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)" ) ;
1736+
1737+ let utxo = wallet1. list_unspent ( ) . next ( ) . expect ( "must take!" ) ;
1738+ let full_tx = wallet1. get_tx ( txid1) . unwrap ( ) . tx_node . tx . clone ( ) ;
1739+ let foreign_utxo_satisfaction = wallet1
1740+ . public_descriptor ( KeychainKind :: External )
1741+ . max_weight_to_satisfy ( )
1742+ . unwrap ( ) ;
1743+
1744+ let psbt_input = psbt:: Input {
1745+ non_witness_utxo : Some ( full_tx. as_ref ( ) . clone ( ) ) ,
1746+ ..Default :: default ( )
1747+ } ;
1748+
1749+ let mut builder = wallet1. build_tx ( ) ;
1750+ let result = builder. add_foreign_utxo (
1751+ OutPoint {
1752+ vout : full_tx. output . len ( ) as u32 + 1 ,
1753+ txid : utxo. outpoint . txid ,
1754+ } ,
1755+ psbt_input,
1756+ foreign_utxo_satisfaction,
1757+ ) ;
1758+ assert ! (
1759+ matches!( result, Err ( AddForeignUtxoError :: InvalidOutpoint { .. } ) ) ,
1760+ "should fail when the outpoint provided index is not one of the possible transaction vouts"
1761+ ) ;
16591762}
16601763
16611764#[ test]
@@ -1674,19 +1777,23 @@ fn test_add_foreign_utxo_where_outpoint_doesnt_match_psbt_input() {
16741777 . unwrap ( ) ;
16751778
16761779 let mut builder = wallet1. build_tx ( ) ;
1780+
1781+ // Check we are activating the code path that should rise the error
16771782 assert ! (
1678- builder
1679- . add_foreign_utxo(
1783+ matches! (
1784+ builder . add_foreign_utxo(
16801785 utxo2. outpoint,
16811786 psbt:: Input {
16821787 non_witness_utxo: Some ( tx1. as_ref( ) . clone( ) ) ,
16831788 ..Default :: default ( )
16841789 } ,
16851790 satisfaction_weight
1686- )
1687- . is_err( ) ,
1688- "should fail when outpoint doesn't match psbt_input"
1791+ ) ,
1792+ Err ( AddForeignUtxoError :: InvalidTxid { .. } )
1793+ ) ,
1794+ "should fail when outpoint txid doesn't match psbt_input txout txid"
16891795 ) ;
1796+
16901797 assert ! (
16911798 builder
16921799 . add_foreign_utxo(
0 commit comments