Skip to content

Commit 11c94dc

Browse files
committed
ln: persist failure_reason with HTLCFailureReason
1 parent 950b697 commit 11c94dc

File tree

1 file changed

+68
-20
lines changed

1 file changed

+68
-20
lines changed

lightning/src/ln/onion_utils.rs

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ use crate::types::features::{ChannelFeatures, NodeFeatures};
2222
use crate::types::payment::{PaymentHash, PaymentPreimage};
2323
use crate::util::errors::{self, APIError};
2424
use crate::util::logger::Logger;
25-
use crate::util::ser::{LengthCalculatingWriter, Readable, ReadableArgs, Writeable, Writer};
25+
use crate::util::ser::{
26+
LengthCalculatingWriter, Readable, ReadableArgs, RequiredWrapper, Writeable, Writer,
27+
};
2628

2729
use bitcoin::hashes::cmp::fixed_time_eq;
2830
use bitcoin::hashes::hmac::{Hmac, HmacEngine};
@@ -1608,6 +1610,49 @@ impl Into<LocalHTLCFailureReason> for u16 {
16081610
}
16091611
}
16101612

1613+
impl_writeable_tlv_based_enum!(LocalHTLCFailureReason,
1614+
(0, TemporaryNodeFailure) => {},
1615+
(2, PermanentNodeFailure) => {},
1616+
(4, RequiredNodeFeature) => {},
1617+
(6, InvalidOnionVersion) => {},
1618+
(8, InvalidOnionHMAC) => {},
1619+
(10, InvalidOnionKey) => {},
1620+
(12, TemporaryChannelFailure) => {},
1621+
(14, PermanentChannelFailure) => {},
1622+
(16, RequiredChannelFeature) => {},
1623+
(18, UnknownNextPeer) => {},
1624+
(20, AmountBelowMinimum) => {},
1625+
(22, FeeInsufficient) => {},
1626+
(24, IncorrectCLTVExpiry) => {},
1627+
(26, CLTVExpiryTooSoon) => {},
1628+
(28, IncorrectPaymentDetails) => {},
1629+
(30, FinalIncorrectCLTVExpiry) => {},
1630+
(32, FinalIncorrectHTLCAmount) => {},
1631+
(34, ChannelDisabled) => {},
1632+
(36, CLTVExpiryTooFar) => {},
1633+
(38, InvalidOnionPayload) => {},
1634+
(40, MPPTimeout) => {},
1635+
(42, InvalidOnionBlinding) => {},
1636+
(44, InvalidTrampolineForward) => {},
1637+
(46, PaymentClaimBuffer) => {},
1638+
(48, DustLimitHolder) => {},
1639+
(50, DustLimitCounterparty) => {},
1640+
(52, FeeSpikeBuffer) => {},
1641+
(54, DroppedPending) => {},
1642+
(56, PrivateChannelForward) => {},
1643+
(58, RealSCIDForward) => {},
1644+
(60, ChannelNotReady) => {},
1645+
(62, InvalidKeysendPreimage) => {},
1646+
(64, InvalidTrampolinePayload) => {},
1647+
(66, PaymentSecretRequired) => {},
1648+
(68, ForwardExpiryBuffer) => {},
1649+
(70, OutgoingCLTVTooSoon) => {},
1650+
(72, ChannelClosed) => {},
1651+
(74, UnknownFailureCode) => {
1652+
(0, code, required),
1653+
}
1654+
);
1655+
16111656
#[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
16121657
#[cfg_attr(test, derive(PartialEq))]
16131658
pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
@@ -1616,14 +1661,14 @@ pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
16161661
#[cfg_attr(test, derive(PartialEq))]
16171662
enum HTLCFailReasonRepr {
16181663
LightningError { err: msgs::OnionErrorPacket },
1619-
Reason { failure_code: u16, data: Vec<u8> },
1664+
Reason { data: Vec<u8>, reason: LocalHTLCFailureReason },
16201665
}
16211666

16221667
impl core::fmt::Debug for HTLCFailReason {
16231668
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
16241669
match self.0 {
1625-
HTLCFailReasonRepr::Reason { ref failure_code, .. } => {
1626-
write!(f, "HTLC error code {}", failure_code)
1670+
HTLCFailReasonRepr::Reason { ref reason, .. } => {
1671+
write!(f, "HTLC error code {}", reason.failure_code())
16271672
},
16281673
HTLCFailReasonRepr::LightningError { .. } => {
16291674
write!(f, "pre-built LightningError")
@@ -1655,8 +1700,19 @@ impl_writeable_tlv_based_enum!(HTLCFailReasonRepr,
16551700
(_unused, err, (static_value, msgs::OnionErrorPacket { data: data.ok_or(DecodeError::InvalidValue)? })),
16561701
},
16571702
(1, Reason) => {
1658-
(0, failure_code, required),
1703+
(0, _failure_code, (legacy, u16,
1704+
|r: &HTLCFailReasonRepr| Some(r.clone()) )),
16591705
(2, data, required_vec),
1706+
// failure_code was required, and is replaced by reason so any time we do not have a
1707+
// reason available failure_code will be Some so we can require reason.
1708+
(4, reason, (default_value,
1709+
if let Some(code) = _failure_code {
1710+
let failure_reason: LocalHTLCFailureReason = code.into();
1711+
RequiredWrapper::from(failure_reason)
1712+
} else {
1713+
reason
1714+
}
1715+
)),
16601716
},
16611717
);
16621718

@@ -1728,7 +1784,7 @@ impl HTLCFailReason {
17281784
},
17291785
}
17301786

1731-
Self(HTLCFailReasonRepr::Reason { failure_code: failure_reason.failure_code(), data })
1787+
Self(HTLCFailReasonRepr::Reason { data, reason: failure_reason })
17321788
}
17331789

17341790
pub(super) fn from_failure_code(failure_reason: LocalHTLCFailureReason) -> Self {
@@ -1750,24 +1806,16 @@ impl HTLCFailReason {
17501806
&self, incoming_packet_shared_secret: &[u8; 32], secondary_shared_secret: &Option<[u8; 32]>,
17511807
) -> msgs::OnionErrorPacket {
17521808
match self.0 {
1753-
HTLCFailReasonRepr::Reason { ref failure_code, ref data } => {
1754-
let failure_code = *failure_code;
1809+
HTLCFailReasonRepr::Reason { ref data, ref reason } => {
17551810
if let Some(secondary_shared_secret) = secondary_shared_secret {
1756-
let mut packet = build_failure_packet(
1757-
secondary_shared_secret,
1758-
failure_code.into(),
1759-
&data[..],
1760-
);
1811+
let mut packet =
1812+
build_failure_packet(secondary_shared_secret, *reason, &data[..]);
17611813

17621814
crypt_failure_packet(incoming_packet_shared_secret, &mut packet);
17631815

17641816
packet
17651817
} else {
1766-
build_failure_packet(
1767-
incoming_packet_shared_secret,
1768-
failure_code.into(),
1769-
&data[..],
1770-
)
1818+
build_failure_packet(incoming_packet_shared_secret, *reason, &data[..])
17711819
}
17721820
},
17731821
HTLCFailReasonRepr::LightningError { ref err } => {
@@ -1791,7 +1839,7 @@ impl HTLCFailReason {
17911839
process_onion_failure(secp_ctx, logger, &htlc_source, err.clone())
17921840
},
17931841
#[allow(unused)]
1794-
HTLCFailReasonRepr::Reason { ref failure_code, ref data, .. } => {
1842+
HTLCFailReasonRepr::Reason { ref data, ref reason } => {
17951843
// we get a fail_malformed_htlc from the first hop
17961844
// TODO: We'd like to generate a NetworkUpdate for temporary
17971845
// failures here, but that would be insufficient as find_route
@@ -1804,7 +1852,7 @@ impl HTLCFailReason {
18041852
short_channel_id: Some(path.hops[0].short_channel_id),
18051853
failed_within_blinded_path: false,
18061854
#[cfg(any(test, feature = "_test_utils"))]
1807-
onion_error_code: Some(*failure_code),
1855+
onion_error_code: Some(reason.failure_code()),
18081856
#[cfg(any(test, feature = "_test_utils"))]
18091857
onion_error_data: Some(data.clone()),
18101858
}

0 commit comments

Comments
 (0)