+ let error_code = u16::from_be_bytes(error_code_slice.try_into().expect("len is 2"));
+ error_code_ret = Some(error_code);
+ error_packet_ret = Some(err_packet.failuremsg[2..].to_vec());
+
+ let (debug_field, debug_field_size) = errors::get_onion_debug_field(error_code);
+
+ // indicate that payment parameter has failed and no need to update Route object
+ let payment_failed = match error_code & 0xff {
+ 15 | 16 | 17 | 18 | 19 | 23 => true,
+ _ => false,
+ } && is_from_final_node; // PERM bit observed below even if this error is from the intermediate nodes
+
+ let mut network_update = None;
+ let mut short_channel_id = None;
+
+ if error_code & BADONION == BADONION {
+ // If the error code has the BADONION bit set, always blame the channel from the node
+ // "originating" the error to its next hop. The "originator" is ultimately actually claiming
+ // that its counterparty is the one who is failing the HTLC.
+ // If the "originator" here isn't lying we should really mark the next-hop node as failed
+ // entirely, but we can't be confident in that, as it would allow any node to get us to
+ // completely ban one of its counterparties. Instead, we simply remove the channel in
+ // question.
+ network_update = Some(NetworkUpdate::ChannelFailure {
+ short_channel_id: failing_route_hop.short_channel_id,
+ is_permanent: true,
+ });
+ } else if error_code & NODE == NODE {
+ let is_permanent = error_code & PERM == PERM;
+ network_update =
+ Some(NetworkUpdate::NodeFailure { node_id: route_hop.pubkey, is_permanent });
+ short_channel_id = Some(route_hop.short_channel_id);
+ } else if error_code & PERM == PERM {
+ if !payment_failed {
+ network_update = Some(NetworkUpdate::ChannelFailure {
+ short_channel_id: failing_route_hop.short_channel_id,
+ is_permanent: true,
+ });
+ short_channel_id = Some(failing_route_hop.short_channel_id);
+ }
+ } else if error_code & UPDATE == UPDATE {
+ if let Some(update_len_slice) =
+ err_packet.failuremsg.get(debug_field_size + 2..debug_field_size + 4)
+ {
+ let update_len =
+ u16::from_be_bytes(update_len_slice.try_into().expect("len is 2")) as usize;
+ if let Some(mut update_slice) = err_packet
+ .failuremsg
+ .get(debug_field_size + 4..debug_field_size + 4 + update_len)
+ {
+ // Historically, the BOLTs were unclear if the message type
+ // bytes should be included here or not. The BOLTs have now
+ // been updated to indicate that they *are* included, but many
+ // nodes still send messages without the type bytes, so we
+ // support both here.
+ // TODO: Switch to hard require the type prefix, as the current
+ // permissiveness introduces the (although small) possibility
+ // that we fail to decode legitimate channel updates that
+ // happen to start with ChannelUpdate::TYPE, i.e., [0x01, 0x02].
+ if update_slice.len() > 2
+ && update_slice[0..2] == msgs::ChannelUpdate::TYPE.to_be_bytes()
+ {
+ update_slice = &update_slice[2..];
+ } else {
+ log_trace!(logger, "Failure provided features a channel update without type prefix. Deprecated, but allowing for now.");
+ }
+ let update_opt = msgs::ChannelUpdate::read(&mut Cursor::new(&update_slice));
+ if update_opt.is_ok() || update_slice.is_empty() {
+ // if channel_update should NOT have caused the failure:
+ // MAY treat the channel_update as invalid.
+ let is_chan_update_invalid = match error_code & 0xff {
+ 7 => false,
+ 11 => {
+ update_opt.is_ok()
+ && amt_to_forward
+ > update_opt.as_ref().unwrap().contents.htlc_minimum_msat
+ },
+ 12 => {
+ update_opt.is_ok()
+ && amt_to_forward
+ .checked_mul(
+ update_opt
+ .as_ref()
+ .unwrap()
+ .contents
+ .fee_proportional_millionths as u64,
+ )
+ .map(|prop_fee| prop_fee / 1_000_000)
+ .and_then(|prop_fee| {
+ prop_fee.checked_add(
+ update_opt.as_ref().unwrap().contents.fee_base_msat
+ as u64,
+ )
+ })
+ .map(|fee_msats| route_hop.fee_msat >= fee_msats)
+ .unwrap_or(false)
+ },
+ 13 => {
+ update_opt.is_ok()
+ && route_hop.cltv_expiry_delta as u16
+ >= update_opt.as_ref().unwrap().contents.cltv_expiry_delta
+ },
+ 14 => false, // expiry_too_soon; always valid?
+ 20 => update_opt.as_ref().unwrap().contents.flags & 2 == 0,
+ _ => false, // unknown error code; take channel_update as valid
+ };
+ if is_chan_update_invalid {
+ // This probably indicates the node which forwarded
+ // to the node in question corrupted something.
+ network_update = Some(NetworkUpdate::ChannelFailure {
+ short_channel_id: route_hop.short_channel_id,
+ is_permanent: true,
+ });
+ } else {
+ if let Ok(chan_update) = update_opt {
+ // Make sure the ChannelUpdate contains the expected
+ // short channel id.
+ if failing_route_hop.short_channel_id
+ == chan_update.contents.short_channel_id
+ {
+ short_channel_id = Some(failing_route_hop.short_channel_id);
+ } else {
+ log_info!(logger, "Node provided a channel_update for which it was not authoritative, ignoring.");
+ }
+ network_update =
+ Some(NetworkUpdate::ChannelUpdateMessage { msg: chan_update })
+ } else {
+ // The node in question intentionally encoded a 0-length channel update. This is
+ // likely due to https://github.com/ElementsProject/lightning/issues/6200.
+ short_channel_id = Some(failing_route_hop.short_channel_id);