@@ -369,6 +369,11 @@ impl OnchainEventEntry {
369
369
// it's broadcastable when we see the previous block.
370
370
conf_threshold = cmp:: max ( conf_threshold, self . height + csv as u32 - 1 ) ;
371
371
} ,
372
+ OnchainEvent :: HTLCSpendConfirmation { on_to_local_output_csv : Some ( csv) , .. } => {
373
+ // A CSV'd transaction is confirmable in block (input height) + CSV delay, which means
374
+ // it's broadcastable when we see the previous block.
375
+ conf_threshold = cmp:: max ( conf_threshold, self . height + csv as u32 - 1 ) ;
376
+ } ,
372
377
_ => { } ,
373
378
}
374
379
conf_threshold
@@ -390,6 +395,7 @@ enum OnchainEvent {
390
395
source : HTLCSource ,
391
396
payment_hash : PaymentHash ,
392
397
onchain_value_satoshis : Option < u64 > ,
398
+ input_idx : Option < u32 > ,
393
399
} ,
394
400
MaturingOutput {
395
401
descriptor : SpendableOutputDescriptor ,
@@ -398,6 +404,12 @@ enum OnchainEvent {
398
404
txid : Txid ,
399
405
on_local_output_csv : Option < u16 > ,
400
406
} ,
407
+ HTLCSpendConfirmation {
408
+ input_idx : u32 ,
409
+ /// Only set if the claim was made by us with a preimage
410
+ our_preimage : Option < PaymentPreimage > ,
411
+ on_to_local_output_csv : Option < u16 > ,
412
+ } ,
401
413
}
402
414
403
415
impl Writeable for OnchainEventEntry {
@@ -434,6 +446,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
434
446
( 0 , source, required) ,
435
447
( 1 , onchain_value_satoshis, option) ,
436
448
( 2 , payment_hash, required) ,
449
+ ( 3 , input_idx, option) ,
437
450
} ,
438
451
( 1 , MaturingOutput ) => {
439
452
( 0 , descriptor, required) ,
@@ -442,6 +455,12 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
442
455
( 0 , txid, required) ,
443
456
( 2 , on_local_output_csv, option) ,
444
457
} ,
458
+ ( 5 , HTLCSpendConfirmation ) => {
459
+ ( 0 , input_idx, required) ,
460
+ ( 2 , our_preimage, option) ,
461
+ ( 4 , on_to_local_output_csv, option) ,
462
+ } ,
463
+
445
464
) ;
446
465
447
466
#[ cfg_attr( any( test, feature = "fuzztarget" , feature = "_test_utils" ) , derive( PartialEq ) ) ]
@@ -502,6 +521,19 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
502
521
} ,
503
522
) ;
504
523
524
+ /// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
525
+ #[ derive( PartialEq ) ]
526
+ struct HTLCIrrevocablyResolved {
527
+ input_idx : u32 ,
528
+ /// Only set if the HTLC claim was ours using a payment preimage
529
+ payment_preimage : Option < PaymentPreimage > ,
530
+ }
531
+
532
+ impl_writeable_tlv_based ! ( HTLCIrrevocablyResolved , {
533
+ ( 0 , input_idx, required) ,
534
+ ( 2 , payment_preimage, option) ,
535
+ } ) ;
536
+
505
537
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
506
538
/// on-chain transactions to ensure no loss of funds occurs.
507
539
///
@@ -615,6 +647,9 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
615
647
holder_tx_signed : bool ,
616
648
617
649
funding_spend_confirmed : Option < Txid > ,
650
+ /// The set of HTLCs which have been either claimed or failed on chain and have reached
651
+ /// ANTI_REORG_DELAY confirmations on the claim/fail transaction.
652
+ htlcs_resolved_on_chain : Vec < HTLCIrrevocablyResolved > ,
618
653
619
654
// We simply modify best_block in Channel's block_connected so that serialization is
620
655
// consistent but hopefully the users' copy handles block_connected in a consistent way.
@@ -675,7 +710,8 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
675
710
self . outputs_to_watch != other. outputs_to_watch ||
676
711
self . lockdown_from_offchain != other. lockdown_from_offchain ||
677
712
self . holder_tx_signed != other. holder_tx_signed ||
678
- self . funding_spend_confirmed != other. funding_spend_confirmed
713
+ self . funding_spend_confirmed != other. funding_spend_confirmed ||
714
+ self . htlcs_resolved_on_chain != other. htlcs_resolved_on_chain
679
715
{
680
716
false
681
717
} else {
@@ -842,6 +878,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
842
878
843
879
write_tlv_fields ! ( writer, {
844
880
( 1 , self . funding_spend_confirmed, option) ,
881
+ ( 3 , self . htlcs_resolved_on_chain, vec_type) ,
845
882
} ) ;
846
883
847
884
Ok ( ( ) )
@@ -941,6 +978,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
941
978
lockdown_from_offchain : false ,
942
979
holder_tx_signed : false ,
943
980
funding_spend_confirmed : None ,
981
+ htlcs_resolved_on_chain : Vec :: new ( ) ,
944
982
945
983
best_block,
946
984
@@ -1307,6 +1345,7 @@ macro_rules! fail_unbroadcast_htlcs {
1307
1345
source: ( * * source) . clone( ) ,
1308
1346
payment_hash: htlc. payment_hash. clone( ) ,
1309
1347
onchain_value_satoshis: Some ( htlc. amount_msat / 1000 ) ,
1348
+ input_idx: None ,
1310
1349
} ,
1311
1350
} ;
1312
1351
log_trace!( $logger, "Failing HTLC with payment_hash {} from {} counterparty commitment tx due to broadcast of {} commitment transaction, waiting for confirmation (at height {})" ,
@@ -2115,6 +2154,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2115
2154
OnchainEvent :: HTLCUpdate { source, .. } => Some ( source) ,
2116
2155
OnchainEvent :: MaturingOutput { .. } => None ,
2117
2156
OnchainEvent :: FundingSpendConfirmation { .. } => None ,
2157
+ OnchainEvent :: HTLCSpendConfirmation { .. } => None ,
2118
2158
} )
2119
2159
. collect ( ) ;
2120
2160
#[ cfg( debug_assertions) ]
@@ -2123,7 +2163,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2123
2163
// Produce actionable events from on-chain events having reached their threshold.
2124
2164
for entry in onchain_events_reaching_threshold_conf. drain ( ..) {
2125
2165
match entry. event {
2126
- OnchainEvent :: HTLCUpdate { ref source, payment_hash, onchain_value_satoshis } => {
2166
+ OnchainEvent :: HTLCUpdate { ref source, payment_hash, onchain_value_satoshis, input_idx } => {
2127
2167
// Check for duplicate HTLC resolutions.
2128
2168
#[ cfg( debug_assertions) ]
2129
2169
{
@@ -2147,13 +2187,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2147
2187
source : source. clone ( ) ,
2148
2188
onchain_value_satoshis,
2149
2189
} ) ) ;
2190
+ if let Some ( idx) = input_idx {
2191
+ self . htlcs_resolved_on_chain . push ( HTLCIrrevocablyResolved { input_idx : idx, payment_preimage : None } ) ;
2192
+ }
2150
2193
} ,
2151
2194
OnchainEvent :: MaturingOutput { descriptor } => {
2152
2195
log_debug ! ( logger, "Descriptor {} has got enough confirmations to be passed upstream" , log_spendable!( descriptor) ) ;
2153
2196
self . pending_events . push ( Event :: SpendableOutputs {
2154
2197
outputs : vec ! [ descriptor]
2155
2198
} ) ;
2156
2199
} ,
2200
+ OnchainEvent :: HTLCSpendConfirmation { input_idx, our_preimage, .. } => {
2201
+ self . htlcs_resolved_on_chain . push ( HTLCIrrevocablyResolved { input_idx, payment_preimage : our_preimage } ) ;
2202
+ } ,
2157
2203
OnchainEvent :: FundingSpendConfirmation { txid, .. } => {
2158
2204
self . funding_spend_confirmed = Some ( txid) ;
2159
2205
} ,
@@ -2335,6 +2381,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2335
2381
|| ( input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) && input. witness [ 1 ] . len ( ) == 33 ) ;
2336
2382
let accepted_preimage_claim = input. witness . len ( ) == 5 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 4 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) ;
2337
2383
let offered_preimage_claim = input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) ;
2384
+ let offered_timeout_claim = input. witness . len ( ) == 5 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) ;
2338
2385
2339
2386
macro_rules! log_claim {
2340
2387
( $tx_info: expr, $holder_tx: expr, $htlc: expr, $source_avail: expr) => {
@@ -2394,6 +2441,21 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2394
2441
}
2395
2442
if payment_data. is_none( ) {
2396
2443
log_claim!( $tx_info, $holder_tx, htlc_output, false ) ;
2444
+ self . onchain_events_awaiting_threshold_conf. push( OnchainEventEntry {
2445
+ txid: tx. txid( ) , height,
2446
+ event: OnchainEvent :: HTLCSpendConfirmation {
2447
+ input_idx: input. previous_output. vout,
2448
+ our_preimage: None ,
2449
+ // `payment_data.is_none()` implies that this is our
2450
+ // payment, as we haven't learned anything to cause us to
2451
+ // update another channel or our offchain state. Thus, wait
2452
+ // for the CSV delay before dropping the HTLC from
2453
+ // claimable balance if the claim was an HTLC-Success or
2454
+ // HTLC-Timeout transaction.
2455
+ on_to_local_output_csv: if accepted_preimage_claim || offered_timeout_claim {
2456
+ Some ( self . on_holder_tx_csv) } else { None } ,
2457
+ } ,
2458
+ } ) ;
2397
2459
continue ' outer_loop;
2398
2460
}
2399
2461
}
@@ -2424,6 +2486,15 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2424
2486
if !self . pending_monitor_events . iter ( ) . any (
2425
2487
|update| if let & MonitorEvent :: HTLCEvent ( ref upd) = update { upd. source == source } else { false } ) {
2426
2488
payment_preimage. 0 . copy_from_slice ( & input. witness [ 3 ] ) ;
2489
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
2490
+ txid : tx. txid ( ) ,
2491
+ height,
2492
+ event : OnchainEvent :: HTLCSpendConfirmation {
2493
+ input_idx : input. previous_output . vout ,
2494
+ our_preimage : Some ( payment_preimage) ,
2495
+ on_to_local_output_csv : None ,
2496
+ } ,
2497
+ } ) ;
2427
2498
self . pending_monitor_events . push ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
2428
2499
source,
2429
2500
payment_preimage : Some ( payment_preimage) ,
@@ -2437,6 +2508,15 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2437
2508
upd. source == source
2438
2509
} else { false } ) {
2439
2510
payment_preimage. 0 . copy_from_slice ( & input. witness [ 1 ] ) ;
2511
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
2512
+ txid : tx. txid ( ) ,
2513
+ height,
2514
+ event : OnchainEvent :: HTLCSpendConfirmation {
2515
+ input_idx : input. previous_output . vout ,
2516
+ our_preimage : Some ( payment_preimage) ,
2517
+ on_to_local_output_csv : None ,
2518
+ } ,
2519
+ } ) ;
2440
2520
self . pending_monitor_events . push ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
2441
2521
source,
2442
2522
payment_preimage : Some ( payment_preimage) ,
@@ -2454,12 +2534,14 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2454
2534
_ => true ,
2455
2535
}
2456
2536
} ) ;
2537
+ let txid = tx. txid ( ) ;
2457
2538
let entry = OnchainEventEntry {
2458
2539
txid : tx. txid ( ) ,
2459
2540
height,
2460
2541
event : OnchainEvent :: HTLCUpdate {
2461
2542
source, payment_hash,
2462
2543
onchain_value_satoshis : Some ( amount_msat / 1000 ) ,
2544
+ input_idx : Some ( input. previous_output . vout ) ,
2463
2545
} ,
2464
2546
} ;
2465
2547
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( ) ) ;
@@ -2832,8 +2914,10 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
2832
2914
}
2833
2915
2834
2916
let mut funding_spend_confirmed = None ;
2917
+ let mut htlcs_resolved_on_chain = Some ( Vec :: new ( ) ) ;
2835
2918
read_tlv_fields ! ( reader, {
2836
2919
( 1 , funding_spend_confirmed, option) ,
2920
+ ( 3 , htlcs_resolved_on_chain, vec_type) ,
2837
2921
} ) ;
2838
2922
2839
2923
let mut secp_ctx = Secp256k1 :: new ( ) ;
@@ -2884,6 +2968,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
2884
2968
lockdown_from_offchain,
2885
2969
holder_tx_signed,
2886
2970
funding_spend_confirmed,
2971
+ htlcs_resolved_on_chain : htlcs_resolved_on_chain. unwrap ( ) ,
2887
2972
2888
2973
best_block,
2889
2974
0 commit comments