@@ -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,10 @@ 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
+ ///
348
+ /// If your wallet does not support signing PSBTs you can call `psbt.extract_tx()` to get the
349
+ /// unsigned transaction and then sign it with your wallet.
350
+ fn sign_psbt ( & self , psbt : PartiallySignedTransaction ) -> Result < Transaction , ( ) > ;
347
351
}
348
352
349
353
/// An alternative to [`CoinSelectionSource`] that can be implemented and used along [`Wallet`] to
@@ -357,7 +361,10 @@ pub trait WalletSource {
357
361
/// Signs and provides the full [`TxIn::script_sig`] and [`TxIn::witness`] for all inputs within
358
362
/// the transaction known to the wallet (i.e., any provided via
359
363
/// [`WalletSource::list_confirmed_utxos`]).
360
- fn sign_tx ( & self , tx : Transaction ) -> Result < Transaction , ( ) > ;
364
+ ///
365
+ /// If your wallet does not support signing PSBTs you can call `psbt.extract_tx()` to get the
366
+ /// unsigned transaction and then sign it with your wallet.
367
+ fn sign_psbt ( & self , psbt : PartiallySignedTransaction ) -> Result < Transaction , ( ) > ;
361
368
}
362
369
363
370
/// A wrapper over [`WalletSource`] that implements [`CoinSelection`] by preferring UTXOs that would
@@ -504,8 +511,8 @@ where
504
511
. or_else ( |_| do_coin_selection ( true , true ) )
505
512
}
506
513
507
- fn sign_tx ( & self , tx : Transaction ) -> Result < Transaction , ( ) > {
508
- self . source . sign_tx ( tx )
514
+ fn sign_psbt ( & self , psbt : PartiallySignedTransaction ) -> Result < Transaction , ( ) > {
515
+ self . source . sign_psbt ( psbt )
509
516
}
510
517
}
511
518
@@ -549,16 +556,16 @@ where
549
556
}
550
557
551
558
/// 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 ( .. ) {
559
+ fn process_coin_selection ( & self , tx : & mut Transaction , coin_selection : & CoinSelection ) {
560
+ for utxo in coin_selection. confirmed_utxos . iter ( ) {
554
561
tx. input . push ( TxIn {
555
562
previous_output : utxo. outpoint ,
556
563
script_sig : ScriptBuf :: new ( ) ,
557
564
sequence : Sequence :: ZERO ,
558
565
witness : Witness :: new ( ) ,
559
566
} ) ;
560
567
}
561
- if let Some ( change_output) = coin_selection. change_output . take ( ) {
568
+ if let Some ( change_output) = coin_selection. change_output . clone ( ) {
562
569
tx. output . push ( change_output) ;
563
570
} else if tx. output . is_empty ( ) {
564
571
// We weren't provided a change output, likely because the input set was a perfect
@@ -595,7 +602,7 @@ where
595
602
596
603
log_debug ! ( self . logger, "Peforming coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW" ,
597
604
package_target_feerate_sat_per_1000_weight) ;
598
- let coin_selection = self . utxo_source . select_confirmed_utxos (
605
+ let coin_selection: CoinSelection = self . utxo_source . select_confirmed_utxos (
599
606
claim_id, must_spend, & [ ] , package_target_feerate_sat_per_1000_weight,
600
607
) ?;
601
608
@@ -613,15 +620,29 @@ where
613
620
let total_input_amount = must_spend_amount +
614
621
coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. output . value ) . sum :: < u64 > ( ) ;
615
622
616
- self . process_coin_selection ( & mut anchor_tx, coin_selection) ;
623
+ self . process_coin_selection ( & mut anchor_tx, & coin_selection) ;
617
624
let anchor_txid = anchor_tx. txid ( ) ;
618
625
619
- debug_assert_eq ! ( anchor_tx. output. len( ) , 1 ) ;
626
+ // construct psbt
627
+ let mut anchor_psbt = PartiallySignedTransaction :: from_unsigned_tx ( anchor_tx) . unwrap ( ) ;
628
+ // add witness_utxo to anchor input
629
+ anchor_psbt. inputs [ 0 ] . witness_utxo = Some ( anchor_descriptor. previous_utxo ( ) ) ;
630
+ // add witness_utxo to remaining inputs
631
+ for ( idx, utxo) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
632
+ // add 1 to skip the anchor input
633
+ let index = idx + 1 ;
634
+ debug_assert_eq ! ( anchor_psbt. unsigned_tx. input[ index] . previous_output, utxo. outpoint) ;
635
+ if utxo. output . script_pubkey . is_witness_program ( ) {
636
+ anchor_psbt. inputs [ index] . witness_utxo = Some ( utxo. output ) ;
637
+ }
638
+ }
639
+
640
+ debug_assert_eq ! ( anchor_psbt. unsigned_tx. output. len( ) , 1 ) ;
620
641
#[ cfg( debug_assertions) ]
621
- let unsigned_tx_weight = anchor_tx . weight ( ) . to_wu ( ) - ( anchor_tx . input . len ( ) as u64 * EMPTY_SCRIPT_SIG_WEIGHT ) ;
642
+ let unsigned_tx_weight = anchor_psbt . unsigned_tx . weight ( ) . to_wu ( ) - ( anchor_psbt . unsigned_tx . input . len ( ) as u64 * EMPTY_SCRIPT_SIG_WEIGHT ) ;
622
643
623
644
log_debug ! ( self . logger, "Signing anchor transaction {}" , anchor_txid) ;
624
- anchor_tx = self . utxo_source . sign_tx ( anchor_tx ) ?;
645
+ anchor_tx = self . utxo_source . sign_psbt ( anchor_psbt ) ?;
625
646
626
647
let signer = anchor_descriptor. derive_channel_signer ( & self . signer_provider ) ;
627
648
let anchor_sig = signer. sign_holder_anchor_input ( & anchor_tx, 0 , & self . secp ) ?;
@@ -690,7 +711,7 @@ where
690
711
#[ cfg( debug_assertions) ]
691
712
let must_spend_amount = must_spend. iter ( ) . map ( |input| input. previous_utxo . value ) . sum :: < u64 > ( ) ;
692
713
693
- let coin_selection = self . utxo_source . select_confirmed_utxos (
714
+ let coin_selection: CoinSelection = self . utxo_source . select_confirmed_utxos (
694
715
claim_id, must_spend, & htlc_tx. output , target_feerate_sat_per_1000_weight,
695
716
) ?;
696
717
@@ -701,13 +722,30 @@ where
701
722
let total_input_amount = must_spend_amount +
702
723
coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. output . value ) . sum :: < u64 > ( ) ;
703
724
704
- self . process_coin_selection ( & mut htlc_tx, coin_selection) ;
725
+ self . process_coin_selection ( & mut htlc_tx, & coin_selection) ;
726
+
727
+ // construct psbt
728
+ let mut htlc_psbt = PartiallySignedTransaction :: from_unsigned_tx ( htlc_tx) . unwrap ( ) ;
729
+ // add witness_utxo to htlc inputs
730
+ for ( i, htlc_descriptor) in htlc_descriptors. iter ( ) . enumerate ( ) {
731
+ debug_assert_eq ! ( htlc_psbt. unsigned_tx. input[ i] . previous_output, htlc_descriptor. outpoint( ) ) ;
732
+ htlc_psbt. inputs [ i] . witness_utxo = Some ( htlc_descriptor. previous_utxo ( & self . secp ) ) ;
733
+ }
734
+ // add witness_utxo to remaining inputs
735
+ for ( idx, utxo) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
736
+ // offset to skip the htlc inputs
737
+ let index = idx + htlc_descriptors. len ( ) ;
738
+ debug_assert_eq ! ( htlc_psbt. unsigned_tx. input[ index] . previous_output, utxo. outpoint) ;
739
+ if utxo. output . script_pubkey . is_witness_program ( ) {
740
+ htlc_psbt. inputs [ index] . witness_utxo = Some ( utxo. output ) ;
741
+ }
742
+ }
705
743
706
744
#[ cfg( debug_assertions) ]
707
- let unsigned_tx_weight = htlc_tx . weight ( ) . to_wu ( ) - ( htlc_tx . input . len ( ) as u64 * EMPTY_SCRIPT_SIG_WEIGHT ) ;
745
+ let unsigned_tx_weight = htlc_psbt . unsigned_tx . weight ( ) . to_wu ( ) - ( htlc_psbt . unsigned_tx . input . len ( ) as u64 * EMPTY_SCRIPT_SIG_WEIGHT ) ;
708
746
709
- log_debug ! ( self . logger, "Signing HTLC transaction {}" , htlc_tx . txid( ) ) ;
710
- htlc_tx = self . utxo_source . sign_tx ( htlc_tx ) ?;
747
+ log_debug ! ( self . logger, "Signing HTLC transaction {}" , htlc_psbt . unsigned_tx . txid( ) ) ;
748
+ htlc_tx = self . utxo_source . sign_psbt ( htlc_psbt ) ?;
711
749
712
750
let mut signers = BTreeMap :: new ( ) ;
713
751
for ( idx, htlc_descriptor) in htlc_descriptors. iter ( ) . enumerate ( ) {
0 commit comments