@@ -23,7 +23,7 @@ use crate::types::payment::{PaymentHash, PaymentPreimage};
2323use crate :: util:: errors:: { self , APIError } ;
2424use crate :: util:: logger:: Logger ;
2525use crate :: util:: ser:: {
26- LengthCalculatingWriter , Readable , ReadableArgs , VecWriter , Writeable , Writer ,
26+ LengthCalculatingWriter , Readable , ReadableArgs , RequiredWrapper , VecWriter , Writeable , Writer
2727} ;
2828
2929use bitcoin:: hashes:: cmp:: fixed_time_eq;
@@ -1711,6 +1711,49 @@ impl Into<LocalHTLCFailureReason> for u16 {
17111711 }
17121712}
17131713
1714+ impl_writeable_tlv_based_enum ! ( LocalHTLCFailureReason ,
1715+ ( 1 , TemporaryNodeFailure ) => { } ,
1716+ ( 3 , PermanentNodeFailure ) => { } ,
1717+ ( 5 , RequiredNodeFeature ) => { } ,
1718+ ( 7 , InvalidOnionVersion ) => { } ,
1719+ ( 9 , InvalidOnionHMAC ) => { } ,
1720+ ( 11 , InvalidOnionKey ) => { } ,
1721+ ( 13 , TemporaryChannelFailure ) => { } ,
1722+ ( 15 , PermanentChannelFailure ) => { } ,
1723+ ( 17 , RequiredChannelFeature ) => { } ,
1724+ ( 19 , UnknownNextPeer ) => { } ,
1725+ ( 21 , AmountBelowMinimum ) => { } ,
1726+ ( 23 , FeeInsufficient ) => { } ,
1727+ ( 25 , IncorrectCLTVExpiry ) => { } ,
1728+ ( 27 , CLTVExpiryTooSoon ) => { } ,
1729+ ( 29 , IncorrectPaymentDetails ) => { } ,
1730+ ( 31 , FinalIncorrectCLTVExpiry ) => { } ,
1731+ ( 33 , FinalIncorrectHTLCAmount ) => { } ,
1732+ ( 35 , ChannelDisabled ) => { } ,
1733+ ( 37 , CLTVExpiryTooFar ) => { } ,
1734+ ( 39 , InvalidOnionPayload ) => { } ,
1735+ ( 41 , MPPTimeout ) => { } ,
1736+ ( 43 , InvalidOnionBlinding ) => { } ,
1737+ ( 45 , InvalidTrampolineForward ) => { } ,
1738+ ( 47 , PaymentClaimBuffer ) => { } ,
1739+ ( 49 , DustLimitHolder ) => { } ,
1740+ ( 51 , DustLimitCounterparty ) => { } ,
1741+ ( 53 , FeeSpikeBuffer ) => { } ,
1742+ ( 55 , DroppedPending ) => { } ,
1743+ ( 57 , PrivateChannelForward ) => { } ,
1744+ ( 59 , RealSCIDForward ) => { } ,
1745+ ( 61 , ChannelNotReady ) => { } ,
1746+ ( 63 , InvalidKeysendPreimage ) => { } ,
1747+ ( 65 , InvalidTrampolinePayload ) => { } ,
1748+ ( 67 , PaymentSecretRequired ) => { } ,
1749+ ( 69 , ForwardExpiryBuffer ) => { } ,
1750+ ( 71 , OutgoingCLTVTooSoon ) => { } ,
1751+ ( 73 , ChannelClosed ) => { } ,
1752+ ( 75 , UnknownFailureCode ) => {
1753+ ( 0 , code, required) ,
1754+ }
1755+ ) ;
1756+
17141757#[ derive( Clone ) ] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
17151758#[ cfg_attr( test, derive( PartialEq ) ) ]
17161759pub ( super ) struct HTLCFailReason ( HTLCFailReasonRepr ) ;
@@ -1719,7 +1762,7 @@ pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
17191762#[ cfg_attr( test, derive( PartialEq ) ) ]
17201763enum HTLCFailReasonRepr {
17211764 LightningError { err : msgs:: OnionErrorPacket , hold_time : Option < u32 > } ,
1722- Reason { failure_code : u16 , data : Vec < u8 > } ,
1765+ Reason { data : Vec < u8 > , reason : LocalHTLCFailureReason } ,
17231766}
17241767
17251768impl HTLCFailReason {
@@ -1736,8 +1779,8 @@ impl HTLCFailReason {
17361779impl core:: fmt:: Debug for HTLCFailReason {
17371780 fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> Result < ( ) , core:: fmt:: Error > {
17381781 match self . 0 {
1739- HTLCFailReasonRepr :: Reason { ref failure_code , .. } => {
1740- write ! ( f, "HTLC error code {}" , failure_code)
1782+ HTLCFailReasonRepr :: Reason { ref reason , .. } => {
1783+ write ! ( f, "HTLC error code {}" , reason . failure_code( ) )
17411784 } ,
17421785 HTLCFailReasonRepr :: LightningError { .. } => {
17431786 write ! ( f, "pre-built LightningError" )
@@ -1777,8 +1820,19 @@ impl_writeable_tlv_based_enum!(HTLCFailReasonRepr,
17771820 ( _unused, err, ( static_value, msgs:: OnionErrorPacket { data: data. ok_or( DecodeError :: InvalidValue ) ?, attribution_data } ) ) ,
17781821 } ,
17791822 ( 1 , Reason ) => {
1780- ( 0 , failure_code, required) ,
1823+ ( 0 , _failure_code, ( legacy, u16 ,
1824+ |r: & HTLCFailReasonRepr | Some ( r. clone( ) ) ) ) ,
17811825 ( 2 , data, required_vec) ,
1826+ // failure_code was required, and is replaced by reason so any time we do not have a
1827+ // reason available failure_code will be Some so we can require reason.
1828+ ( 4 , reason, ( default_value,
1829+ if let Some ( code) = _failure_code {
1830+ let failure_reason: LocalHTLCFailureReason = code. into( ) ;
1831+ RequiredWrapper :: from( failure_reason)
1832+ } else {
1833+ reason
1834+ }
1835+ ) ) ,
17821836 } ,
17831837) ;
17841838
@@ -1850,7 +1904,7 @@ impl HTLCFailReason {
18501904 } ,
18511905 }
18521906
1853- Self ( HTLCFailReasonRepr :: Reason { failure_code : failure_reason. failure_code ( ) , data } )
1907+ Self ( HTLCFailReasonRepr :: Reason { data , reason : failure_reason } )
18541908 }
18551909
18561910 pub ( super ) fn from_failure_code ( failure_reason : LocalHTLCFailureReason ) -> Self {
@@ -1876,15 +1930,15 @@ impl HTLCFailReason {
18761930 & self , incoming_packet_shared_secret : & [ u8 ; 32 ] , secondary_shared_secret : & Option < [ u8 ; 32 ] > ,
18771931 ) -> msgs:: OnionErrorPacket {
18781932 match self . 0 {
1879- HTLCFailReasonRepr :: Reason { ref failure_code , ref data } => {
1933+ HTLCFailReasonRepr :: Reason { ref reason , ref data } => {
18801934 // Final hop always reports zero hold time.
18811935 let hold_time: u32 = 0 ;
18821936
18831937 if let Some ( secondary_shared_secret) = secondary_shared_secret {
18841938 // Phantom hop always reports zero hold time too.
18851939 let mut packet = build_failure_packet (
18861940 secondary_shared_secret,
1887- u16 :: into ( * failure_code ) ,
1941+ * reason ,
18881942 & data[ ..] ,
18891943 hold_time,
18901944 ) ;
@@ -1896,7 +1950,7 @@ impl HTLCFailReason {
18961950 } else {
18971951 build_failure_packet (
18981952 incoming_packet_shared_secret,
1899- u16 :: into ( * failure_code ) ,
1953+ * reason ,
19001954 & data[ ..] ,
19011955 hold_time,
19021956 )
@@ -1925,7 +1979,7 @@ impl HTLCFailReason {
19251979 process_onion_failure ( secp_ctx, logger, & htlc_source, err. clone ( ) )
19261980 } ,
19271981 #[ allow( unused) ]
1928- HTLCFailReasonRepr :: Reason { ref failure_code , ref data , .. } => {
1982+ HTLCFailReasonRepr :: Reason { ref data , ref reason } => {
19291983 // we get a fail_malformed_htlc from the first hop
19301984 // TODO: We'd like to generate a NetworkUpdate for temporary
19311985 // failures here, but that would be insufficient as find_route
@@ -1939,7 +1993,7 @@ impl HTLCFailReason {
19391993 failed_within_blinded_path : false ,
19401994 hold_times : Vec :: new ( ) ,
19411995 #[ cfg( any( test, feature = "_test_utils" ) ) ]
1942- onion_error_code : Some ( * failure_code) ,
1996+ onion_error_code : Some ( reason . failure_code ( ) ) ,
19431997 #[ cfg( any( test, feature = "_test_utils" ) ) ]
19441998 onion_error_data : Some ( data. clone ( ) ) ,
19451999 }
0 commit comments