@@ -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 {})" ,
@@ -2117,6 +2156,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2117
2156
OnchainEvent :: HTLCUpdate { source, .. } => Some ( source) ,
2118
2157
OnchainEvent :: MaturingOutput { .. } => None ,
2119
2158
OnchainEvent :: FundingSpendConfirmation { .. } => None ,
2159
+ OnchainEvent :: HTLCSpendConfirmation { .. } => None ,
2120
2160
} )
2121
2161
. collect ( ) ;
2122
2162
#[ cfg( debug_assertions) ]
@@ -2125,7 +2165,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2125
2165
// Produce actionable events from on-chain events having reached their threshold.
2126
2166
for entry in onchain_events_reaching_threshold_conf. drain ( ..) {
2127
2167
match entry. event {
2128
- OnchainEvent :: HTLCUpdate { ref source, payment_hash, onchain_value_satoshis } => {
2168
+ OnchainEvent :: HTLCUpdate { ref source, payment_hash, onchain_value_satoshis, input_idx } => {
2129
2169
// Check for duplicate HTLC resolutions.
2130
2170
#[ cfg( debug_assertions) ]
2131
2171
{
@@ -2149,13 +2189,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2149
2189
source : source. clone ( ) ,
2150
2190
onchain_value_satoshis,
2151
2191
} ) ) ;
2192
+ if let Some ( idx) = input_idx {
2193
+ self . htlcs_resolved_on_chain . push ( HTLCIrrevocablyResolved { input_idx : idx, payment_preimage : None } ) ;
2194
+ }
2152
2195
} ,
2153
2196
OnchainEvent :: MaturingOutput { descriptor } => {
2154
2197
log_debug ! ( logger, "Descriptor {} has got enough confirmations to be passed upstream" , log_spendable!( descriptor) ) ;
2155
2198
self . pending_events . push ( Event :: SpendableOutputs {
2156
2199
outputs : vec ! [ descriptor]
2157
2200
} ) ;
2158
2201
} ,
2202
+ OnchainEvent :: HTLCSpendConfirmation { input_idx, our_preimage, .. } => {
2203
+ self . htlcs_resolved_on_chain . push ( HTLCIrrevocablyResolved { input_idx, payment_preimage : our_preimage } ) ;
2204
+ } ,
2159
2205
OnchainEvent :: FundingSpendConfirmation { txid, .. } => {
2160
2206
self . funding_spend_confirmed = Some ( txid) ;
2161
2207
} ,
@@ -2337,6 +2383,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2337
2383
|| ( input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) && input. witness [ 1 ] . len ( ) == 33 ) ;
2338
2384
let accepted_preimage_claim = input. witness . len ( ) == 5 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 4 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) ;
2339
2385
let offered_preimage_claim = input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) ;
2386
+ let offered_timeout_claim = input. witness . len ( ) == 5 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) ;
2340
2387
2341
2388
macro_rules! log_claim {
2342
2389
( $tx_info: expr, $holder_tx: expr, $htlc: expr, $source_avail: expr) => {
@@ -2396,6 +2443,21 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2396
2443
}
2397
2444
if payment_data. is_none( ) {
2398
2445
log_claim!( $tx_info, $holder_tx, htlc_output, false ) ;
2446
+ self . onchain_events_awaiting_threshold_conf. push( OnchainEventEntry {
2447
+ txid: tx. txid( ) , height,
2448
+ event: OnchainEvent :: HTLCSpendConfirmation {
2449
+ input_idx: input. previous_output. vout,
2450
+ our_preimage: None ,
2451
+ // `payment_data.is_none()` implies that this is our
2452
+ // payment, as we haven't learned anything to cause us to
2453
+ // update another channel or our offchain state. Thus, wait
2454
+ // for the CSV delay before dropping the HTLC from
2455
+ // claimable balance if the claim was an HTLC-Success or
2456
+ // HTLC-Timeout transaction.
2457
+ on_to_local_output_csv: if accepted_preimage_claim || offered_timeout_claim {
2458
+ Some ( self . on_holder_tx_csv) } else { None } ,
2459
+ } ,
2460
+ } ) ;
2399
2461
continue ' outer_loop;
2400
2462
}
2401
2463
}
@@ -2426,6 +2488,15 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2426
2488
if !self . pending_monitor_events . iter ( ) . any (
2427
2489
|update| if let & MonitorEvent :: HTLCEvent ( ref upd) = update { upd. source == source } else { false } ) {
2428
2490
payment_preimage. 0 . copy_from_slice ( & input. witness [ 3 ] ) ;
2491
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
2492
+ txid : tx. txid ( ) ,
2493
+ height,
2494
+ event : OnchainEvent :: HTLCSpendConfirmation {
2495
+ input_idx : input. previous_output . vout ,
2496
+ our_preimage : Some ( payment_preimage) ,
2497
+ on_to_local_output_csv : None ,
2498
+ } ,
2499
+ } ) ;
2429
2500
self . pending_monitor_events . push ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
2430
2501
source,
2431
2502
payment_preimage : Some ( payment_preimage) ,
@@ -2439,6 +2510,15 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2439
2510
upd. source == source
2440
2511
} else { false } ) {
2441
2512
payment_preimage. 0 . copy_from_slice ( & input. witness [ 1 ] ) ;
2513
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
2514
+ txid : tx. txid ( ) ,
2515
+ height,
2516
+ event : OnchainEvent :: HTLCSpendConfirmation {
2517
+ input_idx : input. previous_output . vout ,
2518
+ our_preimage : Some ( payment_preimage) ,
2519
+ on_to_local_output_csv : None ,
2520
+ } ,
2521
+ } ) ;
2442
2522
self . pending_monitor_events . push ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
2443
2523
source,
2444
2524
payment_preimage : Some ( payment_preimage) ,
@@ -2456,12 +2536,14 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2456
2536
_ => true ,
2457
2537
}
2458
2538
} ) ;
2539
+ let txid = tx. txid ( ) ;
2459
2540
let entry = OnchainEventEntry {
2460
2541
txid : tx. txid ( ) ,
2461
2542
height,
2462
2543
event : OnchainEvent :: HTLCUpdate {
2463
2544
source, payment_hash,
2464
2545
onchain_value_satoshis : Some ( amount_msat / 1000 ) ,
2546
+ input_idx : Some ( input. previous_output . vout ) ,
2465
2547
} ,
2466
2548
} ;
2467
2549
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( ) ) ;
@@ -2834,8 +2916,10 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
2834
2916
}
2835
2917
2836
2918
let mut funding_spend_confirmed = None ;
2919
+ let mut htlcs_resolved_on_chain = Some ( Vec :: new ( ) ) ;
2837
2920
read_tlv_fields ! ( reader, {
2838
2921
( 1 , funding_spend_confirmed, option) ,
2922
+ ( 3 , htlcs_resolved_on_chain, vec_type) ,
2839
2923
} ) ;
2840
2924
2841
2925
let mut secp_ctx = Secp256k1 :: new ( ) ;
@@ -2886,6 +2970,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
2886
2970
lockdown_from_offchain,
2887
2971
holder_tx_signed,
2888
2972
funding_spend_confirmed,
2973
+ htlcs_resolved_on_chain : htlcs_resolved_on_chain. unwrap ( ) ,
2889
2974
2890
2975
best_block,
2891
2976
0 commit comments