Skip to content

Commit 4fd8cb8

Browse files
committed
Ignore partially-pruned channels during routing
If we prune one side of a channel's `ChannelUpdateInfo` that means the node hasn't been online for two weeks (as they haven't generated a new `channel_update` in that time). In such cases, even if we haven't yet pruned the channel entirely, we should definitely not be treating these channels as candidates for routing. Note that this requires some additional `channel_update`s in the router tests, but all of the new ones are added as disabled channels. Fixes #1824
1 parent 37c431a commit 4fd8cb8

File tree

2 files changed

+126
-74
lines changed

2 files changed

+126
-74
lines changed

lightning/src/routing/gossip.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,7 @@ impl ChannelInfo {
879879
/// Returns a [`DirectedChannelInfo`] for the channel directed to the given `target` from a
880880
/// returned `source`, or `None` if `target` is not one of the channel's counterparties.
881881
pub fn as_directed_to(&self, target: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> {
882+
if self.one_to_two.is_none() || self.two_to_one.is_none() { return None; }
882883
let (direction, source, outbound) = {
883884
if target == &self.node_one {
884885
(self.two_to_one.as_ref(), &self.node_two, false)
@@ -888,12 +889,14 @@ impl ChannelInfo {
888889
return None;
889890
}
890891
};
891-
direction.map(|dir| (DirectedChannelInfo::new(self, dir, outbound), source))
892+
let dir = direction.expect("We checked that both directions are available at the start");
893+
Some((DirectedChannelInfo::new(self, dir, outbound), source))
892894
}
893895

894896
/// Returns a [`DirectedChannelInfo`] for the channel directed from the given `source` to a
895897
/// returned `target`, or `None` if `source` is not one of the channel's counterparties.
896898
pub fn as_directed_from(&self, source: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> {
899+
if self.one_to_two.is_none() || self.two_to_one.is_none() { return None; }
897900
let (direction, target, outbound) = {
898901
if source == &self.node_one {
899902
(self.one_to_two.as_ref(), &self.node_two, true)
@@ -903,7 +906,8 @@ impl ChannelInfo {
903906
return None;
904907
}
905908
};
906-
direction.map(|dir| (DirectedChannelInfo::new(self, dir, outbound), target))
909+
let dir = direction.expect("We checked that both directions are available at the start");
910+
Some((DirectedChannelInfo::new(self, dir, outbound), target))
907911
}
908912

909913
/// Returns a [`ChannelUpdateInfo`] based on the direction implied by the channel_flag.

lightning/src/routing/router.rs

+120-72
Original file line numberDiff line numberDiff line change
@@ -5466,6 +5466,18 @@ mod tests {
54665466
fee_proportional_millionths: 0,
54675467
excess_data: Vec::new()
54685468
});
5469+
update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
5470+
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5471+
short_channel_id: 5,
5472+
timestamp: 2,
5473+
flags: 3, // disable direction 1
5474+
cltv_expiry_delta: 0,
5475+
htlc_minimum_msat: 0,
5476+
htlc_maximum_msat: 200_000,
5477+
fee_base_msat: 0,
5478+
fee_proportional_millionths: 0,
5479+
excess_data: Vec::new()
5480+
});
54695481

54705482
// Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
54715483
// Add 100 sats to the capacities of {12, 13}, because these channels
@@ -5643,6 +5655,18 @@ mod tests {
56435655
fee_proportional_millionths: 0,
56445656
excess_data: Vec::new()
56455657
});
5658+
update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
5659+
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5660+
short_channel_id: 5,
5661+
timestamp: 2,
5662+
flags: 3, // disable direction 1
5663+
cltv_expiry_delta: 0,
5664+
htlc_minimum_msat: 0,
5665+
htlc_maximum_msat: 200_000,
5666+
fee_base_msat: 0,
5667+
fee_proportional_millionths: 0,
5668+
excess_data: Vec::new()
5669+
});
56465670

56475671
// Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
56485672
// Add 100 sats to the capacities of {12, 13}, because these channels
@@ -5816,6 +5840,18 @@ mod tests {
58165840
fee_proportional_millionths: 0,
58175841
excess_data: Vec::new()
58185842
});
5843+
update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
5844+
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5845+
short_channel_id: 5,
5846+
timestamp: 2,
5847+
flags: 3, // Disable direction 1
5848+
cltv_expiry_delta: 0,
5849+
htlc_minimum_msat: 0,
5850+
htlc_maximum_msat: 100_000,
5851+
fee_base_msat: 0,
5852+
fee_proportional_millionths: 0,
5853+
excess_data: Vec::new()
5854+
});
58195855

58205856
// Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
58215857
// All channels should be 100 sats capacity. But for the fee experiment,
@@ -6208,92 +6244,104 @@ mod tests {
62086244
let payment_params = PaymentParameters::from_node_id(nodes[6], 42);
62096245

62106246
add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
6211-
update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6212-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6213-
short_channel_id: 6,
6214-
timestamp: 1,
6215-
flags: 0,
6216-
cltv_expiry_delta: (6 << 4) | 0,
6217-
htlc_minimum_msat: 0,
6218-
htlc_maximum_msat: MAX_VALUE_MSAT,
6219-
fee_base_msat: 0,
6220-
fee_proportional_millionths: 0,
6221-
excess_data: Vec::new()
6222-
});
6247+
for (key, flags) in [(&our_privkey, 0), (&privkeys[1], 3)] {
6248+
update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6249+
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6250+
short_channel_id: 6,
6251+
timestamp: 1,
6252+
flags,
6253+
cltv_expiry_delta: (6 << 4) | 0,
6254+
htlc_minimum_msat: 0,
6255+
htlc_maximum_msat: MAX_VALUE_MSAT,
6256+
fee_base_msat: 0,
6257+
fee_proportional_millionths: 0,
6258+
excess_data: Vec::new()
6259+
});
6260+
}
62236261
add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0);
62246262

62256263
add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
6226-
update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
6227-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6228-
short_channel_id: 5,
6229-
timestamp: 1,
6230-
flags: 0,
6231-
cltv_expiry_delta: (5 << 4) | 0,
6232-
htlc_minimum_msat: 0,
6233-
htlc_maximum_msat: MAX_VALUE_MSAT,
6234-
fee_base_msat: 100,
6235-
fee_proportional_millionths: 0,
6236-
excess_data: Vec::new()
6237-
});
6264+
for (key, flags) in [(&privkeys[1], 0), (&privkeys[4], 3)] {
6265+
update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6266+
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6267+
short_channel_id: 5,
6268+
timestamp: 1,
6269+
flags,
6270+
cltv_expiry_delta: (5 << 4) | 0,
6271+
htlc_minimum_msat: 0,
6272+
htlc_maximum_msat: MAX_VALUE_MSAT,
6273+
fee_base_msat: 100,
6274+
fee_proportional_millionths: 0,
6275+
excess_data: Vec::new()
6276+
});
6277+
}
62386278
add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[4], NodeFeatures::from_le_bytes(id_to_feature_flags(4)), 0);
62396279

62406280
add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4);
6241-
update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
6242-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6243-
short_channel_id: 4,
6244-
timestamp: 1,
6245-
flags: 0,
6246-
cltv_expiry_delta: (4 << 4) | 0,
6247-
htlc_minimum_msat: 0,
6248-
htlc_maximum_msat: MAX_VALUE_MSAT,
6249-
fee_base_msat: 0,
6250-
fee_proportional_millionths: 0,
6251-
excess_data: Vec::new()
6252-
});
6281+
for (key, flags) in [(&privkeys[4], 0), (&privkeys[3], 3)] {
6282+
update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6283+
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6284+
short_channel_id: 4,
6285+
timestamp: 1,
6286+
flags,
6287+
cltv_expiry_delta: (4 << 4) | 0,
6288+
htlc_minimum_msat: 0,
6289+
htlc_maximum_msat: MAX_VALUE_MSAT,
6290+
fee_base_msat: 0,
6291+
fee_proportional_millionths: 0,
6292+
excess_data: Vec::new()
6293+
});
6294+
}
62536295
add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[3], NodeFeatures::from_le_bytes(id_to_feature_flags(3)), 0);
62546296

62556297
add_channel(&gossip_sync, &secp_ctx, &privkeys[3], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3);
6256-
update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
6257-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6258-
short_channel_id: 3,
6259-
timestamp: 1,
6260-
flags: 0,
6261-
cltv_expiry_delta: (3 << 4) | 0,
6262-
htlc_minimum_msat: 0,
6263-
htlc_maximum_msat: MAX_VALUE_MSAT,
6264-
fee_base_msat: 0,
6265-
fee_proportional_millionths: 0,
6266-
excess_data: Vec::new()
6267-
});
6298+
for (key, flags) in [(&privkeys[3], 0), (&privkeys[2], 3)] {
6299+
update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6300+
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6301+
short_channel_id: 3,
6302+
timestamp: 1,
6303+
flags,
6304+
cltv_expiry_delta: (3 << 4) | 0,
6305+
htlc_minimum_msat: 0,
6306+
htlc_maximum_msat: MAX_VALUE_MSAT,
6307+
fee_base_msat: 0,
6308+
fee_proportional_millionths: 0,
6309+
excess_data: Vec::new()
6310+
});
6311+
}
62686312
add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[2], NodeFeatures::from_le_bytes(id_to_feature_flags(2)), 0);
62696313

62706314
add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2);
6271-
update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6272-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6273-
short_channel_id: 2,
6274-
timestamp: 1,
6275-
flags: 0,
6276-
cltv_expiry_delta: (2 << 4) | 0,
6277-
htlc_minimum_msat: 0,
6278-
htlc_maximum_msat: MAX_VALUE_MSAT,
6279-
fee_base_msat: 0,
6280-
fee_proportional_millionths: 0,
6281-
excess_data: Vec::new()
6282-
});
6315+
for (key, flags) in [(&privkeys[2], 0), (&privkeys[4], 3)] {
6316+
update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6317+
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6318+
short_channel_id: 2,
6319+
timestamp: 1,
6320+
flags,
6321+
cltv_expiry_delta: (2 << 4) | 0,
6322+
htlc_minimum_msat: 0,
6323+
htlc_maximum_msat: MAX_VALUE_MSAT,
6324+
fee_base_msat: 0,
6325+
fee_proportional_millionths: 0,
6326+
excess_data: Vec::new()
6327+
});
6328+
}
62836329

62846330
add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[6], ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
6285-
update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
6286-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6287-
short_channel_id: 1,
6288-
timestamp: 1,
6289-
flags: 0,
6290-
cltv_expiry_delta: (1 << 4) | 0,
6291-
htlc_minimum_msat: 100,
6292-
htlc_maximum_msat: MAX_VALUE_MSAT,
6293-
fee_base_msat: 0,
6294-
fee_proportional_millionths: 0,
6295-
excess_data: Vec::new()
6296-
});
6331+
for (key, flags) in [(&privkeys[4], 0), (&privkeys[6], 3)] {
6332+
update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6333+
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6334+
short_channel_id: 1,
6335+
timestamp: 1,
6336+
flags,
6337+
cltv_expiry_delta: (1 << 4) | 0,
6338+
htlc_minimum_msat: 100,
6339+
htlc_maximum_msat: MAX_VALUE_MSAT,
6340+
fee_base_msat: 0,
6341+
fee_proportional_millionths: 0,
6342+
excess_data: Vec::new()
6343+
});
6344+
}
62976345
add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[6], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0);
62986346

62996347
{

0 commit comments

Comments
 (0)