Support reading `channel_update`s in onions with message type bytes 2022-04-update-type-bytes
authorMatt Corallo <git@bluematt.me>
Sun, 3 Apr 2022 17:06:44 +0000 (17:06 +0000)
committerMatt Corallo <git@bluematt.me>
Wed, 27 Apr 2022 01:34:13 +0000 (01:34 +0000)
Historically c-lightning and eclair have always sent
`channel_update` messages inside the onion error packets with the
two message type bytes (`0x0102` for `channel_update` messages) but
lnd and us skipped those bytes. We only supported decoding messages
matching our own encoding - decoding a bogus `channel_update` if
the extra bytes were included.

Here we detect the type bytes and, if they're present, start
reading at offset 2.

We also take this opportunity to improve loging and make the
severity more accurate for the previous error.

Fixes #1450.

lightning/src/ln/onion_utils.rs

index 0dd6087f82018d9faf56d53672325b76284caa00..5b9d1787055124b51eb43b3d5d98652078f97f0c 100644 (file)
@@ -404,7 +404,15 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
                                                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(update_slice) = err_packet.failuremsg.get(debug_field_size + 4..debug_field_size + 4 + update_len) {
+                                                               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.
+                                                                       if update_slice.len() > 2 && update_slice[0..2] == [0x01, 0x02] {
+                                                                               update_slice = &update_slice[2..];
+                                                                       }
                                                                        if let Ok(chan_update) = msgs::ChannelUpdate::read(&mut Cursor::new(&update_slice)) {
                                                                                // if channel_update should NOT have caused the failure:
                                                                                // MAY treat the channel_update as invalid.
@@ -434,6 +442,8 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
                                                                                        // 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,
@@ -478,10 +488,10 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
 
                                                let (description, title) = errors::get_onion_error_description(error_code);
                                                if debug_field_size > 0 && err_packet.failuremsg.len() >= 4 + debug_field_size {
-                                                       log_warn!(logger, "Onion Error[from {}: {}({:#x}) {}({})] {}", route_hop.pubkey, title, error_code, debug_field, log_bytes!(&err_packet.failuremsg[4..4+debug_field_size]), description);
+                                                       log_info!(logger, "Onion Error[from {}: {}({:#x}) {}({})] {}", route_hop.pubkey, title, error_code, debug_field, log_bytes!(&err_packet.failuremsg[4..4+debug_field_size]), description);
                                                }
                                                else {
-                                                       log_warn!(logger, "Onion Error[from {}: {}({:#x})] {}", route_hop.pubkey, title, error_code, description);
+                                                       log_info!(logger, "Onion Error[from {}: {}({:#x})] {}", route_hop.pubkey, title, error_code, description);
                                                }
                                        } else {
                                                // Useless packet that we can't use but it passed HMAC, so it