@@ -35,6 +35,7 @@ use bitcoin::{OutPoint, PubkeyHash, Sequence, ScriptBuf, Transaction, TxIn, TxOu
35
35
use bitcoin:: blockdata:: constants:: WITNESS_SCALE_FACTOR ;
36
36
use bitcoin:: blockdata:: locktime:: absolute:: LockTime ;
37
37
use bitcoin:: consensus:: Encodable ;
38
+ use bitcoin:: psbt:: PartiallySignedTransaction ;
38
39
use bitcoin:: secp256k1;
39
40
use bitcoin:: secp256k1:: Secp256k1 ;
40
41
use bitcoin:: secp256k1:: ecdsa:: Signature ;
@@ -343,7 +344,7 @@ pub trait CoinSelectionSource {
343
344
) -> Result < CoinSelection , ( ) > ;
344
345
/// Signs and provides the full witness for all inputs within the transaction known to the
345
346
/// trait (i.e., any provided via [`CoinSelectionSource::select_confirmed_utxos`]).
346
- fn sign_tx ( & self , tx : Transaction ) -> Result < Transaction , ( ) > ;
347
+ fn sign_psbt ( & self , tx : PartiallySignedTransaction ) -> Result < Transaction , ( ) > ;
347
348
}
348
349
349
350
/// An alternative to [`CoinSelectionSource`] that can be implemented and used along [`Wallet`] to
@@ -357,7 +358,7 @@ pub trait WalletSource {
357
358
/// Signs and provides the full [`TxIn::script_sig`] and [`TxIn::witness`] for all inputs within
358
359
/// the transaction known to the wallet (i.e., any provided via
359
360
/// [`WalletSource::list_confirmed_utxos`]).
360
- fn sign_tx ( & self , tx : Transaction ) -> Result < Transaction , ( ) > ;
361
+ fn sign_psbt ( & self , psbt : PartiallySignedTransaction ) -> Result < Transaction , ( ) > ;
361
362
}
362
363
363
364
/// A wrapper over [`WalletSource`] that implements [`CoinSelection`] by preferring UTXOs that would
@@ -504,8 +505,8 @@ where
504
505
. or_else ( |_| do_coin_selection ( true , true ) )
505
506
}
506
507
507
- fn sign_tx ( & self , tx : Transaction ) -> Result < Transaction , ( ) > {
508
- self . source . sign_tx ( tx )
508
+ fn sign_psbt ( & self , psbt : PartiallySignedTransaction ) -> Result < Transaction , ( ) > {
509
+ self . source . sign_psbt ( psbt )
509
510
}
510
511
}
511
512
@@ -549,16 +550,16 @@ where
549
550
}
550
551
551
552
/// Updates a transaction with the result of a successful coin selection attempt.
552
- fn process_coin_selection ( & self , tx : & mut Transaction , mut coin_selection : CoinSelection ) {
553
- for utxo in coin_selection. confirmed_utxos . drain ( .. ) {
553
+ fn process_coin_selection ( & self , tx : & mut Transaction , coin_selection : & CoinSelection ) {
554
+ for utxo in coin_selection. confirmed_utxos . iter ( ) {
554
555
tx. input . push ( TxIn {
555
556
previous_output : utxo. outpoint ,
556
557
script_sig : ScriptBuf :: new ( ) ,
557
558
sequence : Sequence :: ZERO ,
558
559
witness : Witness :: new ( ) ,
559
560
} ) ;
560
561
}
561
- if let Some ( change_output) = coin_selection. change_output . take ( ) {
562
+ if let Some ( change_output) = coin_selection. change_output . clone ( ) {
562
563
tx. output . push ( change_output) ;
563
564
} else if tx. output . is_empty ( ) {
564
565
// We weren't provided a change output, likely because the input set was a perfect
@@ -613,15 +614,28 @@ where
613
614
let total_input_amount = must_spend_amount +
614
615
coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. output . value ) . sum :: < u64 > ( ) ;
615
616
616
- self . process_coin_selection ( & mut anchor_tx, coin_selection) ;
617
+ self . process_coin_selection ( & mut anchor_tx, & coin_selection) ;
617
618
let anchor_txid = anchor_tx. txid ( ) ;
618
619
620
+ // construct psbt
621
+ let mut anchor_psbt = PartiallySignedTransaction :: from_unsigned_tx ( anchor_tx. clone ( ) ) . unwrap ( ) ;
622
+ // add witness_utxo to anchor input
623
+ anchor_psbt. inputs [ 0 ] . witness_utxo = Some ( anchor_descriptor. previous_utxo ( ) ) ;
624
+ // add witness_utxo to remaining inputs
625
+ for ( idx, utxo) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
626
+ // add 1 to skip the anchor input
627
+ let index = idx + 1 ;
628
+ debug_assert_eq ! ( anchor_psbt. unsigned_tx. input[ index] . previous_output, utxo. outpoint) ;
629
+ anchor_psbt. inputs [ index] . witness_utxo = Some ( utxo. output ) ;
630
+ }
631
+
619
632
debug_assert_eq ! ( anchor_tx. output. len( ) , 1 ) ;
620
633
#[ cfg( debug_assertions) ]
621
634
let unsigned_tx_weight = anchor_tx. weight ( ) . to_wu ( ) - ( anchor_tx. input . len ( ) as u64 * EMPTY_SCRIPT_SIG_WEIGHT ) ;
622
635
623
636
log_debug ! ( self . logger, "Signing anchor transaction {}" , anchor_txid) ;
624
- anchor_tx = self . utxo_source . sign_tx ( anchor_tx) ?;
637
+ debug_assert ! ( anchor_psbt. inputs. iter( ) . all( |i| i. witness_utxo. is_some( ) ) ) ;
638
+ anchor_tx = self . utxo_source . sign_psbt ( anchor_psbt) ?;
625
639
626
640
let signer = anchor_descriptor. derive_channel_signer ( & self . signer_provider ) ;
627
641
let anchor_sig = signer. sign_holder_anchor_input ( & anchor_tx, 0 , & self . secp ) ?;
@@ -701,13 +715,29 @@ where
701
715
let total_input_amount = must_spend_amount +
702
716
coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. output . value ) . sum :: < u64 > ( ) ;
703
717
704
- self . process_coin_selection ( & mut htlc_tx, coin_selection) ;
718
+ self . process_coin_selection ( & mut htlc_tx, & coin_selection) ;
719
+
720
+ // construct psbt
721
+ let mut htlc_psbt = PartiallySignedTransaction :: from_unsigned_tx ( htlc_tx. clone ( ) ) . unwrap ( ) ;
722
+ // add witness_utxo to htlc inputs
723
+ for ( i, htlc_descriptor) in htlc_descriptors. iter ( ) . enumerate ( ) {
724
+ debug_assert_eq ! ( htlc_psbt. unsigned_tx. input[ i] . previous_output, htlc_descriptor. outpoint( ) ) ;
725
+ htlc_psbt. inputs [ i] . witness_utxo = Some ( htlc_descriptor. previous_utxo ( & self . secp ) ) ;
726
+ }
727
+ // add witness_utxo to remaining inputs
728
+ for ( idx, utxo) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
729
+ // offset to skip the htlc inputs
730
+ let index = idx + htlc_descriptors. len ( ) ;
731
+ debug_assert_eq ! ( htlc_psbt. unsigned_tx. input[ index] . previous_output, utxo. outpoint) ;
732
+ htlc_psbt. inputs [ index] . witness_utxo = Some ( utxo. output ) ;
733
+ }
705
734
706
735
#[ cfg( debug_assertions) ]
707
736
let unsigned_tx_weight = htlc_tx. weight ( ) . to_wu ( ) - ( htlc_tx. input . len ( ) as u64 * EMPTY_SCRIPT_SIG_WEIGHT ) ;
708
737
709
738
log_debug ! ( self . logger, "Signing HTLC transaction {}" , htlc_tx. txid( ) ) ;
710
- htlc_tx = self . utxo_source . sign_tx ( htlc_tx) ?;
739
+ debug_assert ! ( htlc_psbt. inputs. iter( ) . all( |i| i. witness_utxo. is_some( ) ) ) ;
740
+ htlc_tx = self . utxo_source . sign_psbt ( htlc_psbt) ?;
711
741
712
742
let mut signers = BTreeMap :: new ( ) ;
713
743
for ( idx, htlc_descriptor) in htlc_descriptors. iter ( ) . enumerate ( ) {
0 commit comments