@@ -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 ,
@@ -402,6 +408,12 @@ enum OnchainEvent {
402
408
/// commitment transaction, and this is the delay on the to_self output).
403
409
on_local_output_csv : Option < u16 > ,
404
410
} ,
411
+ HTLCSpendConfirmation {
412
+ input_idx : u32 ,
413
+ /// Only set if the claim was made by us with a preimage
414
+ our_preimage : Option < PaymentPreimage > ,
415
+ on_to_local_output_csv : Option < u16 > ,
416
+ } ,
405
417
}
406
418
407
419
impl Writeable for OnchainEventEntry {
@@ -438,6 +450,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
438
450
( 0 , source, required) ,
439
451
( 1 , onchain_value_satoshis, option) ,
440
452
( 2 , payment_hash, required) ,
453
+ ( 3 , input_idx, option) ,
441
454
} ,
442
455
( 1 , MaturingOutput ) => {
443
456
( 0 , descriptor, required) ,
@@ -446,6 +459,12 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
446
459
( 0 , txid, required) ,
447
460
( 2 , on_local_output_csv, option) ,
448
461
} ,
462
+ ( 5 , HTLCSpendConfirmation ) => {
463
+ ( 0 , input_idx, required) ,
464
+ ( 2 , our_preimage, option) ,
465
+ ( 4 , on_to_local_output_csv, option) ,
466
+ } ,
467
+
449
468
) ;
450
469
451
470
#[ cfg_attr( any( test, feature = "fuzztarget" , feature = "_test_utils" ) , derive( PartialEq ) ) ]
@@ -506,6 +525,19 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
506
525
} ,
507
526
) ;
508
527
528
+ /// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
529
+ #[ derive( PartialEq ) ]
530
+ struct HTLCIrrevocablyResolved {
531
+ input_idx : u32 ,
532
+ /// Only set if the HTLC claim was ours using a payment preimage
533
+ payment_preimage : Option < PaymentPreimage > ,
534
+ }
535
+
536
+ impl_writeable_tlv_based ! ( HTLCIrrevocablyResolved , {
537
+ ( 0 , input_idx, required) ,
538
+ ( 2 , payment_preimage, option) ,
539
+ } ) ;
540
+
509
541
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
510
542
/// on-chain transactions to ensure no loss of funds occurs.
511
543
///
@@ -619,6 +651,9 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
619
651
holder_tx_signed : bool ,
620
652
621
653
funding_spend_confirmed : Option < Txid > ,
654
+ /// The set of HTLCs which have been either claimed or failed on chain and have reached
655
+ /// ANTI_REORG_DELAY confirmations on the claim/fail transaction.
656
+ htlcs_resolved_on_chain : Vec < HTLCIrrevocablyResolved > ,
622
657
623
658
// We simply modify best_block in Channel's block_connected so that serialization is
624
659
// consistent but hopefully the users' copy handles block_connected in a consistent way.
@@ -679,7 +714,8 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
679
714
self . outputs_to_watch != other. outputs_to_watch ||
680
715
self . lockdown_from_offchain != other. lockdown_from_offchain ||
681
716
self . holder_tx_signed != other. holder_tx_signed ||
682
- self . funding_spend_confirmed != other. funding_spend_confirmed
717
+ self . funding_spend_confirmed != other. funding_spend_confirmed ||
718
+ self . htlcs_resolved_on_chain != other. htlcs_resolved_on_chain
683
719
{
684
720
false
685
721
} else {
@@ -846,6 +882,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
846
882
847
883
write_tlv_fields ! ( writer, {
848
884
( 1 , self . funding_spend_confirmed, option) ,
885
+ ( 3 , self . htlcs_resolved_on_chain, vec_type) ,
849
886
} ) ;
850
887
851
888
Ok ( ( ) )
@@ -945,6 +982,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
945
982
lockdown_from_offchain : false ,
946
983
holder_tx_signed : false ,
947
984
funding_spend_confirmed : None ,
985
+ htlcs_resolved_on_chain : Vec :: new ( ) ,
948
986
949
987
best_block,
950
988
@@ -1311,6 +1349,7 @@ macro_rules! fail_unbroadcast_htlcs {
1311
1349
source: ( * * source) . clone( ) ,
1312
1350
payment_hash: htlc. payment_hash. clone( ) ,
1313
1351
onchain_value_satoshis: Some ( htlc. amount_msat / 1000 ) ,
1352
+ input_idx: None ,
1314
1353
} ,
1315
1354
} ;
1316
1355
log_trace!( $logger, "Failing HTLC with payment_hash {} from {} counterparty commitment tx due to broadcast of {} commitment transaction, waiting for confirmation (at height {})" ,
@@ -2119,6 +2158,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2119
2158
OnchainEvent :: HTLCUpdate { source, .. } => Some ( source) ,
2120
2159
OnchainEvent :: MaturingOutput { .. } => None ,
2121
2160
OnchainEvent :: FundingSpendConfirmation { .. } => None ,
2161
+ OnchainEvent :: HTLCSpendConfirmation { .. } => None ,
2122
2162
} )
2123
2163
. collect ( ) ;
2124
2164
#[ cfg( debug_assertions) ]
@@ -2127,7 +2167,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2127
2167
// Produce actionable events from on-chain events having reached their threshold.
2128
2168
for entry in onchain_events_reaching_threshold_conf. drain ( ..) {
2129
2169
match entry. event {
2130
- OnchainEvent :: HTLCUpdate { ref source, payment_hash, onchain_value_satoshis } => {
2170
+ OnchainEvent :: HTLCUpdate { ref source, payment_hash, onchain_value_satoshis, input_idx } => {
2131
2171
// Check for duplicate HTLC resolutions.
2132
2172
#[ cfg( debug_assertions) ]
2133
2173
{
@@ -2151,13 +2191,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2151
2191
source : source. clone ( ) ,
2152
2192
onchain_value_satoshis,
2153
2193
} ) ) ;
2194
+ if let Some ( idx) = input_idx {
2195
+ self . htlcs_resolved_on_chain . push ( HTLCIrrevocablyResolved { input_idx : idx, payment_preimage : None } ) ;
2196
+ }
2154
2197
} ,
2155
2198
OnchainEvent :: MaturingOutput { descriptor } => {
2156
2199
log_debug ! ( logger, "Descriptor {} has got enough confirmations to be passed upstream" , log_spendable!( descriptor) ) ;
2157
2200
self . pending_events . push ( Event :: SpendableOutputs {
2158
2201
outputs : vec ! [ descriptor]
2159
2202
} ) ;
2160
2203
} ,
2204
+ OnchainEvent :: HTLCSpendConfirmation { input_idx, our_preimage, .. } => {
2205
+ self . htlcs_resolved_on_chain . push ( HTLCIrrevocablyResolved { input_idx, payment_preimage : our_preimage } ) ;
2206
+ } ,
2161
2207
OnchainEvent :: FundingSpendConfirmation { txid, .. } => {
2162
2208
self . funding_spend_confirmed = Some ( txid) ;
2163
2209
} ,
@@ -2339,6 +2385,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2339
2385
|| ( input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) && input. witness [ 1 ] . len ( ) == 33 ) ;
2340
2386
let accepted_preimage_claim = input. witness . len ( ) == 5 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 4 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) ;
2341
2387
let offered_preimage_claim = input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) ;
2388
+ let offered_timeout_claim = input. witness . len ( ) == 5 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) ;
2342
2389
2343
2390
macro_rules! log_claim {
2344
2391
( $tx_info: expr, $holder_tx: expr, $htlc: expr, $source_avail: expr) => {
@@ -2398,6 +2445,21 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2398
2445
}
2399
2446
if payment_data. is_none( ) {
2400
2447
log_claim!( $tx_info, $holder_tx, htlc_output, false ) ;
2448
+ self . onchain_events_awaiting_threshold_conf. push( OnchainEventEntry {
2449
+ txid: tx. txid( ) , height,
2450
+ event: OnchainEvent :: HTLCSpendConfirmation {
2451
+ input_idx: input. previous_output. vout,
2452
+ our_preimage: None ,
2453
+ // `payment_data.is_none()` implies that this is our
2454
+ // payment, as we haven't learned anything to cause us to
2455
+ // update another channel or our offchain state. Thus, wait
2456
+ // for the CSV delay before dropping the HTLC from
2457
+ // claimable balance if the claim was an HTLC-Success or
2458
+ // HTLC-Timeout transaction.
2459
+ on_to_local_output_csv: if accepted_preimage_claim || offered_timeout_claim {
2460
+ Some ( self . on_holder_tx_csv) } else { None } ,
2461
+ } ,
2462
+ } ) ;
2401
2463
continue ' outer_loop;
2402
2464
}
2403
2465
}
@@ -2428,6 +2490,15 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2428
2490
if !self . pending_monitor_events . iter ( ) . any (
2429
2491
|update| if let & MonitorEvent :: HTLCEvent ( ref upd) = update { upd. source == source } else { false } ) {
2430
2492
payment_preimage. 0 . copy_from_slice ( & input. witness [ 3 ] ) ;
2493
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
2494
+ txid : tx. txid ( ) ,
2495
+ height,
2496
+ event : OnchainEvent :: HTLCSpendConfirmation {
2497
+ input_idx : input. previous_output . vout ,
2498
+ our_preimage : Some ( payment_preimage) ,
2499
+ on_to_local_output_csv : None ,
2500
+ } ,
2501
+ } ) ;
2431
2502
self . pending_monitor_events . push ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
2432
2503
source,
2433
2504
payment_preimage : Some ( payment_preimage) ,
@@ -2441,6 +2512,15 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2441
2512
upd. source == source
2442
2513
} else { false } ) {
2443
2514
payment_preimage. 0 . copy_from_slice ( & input. witness [ 1 ] ) ;
2515
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
2516
+ txid : tx. txid ( ) ,
2517
+ height,
2518
+ event : OnchainEvent :: HTLCSpendConfirmation {
2519
+ input_idx : input. previous_output . vout ,
2520
+ our_preimage : Some ( payment_preimage) ,
2521
+ on_to_local_output_csv : None ,
2522
+ } ,
2523
+ } ) ;
2444
2524
self . pending_monitor_events . push ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
2445
2525
source,
2446
2526
payment_preimage : Some ( payment_preimage) ,
@@ -2458,12 +2538,14 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2458
2538
_ => true ,
2459
2539
}
2460
2540
} ) ;
2541
+ let txid = tx. txid ( ) ;
2461
2542
let entry = OnchainEventEntry {
2462
2543
txid : tx. txid ( ) ,
2463
2544
height,
2464
2545
event : OnchainEvent :: HTLCUpdate {
2465
2546
source, payment_hash,
2466
2547
onchain_value_satoshis : Some ( amount_msat / 1000 ) ,
2548
+ input_idx : Some ( input. previous_output . vout ) ,
2467
2549
} ,
2468
2550
} ;
2469
2551
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( ) ) ;
@@ -2836,8 +2918,10 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
2836
2918
}
2837
2919
2838
2920
let mut funding_spend_confirmed = None ;
2921
+ let mut htlcs_resolved_on_chain = Some ( Vec :: new ( ) ) ;
2839
2922
read_tlv_fields ! ( reader, {
2840
2923
( 1 , funding_spend_confirmed, option) ,
2924
+ ( 3 , htlcs_resolved_on_chain, vec_type) ,
2841
2925
} ) ;
2842
2926
2843
2927
let mut secp_ctx = Secp256k1 :: new ( ) ;
@@ -2888,6 +2972,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
2888
2972
lockdown_from_offchain,
2889
2973
holder_tx_signed,
2890
2974
funding_spend_confirmed,
2975
+ htlcs_resolved_on_chain : htlcs_resolved_on_chain. unwrap ( ) ,
2891
2976
2892
2977
best_block,
2893
2978
0 commit comments