@@ -1069,11 +1069,6 @@ where
1069
1069
let mut is_from_final_non_blinded_node = false ;
1070
1070
let mut hop_hold_times: Vec < u32 > = Vec :: new ( ) ;
1071
1071
1072
- const BADONION : u16 = 0x8000 ;
1073
- const PERM : u16 = 0x4000 ;
1074
- const NODE : u16 = 0x2000 ;
1075
- const UPDATE : u16 = 0x1000 ;
1076
-
1077
1072
enum ErrorHop < ' a > {
1078
1073
RouteHop ( & ' a RouteHop ) ,
1079
1074
TrampolineHop ( & ' a TrampolineHop ) ,
@@ -1451,6 +1446,188 @@ where
1451
1446
}
1452
1447
}
1453
1448
1449
+ const BADONION : u16 = 0x8000 ;
1450
+ const PERM : u16 = 0x4000 ;
1451
+ const NODE : u16 = 0x2000 ;
1452
+ const UPDATE : u16 = 0x1000 ;
1453
+
1454
+ /// The reason that a HTLC was failed by the local node. These errors represent direct,
1455
+ /// human-readable mappings of BOLT04 error codes.
1456
+ #[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq ) ]
1457
+ pub enum LocalHTLCFailureReason {
1458
+ /// There has been a temporary processing failure on the node which may resolve on retry.
1459
+ TemporaryNodeFailure ,
1460
+ /// These has been a permanent processing failure on the node which will not resolve on retry.
1461
+ PermanentNodeFailure ,
1462
+ /// The HTLC does not implement a feature that is required by our node.
1463
+ ///
1464
+ /// The sender may have outdated gossip, or a bug in its implementation.
1465
+ RequiredNodeFeature ,
1466
+ /// The onion version specified by the HTLC packet is unknown to our node.
1467
+ InvalidOnionVersion ,
1468
+ /// The integrity of the HTLC packet cannot be verified because it has an invalid HMAC.
1469
+ InvalidOnionHMAC ,
1470
+ /// The onion packet has an invalid ephemeral key, so the HTLC cannot be processed.
1471
+ InvalidOnionKey ,
1472
+ /// A temporary forwarding error has occurred which may resolve on retry.
1473
+ TemporaryChannelFailure ,
1474
+ /// A permanent forwarding error has occurred which will not resolve on retry.
1475
+ PermanentChannelFailure ,
1476
+ /// The HTLC does not implement a feature that is required by our channel for processing.
1477
+ RequiredChannelFeature ,
1478
+ /// The HTLC's target outgoing channel that is not known to our node.
1479
+ UnknownNextPeer ,
1480
+ /// The HTLC amount is below our advertised htlc_minimum_msat.
1481
+ ///
1482
+ /// The sender may have outdated gossip, or a bug in its implementation.
1483
+ AmountBelowMinimum ,
1484
+ /// The HTLC does not pay sufficient fees.
1485
+ ///
1486
+ /// The sender may have outdated gossip, or a bug in its implementation.
1487
+ FeeInsufficient ,
1488
+ /// The HTLC does not meet the cltv_expiry_delta advertised by our node, set by
1489
+ /// [`ChannelConfig::cltv_expiry_delta`].
1490
+ ///
1491
+ /// The sender may have outdated gossip, or a bug in its implementation.
1492
+ ///
1493
+ /// [`ChannelConfig::cltv_expiry_delta`]: crate::util::config::ChannelConfig::cltv_expiry_delta
1494
+ IncorrectCLTVExpiry ,
1495
+ /// The HTLC expires too close to the current block height to be safely processed.
1496
+ CLTVExpiryTooSoon ,
1497
+ /// A payment was made to our node that either had incorrect payment information, or was
1498
+ /// unknown to us.
1499
+ IncorrectPaymentDetails ,
1500
+ /// The HTLC's expiry is less than the expiry height specified by the sender.
1501
+ ///
1502
+ /// The forwarding node has either tampered with this value, or the sending node has an
1503
+ /// old best block height.
1504
+ FinalIncorrectCLTVExpiry ,
1505
+ /// The HTLC's amount is less than the amount specified by the sender.
1506
+ ///
1507
+ /// The forwarding node has tampered with this value, or has a bug in its implementation.
1508
+ FinalIncorrectHTLCAmount ,
1509
+ /// The channel has been marked as disabled because the channel peer is offline.
1510
+ ChannelDisabled ,
1511
+ /// The HTLC expires too far in the future, so it is rejected to avoid the worst-case outcome
1512
+ /// of funds being held for extended periods of time.
1513
+ ///
1514
+ /// Limit set by ['crate::ln::channelmanager::CLTV_FAR_FAR_AWAY`].
1515
+ CLTVExpiryTooFar ,
1516
+ /// The HTLC payload contained in the onion packet could not be understood by our node.
1517
+ InvalidOnionPayload ,
1518
+ /// The total amount for a multi-part payment did not arrive in time, so the HTLCs partially
1519
+ /// paying the amount were canceled.
1520
+ MPPTimeout ,
1521
+ /// Our node was selected as part of a blinded path, but the packet we received was not
1522
+ /// properly constructed, or had incorrect values for the blinded path.
1523
+ ///
1524
+ /// This may happen if the forwarding node tamperd with the HTLC or the sender or recipient
1525
+ /// implementations have a bug.
1526
+ InvalidOnionBlinding ,
1527
+ /// UnknownFailureCode represents BOLT04 failure codes that we are not familiar with. We will
1528
+ /// encounter this if:
1529
+ /// - A peer sends us a new failure code that LDK has not yet been upgraded to understand.
1530
+ /// - We read a deprecated failure code from disk that LDK no longer uses.
1531
+ ///
1532
+ /// See <https://github.com/lightning/bolts/blob/master/04-onion-routing.md#returning-errors>
1533
+ /// for latest defined error codes.
1534
+ UnknownFailureCode {
1535
+ /// The bolt 04 failure code.
1536
+ code : u16 ,
1537
+ } ,
1538
+ }
1539
+
1540
+ impl LocalHTLCFailureReason {
1541
+ pub ( super ) fn failure_code ( & self ) -> u16 {
1542
+ match self {
1543
+ Self :: TemporaryNodeFailure => NODE | 2 ,
1544
+ Self :: PermanentNodeFailure => PERM | NODE | 2 ,
1545
+ Self :: RequiredNodeFeature => PERM | NODE | 3 ,
1546
+ Self :: InvalidOnionVersion => BADONION | PERM | 4 ,
1547
+ Self :: InvalidOnionHMAC => BADONION | PERM | 5 ,
1548
+ Self :: InvalidOnionKey => BADONION | PERM | 6 ,
1549
+ Self :: TemporaryChannelFailure => UPDATE | 7 ,
1550
+ Self :: PermanentChannelFailure => PERM | 8 ,
1551
+ Self :: RequiredChannelFeature => PERM | 9 ,
1552
+ Self :: UnknownNextPeer => PERM | 10 ,
1553
+ Self :: AmountBelowMinimum => UPDATE | 11 ,
1554
+ Self :: FeeInsufficient => UPDATE | 12 ,
1555
+ Self :: IncorrectCLTVExpiry => UPDATE | 13 ,
1556
+ Self :: CLTVExpiryTooSoon => UPDATE | 14 ,
1557
+ Self :: IncorrectPaymentDetails => PERM | 15 ,
1558
+ Self :: FinalIncorrectCLTVExpiry => 18 ,
1559
+ Self :: FinalIncorrectHTLCAmount => 19 ,
1560
+ Self :: ChannelDisabled => UPDATE | 20 ,
1561
+ Self :: CLTVExpiryTooFar => 21 ,
1562
+ Self :: InvalidOnionPayload => PERM | 22 ,
1563
+ Self :: MPPTimeout => 23 ,
1564
+ Self :: InvalidOnionBlinding => BADONION | PERM | 24 ,
1565
+ Self :: UnknownFailureCode { code } => * code,
1566
+ }
1567
+ }
1568
+
1569
+ pub ( super ) fn is_temporary ( & self ) -> bool {
1570
+ self . failure_code ( ) & UPDATE == UPDATE
1571
+ }
1572
+
1573
+ #[ cfg( test) ]
1574
+ pub ( super ) fn is_permanent ( & self ) -> bool {
1575
+ self . failure_code ( ) & PERM == PERM
1576
+ }
1577
+ }
1578
+
1579
+ impl From < u16 > for LocalHTLCFailureReason {
1580
+ fn from ( value : u16 ) -> Self {
1581
+ if value == ( NODE | 2 ) {
1582
+ LocalHTLCFailureReason :: TemporaryNodeFailure
1583
+ } else if value == ( PERM | NODE | 2 ) {
1584
+ LocalHTLCFailureReason :: PermanentNodeFailure
1585
+ } else if value == ( PERM | NODE | 3 ) {
1586
+ LocalHTLCFailureReason :: RequiredNodeFeature
1587
+ } else if value == ( BADONION | PERM | 4 ) {
1588
+ LocalHTLCFailureReason :: InvalidOnionVersion
1589
+ } else if value == ( BADONION | PERM | 5 ) {
1590
+ LocalHTLCFailureReason :: InvalidOnionHMAC
1591
+ } else if value == ( BADONION | PERM | 6 ) {
1592
+ LocalHTLCFailureReason :: InvalidOnionKey
1593
+ } else if value == ( UPDATE | 7 ) {
1594
+ LocalHTLCFailureReason :: TemporaryChannelFailure
1595
+ } else if value == ( PERM | 8 ) {
1596
+ LocalHTLCFailureReason :: PermanentChannelFailure
1597
+ } else if value == ( PERM | 9 ) {
1598
+ LocalHTLCFailureReason :: RequiredChannelFeature
1599
+ } else if value == ( PERM | 10 ) {
1600
+ LocalHTLCFailureReason :: UnknownNextPeer
1601
+ } else if value == ( UPDATE | 11 ) {
1602
+ LocalHTLCFailureReason :: AmountBelowMinimum
1603
+ } else if value == ( UPDATE | 12 ) {
1604
+ LocalHTLCFailureReason :: FeeInsufficient
1605
+ } else if value == ( UPDATE | 13 ) {
1606
+ LocalHTLCFailureReason :: IncorrectCLTVExpiry
1607
+ } else if value == ( UPDATE | 14 ) {
1608
+ LocalHTLCFailureReason :: CLTVExpiryTooSoon
1609
+ } else if value == ( PERM | 15 ) {
1610
+ LocalHTLCFailureReason :: IncorrectPaymentDetails
1611
+ } else if value == 18 {
1612
+ LocalHTLCFailureReason :: FinalIncorrectCLTVExpiry
1613
+ } else if value == 19 {
1614
+ LocalHTLCFailureReason :: FinalIncorrectHTLCAmount
1615
+ } else if value == ( UPDATE | 20 ) {
1616
+ LocalHTLCFailureReason :: ChannelDisabled
1617
+ } else if value == 21 {
1618
+ LocalHTLCFailureReason :: CLTVExpiryTooFar
1619
+ } else if value == ( PERM | 22 ) {
1620
+ LocalHTLCFailureReason :: InvalidOnionPayload
1621
+ } else if value == 23 {
1622
+ LocalHTLCFailureReason :: MPPTimeout
1623
+ } else if value == ( BADONION | PERM | 24 ) {
1624
+ LocalHTLCFailureReason :: InvalidOnionBlinding
1625
+ } else {
1626
+ LocalHTLCFailureReason :: UnknownFailureCode { code : value }
1627
+ }
1628
+ }
1629
+ }
1630
+
1454
1631
#[ derive( Clone ) ] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
1455
1632
#[ cfg_attr( test, derive( PartialEq ) ) ]
1456
1633
pub ( super ) struct HTLCFailReason ( HTLCFailReasonRepr ) ;
0 commit comments