@@ -23,10 +23,16 @@ use bitcoin::secp256k1;
2323
2424use ln:: msgs:: DecodeError ;
2525use ln:: PaymentPreimage ;
26+ #[ cfg( anchors) ]
27+ use ln:: chan_utils;
2628use ln:: chan_utils:: { ChannelTransactionParameters , HolderCommitmentTransaction } ;
29+ #[ cfg( anchors) ]
30+ use chain:: chaininterface:: ConfirmationTarget ;
2731use chain:: chaininterface:: { FeeEstimator , BroadcasterInterface , LowerBoundedFeeEstimator } ;
2832use chain:: channelmonitor:: { ANTI_REORG_DELAY , CLTV_SHARED_CLAIM_BUFFER } ;
2933use chain:: keysinterface:: { Sign , KeysInterface } ;
34+ #[ cfg( anchors) ]
35+ use chain:: package:: PackageSolvingData ;
3036use chain:: package:: PackageTemplate ;
3137use util:: logger:: Logger ;
3238use util:: ser:: { Readable , ReadableArgs , MaybeReadable , Writer , Writeable , VecWriter } ;
@@ -162,11 +168,28 @@ impl Writeable for Option<Vec<Option<(usize, Signature)>>> {
162168 }
163169}
164170
171+ // Represents the different types of claims for which events are yielded externally to satisfy said
172+ // claims.
173+ #[ cfg( anchors) ]
174+ pub ( crate ) enum ClaimEvent {
175+ /// Event yielded to signal that the commitment transaction fee must be bumped to claim any
176+ /// encumbered funds and proceed to HTLC resolution, if any HTLCs exist.
177+ BumpCommitment {
178+ package_target_feerate_sat_per_1000_weight : u32 ,
179+ commitment_tx : Transaction ,
180+ anchor_output_idx : u32 ,
181+ } ,
182+ }
183+
165184/// Represents the different ways an output can be claimed (i.e., spent to an address under our
166185/// control) onchain.
167186pub ( crate ) enum OnchainClaim {
168187 /// A finalized transaction pending confirmation spending the output to claim.
169188 Tx ( Transaction ) ,
189+ #[ cfg( anchors) ]
190+ /// An event yielded externally to signal additional inputs must be added to a transaction
191+ /// pending confirmation spending the output to claim.
192+ Event ( ClaimEvent ) ,
170193}
171194
172195/// OnchainTxHandler receives claiming requests, aggregates them if it's sound, broadcast and
@@ -199,6 +222,8 @@ pub struct OnchainTxHandler<ChannelSigner: Sign> {
199222 pub ( crate ) pending_claim_requests : HashMap < Txid , PackageTemplate > ,
200223 #[ cfg( not( test) ) ]
201224 pending_claim_requests : HashMap < Txid , PackageTemplate > ,
225+ #[ cfg( anchors) ]
226+ pending_claim_events : HashMap < Txid , ClaimEvent > ,
202227
203228 // Used to link outpoints claimed in a connected block to a pending claim request.
204229 // Key is outpoint than monitor parsing has detected we have keys/scripts to claim
@@ -348,6 +373,8 @@ impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler<K::Signer> {
348373 locktimed_packages,
349374 pending_claim_requests,
350375 onchain_events_awaiting_threshold_conf,
376+ #[ cfg( anchors) ]
377+ pending_claim_events : HashMap :: new ( ) ,
351378 secp_ctx,
352379 } )
353380 }
@@ -367,6 +394,8 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
367394 claimable_outpoints : HashMap :: new ( ) ,
368395 locktimed_packages : BTreeMap :: new ( ) ,
369396 onchain_events_awaiting_threshold_conf : Vec :: new ( ) ,
397+ #[ cfg( anchors) ]
398+ pending_claim_events : HashMap :: new ( ) ,
370399
371400 secp_ctx,
372401 }
@@ -380,10 +409,14 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
380409 self . holder_commitment . to_broadcaster_value_sat ( )
381410 }
382411
383- /// Lightning security model (i.e being able to redeem/timeout HTLC or penalize coutnerparty onchain) lays on the assumption of claim transactions getting confirmed before timelock expiration
384- /// (CSV or CLTV following cases). In case of high-fee spikes, claim tx may stuck in the mempool, so you need to bump its feerate quickly using Replace-By-Fee or Child-Pay-For-Parent.
385- /// Panics if there are signing errors, because signing operations in reaction to on-chain events
386- /// are not expected to fail, and if they do, we may lose funds.
412+ /// Lightning security model (i.e being able to redeem/timeout HTLC or penalize counterparty
413+ /// onchain) lays on the assumption of claim transactions getting confirmed before timelock
414+ /// expiration (CSV or CLTV following cases). In case of high-fee spikes, claim tx may get stuck
415+ /// in the mempool, so you need to bump its feerate quickly using Replace-By-Fee or
416+ /// Child-Pay-For-Parent.
417+ ///
418+ /// Panics if there are signing errors, because signing operations in reaction to on-chain
419+ /// events are not expected to fail, and if they do, we may lose funds.
387420 fn generate_claim < F : Deref , L : Deref > ( & mut self , cur_height : u32 , cached_request : & PackageTemplate , fee_estimator : & LowerBoundedFeeEstimator < F > , logger : & L ) -> Option < ( Option < u32 > , u64 , OnchainClaim ) >
388421 where F :: Target : FeeEstimator ,
389422 L :: Target : Logger ,
@@ -405,12 +438,60 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
405438 return Some ( ( new_timer, new_feerate, OnchainClaim :: Tx ( transaction) ) )
406439 }
407440 } else {
408- // Note: Currently, amounts of holder outputs spending witnesses aren't used
409- // as we can't malleate spending package to increase their feerate. This
410- // should change with the remaining anchor output patchset.
411- if let Some ( transaction) = cached_request. finalize_untractable_package ( self , logger) {
412- return Some ( ( None , 0 , OnchainClaim :: Tx ( transaction) ) ) ;
441+ // Untractable packages cannot have their fees bumped through Replace-By-Fee. Some
442+ // packages may support fee bumping through Child-Pays-For-Parent, indicated by those
443+ // which require external funding.
444+ #[ cfg( not( anchors) ) ]
445+ let inputs = cached_request. inputs ( ) ;
446+ #[ cfg( anchors) ]
447+ let mut inputs = cached_request. inputs ( ) ;
448+ debug_assert_eq ! ( inputs. len( ) , 1 ) ;
449+ let tx = match cached_request. finalize_untractable_package ( self , logger) {
450+ Some ( tx) => tx,
451+ None => return None ,
452+ } ;
453+ if !cached_request. requires_external_funding ( ) {
454+ return Some ( ( None , 0 , OnchainClaim :: Tx ( tx) ) ) ;
413455 }
456+ #[ cfg( anchors) ]
457+ return inputs. find_map ( |input| match input {
458+ // Commitment inputs with anchors support are the only untractable inputs supported
459+ // thus far that require external funding.
460+ PackageSolvingData :: HolderFundingOutput ( ..) => {
461+ debug_assert_eq ! ( tx. txid( ) , self . holder_commitment. trust( ) . txid( ) ,
462+ "Holder commitment transaction mismatch" ) ;
463+ // We'll locate an anchor output we can spend within the commitment transaction.
464+ let funding_pubkey = & self . channel_transaction_parameters . holder_pubkeys . funding_pubkey ;
465+ match chan_utils:: get_anchor_output ( & tx, funding_pubkey) {
466+ // An anchor output was found, so we should yield a funding event externally.
467+ Some ( ( idx, _) ) => {
468+ // TODO: Use a lower confirmation target when both our and the
469+ // counterparty's latest commitment don't have any HTLCs present.
470+ let conf_target = ConfirmationTarget :: HighPriority ;
471+ let package_target_feerate_sat_per_1000_weight = cached_request
472+ . compute_package_feerate ( fee_estimator, conf_target) ;
473+ Some ( (
474+ new_timer,
475+ package_target_feerate_sat_per_1000_weight as u64 ,
476+ OnchainClaim :: Event ( ClaimEvent :: BumpCommitment {
477+ package_target_feerate_sat_per_1000_weight,
478+ commitment_tx : tx. clone ( ) ,
479+ anchor_output_idx : idx,
480+ } ) ,
481+ ) )
482+ } ,
483+ // An anchor output was not found. There's nothing we can do other than
484+ // attempt to broadcast the transaction with its current fee rate and hope
485+ // it confirms. This is essentially the same behavior as a commitment
486+ // transaction without anchor outputs.
487+ None => Some ( ( None , 0 , OnchainClaim :: Tx ( tx. clone ( ) ) ) ) ,
488+ }
489+ } ,
490+ _ => {
491+ debug_assert ! ( false , "Only HolderFundingOutput inputs should be untractable and require external funding" ) ;
492+ None
493+ } ,
494+ } ) ;
414495 }
415496 None
416497 }
@@ -490,6 +571,15 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
490571 broadcaster. broadcast_transaction ( & tx) ;
491572 tx. txid ( )
492573 } ,
574+ #[ cfg( anchors) ]
575+ OnchainClaim :: Event ( claim_event) => {
576+ log_info ! ( logger, "Yielding onchain event to spend inputs {:?}" , req. outpoints( ) ) ;
577+ let txid = match claim_event {
578+ ClaimEvent :: BumpCommitment { ref commitment_tx, .. } => commitment_tx. txid ( ) ,
579+ } ;
580+ self . pending_claim_events . insert ( txid, claim_event) ;
581+ txid
582+ } ,
493583 } ;
494584 for k in req. outpoints ( ) {
495585 log_info ! ( logger, "Registering claiming request for {}:{}" , k. txid, k. vout) ;
@@ -587,6 +677,8 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
587677 for outpoint in request. outpoints ( ) {
588678 log_debug ! ( logger, "Removing claim tracking for {} due to maturation of claim tx {}." , outpoint, claim_request) ;
589679 self . claimable_outpoints . remove ( & outpoint) ;
680+ #[ cfg( anchors) ]
681+ self . pending_claim_events . remove ( & claim_request) ;
590682 }
591683 }
592684 } ,
@@ -619,6 +711,11 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
619711 log_info ! ( logger, "Broadcasting RBF-bumped onchain {}" , log_tx!( bump_tx) ) ;
620712 broadcaster. broadcast_transaction ( & bump_tx) ;
621713 } ,
714+ #[ cfg( anchors) ]
715+ OnchainClaim :: Event ( claim_event) => {
716+ log_info ! ( logger, "Yielding RBF-bumped onchain event to spend inputs {:?}" , request. outpoints( ) ) ;
717+ self . pending_claim_events . insert ( * first_claim_txid, claim_event) ;
718+ } ,
622719 }
623720 if let Some ( request) = self . pending_claim_requests . get_mut ( first_claim_txid) {
624721 request. set_timer ( new_timer) ;
@@ -681,7 +778,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
681778 self . onchain_events_awaiting_threshold_conf . push ( entry) ;
682779 }
683780 }
684- for ( _ , request) in bump_candidates. iter_mut ( ) {
781+ for ( _first_claim_txid_height , request) in bump_candidates. iter_mut ( ) {
685782 if let Some ( ( new_timer, new_feerate, bump_claim) ) = self . generate_claim ( height, & request, fee_estimator, & & * logger) {
686783 request. set_timer ( new_timer) ;
687784 request. set_feerate ( new_feerate) ;
@@ -690,6 +787,11 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
690787 log_info ! ( logger, "Broadcasting onchain {}" , log_tx!( bump_tx) ) ;
691788 broadcaster. broadcast_transaction ( & bump_tx) ;
692789 } ,
790+ #[ cfg( anchors) ]
791+ OnchainClaim :: Event ( claim_event) => {
792+ log_info ! ( logger, "Yielding onchain event after reorg to spend inputs {:?}" , request. outpoints( ) ) ;
793+ self . pending_claim_events . insert ( _first_claim_txid_height. 0 , claim_event) ;
794+ } ,
693795 }
694796 }
695797 }
0 commit comments