@@ -18,13 +18,15 @@ use bitcoin::blockdata::script::Script;
18
18
19
19
use bitcoin:: hash_types:: Txid ;
20
20
21
+ #[ cfg( anchors) ]
22
+ use bitcoin:: secp256k1:: PublicKey ;
21
23
use bitcoin:: secp256k1:: { Secp256k1 , ecdsa:: Signature } ;
22
24
use bitcoin:: secp256k1;
23
25
24
26
use crate :: ln:: msgs:: DecodeError ;
25
27
use crate :: ln:: PaymentPreimage ;
26
28
#[ cfg( anchors) ]
27
- use crate :: ln:: chan_utils;
29
+ use crate :: ln:: chan_utils:: { self , HTLCOutputInCommitment } ;
28
30
use crate :: ln:: chan_utils:: { ChannelTransactionParameters , HolderCommitmentTransaction } ;
29
31
#[ cfg( anchors) ]
30
32
use crate :: chain:: chaininterface:: ConfirmationTarget ;
@@ -170,6 +172,17 @@ impl Writeable for Option<Vec<Option<(usize, Signature)>>> {
170
172
}
171
173
}
172
174
175
+ #[ cfg( anchors) ]
176
+ /// The claim commonly referred to as the pre-signed second-stage HTLC transaction.
177
+ pub ( crate ) struct ExternalHTLCClaim {
178
+ pub ( crate ) per_commitment_number : u64 ,
179
+ pub ( crate ) htlc : HTLCOutputInCommitment ,
180
+ pub ( crate ) preimage : Option < PaymentPreimage > ,
181
+ pub ( crate ) counterparty_base_htlc_key : PublicKey ,
182
+ pub ( crate ) counterparty_base_revocation_key : PublicKey ,
183
+ pub ( crate ) counterparty_sig : Signature ,
184
+ }
185
+
173
186
// Represents the different types of claims for which events are yielded externally to satisfy said
174
187
// claims.
175
188
#[ cfg( anchors) ]
@@ -181,6 +194,11 @@ pub(crate) enum ClaimEvent {
181
194
commitment_tx : Transaction ,
182
195
anchor_output_idx : u32 ,
183
196
} ,
197
+ BumpHTLC {
198
+ target_feerate_sat_per_1000_weight : u32 ,
199
+ tx_template : Transaction ,
200
+ htlcs : Vec < ExternalHTLCClaim > ,
201
+ } ,
184
202
}
185
203
186
204
/// Represents the different ways an output can be claimed (i.e., spent to an address under our
@@ -472,15 +490,34 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
472
490
// didn't receive confirmation of it before, or not enough reorg-safe depth on top of it).
473
491
let new_timer = Some ( cached_request. get_height_timer ( cur_height) ) ;
474
492
if cached_request. is_malleable ( ) {
493
+ #[ cfg( anchors) ]
494
+ { // Attributes are not allowed on if expressions on our current MSRV of 1.41.
495
+ if cached_request. requires_external_funding ( ) {
496
+ let target_feerate_sat_per_1000_weight = cached_request
497
+ . compute_package_feerate ( fee_estimator, ConfirmationTarget :: HighPriority ) ;
498
+ let ( tx_template, htlcs) = cached_request. construct_malleable_package_with_external_funding ( self ) ;
499
+ return Some ( (
500
+ new_timer,
501
+ target_feerate_sat_per_1000_weight as u64 ,
502
+ OnchainClaim :: Event ( ClaimEvent :: BumpHTLC {
503
+ target_feerate_sat_per_1000_weight,
504
+ tx_template,
505
+ htlcs,
506
+ } ) ,
507
+ ) ) ;
508
+ }
509
+ }
510
+
475
511
let predicted_weight = cached_request. package_weight ( & self . destination_script ) ;
476
- if let Some ( ( output_value, new_feerate) ) =
477
- cached_request. compute_package_output ( predicted_weight, self . destination_script . dust_value ( ) . to_sat ( ) , fee_estimator, logger) {
512
+ if let Some ( ( output_value, new_feerate) ) = cached_request. compute_package_output (
513
+ predicted_weight, self . destination_script . dust_value ( ) . to_sat ( ) , fee_estimator, logger,
514
+ ) {
478
515
assert ! ( new_feerate != 0 ) ;
479
516
480
517
let transaction = cached_request. finalize_malleable_package ( self , output_value, self . destination_script . clone ( ) , logger) . unwrap ( ) ;
481
518
log_trace ! ( logger, "...with timer {} and feerate {}" , new_timer. unwrap( ) , new_feerate) ;
482
519
assert ! ( predicted_weight >= transaction. weight( ) ) ;
483
- return Some ( ( new_timer, new_feerate, OnchainClaim :: Tx ( transaction) ) )
520
+ return Some ( ( new_timer, new_feerate, OnchainClaim :: Tx ( transaction) ) ) ;
484
521
}
485
522
} else {
486
523
// Untractable packages cannot have their fees bumped through Replace-By-Fee. Some
@@ -536,7 +573,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
536
573
debug_assert ! ( false , "Only HolderFundingOutput inputs should be untractable and require external funding" ) ;
537
574
None
538
575
} ,
539
- } ) ;
576
+ } )
540
577
}
541
578
None
542
579
}
@@ -621,6 +658,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
621
658
log_info ! ( logger, "Yielding onchain event to spend inputs {:?}" , req. outpoints( ) ) ;
622
659
let txid = match claim_event {
623
660
ClaimEvent :: BumpCommitment { ref commitment_tx, .. } => commitment_tx. txid ( ) ,
661
+ ClaimEvent :: BumpHTLC { ref tx_template, .. } => tx_template. txid ( ) ,
624
662
} ;
625
663
self . pending_claim_events . insert ( txid, claim_event) ;
626
664
txid
@@ -646,14 +684,33 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
646
684
// outpoints to know if transaction is the original claim or a bumped one issued
647
685
// by us.
648
686
let mut set_equality = true ;
649
- if request. outpoints ( ) . len ( ) != tx. input . len ( ) {
650
- set_equality = false ;
687
+ if !request. requires_external_funding ( ) ||
688
+ ( request. requires_external_funding ( ) && !request. is_malleable ( ) )
689
+ {
690
+ // If the claim does not require external funds to be allocated through
691
+ // additional inputs we can simply check the inputs in order as they
692
+ // cannot change under us.
693
+ if request. outpoints ( ) . len ( ) != tx. input . len ( ) {
694
+ set_equality = false ;
695
+ } else {
696
+ for ( claim_inp, tx_inp) in request. outpoints ( ) . iter ( ) . zip ( tx. input . iter ( ) ) {
697
+ if * * claim_inp != tx_inp. previous_output {
698
+ set_equality = false ;
699
+ }
700
+ }
701
+ }
651
702
} else {
652
- for ( claim_inp, tx_inp) in request. outpoints ( ) . iter ( ) . zip ( tx. input . iter ( ) ) {
653
- if * * claim_inp != tx_inp. previous_output {
654
- set_equality = false ;
703
+ // Otherwise, we'll do a linear search for each input (we don't expect
704
+ // large input sets to exist) to ensure the request's input set is fully
705
+ // spent to be resilient against the external claim reordering inputs.
706
+ let mut spends_all_inputs = true ;
707
+ for request_input in request. outpoints ( ) {
708
+ if tx. input . iter ( ) . find ( |input| input. previous_output == * request_input) . is_none ( ) {
709
+ spends_all_inputs = false ;
710
+ break ;
655
711
}
656
712
}
713
+ set_equality = spends_all_inputs;
657
714
}
658
715
659
716
macro_rules! clean_claim_request_after_safety_delay {
@@ -956,6 +1013,40 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
956
1013
htlc_tx
957
1014
}
958
1015
1016
+ #[ cfg( anchors) ]
1017
+ pub ( crate ) fn unsigned_htlc_tx (
1018
+ & mut self , outp : & :: bitcoin:: OutPoint , preimage : & Option < PaymentPreimage >
1019
+ ) -> Option < ( Transaction , ExternalHTLCClaim ) > {
1020
+ let find_htlc = |holder_commitment : & HolderCommitmentTransaction | -> Option < ( Transaction , ExternalHTLCClaim ) > {
1021
+ let trusted_tx = holder_commitment. trust ( ) ;
1022
+ if outp. txid != trusted_tx. txid ( ) {
1023
+ return None ;
1024
+ }
1025
+ trusted_tx. htlcs ( ) . iter ( ) . enumerate ( )
1026
+ . find ( |( _, htlc) | if let Some ( output_index) = htlc. transaction_output_index {
1027
+ output_index == outp. vout
1028
+ } else {
1029
+ false
1030
+ } )
1031
+ . map ( |( htlc_idx, _) | {
1032
+ let counterparty_htlc_sig = holder_commitment. counterparty_htlc_sigs [ htlc_idx] ;
1033
+ let channel_params = self . channel_transaction_parameters . as_holder_broadcastable ( ) ;
1034
+ let ( htlc_tx, htlc) = trusted_tx. unsigned_htlc_tx ( & channel_params, htlc_idx, preimage) ;
1035
+ ( htlc_tx, ExternalHTLCClaim {
1036
+ per_commitment_number : trusted_tx. commitment_number ( ) ,
1037
+ htlc,
1038
+ preimage : * preimage,
1039
+ counterparty_base_htlc_key : channel_params. countersignatory_pubkeys ( ) . htlc_basepoint ,
1040
+ counterparty_base_revocation_key : channel_params. countersignatory_pubkeys ( ) . revocation_basepoint ,
1041
+ counterparty_sig : counterparty_htlc_sig,
1042
+ } )
1043
+ } )
1044
+ } ;
1045
+ // Check if the HTLC spends from the current holder commitment or the previous one otherwise.
1046
+ find_htlc ( & self . holder_commitment )
1047
+ . or ( self . prev_holder_commitment . as_ref ( ) . map ( |c| find_htlc ( c) ) . flatten ( ) )
1048
+ }
1049
+
959
1050
pub ( crate ) fn opt_anchors ( & self ) -> bool {
960
1051
self . channel_transaction_parameters . opt_anchors . is_some ( )
961
1052
}
0 commit comments