@@ -364,7 +364,8 @@ impl OnchainEventEntry {
364
364
// it's broadcastable when we see the previous block.
365
365
conf_threshold = cmp:: max ( conf_threshold, self . height + descriptor. to_self_delay as u32 - 1 ) ;
366
366
} ,
367
- OnchainEvent :: FundingSpendConfirmation { on_local_output_csv : Some ( csv) , .. } => {
367
+ OnchainEvent :: FundingSpendConfirmation { on_local_output_csv : Some ( csv) , .. } |
368
+ OnchainEvent :: HTLCSpendConfirmation { on_to_local_output_csv : Some ( csv) , .. } => {
368
369
// A CSV'd transaction is confirmable in block (input height) + CSV delay, which means
369
370
// it's broadcastable when we see the previous block.
370
371
conf_threshold = cmp:: max ( conf_threshold, self . height + csv as u32 - 1 ) ;
@@ -383,25 +384,47 @@ impl OnchainEventEntry {
383
384
/// once they mature to enough confirmations (ANTI_REORG_DELAY)
384
385
#[ derive( PartialEq ) ]
385
386
enum OnchainEvent {
386
- /// HTLC output getting solved by a timeout, at maturation we pass upstream payment source information to solve
387
- /// inbound HTLC in backward channel. Note, in case of preimage, we pass info to upstream without delay as we can
388
- /// only win from it, so it's never an OnchainEvent
387
+ /// An outbound HTLC failing after a transaction is confirmed. Used
388
+ /// * when an outbound HTLC output is spent by us after the HTLC timed out
389
+ /// * an outbound HTLC which was not present in the commitment transaction which appeared
390
+ /// on-chain (either because it was not fully committed to or it was dust).
391
+ /// Note that this is *not* used for preimage claims, as those are passed upstream immediately,
392
+ /// appearing only as an `HTLCSpendConfirmation`, below.
389
393
HTLCUpdate {
390
394
source : HTLCSource ,
391
395
payment_hash : PaymentHash ,
392
396
onchain_value_satoshis : Option < u64 > ,
397
+ /// None in the second case, above, ie when there is no relevant output in the commitment
398
+ /// transaction which appeared on chain.
399
+ input_idx : Option < u32 > ,
393
400
} ,
394
401
MaturingOutput {
395
402
descriptor : SpendableOutputDescriptor ,
396
403
} ,
397
404
/// A spend of the funding output, either a commitment transaction or a cooperative closing
398
405
/// transaction.
399
406
FundingSpendConfirmation {
400
- txid : Txid ,
401
407
/// The CSV delay for the output of the funding spend transaction (implying it is a local
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
+ /// A spend of a commitment transaction HTLC output, set in the cases where *no* `HTLCUpdate`
412
+ /// is constructed. This is used when
413
+ /// * an outbound HTLC is claimed by our counterparty with a preimage, causing us to
414
+ /// immediately claim the HTLC on the inbound edge and track the resolution here,
415
+ /// * an inbound HTLC is claimed by our counterparty (with a timeout),
416
+ /// * an inbound HTLC is claimed by us (with a preimage).
417
+ /// * a revoked-state HTLC transaction was broadcasted, which was claimed by the revocation
418
+ /// signature.
419
+ HTLCSpendConfirmation {
420
+ input_idx : u32 ,
421
+ /// If the claim was made by either party with a preimage, this is filled in
422
+ preimage : Option < PaymentPreimage > ,
423
+ /// If the claim was made by us on an inbound HTLC against a local commitment transaction,
424
+ /// we set this to the output CSV value which we will have to wait until to spend the
425
+ /// output (and generate a SpendableOutput event).
426
+ on_to_local_output_csv : Option < u16 > ,
427
+ } ,
405
428
}
406
429
407
430
impl Writeable for OnchainEventEntry {
@@ -438,14 +461,20 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
438
461
( 0 , source, required) ,
439
462
( 1 , onchain_value_satoshis, option) ,
440
463
( 2 , payment_hash, required) ,
464
+ ( 3 , input_idx, option) ,
441
465
} ,
442
466
( 1 , MaturingOutput ) => {
443
467
( 0 , descriptor, required) ,
444
468
} ,
445
469
( 3 , FundingSpendConfirmation ) => {
446
- ( 0 , txid, required) ,
447
- ( 2 , on_local_output_csv, option) ,
470
+ ( 0 , on_local_output_csv, option) ,
448
471
} ,
472
+ ( 5 , HTLCSpendConfirmation ) => {
473
+ ( 0 , input_idx, required) ,
474
+ ( 2 , preimage, option) ,
475
+ ( 4 , on_to_local_output_csv, option) ,
476
+ } ,
477
+
449
478
) ;
450
479
451
480
#[ cfg_attr( any( test, feature = "fuzztarget" , feature = "_test_utils" ) , derive( PartialEq ) ) ]
@@ -506,6 +535,19 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
506
535
} ,
507
536
) ;
508
537
538
+ /// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
539
+ #[ derive( PartialEq ) ]
540
+ struct IrrevocablyResolvedHTLC {
541
+ input_idx : u32 ,
542
+ /// Only set if the HTLC claim was ours using a payment preimage
543
+ payment_preimage : Option < PaymentPreimage > ,
544
+ }
545
+
546
+ impl_writeable_tlv_based ! ( IrrevocablyResolvedHTLC , {
547
+ ( 0 , input_idx, required) ,
548
+ ( 2 , payment_preimage, option) ,
549
+ } ) ;
550
+
509
551
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
510
552
/// on-chain transactions to ensure no loss of funds occurs.
511
553
///
@@ -619,6 +661,10 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
619
661
holder_tx_signed : bool ,
620
662
621
663
funding_spend_confirmed : Option < Txid > ,
664
+ /// The set of HTLCs which have been either claimed or failed on chain and have reached
665
+ /// the requisite confirmations on the claim/fail transaction (either ANTI_REORG_DELAY or the
666
+ /// spending CSV for revocable outputs).
667
+ htlcs_resolved_on_chain : Vec < IrrevocablyResolvedHTLC > ,
622
668
623
669
// We simply modify best_block in Channel's block_connected so that serialization is
624
670
// consistent but hopefully the users' copy handles block_connected in a consistent way.
@@ -679,7 +725,8 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
679
725
self . outputs_to_watch != other. outputs_to_watch ||
680
726
self . lockdown_from_offchain != other. lockdown_from_offchain ||
681
727
self . holder_tx_signed != other. holder_tx_signed ||
682
- self . funding_spend_confirmed != other. funding_spend_confirmed
728
+ self . funding_spend_confirmed != other. funding_spend_confirmed ||
729
+ self . htlcs_resolved_on_chain != other. htlcs_resolved_on_chain
683
730
{
684
731
false
685
732
} else {
@@ -846,6 +893,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
846
893
847
894
write_tlv_fields ! ( writer, {
848
895
( 1 , self . funding_spend_confirmed, option) ,
896
+ ( 3 , self . htlcs_resolved_on_chain, vec_type) ,
849
897
} ) ;
850
898
851
899
Ok ( ( ) )
@@ -945,6 +993,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
945
993
lockdown_from_offchain : false ,
946
994
holder_tx_signed : false ,
947
995
funding_spend_confirmed : None ,
996
+ htlcs_resolved_on_chain : Vec :: new ( ) ,
948
997
949
998
best_block,
950
999
@@ -1311,6 +1360,7 @@ macro_rules! fail_unbroadcast_htlcs {
1311
1360
source: ( * * source) . clone( ) ,
1312
1361
payment_hash: htlc. payment_hash. clone( ) ,
1313
1362
onchain_value_satoshis: Some ( htlc. amount_msat / 1000 ) ,
1363
+ input_idx: None ,
1314
1364
} ,
1315
1365
} ;
1316
1366
log_trace!( $logger, "Failing HTLC with payment_hash {} from {} counterparty commitment tx due to broadcast of {} commitment transaction, waiting for confirmation (at height {})" ,
@@ -2024,7 +2074,6 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2024
2074
txid,
2025
2075
height : height,
2026
2076
event : OnchainEvent :: FundingSpendConfirmation {
2027
- txid,
2028
2077
on_local_output_csv : balance_spendable_csv,
2029
2078
} ,
2030
2079
} ) ;
@@ -2115,8 +2164,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2115
2164
. iter ( )
2116
2165
. filter_map ( |entry| match & entry. event {
2117
2166
OnchainEvent :: HTLCUpdate { source, .. } => Some ( source) ,
2118
- OnchainEvent :: MaturingOutput { .. } => None ,
2119
- OnchainEvent :: FundingSpendConfirmation { .. } => None ,
2167
+ _ => None ,
2120
2168
} )
2121
2169
. collect ( ) ;
2122
2170
#[ cfg( debug_assertions) ]
@@ -2125,7 +2173,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2125
2173
// Produce actionable events from on-chain events having reached their threshold.
2126
2174
for entry in onchain_events_reaching_threshold_conf. drain ( ..) {
2127
2175
match entry. event {
2128
- OnchainEvent :: HTLCUpdate { ref source, payment_hash, onchain_value_satoshis } => {
2176
+ OnchainEvent :: HTLCUpdate { ref source, payment_hash, onchain_value_satoshis, input_idx } => {
2129
2177
// Check for duplicate HTLC resolutions.
2130
2178
#[ cfg( debug_assertions) ]
2131
2179
{
@@ -2149,15 +2197,21 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2149
2197
source : source. clone ( ) ,
2150
2198
onchain_value_satoshis,
2151
2199
} ) ) ;
2200
+ if let Some ( idx) = input_idx {
2201
+ self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC { input_idx : idx, payment_preimage : None } ) ;
2202
+ }
2152
2203
} ,
2153
2204
OnchainEvent :: MaturingOutput { descriptor } => {
2154
2205
log_debug ! ( logger, "Descriptor {} has got enough confirmations to be passed upstream" , log_spendable!( descriptor) ) ;
2155
2206
self . pending_events . push ( Event :: SpendableOutputs {
2156
2207
outputs : vec ! [ descriptor]
2157
2208
} ) ;
2158
2209
} ,
2159
- OnchainEvent :: FundingSpendConfirmation { txid, .. } => {
2160
- self . funding_spend_confirmed = Some ( txid) ;
2210
+ OnchainEvent :: HTLCSpendConfirmation { input_idx, preimage, .. } => {
2211
+ self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC { input_idx, payment_preimage : preimage } ) ;
2212
+ } ,
2213
+ OnchainEvent :: FundingSpendConfirmation { .. } => {
2214
+ self . funding_spend_confirmed = Some ( entry. txid ) ;
2161
2215
} ,
2162
2216
}
2163
2217
}
@@ -2336,15 +2390,32 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2336
2390
let revocation_sig_claim = ( input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) && input. witness [ 1 ] . len ( ) == 33 )
2337
2391
|| ( input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) && input. witness [ 1 ] . len ( ) == 33 ) ;
2338
2392
let accepted_preimage_claim = input. witness . len ( ) == 5 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 4 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) ;
2339
- let offered_preimage_claim = input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) ;
2393
+ let accepted_timeout_claim = input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: AcceptedHTLC ) && !revocation_sig_claim;
2394
+ let offered_preimage_claim = input. witness . len ( ) == 3 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 2 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) && !revocation_sig_claim;
2395
+ let offered_timeout_claim = input. witness . len ( ) == 5 && HTLCType :: scriptlen_to_htlctype ( input. witness [ 4 ] . len ( ) ) == Some ( HTLCType :: OfferedHTLC ) ;
2396
+
2397
+ let mut payment_preimage = PaymentPreimage ( [ 0 ; 32 ] ) ;
2398
+ if accepted_preimage_claim {
2399
+ payment_preimage. 0 . copy_from_slice ( & input. witness [ 3 ] ) ;
2400
+ } else if offered_preimage_claim {
2401
+ payment_preimage. 0 . copy_from_slice ( & input. witness [ 1 ] ) ;
2402
+ }
2340
2403
2341
2404
macro_rules! log_claim {
2342
2405
( $tx_info: expr, $holder_tx: expr, $htlc: expr, $source_avail: expr) => {
2343
- // We found the output in question, but aren't failing it backwards
2344
- // as we have no corresponding source and no valid counterparty commitment txid
2345
- // to try a weak source binding with same-hash, same-value still-valid offered HTLC.
2346
- // This implies either it is an inbound HTLC or an outbound HTLC on a revoked transaction.
2347
2406
let outbound_htlc = $holder_tx == $htlc. offered;
2407
+ // HTLCs must either be claimed by a matching script type or through the
2408
+ // revocation path:
2409
+ #[ cfg( not( fuzzing) ) ] // Note that the fuzzer is not bound by pesky things like "signatures"
2410
+ debug_assert!( !$htlc. offered || offered_preimage_claim || offered_timeout_claim || revocation_sig_claim) ;
2411
+ #[ cfg( not( fuzzing) ) ] // Note that the fuzzer is not bound by pesky things like "signatures"
2412
+ debug_assert!( $htlc. offered || accepted_preimage_claim || accepted_timeout_claim || revocation_sig_claim) ;
2413
+ // Further, only exactly one of the possible spend paths should have been
2414
+ // matched by any HTLC spend:
2415
+ #[ cfg( not( fuzzing) ) ] // Note that the fuzzer is not bound by pesky things like "signatures"
2416
+ debug_assert_eq!( accepted_preimage_claim as u8 + accepted_timeout_claim as u8 +
2417
+ offered_preimage_claim as u8 + offered_timeout_claim as u8 +
2418
+ revocation_sig_claim as u8 , 1 ) ;
2348
2419
if ( $holder_tx && revocation_sig_claim) ||
2349
2420
( outbound_htlc && !$source_avail && ( accepted_preimage_claim || offered_preimage_claim) ) {
2350
2421
log_error!( logger, "Input spending {} ({}:{}) in {} resolves {} HTLC with payment hash {} with {}!" ,
@@ -2396,6 +2467,30 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2396
2467
}
2397
2468
if payment_data. is_none( ) {
2398
2469
log_claim!( $tx_info, $holder_tx, htlc_output, false ) ;
2470
+ let outbound_htlc = $holder_tx == htlc_output. offered;
2471
+ if !outbound_htlc || revocation_sig_claim {
2472
+ self . onchain_events_awaiting_threshold_conf. push( OnchainEventEntry {
2473
+ txid: tx. txid( ) , height,
2474
+ event: OnchainEvent :: HTLCSpendConfirmation {
2475
+ input_idx: input. previous_output. vout,
2476
+ preimage: if accepted_preimage_claim || offered_preimage_claim {
2477
+ Some ( payment_preimage) } else { None } ,
2478
+ // If this is a payment to us (!outbound_htlc, above),
2479
+ // wait for the CSV delay before dropping the HTLC from
2480
+ // claimable balance if the claim was an HTLC-Success
2481
+ // transaction.
2482
+ on_to_local_output_csv: if accepted_preimage_claim {
2483
+ Some ( self . on_holder_tx_csv) } else { None } ,
2484
+ } ,
2485
+ } ) ;
2486
+ } else {
2487
+ // Outbound claims should always have payment_data, unless
2488
+ // we've already failed the HTLC as the commitment transaction
2489
+ // which was broadcasted was revoked. In that case, we should
2490
+ // spend the HTLC output here immediately, and expose that fact
2491
+ // as a ClaimableBalance, something which we do not yet do.
2492
+ // TODO: Track the above as claimable!
2493
+ }
2399
2494
continue ' outer_loop;
2400
2495
}
2401
2496
}
@@ -2421,11 +2516,18 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2421
2516
// Check that scan_commitment, above, decided there is some source worth relaying an
2422
2517
// HTLC resolution backwards to and figure out whether we learned a preimage from it.
2423
2518
if let Some ( ( source, payment_hash, amount_msat) ) = payment_data {
2424
- let mut payment_preimage = PaymentPreimage ( [ 0 ; 32 ] ) ;
2425
2519
if accepted_preimage_claim {
2426
2520
if !self . pending_monitor_events . iter ( ) . any (
2427
2521
|update| if let & MonitorEvent :: HTLCEvent ( ref upd) = update { upd. source == source } else { false } ) {
2428
- payment_preimage. 0 . copy_from_slice ( & input. witness [ 3 ] ) ;
2522
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
2523
+ txid : tx. txid ( ) ,
2524
+ height,
2525
+ event : OnchainEvent :: HTLCSpendConfirmation {
2526
+ input_idx : input. previous_output . vout ,
2527
+ preimage : Some ( payment_preimage) ,
2528
+ on_to_local_output_csv : None ,
2529
+ } ,
2530
+ } ) ;
2429
2531
self . pending_monitor_events . push ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
2430
2532
source,
2431
2533
payment_preimage : Some ( payment_preimage) ,
@@ -2438,7 +2540,15 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2438
2540
|update| if let & MonitorEvent :: HTLCEvent ( ref upd) = update {
2439
2541
upd. source == source
2440
2542
} else { false } ) {
2441
- payment_preimage. 0 . copy_from_slice ( & input. witness [ 1 ] ) ;
2543
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
2544
+ txid : tx. txid ( ) ,
2545
+ height,
2546
+ event : OnchainEvent :: HTLCSpendConfirmation {
2547
+ input_idx : input. previous_output . vout ,
2548
+ preimage : Some ( payment_preimage) ,
2549
+ on_to_local_output_csv : None ,
2550
+ } ,
2551
+ } ) ;
2442
2552
self . pending_monitor_events . push ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
2443
2553
source,
2444
2554
payment_preimage : Some ( payment_preimage) ,
@@ -2462,6 +2572,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2462
2572
event : OnchainEvent :: HTLCUpdate {
2463
2573
source, payment_hash,
2464
2574
onchain_value_satoshis : Some ( amount_msat / 1000 ) ,
2575
+ input_idx : Some ( input. previous_output . vout ) ,
2465
2576
} ,
2466
2577
} ;
2467
2578
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 +2945,10 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
2834
2945
}
2835
2946
2836
2947
let mut funding_spend_confirmed = None ;
2948
+ let mut htlcs_resolved_on_chain = Some ( Vec :: new ( ) ) ;
2837
2949
read_tlv_fields ! ( reader, {
2838
2950
( 1 , funding_spend_confirmed, option) ,
2951
+ ( 3 , htlcs_resolved_on_chain, vec_type) ,
2839
2952
} ) ;
2840
2953
2841
2954
let mut secp_ctx = Secp256k1 :: new ( ) ;
@@ -2886,6 +2999,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
2886
2999
lockdown_from_offchain,
2887
3000
holder_tx_signed,
2888
3001
funding_spend_confirmed,
3002
+ htlcs_resolved_on_chain : htlcs_resolved_on_chain. unwrap ( ) ,
2889
3003
2890
3004
best_block,
2891
3005
0 commit comments