@@ -18,13 +18,15 @@ use bitcoin::blockdata::script::Script;
18
18
19
19
use bitcoin:: hash_types:: { Txid , BlockHash } ;
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 ;
@@ -174,6 +176,17 @@ impl Writeable for Option<Vec<Option<(usize, Signature)>>> {
174
176
}
175
177
}
176
178
179
+ #[ cfg( anchors) ]
180
+ /// The claim commonly referred to as the pre-signed second-stage HTLC transaction.
181
+ pub ( crate ) struct ExternalHTLCClaim {
182
+ pub ( crate ) per_commitment_number : u64 ,
183
+ pub ( crate ) htlc : HTLCOutputInCommitment ,
184
+ pub ( crate ) preimage : Option < PaymentPreimage > ,
185
+ pub ( crate ) counterparty_base_htlc_key : PublicKey ,
186
+ pub ( crate ) counterparty_base_revocation_key : PublicKey ,
187
+ pub ( crate ) counterparty_sig : Signature ,
188
+ }
189
+
177
190
// Represents the different types of claims for which events are yielded externally to satisfy said
178
191
// claims.
179
192
#[ cfg( anchors) ]
@@ -185,6 +198,11 @@ pub(crate) enum ClaimEvent {
185
198
commitment_tx : Transaction ,
186
199
anchor_output_idx : u32 ,
187
200
} ,
201
+ BumpHTLC {
202
+ target_feerate_sat_per_1000_weight : u32 ,
203
+ tx_template : Transaction ,
204
+ htlcs : Vec < ExternalHTLCClaim > ,
205
+ } ,
188
206
}
189
207
190
208
/// Represents the different ways an output can be claimed (i.e., spent to an address under our
@@ -476,15 +494,34 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
476
494
// didn't receive confirmation of it before, or not enough reorg-safe depth on top of it).
477
495
let new_timer = Some ( cached_request. get_height_timer ( cur_height) ) ;
478
496
if cached_request. is_malleable ( ) {
497
+ #[ cfg( anchors) ]
498
+ { // Attributes are not allowed on if expressions on our current MSRV of 1.41.
499
+ if cached_request. requires_external_funding ( ) {
500
+ let target_feerate_sat_per_1000_weight = cached_request
501
+ . compute_package_feerate ( fee_estimator, ConfirmationTarget :: HighPriority ) ;
502
+ let ( tx_template, htlcs) = cached_request. construct_malleable_package_with_external_funding ( self ) ;
503
+ return Some ( (
504
+ new_timer,
505
+ target_feerate_sat_per_1000_weight as u64 ,
506
+ OnchainClaim :: Event ( ClaimEvent :: BumpHTLC {
507
+ target_feerate_sat_per_1000_weight,
508
+ tx_template,
509
+ htlcs,
510
+ } ) ,
511
+ ) ) ;
512
+ }
513
+ }
514
+
479
515
let predicted_weight = cached_request. package_weight ( & self . destination_script ) ;
480
- if let Some ( ( output_value, new_feerate) ) =
481
- cached_request. compute_package_output ( predicted_weight, self . destination_script . dust_value ( ) . to_sat ( ) , fee_estimator, logger) {
516
+ if let Some ( ( output_value, new_feerate) ) = cached_request. compute_package_output (
517
+ predicted_weight, self . destination_script . dust_value ( ) . to_sat ( ) , fee_estimator, logger,
518
+ ) {
482
519
assert ! ( new_feerate != 0 ) ;
483
520
484
521
let transaction = cached_request. finalize_malleable_package ( self , output_value, self . destination_script . clone ( ) , logger) . unwrap ( ) ;
485
522
log_trace ! ( logger, "...with timer {} and feerate {}" , new_timer. unwrap( ) , new_feerate) ;
486
523
assert ! ( predicted_weight >= transaction. weight( ) ) ;
487
- return Some ( ( new_timer, new_feerate, OnchainClaim :: Tx ( transaction) ) )
524
+ return Some ( ( new_timer, new_feerate, OnchainClaim :: Tx ( transaction) ) ) ;
488
525
}
489
526
} else {
490
527
// Untractable packages cannot have their fees bumped through Replace-By-Fee. Some
@@ -540,7 +577,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
540
577
debug_assert ! ( false , "Only HolderFundingOutput inputs should be untractable and require external funding" ) ;
541
578
None
542
579
} ,
543
- } ) ;
580
+ } )
544
581
}
545
582
None
546
583
}
@@ -630,6 +667,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
630
667
log_info ! ( logger, "Yielding onchain event to spend inputs {:?}" , req. outpoints( ) ) ;
631
668
let txid = match claim_event {
632
669
ClaimEvent :: BumpCommitment { ref commitment_tx, .. } => commitment_tx. txid ( ) ,
670
+ ClaimEvent :: BumpHTLC { ref tx_template, .. } => tx_template. txid ( ) ,
633
671
} ;
634
672
self . pending_claim_events . insert ( txid, claim_event) ;
635
673
txid
@@ -673,14 +711,33 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
673
711
// outpoints to know if transaction is the original claim or a bumped one issued
674
712
// by us.
675
713
let mut set_equality = true ;
676
- if request. outpoints ( ) . len ( ) != tx. input . len ( ) {
677
- set_equality = false ;
714
+ if !request. requires_external_funding ( ) ||
715
+ ( request. requires_external_funding ( ) && !request. is_malleable ( ) )
716
+ {
717
+ // If the claim does not require external funds to be allocated through
718
+ // additional inputs we can simply check the inputs in order as they
719
+ // cannot change under us.
720
+ if request. outpoints ( ) . len ( ) != tx. input . len ( ) {
721
+ set_equality = false ;
722
+ } else {
723
+ for ( claim_inp, tx_inp) in request. outpoints ( ) . iter ( ) . zip ( tx. input . iter ( ) ) {
724
+ if * * claim_inp != tx_inp. previous_output {
725
+ set_equality = false ;
726
+ }
727
+ }
728
+ }
678
729
} else {
679
- for ( claim_inp, tx_inp) in request. outpoints ( ) . iter ( ) . zip ( tx. input . iter ( ) ) {
680
- if * * claim_inp != tx_inp. previous_output {
681
- set_equality = false ;
730
+ // Otherwise, we'll do a linear search for each input (we don't expect
731
+ // large input sets to exist) to ensure the request's input set is fully
732
+ // spent to be resilient against the external claim reordering inputs.
733
+ let mut spends_all_inputs = true ;
734
+ for request_input in request. outpoints ( ) {
735
+ if tx. input . iter ( ) . find ( |input| input. previous_output == * request_input) . is_none ( ) {
736
+ spends_all_inputs = false ;
737
+ break ;
682
738
}
683
739
}
740
+ set_equality = spends_all_inputs;
684
741
}
685
742
686
743
macro_rules! clean_claim_request_after_safety_delay {
@@ -985,6 +1042,40 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
985
1042
htlc_tx
986
1043
}
987
1044
1045
+ #[ cfg( anchors) ]
1046
+ pub ( crate ) fn unsigned_htlc_tx (
1047
+ & mut self , outp : & :: bitcoin:: OutPoint , preimage : & Option < PaymentPreimage >
1048
+ ) -> Option < ( Transaction , ExternalHTLCClaim ) > {
1049
+ let find_htlc = |holder_commitment : & HolderCommitmentTransaction | -> Option < ( Transaction , ExternalHTLCClaim ) > {
1050
+ let trusted_tx = holder_commitment. trust ( ) ;
1051
+ if outp. txid != trusted_tx. txid ( ) {
1052
+ return None ;
1053
+ }
1054
+ trusted_tx. htlcs ( ) . iter ( ) . enumerate ( )
1055
+ . find ( |( _, htlc) | if let Some ( output_index) = htlc. transaction_output_index {
1056
+ output_index == outp. vout
1057
+ } else {
1058
+ false
1059
+ } )
1060
+ . map ( |( htlc_idx, _) | {
1061
+ let counterparty_htlc_sig = holder_commitment. counterparty_htlc_sigs [ htlc_idx] ;
1062
+ let channel_params = self . channel_transaction_parameters . as_holder_broadcastable ( ) ;
1063
+ let ( htlc_tx, htlc) = trusted_tx. unsigned_htlc_tx ( & channel_params, htlc_idx, preimage) ;
1064
+ ( htlc_tx, ExternalHTLCClaim {
1065
+ per_commitment_number : trusted_tx. commitment_number ( ) ,
1066
+ htlc,
1067
+ preimage : * preimage,
1068
+ counterparty_base_htlc_key : channel_params. countersignatory_pubkeys ( ) . htlc_basepoint ,
1069
+ counterparty_base_revocation_key : channel_params. countersignatory_pubkeys ( ) . revocation_basepoint ,
1070
+ counterparty_sig : counterparty_htlc_sig,
1071
+ } )
1072
+ } )
1073
+ } ;
1074
+ // Check if the HTLC spends from the current holder commitment or the previous one otherwise.
1075
+ find_htlc ( & self . holder_commitment )
1076
+ . or ( self . prev_holder_commitment . as_ref ( ) . map ( |c| find_htlc ( c) ) . flatten ( ) )
1077
+ }
1078
+
988
1079
pub ( crate ) fn opt_anchors ( & self ) -> bool {
989
1080
self . channel_transaction_parameters . opt_anchors . is_some ( )
990
1081
}
0 commit comments