@@ -2077,36 +2077,14 @@ impl ChannelManager {
2077
2077
// Process failure we got back from upstream on a payment we sent. Returns update and a boolean
2078
2078
// indicating that the payment itself failed
2079
2079
fn process_onion_failure ( & self , htlc_source : & HTLCSource , mut packet_decrypted : Vec < u8 > ) -> ( Option < msgs:: HTLCFailChannelUpdate > , bool , Option < u16 > ) {
2080
+ use util:: errors:: { get_onion_error_description, get_onion_debug_field} ;
2080
2081
if let & HTLCSource :: OutboundRoute { ref route, ref session_priv, ref first_hop_htlc_msat } = htlc_source {
2081
- macro_rules! onion_failure_log {
2082
- ( $error_code_textual: expr, $error_code: expr, $reported_name: expr, $reported_value: expr ) => { {
2083
- log_info!( self , "{}({:#x}) {}({})" , $error_code_textual, $error_code, $reported_name, $reported_value) ;
2084
- } } ;
2085
- ( $error_code_textual: expr, $error_code: expr ) => { {
2086
- log_info!( self , "{}({:#x})" , $error_code_textual, $error_code) ;
2087
- } } ;
2088
- }
2089
-
2090
- // when a node has sent invalid code or malformed failure msg
2091
- macro_rules! return_node_fail_update {
2092
- ( $res: ident, $node_id: expr, $retry: expr) => { {
2093
- $res = Some ( ( Some ( msgs:: HTLCFailChannelUpdate :: NodeFailure {
2094
- node_id: $node_id,
2095
- is_permanent: true ,
2096
- } ) , $retry) ) ;
2097
- return ;
2098
- } }
2099
- }
2100
-
2101
- const BADONION : u16 = 0x8000 ;
2102
- const PERM : u16 = 0x4000 ;
2103
- const NODE : u16 = 0x2000 ;
2104
- const UPDATE : u16 = 0x1000 ;
2105
2082
2106
2083
let mut res = None ;
2107
2084
let mut htlc_msat = * first_hop_htlc_msat;
2108
2085
let mut error_code_ret = None ;
2109
2086
let mut next_route_hop_ix = 0 ;
2087
+ let mut is_from_final_node = false ;
2110
2088
2111
2089
// Handle packed channel/node updates for passing back for the route handler
2112
2090
Self :: construct_onion_keys_callback ( & self . secp_ctx , route, session_priv, |shared_secret, _, _, route_hop| {
@@ -2125,7 +2103,7 @@ impl ChannelManager {
2125
2103
chacha. process ( & packet_decrypted, & mut decryption_tmp[ ..] ) ;
2126
2104
packet_decrypted = decryption_tmp;
2127
2105
2128
- let is_from_final_node = route. hops . last ( ) . unwrap ( ) . pubkey == route_hop. pubkey ;
2106
+ is_from_final_node = route. hops . last ( ) . unwrap ( ) . pubkey == route_hop. pubkey ;
2129
2107
2130
2108
if let Ok ( err_packet) = msgs:: DecodedOnionErrorPacket :: read ( & mut Cursor :: new ( & packet_decrypted) ) {
2131
2109
let um = ChannelManager :: gen_um_from_shared_secret ( & shared_secret[ ..] ) ;
@@ -2138,175 +2116,92 @@ impl ChannelManager {
2138
2116
if err_packet. failuremsg . len ( ) < 2 {
2139
2117
// Useless packet that we can't use but it passed HMAC, so it
2140
2118
// definitely came from the peer in question
2141
- return_node_fail_update ! ( res, route_hop. pubkey, !is_from_final_node) ;
2119
+ res = Some ( ( Some ( msgs:: HTLCFailChannelUpdate :: NodeFailure {
2120
+ node_id : route_hop. pubkey ,
2121
+ is_permanent : true ,
2122
+ } ) , !is_from_final_node) ) ;
2142
2123
} else {
2124
+
2125
+ const PERM : u16 = 0x4000 ;
2126
+ const NODE : u16 = 0x2000 ;
2127
+ const UPDATE : u16 = 0x1000 ;
2128
+
2143
2129
let error_code = byte_utils:: slice_to_be16 ( & err_packet. failuremsg [ 0 ..2 ] ) ;
2144
2130
error_code_ret = Some ( error_code) ;
2145
2131
2146
- // either from intermediate or final node
2147
- if error_code& 0xff == 1 || error_code& 0xff == 2 || error_code& 0xff == 3 {
2148
- match error_code {
2149
- _c if _c == PERM |1 => onion_failure_log ! ( "invalid_realm" , error_code) ,
2150
- _c if _c == NODE |2 => onion_failure_log ! ( "temporary_node_failure" , error_code) ,
2151
- _c if _c == PERM |NODE |2 => onion_failure_log ! ( "permanent_node_failure" , error_code) ,
2152
- _c if _c == PERM |NODE |3 => onion_failure_log ! ( "required_node_feature_mssing" , error_code) ,
2153
- _ => return_node_fail_update ! ( res, route_hop. pubkey, !is_from_final_node) ,
2154
- }
2155
- // node returning invalid_realm is removed from network_map,
2156
- // although NODE flag is not set, TODO: or remove channel only?
2157
- // retry payment when removed node is not a final node
2158
- let is_permanent = error_code & PERM == PERM ;
2159
- if error_code & 0xff00 & NODE == NODE {
2160
- res = Some ( ( Some ( msgs:: HTLCFailChannelUpdate :: NodeFailure {
2161
- node_id : route_hop. pubkey ,
2162
- is_permanent,
2163
- } ) , !( error_code & PERM == PERM && is_from_final_node) ) ) ;
2164
- } else {
2165
- res = Some ( ( Some ( msgs:: HTLCFailChannelUpdate :: ChannelClosed {
2166
- // failing incoming channel to the erring node
2167
- short_channel_id : route_hop. short_channel_id ,
2168
- is_permanent,
2169
- } ) , !( error_code & PERM == PERM && is_from_final_node) ) ) ;
2170
- }
2171
- return ;
2172
- }
2132
+ let ( debug_field, debug_field_size) = get_onion_debug_field ( error_code) ;
2173
2133
2174
- if is_from_final_node {
2175
- let payment_retryable = match error_code {
2176
- _c if _c == PERM |15 => { onion_failure_log ! ( "unknwon_payment_hash" , error_code) ; false } ,
2177
- _c if _c == PERM |16 => { onion_failure_log ! ( "incorrect_payment_amount" , error_code) ; false } ,
2178
- 17 => { onion_failure_log ! ( "final_expiry_too_soon" , error_code) ; true } ,
2179
- 18 if err_packet. failuremsg . len ( ) == 6 => {
2180
- onion_failure_log ! ( "final_incorrect_cltv_expiry" , error_code, "cltv_expiry" , byte_utils:: slice_to_be32( & err_packet. failuremsg[ 2 ..2 +4 ] ) ) ;
2181
- true
2182
- } ,
2183
- 19 if err_packet. failuremsg . len ( ) == 10 => {
2184
- onion_failure_log ! ( "final_incorrect_htlc_amount" , error_code, "incoming_htlc_msat" , byte_utils:: slice_to_be64( & err_packet. failuremsg[ 2 ..2 +8 ] ) ) ;
2185
- true
2186
- } ,
2187
- _ => {
2188
- // A final node has sent us either an invalid code or an error_code that
2189
- // MUST be sent from the processing node, or the formmat of failuremsg
2190
- // does not coform to the spec.
2191
- // Remove it from the network map and don't may retry payment
2192
- return_node_fail_update ! ( res, route_hop. pubkey, false ) ;
2193
- }
2194
- } ;
2195
- res = Some ( ( None , payment_retryable) ) ;
2196
- return ;
2197
- }
2134
+ // indicate that payment parameter has failed and no need to
2135
+ // update route db
2136
+ let payment_failed = match error_code & 0xff {
2137
+ 15 |16 |17 |18 |19 => true ,
2138
+ _ => false ,
2139
+ } && is_from_final_node; // PERM bit observed below even this error is from the intermediate nodes
2198
2140
2199
- // now, error_code should be only from the intermediate nodes
2200
- match error_code {
2201
- _c if _c & 0xff00 == PERM |BADONION => {
2202
- if err_packet. failuremsg . len ( ) == 2 + 32 {
2203
- let ref onion_hash = DebugBytes ( & err_packet. failuremsg [ 2 ..2 +32 ] ) ;
2204
- match error_code & 0xff {
2205
- 4 => onion_failure_log ! ( "invalid_onion_version" , error_code, "sha256_of_onion" , onion_hash) ,
2206
- 5 => onion_failure_log ! ( "invalid_onion_hmac" , error_code, "sha256_of_onion" , onion_hash) ,
2207
- 6 => onion_failure_log ! ( "invalid_onion_key" , error_code, "sha256_of_onion" , onion_hash) ,
2208
- _ => return_node_fail_update ! ( res, route_hop. pubkey, true ) ,
2209
- }
2210
- } else { return_node_fail_update ! ( res, route_hop. pubkey, true ) ; }
2211
-
2212
- res = Some ( ( Some ( msgs:: HTLCFailChannelUpdate :: ChannelClosed {
2213
- short_channel_id : route_hop. short_channel_id ,
2214
- is_permanent : true ,
2215
- } ) , true ) ) ;
2216
- return ;
2217
- } ,
2218
- _c if _c & 0xff00 == PERM => {
2219
- match error_code & 0xff {
2220
- 8 => onion_failure_log ! ( "permanent_channel_failure" , error_code) ,
2221
- 9 => onion_failure_log ! ( "required_channel_feature_missing" , error_code) ,
2222
- 10 => onion_failure_log ! ( "unknown_next_peer" , error_code) ,
2223
- _ => return_node_fail_update ! ( res, route_hop. pubkey, true ) ,
2224
- }
2225
- assert ! ( next_route_hop_ix < route. hops. len( ) ) ;
2226
- res = Some ( ( Some ( msgs:: HTLCFailChannelUpdate :: ChannelClosed {
2227
- short_channel_id : route. hops [ next_route_hop_ix] . short_channel_id ,
2228
- is_permanent : true ,
2229
- } ) , true ) ) ;
2230
- return ;
2231
- } ,
2232
- _c if _c & 0xff00 == UPDATE => {
2233
- let offset = match error_code & 0xff {
2234
- 7 => 0 , // temporary_channel_failure
2235
- 11 => 8 , // amount_below_minimum
2236
- 12 => 8 , // fee_insufficient
2237
- 13 => 4 , // incorrect_cltv_expiry
2238
- 14 => 0 , // expiry_too_soon
2239
- 20 => 2 , // channel_disabled
2240
- _ => return_node_fail_update ! ( res, route_hop. pubkey, true ) ,
2241
- } ;
2242
- if err_packet. failuremsg . len ( ) >= offset + 2 {
2243
- let update_len = byte_utils:: slice_to_be16 ( & err_packet. failuremsg [ offset+2 ..offset+4 ] ) as usize ;
2244
- if err_packet. failuremsg . len ( ) >= offset + 4 + update_len {
2245
- if let Ok ( chan_update) = msgs:: ChannelUpdate :: read ( & mut Cursor :: new ( & err_packet. failuremsg [ offset + 4 ..offset + 4 + update_len] ) ) {
2246
-
2247
- // if channel_update should NOT have caused the failure:
2248
- // MAY treat the channel_update as invalid.
2249
- let is_chan_update_invalid = match error_code & 0xff {
2250
- 7 => {
2251
- onion_failure_log ! ( "temporary_channel_failure" , error_code) ;
2252
- false
2253
- } ,
2254
- 11 => {
2255
- onion_failure_log ! ( "amount_below_minimum" , error_code, "htlc_msat" , byte_utils:: slice_to_be64( & err_packet. failuremsg[ 2 ..2 +8 ] ) ) ;
2256
- amt_to_forward > chan_update. contents . htlc_minimum_msat
2257
- } ,
2258
- 12 => {
2259
- let new_fee = amt_to_forward. checked_mul ( chan_update. contents . fee_proportional_millionths as u64 ) . and_then ( |prop_fee| { ( prop_fee / 1000000 ) . checked_add ( chan_update. contents . fee_base_msat as u64 ) } ) ;
2260
- onion_failure_log ! ( "fee_insufficient" , error_code, "htlc_msat" , byte_utils:: slice_to_be64( & err_packet. failuremsg[ 2 ..2 +8 ] ) ) ;
2261
- new_fee. is_none ( ) || incoming_htlc_msat >= new_fee. unwrap ( ) && incoming_htlc_msat >= amt_to_forward + new_fee. unwrap ( )
2262
- }
2263
- 13 => {
2264
- onion_failure_log ! ( "incorrect_cltv_expiry" , error_code, "cltv_expiry" , byte_utils:: slice_to_be32( & err_packet. failuremsg[ 2 ..2 +4 ] ) ) ;
2265
- route_hop. cltv_expiry_delta as u16 >= chan_update. contents . cltv_expiry_delta
2266
- } ,
2267
- 14 => { // expiry_too_soon
2268
- onion_failure_log ! ( "expiry_too_soon" , error_code) ;
2269
- // always valid?
2270
- false
2271
- } ,
2272
- 20 => {
2273
- onion_failure_log ! ( "channel_disabled" , error_code, "flags" , byte_utils:: slice_to_be16( & err_packet. failuremsg[ 2 ..2 +2 ] ) ) ;
2274
- chan_update. contents . flags & 0x0200 == 1
2275
- } ,
2276
- _ => return_node_fail_update ! ( res, route_hop. pubkey, true ) ,
2277
- } ;
2278
-
2279
- let msg = if is_chan_update_invalid { None } else {
2280
- Some ( msgs:: HTLCFailChannelUpdate :: ChannelUpdateMessage {
2281
- msg : chan_update,
2282
- } )
2283
- } ;
2284
- res = Some ( ( msg, true ) ) ;
2285
- return ;
2286
- }
2141
+ let mut fail_channel_update = None ;
2142
+
2143
+ if error_code & NODE == NODE {
2144
+ fail_channel_update = Some ( msgs:: HTLCFailChannelUpdate :: NodeFailure { node_id : route_hop. pubkey , is_permanent : error_code & PERM == PERM } ) ;
2145
+ }
2146
+ else if error_code & PERM == PERM {
2147
+ fail_channel_update = if payment_failed { None } else { Some ( msgs:: HTLCFailChannelUpdate :: ChannelClosed {
2148
+ short_channel_id : match error_code & 0xff {
2149
+ 8 |9 |10 => route. hops [ next_route_hop_ix] . short_channel_id , // outgoing (permanent_channel_failure/required_channel_feature_missing/unknown_next_peer)
2150
+ _ => route_hop. short_channel_id , // incoming channel (invalid_realm & BADONION)
2151
+ } ,
2152
+ is_permanent : error_code & PERM == PERM ,
2153
+ } ) } ;
2154
+ }
2155
+ else if error_code & UPDATE == UPDATE {
2156
+ if err_packet. failuremsg . len ( ) >= debug_field_size + 2 {
2157
+ let update_len = byte_utils:: slice_to_be16 ( & err_packet. failuremsg [ debug_field_size+2 ..debug_field_size+4 ] ) as usize ;
2158
+ if err_packet. failuremsg . len ( ) >= debug_field_size + 4 + update_len {
2159
+ if let Ok ( chan_update) = msgs:: ChannelUpdate :: read ( & mut Cursor :: new ( & err_packet. failuremsg [ debug_field_size + 4 ..debug_field_size + 4 + update_len] ) ) {
2160
+ // if channel_update should NOT have caused the failure:
2161
+ // MAY treat the channel_update as invalid.
2162
+ let is_chan_update_invalid = match error_code & 0xff {
2163
+ 7 => false ,
2164
+ 11 => amt_to_forward > chan_update. contents . htlc_minimum_msat ,
2165
+ 12 => {
2166
+ let new_fee = amt_to_forward. checked_mul ( chan_update. contents . fee_proportional_millionths as u64 ) . and_then ( |prop_fee| { ( prop_fee / 1000000 ) . checked_add ( chan_update. contents . fee_base_msat as u64 ) } ) ;
2167
+ new_fee. is_none ( ) || incoming_htlc_msat >= new_fee. unwrap ( ) && incoming_htlc_msat >= amt_to_forward + new_fee. unwrap ( )
2168
+ }
2169
+ 13 => route_hop. cltv_expiry_delta as u16 >= chan_update. contents . cltv_expiry_delta ,
2170
+ 14 => false , // expiry_too_soon; always valid?
2171
+ 20 => chan_update. contents . flags & 0x0200 == 1 ,
2172
+ _ => false , // unknown error code; take channel_update as valid
2173
+ } ;
2174
+ fail_channel_update = if is_chan_update_invalid { None } else {
2175
+ Some ( msgs:: HTLCFailChannelUpdate :: ChannelUpdateMessage {
2176
+ msg : chan_update,
2177
+ } )
2178
+ } ;
2287
2179
}
2288
2180
}
2289
- return_node_fail_update ! ( res, route_hop. pubkey, true ) ;
2290
- } ,
2291
- 21 => {
2292
- onion_failure_log ! ( "expiry_too_far" , error_code) ;
2293
- res = Some ( ( None , true ) ) ;
2294
- return ;
2295
- } ,
2296
- _ => {
2297
- return_node_fail_update ! ( res, route_hop. pubkey, true ) ;
2298
2181
}
2299
2182
}
2183
+
2184
+ res = Some ( ( fail_channel_update, !( error_code & PERM == PERM && is_from_final_node) ) ) ;
2185
+
2186
+ let ( description, title) = get_onion_error_description ( error_code) ;
2187
+ if debug_field_size > 0 && err_packet. failuremsg . len ( ) >= 2 + debug_field_size {
2188
+ log_warn ! ( self , "Onion Error[{}({:#x}) {}({})] {}" , title, error_code, debug_field, DebugBytes ( & err_packet. failuremsg[ 2 ..2 +debug_field_size] ) , description) ;
2189
+ }
2190
+ else {
2191
+ log_warn ! ( self , "Onion Error[{}({:#x})] {}" , title, error_code, description) ;
2192
+ }
2300
2193
}
2301
2194
}
2302
2195
}
2303
2196
} ) . expect ( "Route that we sent via spontaneously grew invalid keys in the middle of it?" ) ;
2304
- let ( channel_update, payment_retryable) = res. expect ( "should have been set!" ) ;
2305
- ( channel_update, payment_retryable, error_code_ret)
2306
- } else {
2307
- // htlc_source should have been matched in the callsite
2308
- unreachable ! ( ) ;
2309
- }
2197
+ if let Some ( ( channel_update, payment_retryable) ) = res {
2198
+ ( channel_update, payment_retryable, error_code_ret)
2199
+ } else {
2200
+ // only not set either packet unparseable or hmac does not match with any
2201
+ // payment not retryable only when garbage is from the final node
2202
+ ( None , !is_from_final_node, None )
2203
+ }
2204
+ } else { unreachable ! ( ) ; }
2310
2205
}
2311
2206
2312
2207
fn internal_update_fail_htlc ( & self , their_node_id : & PublicKey , msg : & msgs:: UpdateFailHTLC ) -> Result < ( ) , MsgHandleErrInternal > {
@@ -4952,7 +4847,6 @@ mod tests {
4952
4847
assert ! ( updates_2. update_fee. is_none( ) ) ;
4953
4848
4954
4849
nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & updates_2. update_fail_htlcs [ 0 ] ) . unwrap ( ) ;
4955
-
4956
4850
commitment_signed_dance ! ( nodes[ 0 ] , nodes[ 1 ] , updates_2. commitment_signed, false , true ) ;
4957
4851
4958
4852
let events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
0 commit comments