Skip to content

Commit 96efbc3

Browse files
committed
ln: persist failure_reason with HTLCFailureReason
Update the failure reason that's persisted in HTLCFailReasonRepr to store our newly added enum, rather than the old u16. In the commits that follow, we'll add more variants create a many-to-one mapping from enum to BOLT04 code (as we're surfacing internal information that is intentionally erased by the BOLT04 codes). Without this change to persistence, we'll lose the detail that these variants contain by storing them as their erased BOLT04 code.
1 parent 6f442d9 commit 96efbc3

File tree

1 file changed

+50
-10
lines changed

1 file changed

+50
-10
lines changed

lightning/src/ln/onion_utils.rs

+50-10
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,34 @@ impl From<u16> for LocalHTLCFailureReason {
16271627
}
16281628
}
16291629

1630+
impl_writeable_tlv_based_enum!(LocalHTLCFailureReason,
1631+
(1, TemporaryNodeFailure) => {},
1632+
(3, PermanentNodeFailure) => {},
1633+
(5, RequiredNodeFeature) => {},
1634+
(7, InvalidOnionVersion) => {},
1635+
(9, InvalidOnionHMAC) => {},
1636+
(11, InvalidOnionKey) => {},
1637+
(13, TemporaryChannelFailure) => {},
1638+
(15, PermanentChannelFailure) => {},
1639+
(17, RequiredChannelFeature) => {},
1640+
(19, UnknownNextPeer) => {},
1641+
(21, AmountBelowMinimum) => {},
1642+
(23, FeeInsufficient) => {},
1643+
(25, IncorrectCLTVExpiry) => {},
1644+
(27, CLTVExpiryTooSoon) => {},
1645+
(29, IncorrectPaymentDetails) => {},
1646+
(31, FinalIncorrectCLTVExpiry) => {},
1647+
(33, FinalIncorrectHTLCAmount) => {},
1648+
(35, ChannelDisabled) => {},
1649+
(37, CLTVExpiryTooFar) => {},
1650+
(39, InvalidOnionPayload) => {},
1651+
(41, MPPTimeout) => {},
1652+
(43, InvalidOnionBlinding) => {},
1653+
(45, UnknownFailureCode) => {
1654+
(0, code, required),
1655+
},
1656+
);
1657+
16301658
#[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
16311659
#[cfg_attr(test, derive(PartialEq))]
16321660
pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
@@ -1635,7 +1663,7 @@ pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
16351663
#[cfg_attr(test, derive(PartialEq))]
16361664
enum HTLCFailReasonRepr {
16371665
LightningError { err: msgs::OnionErrorPacket, hold_time: Option<u32> },
1638-
Reason { failure_code: u16, data: Vec<u8> },
1666+
Reason { data: Vec<u8>, failure_reason: LocalHTLCFailureReason },
16391667
}
16401668

16411669
impl HTLCFailReason {
@@ -1652,8 +1680,13 @@ impl HTLCFailReason {
16521680
impl core::fmt::Debug for HTLCFailReason {
16531681
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
16541682
match self.0 {
1655-
HTLCFailReasonRepr::Reason { ref failure_code, .. } => {
1656-
write!(f, "HTLC error code {}", failure_code)
1683+
HTLCFailReasonRepr::Reason { ref failure_reason, .. } => {
1684+
write!(
1685+
f,
1686+
"HTLC failure {:?} error code {}",
1687+
failure_reason,
1688+
failure_reason.failure_code()
1689+
)
16571690
},
16581691
HTLCFailReasonRepr::LightningError { .. } => {
16591692
write!(f, "pre-built LightningError")
@@ -1693,7 +1726,14 @@ impl_writeable_tlv_based_enum!(HTLCFailReasonRepr,
16931726
(_unused, err, (static_value, msgs::OnionErrorPacket { data: data.ok_or(DecodeError::InvalidValue)?, attribution_data })),
16941727
},
16951728
(1, Reason) => {
1696-
(0, failure_code, required),
1729+
(0, _failure_code, (legacy, u16,
1730+
|r: &HTLCFailReasonRepr| match r {
1731+
HTLCFailReasonRepr::LightningError{ .. } => None,
1732+
HTLCFailReasonRepr::Reason{ failure_reason, .. } => Some(failure_reason.failure_code())
1733+
})),
1734+
// failure_code was required, and is replaced by reason in 0.2 so any time we do not have a
1735+
// reason available failure_code will be Some and can be expressed as a reason.
1736+
(1, failure_reason, (default_value, LocalHTLCFailureReason::from(_failure_code.ok_or(DecodeError::InvalidValue)?))),
16971737
(2, data, required_vec),
16981738
},
16991739
);
@@ -1749,7 +1789,7 @@ impl HTLCFailReason {
17491789
},
17501790
}
17511791

1752-
Self(HTLCFailReasonRepr::Reason { failure_code: failure_reason.failure_code(), data })
1792+
Self(HTLCFailReasonRepr::Reason { data, failure_reason })
17531793
}
17541794

17551795
pub(super) fn from_failure_code(failure_reason: LocalHTLCFailureReason) -> Self {
@@ -1775,15 +1815,15 @@ impl HTLCFailReason {
17751815
&self, incoming_packet_shared_secret: &[u8; 32], secondary_shared_secret: &Option<[u8; 32]>,
17761816
) -> msgs::OnionErrorPacket {
17771817
match self.0 {
1778-
HTLCFailReasonRepr::Reason { ref failure_code, ref data } => {
1818+
HTLCFailReasonRepr::Reason { ref data, ref failure_reason } => {
17791819
// Final hop always reports zero hold time.
17801820
let hold_time: u32 = 0;
17811821

17821822
if let Some(secondary_shared_secret) = secondary_shared_secret {
17831823
// Phantom hop always reports zero hold time too.
17841824
let mut packet = build_failure_packet(
17851825
secondary_shared_secret,
1786-
u16::into(*failure_code),
1826+
*failure_reason,
17871827
&data[..],
17881828
hold_time,
17891829
);
@@ -1795,7 +1835,7 @@ impl HTLCFailReason {
17951835
} else {
17961836
build_failure_packet(
17971837
incoming_packet_shared_secret,
1798-
u16::into(*failure_code),
1838+
*failure_reason,
17991839
&data[..],
18001840
hold_time,
18011841
)
@@ -1824,7 +1864,7 @@ impl HTLCFailReason {
18241864
process_onion_failure(secp_ctx, logger, &htlc_source, err.clone())
18251865
},
18261866
#[allow(unused)]
1827-
HTLCFailReasonRepr::Reason { ref failure_code, ref data, .. } => {
1867+
HTLCFailReasonRepr::Reason { ref data, ref failure_reason } => {
18281868
// we get a fail_malformed_htlc from the first hop
18291869
// TODO: We'd like to generate a NetworkUpdate for temporary
18301870
// failures here, but that would be insufficient as find_route
@@ -1838,7 +1878,7 @@ impl HTLCFailReason {
18381878
failed_within_blinded_path: false,
18391879
hold_times: Vec::new(),
18401880
#[cfg(any(test, feature = "_test_utils"))]
1841-
onion_error_code: Some(*failure_code),
1881+
onion_error_code: Some(failure_reason.failure_code()),
18421882
#[cfg(any(test, feature = "_test_utils"))]
18431883
onion_error_data: Some(data.clone()),
18441884
}

0 commit comments

Comments
 (0)