diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs index db35ff01b..b169b356f 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -879,6 +879,7 @@ impl ChannelInfo { /// Returns a [`DirectedChannelInfo`] for the channel directed to the given `target` from a /// returned `source`, or `None` if `target` is not one of the channel's counterparties. pub fn as_directed_to(&self, target: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> { + if self.one_to_two.is_none() || self.two_to_one.is_none() { return None; } let (direction, source, outbound) = { if target == &self.node_one { (self.two_to_one.as_ref(), &self.node_two, false) @@ -888,12 +889,14 @@ impl ChannelInfo { return None; } }; - direction.map(|dir| (DirectedChannelInfo::new(self, dir, outbound), source)) + let dir = direction.expect("We checked that both directions are available at the start"); + Some((DirectedChannelInfo::new(self, dir, outbound), source)) } /// Returns a [`DirectedChannelInfo`] for the channel directed from the given `source` to a /// returned `target`, or `None` if `source` is not one of the channel's counterparties. pub fn as_directed_from(&self, source: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> { + if self.one_to_two.is_none() || self.two_to_one.is_none() { return None; } let (direction, target, outbound) = { if source == &self.node_one { (self.one_to_two.as_ref(), &self.node_two, true) @@ -903,7 +906,8 @@ impl ChannelInfo { return None; } }; - direction.map(|dir| (DirectedChannelInfo::new(self, dir, outbound), target)) + let dir = direction.expect("We checked that both directions are available at the start"); + Some((DirectedChannelInfo::new(self, dir, outbound), target)) } /// Returns a [`ChannelUpdateInfo`] based on the direction implied by the channel_flag. diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 08759ad44..95c03c443 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -5503,6 +5503,18 @@ mod tests { fee_proportional_millionths: 0, excess_data: Vec::new() }); + update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 5, + timestamp: 2, + flags: 3, // disable direction 1 + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 200_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new() + }); // Path via {node7, node2, node4} is channels {12, 13, 6, 11}. // Add 100 sats to the capacities of {12, 13}, because these channels @@ -5680,6 +5692,18 @@ mod tests { fee_proportional_millionths: 0, excess_data: Vec::new() }); + update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 5, + timestamp: 2, + flags: 3, // disable direction 1 + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 200_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new() + }); // Path via {node7, node2, node4} is channels {12, 13, 6, 11}. // Add 100 sats to the capacities of {12, 13}, because these channels @@ -5853,6 +5877,18 @@ mod tests { fee_proportional_millionths: 0, excess_data: Vec::new() }); + update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 5, + timestamp: 2, + flags: 3, // Disable direction 1 + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new() + }); // Path via {node7, node2, node4} is channels {12, 13, 6, 11}. // All channels should be 100 sats capacity. But for the fee experiment, @@ -6245,92 +6281,104 @@ mod tests { let payment_params = PaymentParameters::from_node_id(nodes[6], 42); add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 1, - flags: 0, - cltv_expiry_delta: (6 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + for (key, flags) in [(&our_privkey, 0), (&privkeys[1], 3)] { + update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 1, + flags, + cltv_expiry_delta: (6 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new() + }); + } add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0); add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 5, - timestamp: 1, - flags: 0, - cltv_expiry_delta: (5 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 100, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + for (key, flags) in [(&privkeys[1], 0), (&privkeys[4], 3)] { + update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 5, + timestamp: 1, + flags, + cltv_expiry_delta: (5 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 100, + fee_proportional_millionths: 0, + excess_data: Vec::new() + }); + } add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[4], NodeFeatures::from_le_bytes(id_to_feature_flags(4)), 0); add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4); - update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 1, - flags: 0, - cltv_expiry_delta: (4 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + for (key, flags) in [(&privkeys[4], 0), (&privkeys[3], 3)] { + update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 1, + flags, + cltv_expiry_delta: (4 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new() + }); + } add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[3], NodeFeatures::from_le_bytes(id_to_feature_flags(3)), 0); add_channel(&gossip_sync, &secp_ctx, &privkeys[3], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3); - update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 1, - flags: 0, - cltv_expiry_delta: (3 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + for (key, flags) in [(&privkeys[3], 0), (&privkeys[2], 3)] { + update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 1, + flags, + cltv_expiry_delta: (3 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new() + }); + } add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[2], NodeFeatures::from_le_bytes(id_to_feature_flags(2)), 0); add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 1, - flags: 0, - cltv_expiry_delta: (2 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + for (key, flags) in [(&privkeys[2], 0), (&privkeys[4], 3)] { + update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 1, + flags, + cltv_expiry_delta: (2 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new() + }); + } add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[6], ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1); - update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 1, - flags: 0, - cltv_expiry_delta: (1 << 4) | 0, - htlc_minimum_msat: 100, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + for (key, flags) in [(&privkeys[4], 0), (&privkeys[6], 3)] { + update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 1, + flags, + cltv_expiry_delta: (1 << 4) | 0, + htlc_minimum_msat: 100, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new() + }); + } add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[6], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0); {