@@ -22,7 +22,9 @@ use crate::types::features::{ChannelFeatures, NodeFeatures};
2222use crate :: types:: payment:: { PaymentHash , PaymentPreimage } ;
2323use crate :: util:: errors:: { self , APIError } ;
2424use 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
2729use bitcoin:: hashes:: cmp:: fixed_time_eq;
2830use 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+ ( 1 , TemporaryNodeFailure ) => { } ,
1615+ ( 3 , PermanentNodeFailure ) => { } ,
1616+ ( 5 , RequiredNodeFeature ) => { } ,
1617+ ( 7 , InvalidOnionVersion ) => { } ,
1618+ ( 9 , InvalidOnionHMAC ) => { } ,
1619+ ( 11 , InvalidOnionKey ) => { } ,
1620+ ( 13 , TemporaryChannelFailure ) => { } ,
1621+ ( 15 , PermanentChannelFailure ) => { } ,
1622+ ( 17 , RequiredChannelFeature ) => { } ,
1623+ ( 19 , UnknownNextPeer ) => { } ,
1624+ ( 21 , AmountBelowMinimum ) => { } ,
1625+ ( 23 , FeeInsufficient ) => { } ,
1626+ ( 25 , IncorrectCLTVExpiry ) => { } ,
1627+ ( 27 , CLTVExpiryTooSoon ) => { } ,
1628+ ( 29 , IncorrectPaymentDetails ) => { } ,
1629+ ( 31 , FinalIncorrectCLTVExpiry ) => { } ,
1630+ ( 33 , FinalIncorrectHTLCAmount ) => { } ,
1631+ ( 35 , ChannelDisabled ) => { } ,
1632+ ( 37 , CLTVExpiryTooFar ) => { } ,
1633+ ( 39 , InvalidOnionPayload ) => { } ,
1634+ ( 41 , MPPTimeout ) => { } ,
1635+ ( 43 , InvalidOnionBlinding ) => { } ,
1636+ ( 45 , InvalidTrampolineForward ) => { } ,
1637+ ( 47 , PaymentClaimBuffer ) => { } ,
1638+ ( 49 , DustLimitHolder ) => { } ,
1639+ ( 51 , DustLimitCounterparty ) => { } ,
1640+ ( 53 , FeeSpikeBuffer ) => { } ,
1641+ ( 55 , DroppedPending ) => { } ,
1642+ ( 57 , PrivateChannelForward ) => { } ,
1643+ ( 59 , RealSCIDForward ) => { } ,
1644+ ( 61 , ChannelNotReady ) => { } ,
1645+ ( 63 , InvalidKeysendPreimage ) => { } ,
1646+ ( 65 , InvalidTrampolinePayload ) => { } ,
1647+ ( 67 , PaymentSecretRequired ) => { } ,
1648+ ( 69 , ForwardExpiryBuffer ) => { } ,
1649+ ( 71 , OutgoingCLTVTooSoon ) => { } ,
1650+ ( 73 , ChannelClosed ) => { } ,
1651+ ( 75 , 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 ) ) ]
16131658pub ( super ) struct HTLCFailReason ( HTLCFailReasonRepr ) ;
@@ -1616,14 +1661,14 @@ pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
16161661#[ cfg_attr( test, derive( PartialEq ) ) ]
16171662enum HTLCFailReasonRepr {
16181663 LightningError { err : msgs:: OnionErrorPacket } ,
1619- Reason { failure_code : u16 , data : Vec < u8 > } ,
1664+ Reason { data : Vec < u8 > , reason : LocalHTLCFailureReason } ,
16201665}
16211666
16221667impl 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