@@ -29,6 +29,7 @@ use crate::ln::chan_utils::{
2929 HTLC_TIMEOUT_INPUT_KEYED_ANCHOR_WITNESS_WEIGHT , HTLC_TIMEOUT_INPUT_P2A_ANCHOR_WITNESS_WEIGHT ,
3030 P2WSH_TXOUT_WEIGHT , SEGWIT_MARKER_FLAG_WEIGHT , TRUC_CHILD_MAX_WEIGHT , TRUC_MAX_WEIGHT ,
3131} ;
32+ use crate :: ln:: funding:: ConfirmedUtxo ;
3233use crate :: ln:: types:: ChannelId ;
3334use crate :: prelude:: * ;
3435use crate :: sign:: ecdsa:: EcdsaChannelSigner ;
@@ -345,14 +346,24 @@ impl Utxo {
345346pub struct CoinSelection {
346347 /// The set of UTXOs (with at least 1 confirmation) to spend and use within a transaction
347348 /// requiring additional fees.
348- pub confirmed_utxos : Vec < Utxo > ,
349+ pub confirmed_utxos : Vec < ConfirmedUtxo > ,
349350 /// An additional output tracking whether any change remained after coin selection. This output
350351 /// should always have a value above dust for its given `script_pubkey`. It should not be
351352 /// spent until the transaction it belongs to confirms to ensure mempool descendant limits are
352353 /// not met. This implies no other party should be able to spend it except us.
353354 pub change_output : Option < TxOut > ,
354355}
355356
357+ impl CoinSelection {
358+ fn satisfaction_weight ( & self ) -> u64 {
359+ self . confirmed_utxos . iter ( ) . map ( |ConfirmedUtxo { utxo, .. } | utxo. satisfaction_weight ) . sum ( )
360+ }
361+
362+ fn amount ( & self ) -> Amount {
363+ self . confirmed_utxos . iter ( ) . map ( |ConfirmedUtxo { utxo, .. } | utxo. output . value ) . sum ( )
364+ }
365+ }
366+
356367/// An abstraction over a bitcoin wallet that can perform coin selection over a set of UTXOs and can
357368/// sign for them. The coin selection method aims to mimic Bitcoin Core's `fundrawtransaction` RPC,
358369/// which most wallets should be able to satisfy. Otherwise, consider implementing [`WalletSource`],
@@ -419,9 +430,14 @@ pub trait CoinSelectionSource {
419430pub trait WalletSource {
420431 /// Returns all UTXOs, with at least 1 confirmation each, that are available to spend.
421432 fn list_confirmed_utxos < ' a > ( & ' a self ) -> AsyncResult < ' a , Vec < Utxo > , ( ) > ;
433+
434+ /// Returns the previous transaction containing the UTXO.
435+ fn get_prevtx < ' a > ( & ' a self , utxo : & Utxo ) -> AsyncResult < ' a , Transaction , ( ) > ;
436+
422437 /// Returns a script to use for change above dust resulting from a successful coin selection
423438 /// attempt.
424439 fn get_change_script < ' a > ( & ' a self ) -> AsyncResult < ' a , ScriptBuf , ( ) > ;
440+
425441 /// Signs and provides the full [`TxIn::script_sig`] and [`TxIn::witness`] for all inputs within
426442 /// the transaction known to the wallet (i.e., any provided via
427443 /// [`WalletSource::list_confirmed_utxos`]).
@@ -607,10 +623,13 @@ where
607623 Some ( TxOut { script_pubkey : change_script, value : change_output_amount } )
608624 } ;
609625
610- Ok ( CoinSelection {
611- confirmed_utxos : selected_utxos. into_iter ( ) . map ( |( utxo, _) | utxo) . collect ( ) ,
612- change_output,
613- } )
626+ let mut confirmed_utxos = Vec :: with_capacity ( selected_utxos. len ( ) ) ;
627+ for ( utxo, _) in selected_utxos {
628+ let prevtx = self . source . get_prevtx ( & utxo) . await ?;
629+ confirmed_utxos. push ( ConfirmedUtxo { utxo, prevtx } ) ;
630+ }
631+
632+ Ok ( CoinSelection { confirmed_utxos, change_output } )
614633 }
615634}
616635
@@ -719,7 +738,7 @@ where
719738
720739 /// Updates a transaction with the result of a successful coin selection attempt.
721740 fn process_coin_selection ( & self , tx : & mut Transaction , coin_selection : & CoinSelection ) {
722- for utxo in coin_selection. confirmed_utxos . iter ( ) {
741+ for ConfirmedUtxo { utxo, .. } in coin_selection. confirmed_utxos . iter ( ) {
723742 tx. input . push ( TxIn {
724743 previous_output : utxo. outpoint ,
725744 script_sig : ScriptBuf :: new ( ) ,
@@ -841,12 +860,10 @@ where
841860 output : vec ! [ ] ,
842861 } ;
843862
844- let input_satisfaction_weight: u64 =
845- coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. satisfaction_weight ) . sum ( ) ;
863+ let input_satisfaction_weight = coin_selection. satisfaction_weight ( ) ;
846864 let total_satisfaction_weight =
847865 anchor_input_witness_weight + EMPTY_SCRIPT_SIG_WEIGHT + input_satisfaction_weight;
848- let total_input_amount = must_spend_amount
849- + coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. output . value ) . sum ( ) ;
866+ let total_input_amount = must_spend_amount + coin_selection. amount ( ) ;
850867
851868 self . process_coin_selection ( & mut anchor_tx, & coin_selection) ;
852869 let anchor_txid = anchor_tx. compute_txid ( ) ;
@@ -856,7 +873,7 @@ where
856873 // add witness_utxo to anchor input
857874 anchor_psbt. inputs [ 0 ] . witness_utxo = Some ( anchor_descriptor. previous_utxo ( ) ) ;
858875 // add witness_utxo to remaining inputs
859- for ( idx, utxo) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
876+ for ( idx, ConfirmedUtxo { utxo, .. } ) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
860877 // add 1 to skip the anchor input
861878 let index = idx + 1 ;
862879 debug_assert_eq ! (
@@ -1096,13 +1113,11 @@ where
10961113 utxo_id = claim_id. step_with_bytes ( & broadcasted_htlcs. to_be_bytes ( ) ) ;
10971114
10981115 #[ cfg( debug_assertions) ]
1099- let input_satisfaction_weight: u64 =
1100- coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. satisfaction_weight ) . sum ( ) ;
1116+ let input_satisfaction_weight = coin_selection. satisfaction_weight ( ) ;
11011117 #[ cfg( debug_assertions) ]
11021118 let total_satisfaction_weight = must_spend_satisfaction_weight + input_satisfaction_weight;
11031119 #[ cfg( debug_assertions) ]
1104- let input_value: u64 =
1105- coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. output . value . to_sat ( ) ) . sum ( ) ;
1120+ let input_value = coin_selection. amount ( ) . to_sat ( ) ;
11061121 #[ cfg( debug_assertions) ]
11071122 let total_input_amount = must_spend_amount + input_value;
11081123
@@ -1120,7 +1135,7 @@ where
11201135 }
11211136
11221137 // add witness_utxo to remaining inputs
1123- for ( idx, utxo) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
1138+ for ( idx, ConfirmedUtxo { utxo, .. } ) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
11241139 // offset to skip the htlc inputs
11251140 let index = idx + selected_htlcs. len ( ) ;
11261141 debug_assert_eq ! ( htlc_psbt. unsigned_tx. input[ index] . previous_output, utxo. outpoint) ;
@@ -1269,9 +1284,8 @@ mod tests {
12691284 use crate :: util:: ser:: Readable ;
12701285 use crate :: util:: test_utils:: { TestBroadcaster , TestLogger } ;
12711286
1272- use bitcoin:: hashes:: Hash ;
12731287 use bitcoin:: hex:: FromHex ;
1274- use bitcoin:: { Network , ScriptBuf , Transaction , Txid } ;
1288+ use bitcoin:: { Network , ScriptBuf , Transaction } ;
12751289
12761290 struct TestCoinSelectionSource {
12771291 // (commitment + anchor value, commitment + input weight, target feerate, result)
@@ -1291,8 +1305,12 @@ mod tests {
12911305 Ok ( res)
12921306 }
12931307 fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > {
1294- // FIXME: Why does handle_channel_close override the witness?
1295- Ok ( psbt. unsigned_tx )
1308+ let mut tx = psbt. unsigned_tx ;
1309+ // Channel output, add a realistic size witness to make the assertions happy
1310+ //
1311+ // FIXME: This doesn't seem to be needed since handle_channel_close overrides it
1312+ tx. input . first_mut ( ) . unwrap ( ) . witness = Witness :: from_slice ( & [ vec ! [ 42 ; 162 ] ] ) ;
1313+ Ok ( tx)
12961314 }
12971315 }
12981316
@@ -1328,6 +1346,16 @@ mod tests {
13281346 . weight ( )
13291347 . to_wu ( ) ;
13301348
1349+ let prevtx = Transaction {
1350+ version : Version :: TWO ,
1351+ lock_time : LockTime :: ZERO ,
1352+ input : vec ! [ ] ,
1353+ output : vec ! [ TxOut {
1354+ value: Amount :: from_sat( 200 ) ,
1355+ script_pubkey: ScriptBuf :: new( )
1356+ } ] ,
1357+ } ;
1358+
13311359 let broadcaster = TestBroadcaster :: new ( Network :: Testnet ) ;
13321360 let source = TestCoinSelectionSource {
13331361 expected_selects : Mutex :: new ( vec ! [
@@ -1342,14 +1370,14 @@ mod tests {
13421370 commitment_and_anchor_fee,
13431371 868 ,
13441372 CoinSelection {
1345- confirmed_utxos: vec![ Utxo {
1346- outpoint: OutPoint { txid: Txid :: from_byte_array( [ 44 ; 32 ] ) , vout: 0 } ,
1347- output: TxOut {
1348- value: Amount :: from_sat( 200 ) ,
1349- script_pubkey: ScriptBuf :: new( ) ,
1373+ confirmed_utxos: vec![ ConfirmedUtxo {
1374+ utxo: Utxo {
1375+ outpoint: OutPoint { txid: prevtx. compute_txid( ) , vout: 0 } ,
1376+ output: prevtx. output[ 0 ] . clone( ) ,
1377+ satisfaction_weight: 5 , // Just the script_sig and witness lengths
1378+ sequence: Sequence :: ENABLE_RBF_NO_LOCKTIME ,
13501379 } ,
1351- satisfaction_weight: 5 , // Just the script_sig and witness lengths
1352- sequence: Sequence :: ENABLE_RBF_NO_LOCKTIME ,
1380+ prevtx,
13531381 } ] ,
13541382 change_output: None ,
13551383 } ,
0 commit comments