- let node1 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("0202020202020202020202020202020202020202020202020202020202020202").unwrap()[..]).unwrap());
- let node2 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("0303030303030303030303030303030303030303030303030303030303030303").unwrap()[..]).unwrap());
- let node3 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("0404040404040404040404040404040404040404040404040404040404040404").unwrap()[..]).unwrap());
- let node4 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("0505050505050505050505050505050505050505050505050505050505050505").unwrap()[..]).unwrap());
- let node5 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("0606060606060606060606060606060606060606060606060606060606060606").unwrap()[..]).unwrap());
- let node6 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("0707070707070707070707070707070707070707070707070707070707070707").unwrap()[..]).unwrap());
- let node7 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("0808080808080808080808080808080808080808080808080808080808080808").unwrap()[..]).unwrap());
- let node8 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("0909090909090909090909090909090909090909090909090909090909090909").unwrap()[..]).unwrap());
-
- macro_rules! id_to_feature_flags {
- // Set the feature flags to the id'th odd (ie non-required) feature bit so that we can
- // test for it later.
- ($id: expr) => { {
- let idx = ($id - 1) * 2 + 1;
- if idx > 8*3 {
- vec![1 << (idx - 8*3), 0, 0, 0]
- } else if idx > 8*2 {
- vec![1 << (idx - 8*2), 0, 0]
- } else if idx > 8*1 {
- vec![1 << (idx - 8*1), 0]
- } else {
- vec![1 << idx]
- }
- } }
- }
-
- {
- let mut network = router.network_map.write().unwrap();
-
- network.nodes.insert(node1.clone(), NodeInfo {
- channels: vec!(1, 3),
- lowest_inbound_channel_fee_base_msat: 100,
- lowest_inbound_channel_fee_proportional_millionths: 0,
- features: NodeFeatures::from_le_bytes(id_to_feature_flags!(1)),
- last_update: Some(1),
- rgb: [0; 3],
- alias: [0; 32],
- addresses: Vec::new(),
- announcement_message: None,
- });
- network.channels.insert(1, ChannelInfo {
- features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(1)),
- one_to_two: DirectionalChannelInfo {
- src_node_id: our_id.clone(),
- last_update: 0,
- enabled: false,
- cltv_expiry_delta: u16::max_value(), // This value should be ignored
- htlc_minimum_msat: 0,
- fee_base_msat: u32::max_value(), // This value should be ignored
- fee_proportional_millionths: u32::max_value(), // This value should be ignored
- last_update_message: None,
- }, two_to_one: DirectionalChannelInfo {
- src_node_id: node1.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: 0,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- },
- announcement_message: None,
- });
- network.nodes.insert(node2.clone(), NodeInfo {
- channels: vec!(2, 4),
- lowest_inbound_channel_fee_base_msat: 0,
- lowest_inbound_channel_fee_proportional_millionths: 0,
- features: NodeFeatures::from_le_bytes(id_to_feature_flags!(2)),
- last_update: Some(1),
- rgb: [0; 3],
- alias: [0; 32],
- addresses: Vec::new(),
- announcement_message: None,
- });
- network.channels.insert(2, ChannelInfo {
- features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(2)),
- one_to_two: DirectionalChannelInfo {
- src_node_id: our_id.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: u16::max_value(), // This value should be ignored
- htlc_minimum_msat: 0,
- fee_base_msat: u32::max_value(), // This value should be ignored
- fee_proportional_millionths: u32::max_value(), // This value should be ignored
- last_update_message: None,
- }, two_to_one: DirectionalChannelInfo {
- src_node_id: node2.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: 0,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- },
- announcement_message: None,
- });
- network.nodes.insert(node8.clone(), NodeInfo {
- channels: vec!(12, 13),
- lowest_inbound_channel_fee_base_msat: 0,
- lowest_inbound_channel_fee_proportional_millionths: 0,
- features: NodeFeatures::from_le_bytes(id_to_feature_flags!(8)),
- last_update: Some(1),
- rgb: [0; 3],
- alias: [0; 32],
- addresses: Vec::new(),
- announcement_message: None,
- });
- network.channels.insert(12, ChannelInfo {
- features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(12)),
- one_to_two: DirectionalChannelInfo {
- src_node_id: our_id.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: u16::max_value(), // This value should be ignored
- htlc_minimum_msat: 0,
- fee_base_msat: u32::max_value(), // This value should be ignored
- fee_proportional_millionths: u32::max_value(), // This value should be ignored
- last_update_message: None,
- }, two_to_one: DirectionalChannelInfo {
- src_node_id: node8.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: 0,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- },
- announcement_message: None,
- });
- network.nodes.insert(node3.clone(), NodeInfo {
- channels: vec!(
- 3,
- 4,
- 13,
- 5,
- 6,
- 7),
- lowest_inbound_channel_fee_base_msat: 0,
- lowest_inbound_channel_fee_proportional_millionths: 0,
- features: NodeFeatures::from_le_bytes(id_to_feature_flags!(3)),
- last_update: Some(1),
- rgb: [0; 3],
- alias: [0; 32],
- addresses: Vec::new(),
- announcement_message: None,
- });
- network.channels.insert(3, ChannelInfo {
- features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(3)),
- one_to_two: DirectionalChannelInfo {
- src_node_id: node1.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (3 << 8) | 1,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- }, two_to_one: DirectionalChannelInfo {
- src_node_id: node3.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (3 << 8) | 2,
- htlc_minimum_msat: 0,
- fee_base_msat: 100,
- fee_proportional_millionths: 0,
- last_update_message: None,
- },
- announcement_message: None,
- });
- network.channels.insert(4, ChannelInfo {
- features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(4)),
- one_to_two: DirectionalChannelInfo {
- src_node_id: node2.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (4 << 8) | 1,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 1000000,
- last_update_message: None,
- }, two_to_one: DirectionalChannelInfo {
- src_node_id: node3.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (4 << 8) | 2,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- },
- announcement_message: None,
- });
- network.channels.insert(13, ChannelInfo {
- features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(13)),
- one_to_two: DirectionalChannelInfo {
- src_node_id: node8.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (13 << 8) | 1,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 2000000,
- last_update_message: None,
- }, two_to_one: DirectionalChannelInfo {
- src_node_id: node3.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (13 << 8) | 2,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- },
- announcement_message: None,
- });
- network.nodes.insert(node4.clone(), NodeInfo {
- channels: vec!(5, 11),
- lowest_inbound_channel_fee_base_msat: 0,
- lowest_inbound_channel_fee_proportional_millionths: 0,
- features: NodeFeatures::from_le_bytes(id_to_feature_flags!(4)),
- last_update: Some(1),
- rgb: [0; 3],
- alias: [0; 32],
- addresses: Vec::new(),
- announcement_message: None,
- });
- network.channels.insert(5, ChannelInfo {
- features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(5)),
- one_to_two: DirectionalChannelInfo {
- src_node_id: node3.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (5 << 8) | 1,
- htlc_minimum_msat: 0,
- fee_base_msat: 100,
- fee_proportional_millionths: 0,
- last_update_message: None,
- }, two_to_one: DirectionalChannelInfo {
- src_node_id: node4.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (5 << 8) | 2,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- },
- announcement_message: None,
- });
- network.nodes.insert(node5.clone(), NodeInfo {
- channels: vec!(6, 11),
- lowest_inbound_channel_fee_base_msat: 0,
- lowest_inbound_channel_fee_proportional_millionths: 0,
- features: NodeFeatures::from_le_bytes(id_to_feature_flags!(5)),
- last_update: Some(1),
- rgb: [0; 3],
- alias: [0; 32],
- addresses: Vec::new(),
- announcement_message: None,
- });
- network.channels.insert(6, ChannelInfo {
- features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(6)),
- one_to_two: DirectionalChannelInfo {
- src_node_id: node3.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (6 << 8) | 1,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- }, two_to_one: DirectionalChannelInfo {
- src_node_id: node5.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (6 << 8) | 2,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- },
- announcement_message: None,
- });
- network.channels.insert(11, ChannelInfo {
- features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(11)),
- one_to_two: DirectionalChannelInfo {
- src_node_id: node5.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (11 << 8) | 1,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- }, two_to_one: DirectionalChannelInfo {
- src_node_id: node4.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (11 << 8) | 2,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- },
- announcement_message: None,
- });
- network.nodes.insert(node6.clone(), NodeInfo {
- channels: vec!(7),
- lowest_inbound_channel_fee_base_msat: 0,
- lowest_inbound_channel_fee_proportional_millionths: 0,
- features: NodeFeatures::from_le_bytes(id_to_feature_flags!(6)),
- last_update: Some(1),
- rgb: [0; 3],
- alias: [0; 32],
- addresses: Vec::new(),
- announcement_message: None,
- });
- network.channels.insert(7, ChannelInfo {
- features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(7)),
- one_to_two: DirectionalChannelInfo {
- src_node_id: node3.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (7 << 8) | 1,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 1000000,
- last_update_message: None,
- }, two_to_one: DirectionalChannelInfo {
- src_node_id: node6.clone(),
- last_update: 0,
- enabled: true,
- cltv_expiry_delta: (7 << 8) | 2,
- htlc_minimum_msat: 0,
- fee_base_msat: 0,
- fee_proportional_millionths: 0,
- last_update_message: None,
- },
- announcement_message: None,
- });
- }
-
- { // Simple route to 3 via 2
- let route = router.get_route(&node3, None, &Vec::new(), 100, 42).unwrap();
- assert_eq!(route.paths[0].len(), 2);
-
- assert_eq!(route.paths[0][0].pubkey, node2);
- assert_eq!(route.paths[0][0].short_channel_id, 2);
- assert_eq!(route.paths[0][0].fee_msat, 100);
- assert_eq!(route.paths[0][0].cltv_expiry_delta, (4 << 8) | 1);
- assert_eq!(route.paths[0][0].node_features.le_flags(), &id_to_feature_flags!(2));
- assert_eq!(route.paths[0][0].channel_features.le_flags(), &id_to_feature_flags!(2));
-
- assert_eq!(route.paths[0][1].pubkey, node3);
- assert_eq!(route.paths[0][1].short_channel_id, 4);
- assert_eq!(route.paths[0][1].fee_msat, 100);
- assert_eq!(route.paths[0][1].cltv_expiry_delta, 42);
- assert_eq!(route.paths[0][1].node_features.le_flags(), &id_to_feature_flags!(3));
- assert_eq!(route.paths[0][1].channel_features.le_flags(), &id_to_feature_flags!(4));
- }
-
- { // Disable channels 4 and 12 by requiring unknown feature bits
- let mut network = router.network_map.write().unwrap();
- network.channels.get_mut(&4).unwrap().features.set_required_unknown_bits();
- network.channels.get_mut(&12).unwrap().features.set_required_unknown_bits();
- }
-
- { // If all the channels require some features we don't understand, route should fail
- if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = router.get_route(&node3, None, &Vec::new(), 100, 42) {
- assert_eq!(err, "Failed to find a path to the given destination");
- } else { panic!(); }
- }
-
- { // If we specify a channel to node8, that overrides our local channel view and that gets used
- let our_chans = vec![channelmanager::ChannelDetails {
- channel_id: [0; 32],
- short_channel_id: Some(42),
- remote_network_id: node8.clone(),
- counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
- channel_value_satoshis: 0,
- user_id: 0,
- outbound_capacity_msat: 0,
- inbound_capacity_msat: 0,
- is_live: true,
- }];
- let route = router.get_route(&node3, Some(&our_chans), &Vec::new(), 100, 42).unwrap();
- assert_eq!(route.paths[0].len(), 2);
-
- assert_eq!(route.paths[0][0].pubkey, node8);
- assert_eq!(route.paths[0][0].short_channel_id, 42);
- assert_eq!(route.paths[0][0].fee_msat, 200);
- assert_eq!(route.paths[0][0].cltv_expiry_delta, (13 << 8) | 1);
- assert_eq!(route.paths[0][0].node_features.le_flags(), &vec![0b11]); // it should also override our view of their features
- assert_eq!(route.paths[0][0].channel_features.le_flags(), &Vec::new()); // No feature flags will meet the relevant-to-channel conversion
-
- assert_eq!(route.paths[0][1].pubkey, node3);
- assert_eq!(route.paths[0][1].short_channel_id, 13);
- assert_eq!(route.paths[0][1].fee_msat, 100);
- assert_eq!(route.paths[0][1].cltv_expiry_delta, 42);
- assert_eq!(route.paths[0][1].node_features.le_flags(), &id_to_feature_flags!(3));
- assert_eq!(route.paths[0][1].channel_features.le_flags(), &id_to_feature_flags!(13));
- }