@@ -1650,6 +1650,34 @@ impl From<u16> for LocalHTLCFailureReason {
16501650 }
16511651}
16521652
1653+ impl_writeable_tlv_based_enum ! ( LocalHTLCFailureReason ,
1654+ ( 1 , TemporaryNodeFailure ) => { } ,
1655+ ( 3 , PermanentNodeFailure ) => { } ,
1656+ ( 5 , RequiredNodeFeature ) => { } ,
1657+ ( 7 , InvalidOnionVersion ) => { } ,
1658+ ( 9 , InvalidOnionHMAC ) => { } ,
1659+ ( 11 , InvalidOnionKey ) => { } ,
1660+ ( 13 , TemporaryChannelFailure ) => { } ,
1661+ ( 15 , PermanentChannelFailure ) => { } ,
1662+ ( 17 , RequiredChannelFeature ) => { } ,
1663+ ( 19 , UnknownNextPeer ) => { } ,
1664+ ( 21 , AmountBelowMinimum ) => { } ,
1665+ ( 23 , FeeInsufficient ) => { } ,
1666+ ( 25 , IncorrectCLTVExpiry ) => { } ,
1667+ ( 27 , CLTVExpiryTooSoon ) => { } ,
1668+ ( 29 , IncorrectPaymentDetails ) => { } ,
1669+ ( 31 , FinalIncorrectCLTVExpiry ) => { } ,
1670+ ( 33 , FinalIncorrectHTLCAmount ) => { } ,
1671+ ( 35 , ChannelDisabled ) => { } ,
1672+ ( 37 , CLTVExpiryTooFar ) => { } ,
1673+ ( 39 , InvalidOnionPayload ) => { } ,
1674+ ( 41 , MPPTimeout ) => { } ,
1675+ ( 43 , InvalidOnionBlinding ) => { } ,
1676+ ( 45 , UnknownFailureCode ) => {
1677+ ( 0 , code, required) ,
1678+ } ,
1679+ ) ;
1680+
16531681#[ derive( Clone ) ] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
16541682#[ cfg_attr( test, derive( PartialEq ) ) ]
16551683pub ( super ) struct HTLCFailReason ( HTLCFailReasonRepr ) ;
@@ -1658,7 +1686,7 @@ pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
16581686#[ cfg_attr( test, derive( PartialEq ) ) ]
16591687enum HTLCFailReasonRepr {
16601688 LightningError { err : msgs:: OnionErrorPacket , hold_time : Option < u32 > } ,
1661- Reason { failure_code : u16 , data : Vec < u8 > } ,
1689+ Reason { data : Vec < u8 > , failure_reason : LocalHTLCFailureReason } ,
16621690}
16631691
16641692impl HTLCFailReason {
@@ -1675,8 +1703,8 @@ impl HTLCFailReason {
16751703impl core:: fmt:: Debug for HTLCFailReason {
16761704 fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> Result < ( ) , core:: fmt:: Error > {
16771705 match self . 0 {
1678- HTLCFailReasonRepr :: Reason { ref failure_code , .. } => {
1679- write ! ( f, "HTLC error code {}" , failure_code)
1706+ HTLCFailReasonRepr :: Reason { ref failure_reason , .. } => {
1707+ write ! ( f, "HTLC error code {}" , failure_reason . failure_code( ) )
16801708 } ,
16811709 HTLCFailReasonRepr :: LightningError { .. } => {
16821710 write ! ( f, "pre-built LightningError" )
@@ -1716,8 +1744,15 @@ impl_writeable_tlv_based_enum!(HTLCFailReasonRepr,
17161744 ( _unused, err, ( static_value, msgs:: OnionErrorPacket { data: data. ok_or( DecodeError :: InvalidValue ) ?, attribution_data } ) ) ,
17171745 } ,
17181746 ( 1 , Reason ) => {
1719- ( 0 , failure_code, required) ,
1747+ ( 0 , _failure_code, ( legacy, u16 ,
1748+ |r: & HTLCFailReasonRepr | match r {
1749+ HTLCFailReasonRepr :: LightningError { .. } => None ,
1750+ HTLCFailReasonRepr :: Reason { failure_reason, .. } => Some ( failure_reason. failure_code( ) )
1751+ } ) ) ,
17201752 ( 2 , data, required_vec) ,
1753+ // failure_code was required, and is replaced by reason in 0.2 so any time we do not have a
1754+ // reason available failure_code will be Some and can be expressed as a reason.
1755+ ( 4 , failure_reason, ( default_value, LocalHTLCFailureReason :: from( _failure_code. ok_or( DecodeError :: InvalidValue ) ?) ) ) ,
17211756 } ,
17221757) ;
17231758
@@ -1772,7 +1807,7 @@ impl HTLCFailReason {
17721807 } ,
17731808 }
17741809
1775- Self ( HTLCFailReasonRepr :: Reason { failure_code : failure_reason . failure_code ( ) , data } )
1810+ Self ( HTLCFailReasonRepr :: Reason { data , failure_reason } )
17761811 }
17771812
17781813 pub ( super ) fn from_failure_code ( failure_reason : LocalHTLCFailureReason ) -> Self {
@@ -1798,15 +1833,15 @@ impl HTLCFailReason {
17981833 & self , incoming_packet_shared_secret : & [ u8 ; 32 ] , secondary_shared_secret : & Option < [ u8 ; 32 ] > ,
17991834 ) -> msgs:: OnionErrorPacket {
18001835 match self . 0 {
1801- HTLCFailReasonRepr :: Reason { ref failure_code , ref data } => {
1836+ HTLCFailReasonRepr :: Reason { ref data , ref failure_reason } => {
18021837 // Final hop always reports zero hold time.
18031838 let hold_time: u32 = 0 ;
18041839
18051840 if let Some ( secondary_shared_secret) = secondary_shared_secret {
18061841 // Phantom hop always reports zero hold time too.
18071842 let mut packet = build_failure_packet (
18081843 secondary_shared_secret,
1809- u16 :: into ( * failure_code ) ,
1844+ * failure_reason ,
18101845 & data[ ..] ,
18111846 hold_time,
18121847 ) ;
@@ -1818,7 +1853,7 @@ impl HTLCFailReason {
18181853 } else {
18191854 build_failure_packet (
18201855 incoming_packet_shared_secret,
1821- u16 :: into ( * failure_code ) ,
1856+ * failure_reason ,
18221857 & data[ ..] ,
18231858 hold_time,
18241859 )
@@ -1847,7 +1882,7 @@ impl HTLCFailReason {
18471882 process_onion_failure ( secp_ctx, logger, & htlc_source, err. clone ( ) )
18481883 } ,
18491884 #[ allow( unused) ]
1850- HTLCFailReasonRepr :: Reason { ref failure_code , ref data , .. } => {
1885+ HTLCFailReasonRepr :: Reason { ref data , ref failure_reason } => {
18511886 // we get a fail_malformed_htlc from the first hop
18521887 // TODO: We'd like to generate a NetworkUpdate for temporary
18531888 // failures here, but that would be insufficient as find_route
@@ -1861,7 +1896,7 @@ impl HTLCFailReason {
18611896 failed_within_blinded_path : false ,
18621897 hold_times : Vec :: new ( ) ,
18631898 #[ cfg( any( test, feature = "_test_utils" ) ) ]
1864- onion_error_code : Some ( * failure_code) ,
1899+ onion_error_code : Some ( failure_reason . failure_code ( ) ) ,
18651900 #[ cfg( any( test, feature = "_test_utils" ) ) ]
18661901 onion_error_data : Some ( data. clone ( ) ) ,
18671902 }
0 commit comments