Skip `channel_update` signature checks if we have a newer state 2022-03-skip-redundant-sig-checks
authorMatt Corallo <git@bluematt.me>
Wed, 23 Mar 2022 22:10:15 +0000 (22:10 +0000)
committerMatt Corallo <git@bluematt.me>
Thu, 24 Mar 2022 17:21:30 +0000 (17:21 +0000)
`channel_update` messages already have their signatures checked
with the network graph write lock held, so there's no reason to
check the signatures before doing other quicker checks first,
including checking if we're already aware of a newer update for the
channel.

This reduces common-case CPU usage as `channel_update`s are sent
rather liberally over the p2p network to gossip them.

lightning/src/routing/network_graph.rs

index 012357df361767e330a698f492846a6b44e8917b..13e6beedd4da247c777b37aea628550d9473ce63 100644 (file)
@@ -1376,8 +1376,8 @@ impl NetworkGraph {
                                                }
                                        }
                                }
-                               macro_rules! maybe_update_channel_info {
-                                       ( $target: expr, $src_node: expr) => {
+                               macro_rules! check_update_latest {
+                                       ($target: expr) => {
                                                if let Some(existing_chan_info) = $target.as_ref() {
                                                        // The timestamp field is somewhat of a misnomer - the BOLTs use it to
                                                        // order updates to ensure you always have the latest one, only
@@ -1394,7 +1394,11 @@ impl NetworkGraph {
                                                } else {
                                                        chan_was_enabled = false;
                                                }
+                                       }
+                               }
 
+                               macro_rules! get_new_channel_info {
+                                       () => { {
                                                let last_update_message = if msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY
                                                        { full_msg.cloned() } else { None };
 
@@ -1410,29 +1414,31 @@ impl NetworkGraph {
                                                        },
                                                        last_update_message
                                                };
-                                               $target = Some(updated_channel_update_info);
-                                       }
+                                               Some(updated_channel_update_info)
+                                       } }
                                }
 
                                let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
                                if msg.flags & 1 == 1 {
                                        dest_node_id = channel.node_one.clone();
+                                       check_update_latest!(channel.two_to_one);
                                        if let Some((sig, ctx)) = sig_info {
                                                secp_verify_sig!(ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_two.as_slice()).map_err(|_| LightningError{
                                                        err: "Couldn't parse source node pubkey".to_owned(),
                                                        action: ErrorAction::IgnoreAndLog(Level::Debug)
                                                })?, "channel_update");
                                        }
-                                       maybe_update_channel_info!(channel.two_to_one, channel.node_two);
+                                       channel.two_to_one = get_new_channel_info!();
                                } else {
                                        dest_node_id = channel.node_two.clone();
+                                       check_update_latest!(channel.one_to_two);
                                        if let Some((sig, ctx)) = sig_info {
                                                secp_verify_sig!(ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_one.as_slice()).map_err(|_| LightningError{
                                                        err: "Couldn't parse destination node pubkey".to_owned(),
                                                        action: ErrorAction::IgnoreAndLog(Level::Debug)
                                                })?, "channel_update");
                                        }
-                                       maybe_update_channel_info!(channel.one_to_two, channel.node_one);
+                                       channel.one_to_two = get_new_channel_info!();
                                }
                        }
                }