@@ -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 ) ) ]
16321660pub ( super ) struct HTLCFailReason ( HTLCFailReasonRepr ) ;
@@ -1635,7 +1663,7 @@ pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
16351663#[ cfg_attr( test, derive( PartialEq ) ) ]
16361664enum 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
16411669impl HTLCFailReason {
@@ -1652,8 +1680,13 @@ impl HTLCFailReason {
16521680impl 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