Skip to content

Commit 0b7838b

Browse files
committed
Refactor channel_update processing logic into local fns
In the next commit we'll move to checking `channel_update`s in three steps - first we check if the `channel_update` is new and the latest for a channel, then we check the signature, and finally we update our local state. This allows us to avoid holding a lock on `NetworkGraph::channels` while validating the message signature. Here we do a quick prefactor to make that simpler - moving the validation logic of `channel_update` that we'll do in step one (and repeat in step three) into a local function. We also take this opportunity to do one static check unlocked which we had been doing while holding a `channel` lock.
1 parent db905e8 commit 0b7838b

File tree

1 file changed

+42
-34
lines changed

1 file changed

+42
-34
lines changed

lightning/src/routing/gossip.rs

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,6 +2253,47 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
22532253
msg.timestamp
22542254
);
22552255

2256+
if msg.htlc_maximum_msat > MAX_VALUE_MSAT {
2257+
return Err(LightningError{err:
2258+
"htlc_maximum_msat is larger than maximum possible msats".to_owned(),
2259+
action: ErrorAction::IgnoreError});
2260+
}
2261+
2262+
let check_update_latest = |target: &Option<ChannelUpdateInfo>| -> Result<(), LightningError> {
2263+
if let Some(existing_chan_info) = target {
2264+
// The timestamp field is somewhat of a misnomer - the BOLTs use it to
2265+
// order updates to ensure you always have the latest one, only
2266+
// suggesting that it be at least the current time. For
2267+
// channel_updates specifically, the BOLTs discuss the possibility of
2268+
// pruning based on the timestamp field being more than two weeks old,
2269+
// but only in the non-normative section.
2270+
if existing_chan_info.last_update > msg.timestamp {
2271+
return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip});
2272+
} else if existing_chan_info.last_update == msg.timestamp {
2273+
return Err(LightningError{err: "Update had same timestamp as last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip});
2274+
}
2275+
}
2276+
Ok(())
2277+
};
2278+
2279+
let check_msg_sanity = |channel: &ChannelInfo| -> Result<(), LightningError> {
2280+
if let Some(capacity_sats) = channel.capacity_sats {
2281+
// It's possible channel capacity is available now, although it wasn't available at announcement (so the field is None).
2282+
// Don't query UTXO set here to reduce DoS risks.
2283+
if capacity_sats > MAX_VALUE_MSAT / 1000 || msg.htlc_maximum_msat > capacity_sats * 1000 {
2284+
return Err(LightningError{err:
2285+
"htlc_maximum_msat is larger than channel capacity or capacity is bogus".to_owned(),
2286+
action: ErrorAction::IgnoreError});
2287+
}
2288+
}
2289+
2290+
if msg.channel_flags & 1 == 1 {
2291+
check_update_latest(&channel.two_to_one)
2292+
} else {
2293+
check_update_latest(&channel.one_to_two)
2294+
}
2295+
};
2296+
22562297
let mut channels = self.channels.write().unwrap();
22572298
match channels.get_mut(&msg.short_channel_id) {
22582299
None => {
@@ -2264,38 +2305,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
22642305
});
22652306
},
22662307
Some(channel) => {
2267-
if msg.htlc_maximum_msat > MAX_VALUE_MSAT {
2268-
return Err(LightningError{err:
2269-
"htlc_maximum_msat is larger than maximum possible msats".to_owned(),
2270-
action: ErrorAction::IgnoreError});
2271-
}
2272-
2273-
if let Some(capacity_sats) = channel.capacity_sats {
2274-
// It's possible channel capacity is available now, although it wasn't available at announcement (so the field is None).
2275-
// Don't query UTXO set here to reduce DoS risks.
2276-
if capacity_sats > MAX_VALUE_MSAT / 1000 || msg.htlc_maximum_msat > capacity_sats * 1000 {
2277-
return Err(LightningError{err:
2278-
"htlc_maximum_msat is larger than channel capacity or capacity is bogus".to_owned(),
2279-
action: ErrorAction::IgnoreError});
2280-
}
2281-
}
2282-
macro_rules! check_update_latest {
2283-
($target: expr) => {
2284-
if let Some(existing_chan_info) = $target.as_ref() {
2285-
// The timestamp field is somewhat of a misnomer - the BOLTs use it to
2286-
// order updates to ensure you always have the latest one, only
2287-
// suggesting that it be at least the current time. For
2288-
// channel_updates specifically, the BOLTs discuss the possibility of
2289-
// pruning based on the timestamp field being more than two weeks old,
2290-
// but only in the non-normative section.
2291-
if existing_chan_info.last_update > msg.timestamp {
2292-
return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip});
2293-
} else if existing_chan_info.last_update == msg.timestamp {
2294-
return Err(LightningError{err: "Update had same timestamp as last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip});
2295-
}
2296-
}
2297-
}
2298-
}
2308+
check_msg_sanity(channel)?;
22992309

23002310
macro_rules! get_new_channel_info {
23012311
() => { {
@@ -2320,7 +2330,6 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
23202330

23212331
let msg_hash = hash_to_message!(&message_sha256d_hash(&msg)[..]);
23222332
if msg.channel_flags & 1 == 1 {
2323-
check_update_latest!(channel.two_to_one);
23242333
if let Some(sig) = sig {
23252334
secp_verify_sig!(self.secp_ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_two.as_slice()).map_err(|_| LightningError{
23262335
err: "Couldn't parse source node pubkey".to_owned(),
@@ -2331,7 +2340,6 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
23312340
channel.two_to_one = get_new_channel_info!();
23322341
}
23332342
} else {
2334-
check_update_latest!(channel.one_to_two);
23352343
if let Some(sig) = sig {
23362344
secp_verify_sig!(self.secp_ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_one.as_slice()).map_err(|_| LightningError{
23372345
err: "Couldn't parse destination node pubkey".to_owned(),

0 commit comments

Comments
 (0)