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