@@ -23,11 +23,12 @@ use bitcoin::secp256k1;
23
23
24
24
use ln:: msgs:: DecodeError ;
25
25
use ln:: PaymentPreimage ;
26
+ use ln:: chan_utils;
26
27
use ln:: chan_utils:: { ChannelTransactionParameters , HolderCommitmentTransaction } ;
27
- use chain:: chaininterface:: { FeeEstimator , BroadcasterInterface , LowerBoundedFeeEstimator } ;
28
+ use chain:: chaininterface:: { ConfirmationTarget , FeeEstimator , BroadcasterInterface , LowerBoundedFeeEstimator } ;
28
29
use chain:: channelmonitor:: { ANTI_REORG_DELAY , CLTV_SHARED_CLAIM_BUFFER } ;
29
30
use chain:: keysinterface:: { Sign , KeysInterface } ;
30
- use chain:: package:: PackageTemplate ;
31
+ use chain:: package:: { PackageSolvingData , PackageTemplate } ;
31
32
use util:: logger:: Logger ;
32
33
use util:: ser:: { Readable , ReadableArgs , MaybeReadable , Writer , Writeable , VecWriter } ;
33
34
use util:: byte_utils;
@@ -36,6 +37,7 @@ use io;
36
37
use prelude:: * ;
37
38
use alloc:: collections:: BTreeMap ;
38
39
use core:: cmp;
40
+ use core:: convert:: TryInto ;
39
41
use core:: ops:: Deref ;
40
42
use core:: mem:: replace;
41
43
use bitcoin:: hashes:: Hash ;
@@ -162,8 +164,17 @@ impl Writeable for Option<Vec<Option<(usize, Signature)>>> {
162
164
}
163
165
}
164
166
167
+ pub ( crate ) enum ClaimEvent {
168
+ BumpCommitment {
169
+ target_feerate_sat_per_1000_weight : u32 ,
170
+ commitment_tx : Transaction ,
171
+ anchor_output_idx : u32 ,
172
+ } ,
173
+ }
174
+
165
175
pub ( crate ) enum OnchainClaim {
166
176
Tx ( Transaction ) ,
177
+ Event ( ClaimEvent ) ,
167
178
}
168
179
169
180
/// OnchainTxHandler receives claiming requests, aggregates them if it's sound, broadcast and
@@ -196,6 +207,7 @@ pub struct OnchainTxHandler<ChannelSigner: Sign> {
196
207
pub ( crate ) pending_claim_requests : HashMap < Txid , PackageTemplate > ,
197
208
#[ cfg( not( test) ) ]
198
209
pending_claim_requests : HashMap < Txid , PackageTemplate > ,
210
+ pending_claim_events : HashMap < Txid , ClaimEvent > ,
199
211
200
212
// Used to link outpoints claimed in a connected block to a pending claim request.
201
213
// Key is outpoint than monitor parsing has detected we have keys/scripts to claim
@@ -345,6 +357,7 @@ impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler<K::Signer> {
345
357
locktimed_packages,
346
358
pending_claim_requests,
347
359
onchain_events_awaiting_threshold_conf,
360
+ pending_claim_events : HashMap :: new ( ) ,
348
361
secp_ctx,
349
362
} )
350
363
}
@@ -364,6 +377,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
364
377
claimable_outpoints : HashMap :: new ( ) ,
365
378
locktimed_packages : BTreeMap :: new ( ) ,
366
379
onchain_events_awaiting_threshold_conf : Vec :: new ( ) ,
380
+ pending_claim_events : HashMap :: new ( ) ,
367
381
368
382
secp_ctx,
369
383
}
@@ -402,12 +416,63 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
402
416
return Some ( ( new_timer, new_feerate, OnchainClaim :: Tx ( transaction) ) )
403
417
}
404
418
} else {
405
- // Note: Currently, amounts of holder outputs spending witnesses aren't used
406
- // as we can't malleate spending package to increase their feerate. This
407
- // should change with the remaining anchor output patchset.
408
- if let Some ( transaction) = cached_request. finalize_untractable_package ( self , logger) {
409
- return Some ( ( None , 0 , OnchainClaim :: Tx ( transaction) ) ) ;
419
+ // Untractable packages cannot have their fees bumped through Replace-By-Fee. Some
420
+ // packages may support fee bumping through Child-Pays-For-Parent, indicated by those
421
+ // which require external funding.
422
+ let inputs = cached_request. inputs ( ) ;
423
+ debug_assert_eq ! ( inputs. len( ) , 1 ) ;
424
+ let tx = match cached_request. finalize_untractable_package ( self , logger) {
425
+ Some ( tx) => tx,
426
+ None => return None ,
427
+ } ;
428
+ if !cached_request. requires_external_funding ( ) {
429
+ return Some ( ( None , 0 , OnchainClaim :: Tx ( tx) ) ) ;
410
430
}
431
+ return inputs. iter ( ) . find_map ( |input| match input. solving_data {
432
+ // Commitment inputs with anchors support are the only untractable inputs supported
433
+ // thus far that require external funding.
434
+ PackageSolvingData :: HolderFundingOutput ( ..) => {
435
+ // We'll locate an anchor output we can spend within the commitment transaction.
436
+ let commitment_tx = tx. clone ( ) ;
437
+ let anchor_script = chan_utils:: get_anchor_redeemscript (
438
+ & self . channel_transaction_parameters . holder_pubkeys . funding_pubkey ,
439
+ ) . to_v0_p2wsh ( ) ;
440
+ match commitment_tx. output . iter ( ) . enumerate ( )
441
+ . find ( |( _, txout) | txout. script_pubkey == anchor_script)
442
+ . map ( |( idx, _) | idx as u32 )
443
+ {
444
+ // An anchor output was found, so we should yield a funding event externally.
445
+ Some ( anchor_output_idx) => {
446
+ let target_feerate_sat_per_1000_weight: u32 = match cached_request
447
+ . compute_package_child_feerate ( & tx, fee_estimator, ConfirmationTarget :: HighPriority )
448
+ . map ( |f| f. try_into ( ) . ok ( ) )
449
+ . flatten ( )
450
+ {
451
+ Some ( f) => f,
452
+ _ => return None ,
453
+ } ;
454
+ Some ( (
455
+ new_timer,
456
+ target_feerate_sat_per_1000_weight as u64 ,
457
+ OnchainClaim :: Event ( ClaimEvent :: BumpCommitment {
458
+ target_feerate_sat_per_1000_weight,
459
+ commitment_tx,
460
+ anchor_output_idx,
461
+ } ) ,
462
+ ) )
463
+ } ,
464
+ // An anchor output was not found. There's nothing we can do other than
465
+ // attempt to broadcast the transaction with its current fee rate and hope
466
+ // it confirms. This is essentially the same behavior as a commitment
467
+ // transaction without anchor outputs.
468
+ None => Some ( ( None , 0 , OnchainClaim :: Tx ( commitment_tx) ) ) ,
469
+ }
470
+ } ,
471
+ _ => {
472
+ debug_assert ! ( false , "Only HolderFundingOutput inputs should be untractable and require external funding" ) ;
473
+ None
474
+ } ,
475
+ } ) ;
411
476
}
412
477
None
413
478
}
@@ -481,18 +546,25 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
481
546
if let Some ( ( new_timer, new_feerate, claim) ) = self . generate_claim ( cur_height, & req, & * fee_estimator, & * logger) {
482
547
req. set_timer ( new_timer) ;
483
548
req. set_feerate ( new_feerate) ;
484
- match claim {
549
+ let txid = match claim {
485
550
OnchainClaim :: Tx ( tx) => {
486
- let txid = tx. txid ( ) ;
487
- for k in req. outpoints ( ) {
488
- log_info ! ( logger, "Registering claiming request for {}:{}" , k. txid, k. vout) ;
489
- self . claimable_outpoints . insert ( k. clone ( ) , ( txid, conf_height) ) ;
490
- }
491
- self . pending_claim_requests . insert ( txid, req) ;
492
551
log_info ! ( logger, "Broadcasting onchain {}" , log_tx!( tx) ) ;
493
552
broadcaster. broadcast_transaction ( & tx) ;
553
+ tx. txid ( )
554
+ } ,
555
+ OnchainClaim :: Event ( claim_event) => {
556
+ let txid = match claim_event {
557
+ ClaimEvent :: BumpCommitment { ref commitment_tx, .. } => commitment_tx. txid ( ) ,
558
+ } ;
559
+ self . pending_claim_events . insert ( txid, claim_event) ;
560
+ txid
494
561
} ,
562
+ } ;
563
+ for k in req. outpoints ( ) {
564
+ log_info ! ( logger, "Registering claiming request for {}:{}" , k. txid, k. vout) ;
565
+ self . claimable_outpoints . insert ( k. clone ( ) , ( txid, conf_height) ) ;
495
566
}
567
+ self . pending_claim_requests . insert ( txid, req) ;
496
568
}
497
569
}
498
570
@@ -584,6 +656,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
584
656
for outpoint in request. outpoints ( ) {
585
657
log_debug ! ( logger, "Removing claim tracking for {} due to maturation of claim tx {}." , outpoint, claim_request) ;
586
658
self . claimable_outpoints . remove ( & outpoint) ;
659
+ self . pending_claim_events . remove ( & claim_request) ;
587
660
}
588
661
}
589
662
} ,
@@ -616,6 +689,9 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
616
689
log_info ! ( logger, "Broadcasting RBF-bumped onchain {}" , log_tx!( bump_tx) ) ;
617
690
broadcaster. broadcast_transaction ( & bump_tx) ;
618
691
} ,
692
+ OnchainClaim :: Event ( claim_event) => {
693
+ self . pending_claim_events . insert ( * first_claim_txid, claim_event) ;
694
+ } ,
619
695
}
620
696
if let Some ( request) = self . pending_claim_requests . get_mut ( first_claim_txid) {
621
697
request. set_timer ( new_timer) ;
@@ -678,7 +754,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
678
754
self . onchain_events_awaiting_threshold_conf . push ( entry) ;
679
755
}
680
756
}
681
- for ( _ , request) in bump_candidates. iter_mut ( ) {
757
+ for ( first_claim_txid_height , request) in bump_candidates. iter_mut ( ) {
682
758
if let Some ( ( new_timer, new_feerate, bump_claim) ) = self . generate_claim ( height, & request, fee_estimator, & & * logger) {
683
759
request. set_timer ( new_timer) ;
684
760
request. set_feerate ( new_feerate) ;
@@ -687,6 +763,9 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
687
763
log_info ! ( logger, "Broadcasting onchain {}" , log_tx!( bump_tx) ) ;
688
764
broadcaster. broadcast_transaction ( & bump_tx) ;
689
765
} ,
766
+ OnchainClaim :: Event ( claim_event) => {
767
+ self . pending_claim_events . insert ( first_claim_txid_height. 0 , claim_event) ;
768
+ } ,
690
769
}
691
770
}
692
771
}
0 commit comments