@@ -289,6 +289,30 @@ struct ReceiveError {
289
289
msg : & ' static str ,
290
290
}
291
291
292
+ /// This enum is used to specify which error data to send to peers when failing back an HTLC
293
+ /// using [`ChannelManager::fail_htlc_backwards_with_reason`].
294
+ ///
295
+ /// For more info on failure codes, see <https://github.com/lightning/bolts/blob/master/04-onion-routing.md#failure-messages>.
296
+ #[ derive( Clone , Copy ) ]
297
+ pub enum FailureCode {
298
+ /// We had a temporary error processing the payment. Useful if no other error codes fit
299
+ /// and you want to indicate that the payer may want to retry.
300
+ TemporaryNodeFailure = 0x2000 | 2 ,
301
+ /// We have a required feature which was not in this onion. For example, you may require
302
+ /// some additional metadata that was not provided with this payment.
303
+ RequiredNodeFeatureMissing = 0x4000 | 0x2000 | 3 ,
304
+ /// The CLTV expiry is too close to the current block height for safe handling by us. This
305
+ /// should only be used when failing back as a forwarding node.
306
+ ExpiryTooSoon = 0x1000 | 14 ,
307
+ /// You may wish to use this when a `payment_hash` is unknown, the `payment_secret` is
308
+ /// required and not present, the `payment_secret` doesn't match the `payment_hash`, the
309
+ /// received amount is incorrect, the CLTV expiry of the HTLC is too close to the current
310
+ /// block height for safe handling, or `payment_metadata` isn't present when it should be.
311
+ /// Using this failure code in [`ChannelManager::fail_htlc_backwards_with_reason`] is
312
+ /// equivalent to calling [`ChannelManager::fail_htlc_backwards`].
313
+ IncorrectOrUnknownPaymentDetails = 0x4000 | 15 ,
314
+ }
315
+
292
316
type ShutdownResult = ( Option < ( OutPoint , ChannelMonitorUpdate ) > , Vec < ( HTLCSource , PaymentHash , PublicKey , [ u8 ; 32 ] ) > ) ;
293
317
294
318
/// Error type returned across the peer_state mutex boundary. When an Err is generated for a
@@ -3472,16 +3496,45 @@ where
3472
3496
/// [`events::Event::PaymentClaimed`] events even for payments you intend to fail, especially on
3473
3497
/// startup during which time claims that were in-progress at shutdown may be replayed.
3474
3498
pub fn fail_htlc_backwards ( & self , payment_hash : & PaymentHash ) {
3499
+ self . fail_htlc_backwards_with_reason ( payment_hash, & FailureCode :: IncorrectOrUnknownPaymentDetails ) ;
3500
+ }
3501
+
3502
+ /// This is a variant of [`ChannelManager::fail_htlc_backwards`] that allows you to specify the
3503
+ /// reason for the failure.
3504
+ ///
3505
+ /// See [`FailureCode`] for valid failure codes.
3506
+ pub fn fail_htlc_backwards_with_reason ( & self , payment_hash : & PaymentHash , failure_code : & FailureCode ) {
3475
3507
let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop ( & self . total_consistency_lock , & self . persistence_notifier ) ;
3476
3508
3477
3509
let removed_source = self . claimable_payments . lock ( ) . unwrap ( ) . claimable_htlcs . remove ( payment_hash) ;
3478
3510
if let Some ( ( _, mut sources) ) = removed_source {
3479
3511
for htlc in sources. drain ( ..) {
3480
- let mut htlc_msat_height_data = htlc. value . to_be_bytes ( ) . to_vec ( ) ;
3481
- htlc_msat_height_data. extend_from_slice ( & self . best_block . read ( ) . unwrap ( ) . height ( ) . to_be_bytes ( ) ) ;
3482
- let source = HTLCSource :: PreviousHopData ( htlc. prev_hop ) ;
3483
- let reason = HTLCFailReason :: reason ( 0x4000 | 15 , htlc_msat_height_data) ;
3512
+ let source = HTLCSource :: PreviousHopData ( htlc. prev_hop . clone ( ) ) ;
3484
3513
let receiver = HTLCDestination :: FailedPayment { payment_hash : * payment_hash } ;
3514
+
3515
+ let reason = match failure_code {
3516
+ FailureCode :: TemporaryNodeFailure => HTLCFailReason :: from_failure_code ( * failure_code as u16 ) ,
3517
+ FailureCode :: RequiredNodeFeatureMissing => HTLCFailReason :: from_failure_code ( * failure_code as u16 ) ,
3518
+ FailureCode :: ExpiryTooSoon => {
3519
+ let short_channel_id = htlc. prev_hop . short_channel_id ;
3520
+ let ( counterparty_node_id, chan_id) = self . short_to_chan_info . read ( ) . unwrap ( ) . get ( & short_channel_id) . cloned ( ) . unwrap ( ) ;
3521
+ let per_peer_state = self . per_peer_state . read ( ) . unwrap ( ) ;
3522
+ let peer_state = per_peer_state. get ( & counterparty_node_id) . unwrap ( ) . lock ( ) . unwrap ( ) ;
3523
+ let chan = peer_state. channel_by_id . get ( & chan_id) . unwrap ( ) ;
3524
+ let channel_update = self . get_channel_update_for_onion ( short_channel_id, chan) . unwrap ( ) ;
3525
+ let mut channel_update_data = Vec :: new ( ) ;
3526
+ ( channel_update. serialized_length ( ) as u16 + 2 ) . write ( & mut channel_update_data) . expect ( "Writes cannot fail" ) ;
3527
+ msgs:: ChannelUpdate :: TYPE . write ( & mut channel_update_data) . expect ( "Writes cannot fail" ) ;
3528
+ channel_update. write ( & mut channel_update_data) . expect ( "Writes cannot fail" ) ;
3529
+ HTLCFailReason :: reason ( * failure_code as u16 , channel_update_data)
3530
+ } ,
3531
+ FailureCode :: IncorrectOrUnknownPaymentDetails => {
3532
+ let mut htlc_msat_height_data = htlc. value . to_be_bytes ( ) . to_vec ( ) ;
3533
+ htlc_msat_height_data. extend_from_slice ( & self . best_block . read ( ) . unwrap ( ) . height ( ) . to_be_bytes ( ) ) ;
3534
+ HTLCFailReason :: reason ( * failure_code as u16 , htlc_msat_height_data)
3535
+ }
3536
+ } ;
3537
+
3485
3538
self . fail_htlc_backwards_internal ( & source, & payment_hash, & reason, receiver) ;
3486
3539
}
3487
3540
}
0 commit comments