@@ -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 } ;
@@ -1595,6 +1597,49 @@ impl Into<LocalHTLCFailureReason> for u16 {
15951597 }
15961598}
15971599
1600+ impl_writeable_tlv_based_enum ! ( LocalHTLCFailureReason ,
1601+ ( 0 , TemporaryNodeFailure ) => { } ,
1602+ ( 1 , PermanentNodeFailure ) => { } ,
1603+ ( 2 , RequiredNodeFeature ) => { } ,
1604+ ( 3 , InvalidOnionVersion ) => { } ,
1605+ ( 4 , InvalidOnionHMAC ) => { } ,
1606+ ( 5 , InvalidOnionKey ) => { } ,
1607+ ( 6 , TemporaryChannelFailure ) => { } ,
1608+ ( 7 , PermanentChannelFailure ) => { } ,
1609+ ( 8 , RequiredChannelFeature ) => { } ,
1610+ ( 9 , UnknownNextPeer ) => { } ,
1611+ ( 10 , AmountBelowMinimum ) => { } ,
1612+ ( 11 , FeeInsufficient ) => { } ,
1613+ ( 12 , IncorrectCLTVExpiry ) => { } ,
1614+ ( 13 , CLTVExpiryTooSoon ) => { } ,
1615+ ( 14 , IncorrectPaymentDetails ) => { } ,
1616+ ( 15 , FinalIncorrectCLTVExpiry ) => { } ,
1617+ ( 16 , FinalIncorrectHTLCAmount ) => { } ,
1618+ ( 17 , ChannelDisabled ) => { } ,
1619+ ( 18 , CLTVExpiryTooFar ) => { } ,
1620+ ( 19 , InvalidOnionPayload ) => { } ,
1621+ ( 20 , MPPTimeout ) => { } ,
1622+ ( 21 , InvalidOnionBlinding ) => { } ,
1623+ ( 22 , InvalidTrampolineForward ) => { } ,
1624+ ( 23 , PaymentClaimBuffer ) => { } ,
1625+ ( 24 , DustLimitHolder ) => { } ,
1626+ ( 25 , DustLimitCounterparty ) => { } ,
1627+ ( 26 , FeeSpikeBuffer ) => { } ,
1628+ ( 27 , DroppedPending ) => { } ,
1629+ ( 28 , PrivateChannelForward ) => { } ,
1630+ ( 29 , RealSCIDForward ) => { } ,
1631+ ( 30 , ChannelNotReady ) => { } ,
1632+ ( 31 , InvalidKeysendPreimage ) => { } ,
1633+ ( 32 , InvalidTrampolineHop ) => { } ,
1634+ ( 33 , PaymentSecretRequired ) => { } ,
1635+ ( 34 , ForwardExpiryBuffer ) => { } ,
1636+ ( 35 , OutgoingCLTVTooSoon ) => { } ,
1637+ ( 36 , ChannelClosed ) => { } ,
1638+ ( 37 , UnknownFailureCode ) => {
1639+ ( 0 , code, required) ,
1640+ }
1641+ ) ;
1642+
15981643#[ derive( Clone ) ] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
15991644#[ cfg_attr( test, derive( PartialEq ) ) ]
16001645pub ( super ) struct HTLCFailReason ( HTLCFailReasonRepr ) ;
@@ -1603,14 +1648,14 @@ pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
16031648#[ cfg_attr( test, derive( PartialEq ) ) ]
16041649enum HTLCFailReasonRepr {
16051650 LightningError { err : msgs:: OnionErrorPacket } ,
1606- Reason { failure_code : u16 , data : Vec < u8 > } ,
1651+ Reason { data : Vec < u8 > , reason : LocalHTLCFailureReason } ,
16071652}
16081653
16091654impl core:: fmt:: Debug for HTLCFailReason {
16101655 fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> Result < ( ) , core:: fmt:: Error > {
16111656 match self . 0 {
1612- HTLCFailReasonRepr :: Reason { ref failure_code , .. } => {
1613- write ! ( f, "HTLC error code {}" , failure_code)
1657+ HTLCFailReasonRepr :: Reason { ref reason , .. } => {
1658+ write ! ( f, "HTLC error code {}" , reason . failure_code( ) )
16141659 } ,
16151660 HTLCFailReasonRepr :: LightningError { .. } => {
16161661 write ! ( f, "pre-built LightningError" )
@@ -1642,8 +1687,19 @@ impl_writeable_tlv_based_enum!(HTLCFailReasonRepr,
16421687 ( _unused, err, ( static_value, msgs:: OnionErrorPacket { data: data. ok_or( DecodeError :: InvalidValue ) ? } ) ) ,
16431688 } ,
16441689 ( 1 , Reason ) => {
1645- ( 0 , failure_code, required) ,
1690+ ( 0 , _failure_code, ( legacy, u16 ,
1691+ |r: & HTLCFailReasonRepr | Some ( r. clone( ) ) ) ) ,
16461692 ( 2 , data, required_vec) ,
1693+ // failure_code was required, and is replaced by reason so any time we do not have a
1694+ // reason available failure_code will be Some so we can require reason.
1695+ ( 4 , reason, ( default_value,
1696+ if let Some ( code) = _failure_code {
1697+ let failure_reason: LocalHTLCFailureReason = code. into( ) ;
1698+ RequiredWrapper :: from( failure_reason)
1699+ } else {
1700+ reason
1701+ }
1702+ ) ) ,
16471703 } ,
16481704) ;
16491705
@@ -1715,7 +1771,7 @@ impl HTLCFailReason {
17151771 } ,
17161772 }
17171773
1718- Self ( HTLCFailReasonRepr :: Reason { failure_code : failure_reason. failure_code ( ) , data } )
1774+ Self ( HTLCFailReasonRepr :: Reason { data , reason : failure_reason } )
17191775 }
17201776
17211777 pub ( super ) fn from_failure_code ( failure_reason : LocalHTLCFailureReason ) -> Self {
@@ -1737,24 +1793,16 @@ impl HTLCFailReason {
17371793 & self , incoming_packet_shared_secret : & [ u8 ; 32 ] , secondary_shared_secret : & Option < [ u8 ; 32 ] > ,
17381794 ) -> msgs:: OnionErrorPacket {
17391795 match self . 0 {
1740- HTLCFailReasonRepr :: Reason { ref failure_code, ref data } => {
1741- let failure_code = * failure_code;
1796+ HTLCFailReasonRepr :: Reason { ref data, ref reason } => {
17421797 if let Some ( secondary_shared_secret) = secondary_shared_secret {
1743- let mut packet = build_failure_packet (
1744- secondary_shared_secret,
1745- failure_code. into ( ) ,
1746- & data[ ..] ,
1747- ) ;
1798+ let mut packet =
1799+ build_failure_packet ( secondary_shared_secret, * reason, & data[ ..] ) ;
17481800
17491801 crypt_failure_packet ( incoming_packet_shared_secret, & mut packet) ;
17501802
17511803 packet
17521804 } else {
1753- build_failure_packet (
1754- incoming_packet_shared_secret,
1755- failure_code. into ( ) ,
1756- & data[ ..] ,
1757- )
1805+ build_failure_packet ( incoming_packet_shared_secret, * reason, & data[ ..] )
17581806 }
17591807 } ,
17601808 HTLCFailReasonRepr :: LightningError { ref err } => {
@@ -1778,7 +1826,7 @@ impl HTLCFailReason {
17781826 process_onion_failure ( secp_ctx, logger, & htlc_source, err. clone ( ) )
17791827 } ,
17801828 #[ allow( unused) ]
1781- HTLCFailReasonRepr :: Reason { ref failure_code , ref data , .. } => {
1829+ HTLCFailReasonRepr :: Reason { ref data , ref reason } => {
17821830 // we get a fail_malformed_htlc from the first hop
17831831 // TODO: We'd like to generate a NetworkUpdate for temporary
17841832 // failures here, but that would be insufficient as find_route
@@ -1791,7 +1839,7 @@ impl HTLCFailReason {
17911839 short_channel_id : Some ( path. hops [ 0 ] . short_channel_id ) ,
17921840 failed_within_blinded_path : false ,
17931841 #[ cfg( any( test, feature = "_test_utils" ) ) ]
1794- onion_error_code : Some ( * failure_code) ,
1842+ onion_error_code : Some ( reason . failure_code ( ) ) ,
17951843 #[ cfg( any( test, feature = "_test_utils" ) ) ]
17961844 onion_error_data : Some ( data. clone ( ) ) ,
17971845 }
0 commit comments