@@ -367,6 +367,11 @@ impl OnchainEventEntry {
367
367
// it's broadcastable when we see the previous block.
368
368
conf_threshold = cmp:: max ( conf_threshold, self . height + csv as u32 - 1 ) ;
369
369
} ,
370
+ OnchainEvent :: HTLCSpendConfirmation { on_to_local_output_csv : Some ( csv) , .. } => {
371
+ // A CSV'd transaction is confirmable in block (input height) + CSV delay, which means
372
+ // it's broadcastable when we see the previous block.
373
+ conf_threshold = cmp:: max ( conf_threshold, self . height + csv as u32 - 1 ) ;
374
+ } ,
370
375
_ => { } ,
371
376
}
372
377
conf_threshold
@@ -387,6 +392,7 @@ enum OnchainEvent {
387
392
HTLCUpdate {
388
393
source : HTLCSource ,
389
394
payment_hash : PaymentHash ,
395
+ input_idx : Option < u32 > ,
390
396
} ,
391
397
MaturingOutput {
392
398
descriptor : SpendableOutputDescriptor ,
@@ -395,6 +401,12 @@ enum OnchainEvent {
395
401
txid : Txid ,
396
402
on_local_output_csv : Option < u16 > ,
397
403
} ,
404
+ HTLCSpendConfirmation {
405
+ input_idx : u32 ,
406
+ /// Only set if the claim was made by us with a preimage
407
+ our_preimage : Option < PaymentPreimage > ,
408
+ on_to_local_output_csv : Option < u16 > ,
409
+ } ,
398
410
}
399
411
400
412
impl Writeable for OnchainEventEntry {
@@ -429,6 +441,7 @@ impl MaybeReadable for OnchainEventEntry {
429
441
impl_writeable_tlv_based_enum_upgradable ! ( OnchainEvent ,
430
442
( 0 , HTLCUpdate ) => {
431
443
( 0 , source, required) ,
444
+ ( 1 , input_idx, option) ,
432
445
( 2 , payment_hash, required) ,
433
446
} ,
434
447
( 1 , MaturingOutput ) => {
@@ -438,6 +451,12 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
438
451
( 0 , txid, required) ,
439
452
( 2 , on_local_output_csv, option) ,
440
453
} ,
454
+ ( 5 , HTLCSpendConfirmation ) => {
455
+ ( 0 , input_idx, required) ,
456
+ ( 2 , our_preimage, option) ,
457
+ ( 4 , on_to_local_output_csv, option) ,
458
+ } ,
459
+
441
460
) ;
442
461
443
462
#[ cfg_attr( any( test, feature = "fuzztarget" , feature = "_test_utils" ) , derive( PartialEq ) ) ]
@@ -492,6 +511,19 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
492
511
} ,
493
512
) ;
494
513
514
+ /// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
515
+ #[ derive( PartialEq ) ]
516
+ struct HTLCIrrevocablyResolved {
517
+ input_idx : u32 ,
518
+ /// Only set if the HTLC claim was ours using a payment preimage
519
+ payment_preimage : Option < PaymentPreimage > ,
520
+ }
521
+
522
+ impl_writeable_tlv_based ! ( HTLCIrrevocablyResolved , {
523
+ ( 0 , input_idx, required) ,
524
+ ( 2 , payment_preimage, option) ,
525
+ } ) ;
526
+
495
527
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
496
528
/// on-chain transactions to ensure no loss of funds occurs.
497
529
///
@@ -602,6 +634,9 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
602
634
holder_tx_signed : bool ,
603
635
604
636
funding_spend_confirmed : Option < Txid > ,
637
+ /// The set of HTLCs which have been either claimed or failed on chain and have reached
638
+ /// ANTI_REORG_DELAY confirmations on the claim/fail transaction.
639
+ htlcs_resolved_on_chain : Vec < HTLCIrrevocablyResolved > ,
605
640
606
641
// We simply modify best_block in Channel's block_connected so that serialization is
607
642
// consistent but hopefully the users' copy handles block_connected in a consistent way.
@@ -662,7 +697,8 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
662
697
self . outputs_to_watch != other. outputs_to_watch ||
663
698
self . lockdown_from_offchain != other. lockdown_from_offchain ||
664
699
self . holder_tx_signed != other. holder_tx_signed ||
665
- self . funding_spend_confirmed != other. funding_spend_confirmed
700
+ self . funding_spend_confirmed != other. funding_spend_confirmed ||
701
+ self . htlcs_resolved_on_chain != other. htlcs_resolved_on_chain
666
702
{
667
703
false
668
704
} else {
@@ -826,6 +862,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
826
862
827
863
write_tlv_fields ! ( writer, {
828
864
( 1 , self . funding_spend_confirmed, option) ,
865
+ ( 3 , self . htlcs_resolved_on_chain, vec_type) ,
829
866
} ) ;
830
867
831
868
Ok ( ( ) )
@@ -927,6 +964,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
927
964
lockdown_from_offchain : false ,
928
965
holder_tx_signed : false ,
929
966
funding_spend_confirmed : None ,
967
+ htlcs_resolved_on_chain : Vec :: new ( ) ,
930
968
931
969
best_block,
932
970
@@ -1280,6 +1318,7 @@ macro_rules! fail_unbroadcast_htlcs {
1280
1318
event: OnchainEvent :: HTLCUpdate {
1281
1319
source: ( * * source) . clone( ) ,
1282
1320
payment_hash: htlc. payment_hash. clone( ) ,
1321
+ input_idx: None ,
1283
1322
} ,
1284
1323
} ;
1285
1324
log_trace!( $logger, "Failing HTLC with payment_hash {} from {} counterparty commitment tx due to broadcast of {} commitment transaction, waiting for confirmation (at height {})" ,
@@ -2082,6 +2121,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2082
2121
OnchainEvent :: HTLCUpdate { source, .. } => Some ( source) ,
2083
2122
OnchainEvent :: MaturingOutput { .. } => None ,
2084
2123
OnchainEvent :: FundingSpendConfirmation { .. } => None ,
2124
+ OnchainEvent :: HTLCSpendConfirmation { .. } => None ,
2085
2125
} )
2086
2126
. collect ( ) ;
2087
2127
#[ cfg( debug_assertions) ]
@@ -2090,7 +2130,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2090
2130
// Produce actionable events from on-chain events having reached their threshold.
2091
2131
for entry in onchain_events_reaching_threshold_conf. drain ( ..) {
2092
2132
match entry. event {
2093
- OnchainEvent :: HTLCUpdate { ref source, payment_hash } => {
2133
+ OnchainEvent :: HTLCUpdate { ref source, payment_hash, input_idx } => {
2094
2134
// Check for duplicate HTLC resolutions.
2095
2135
#[ cfg( debug_assertions) ]
2096
2136
{
@@ -2113,13 +2153,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2113
2153
payment_preimage : None ,
2114
2154
source : source. clone ( ) ,
2115
2155
} ) ) ;
2156
+ if let Some ( idx) = input_idx {
2157
+ self . htlcs_resolved_on_chain . push ( HTLCIrrevocablyResolved { input_idx : idx, payment_preimage : None } ) ;
2158
+ }
2116
2159
} ,
2117
2160
OnchainEvent :: MaturingOutput { descriptor } => {
2118
2161
log_debug ! ( logger, "Descriptor {} has got enough confirmations to be passed upstream" , log_spendable!( descriptor) ) ;
2119
2162
self . pending_events . push ( Event :: SpendableOutputs {
2120
2163
outputs : vec ! [ descriptor]
2121
2164
} ) ;
2122
2165
} ,
2166
+ OnchainEvent :: HTLCSpendConfirmation { input_idx, our_preimage, .. } => {
2167
+ self . htlcs_resolved_on_chain . push ( HTLCIrrevocablyResolved { input_idx, payment_preimage : our_preimage } ) ;
2168
+ } ,
2123
2169
OnchainEvent :: FundingSpendConfirmation { txid, .. } => {
2124
2170
self . funding_spend_confirmed = Some ( txid) ;
2125
2171
} ,
@@ -2301,6 +2347,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2301
2347
|| ( input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) && input. witness [ 1 ] . len ( ) == 33 ) ;
2302
2348
let accepted_preimage_claim = input. witness . len ( ) == 5 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 4 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) ;
2303
2349
let offered_preimage_claim = input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) ;
2350
+ let offered_timeout_claim = input. witness . len ( ) == 5 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) ;
2304
2351
2305
2352
macro_rules! log_claim {
2306
2353
( $tx_info: expr, $holder_tx: expr, $htlc: expr, $source_avail: expr) => {
@@ -2360,6 +2407,21 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2360
2407
}
2361
2408
if payment_data. is_none( ) {
2362
2409
log_claim!( $tx_info, $holder_tx, htlc_output, false ) ;
2410
+ self . onchain_events_awaiting_threshold_conf. push( OnchainEventEntry {
2411
+ txid: tx. txid( ) , height,
2412
+ event: OnchainEvent :: HTLCSpendConfirmation {
2413
+ input_idx: input. previous_output. vout,
2414
+ our_preimage: None ,
2415
+ // `payment_data.is_none()` implies that this is our
2416
+ // payment, as we haven't learned anything to cause us to
2417
+ // update another channel or our offchain state. Thus, wait
2418
+ // for the CSV delay before dropping the HTLC from
2419
+ // claimable balance if the claim was an HTLC-Success or
2420
+ // HTLC-Timeout transaction.
2421
+ on_to_local_output_csv: if accepted_preimage_claim || offered_timeout_claim {
2422
+ Some ( self . on_holder_tx_csv) } else { None } ,
2423
+ } ,
2424
+ } ) ;
2363
2425
continue ' outer_loop;
2364
2426
}
2365
2427
}
@@ -2390,6 +2452,15 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2390
2452
if !self . pending_monitor_events . iter ( ) . any (
2391
2453
|update| if let & MonitorEvent :: HTLCEvent ( ref upd) = update { upd. source == source } else { false } ) {
2392
2454
payment_preimage. 0 . copy_from_slice ( & input. witness [ 3 ] ) ;
2455
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
2456
+ txid : tx. txid ( ) ,
2457
+ height,
2458
+ event : OnchainEvent :: HTLCSpendConfirmation {
2459
+ input_idx : input. previous_output . vout ,
2460
+ our_preimage : Some ( payment_preimage) ,
2461
+ on_to_local_output_csv : None ,
2462
+ } ,
2463
+ } ) ;
2393
2464
self . pending_monitor_events . push ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
2394
2465
source,
2395
2466
payment_preimage : Some ( payment_preimage) ,
@@ -2402,6 +2473,15 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2402
2473
upd. source == source
2403
2474
} else { false } ) {
2404
2475
payment_preimage. 0 . copy_from_slice ( & input. witness [ 1 ] ) ;
2476
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
2477
+ txid : tx. txid ( ) ,
2478
+ height,
2479
+ event : OnchainEvent :: HTLCSpendConfirmation {
2480
+ input_idx : input. previous_output . vout ,
2481
+ our_preimage : Some ( payment_preimage) ,
2482
+ on_to_local_output_csv : None ,
2483
+ } ,
2484
+ } ) ;
2405
2485
self . pending_monitor_events . push ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
2406
2486
source,
2407
2487
payment_preimage : Some ( payment_preimage) ,
@@ -2418,10 +2498,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2418
2498
_ => true ,
2419
2499
}
2420
2500
} ) ;
2501
+ let txid = tx. txid ( ) ;
2421
2502
let entry = OnchainEventEntry {
2422
- txid : tx. txid ( ) ,
2423
- height,
2424
- event : OnchainEvent :: HTLCUpdate { source : source, payment_hash : payment_hash } ,
2503
+ txid, height,
2504
+ event : OnchainEvent :: HTLCUpdate { source : source, payment_hash : payment_hash, input_idx : Some ( input. previous_output . vout ) } ,
2425
2505
} ;
2426
2506
log_info ! ( logger, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting for confirmation (at height {})" , log_bytes!( payment_hash. 0 ) , entry. confirmation_threshold( ) ) ;
2427
2507
self . onchain_events_awaiting_threshold_conf . push ( entry) ;
@@ -2790,8 +2870,10 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
2790
2870
}
2791
2871
2792
2872
let mut funding_spend_confirmed = None ;
2873
+ let mut htlcs_resolved_on_chain = Some ( Vec :: new ( ) ) ;
2793
2874
read_tlv_fields ! ( reader, {
2794
2875
( 1 , funding_spend_confirmed, option) ,
2876
+ ( 3 , htlcs_resolved_on_chain, vec_type) ,
2795
2877
} ) ;
2796
2878
2797
2879
let mut secp_ctx = Secp256k1 :: new ( ) ;
@@ -2842,6 +2924,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
2842
2924
lockdown_from_offchain,
2843
2925
holder_tx_signed,
2844
2926
funding_spend_confirmed,
2927
+ htlcs_resolved_on_chain : htlcs_resolved_on_chain. unwrap ( ) ,
2845
2928
2846
2929
best_block,
2847
2930
0 commit comments