Merge pull request #646 from naumenkogs/2020-06-router-mpp
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Wed, 3 Mar 2021 01:32:45 +0000 (20:32 -0500)
committerMatt Corallo <git@bluematt.me>
Wed, 3 Mar 2021 01:33:08 +0000 (20:33 -0500)
MPP on the router side

1  2 
fuzz/src/router.rs
lightning/src/ln/channel.rs
lightning/src/ln/functional_tests.rs
lightning/src/routing/network_graph.rs
lightning/src/routing/router.rs

Simple merge
index 2bbe367de75e8d8749e11216ea53d76355aad62c,3c8be717f3237edc56297d559c806bdb96d80780..633652222d11352f64be2f1f13a75d543e07eca4
@@@ -3325,9 -3167,9 +3325,9 @@@ impl<Signer: Sign> Channel<Signer> 
                        // Upper bound by capacity. We make it a bit less than full capacity to prevent attempts
                        // to use full capacity. This is an effort to reduce routing failures, because in many cases
                        // channel might have been used to route very small values (either by honest users or as DoS).
-                       self.channel_value_satoshis * 9 / 10,
+                       self.channel_value_satoshis * 1000 * 9 / 10,
  
 -                      Channel::<ChanSigner>::get_holder_max_htlc_value_in_flight_msat(self.channel_value_satoshis)
 +                      Channel::<Signer>::get_holder_max_htlc_value_in_flight_msat(self.channel_value_satoshis)
                );
        }
  
Simple merge
index 9f1b60e0d27adf83735dfc02c0f20720e9c67161,dd18f1bc716af92748e500469a1edb3344a0451a..7819b06c0279650c17063dfaed81aebac610d884
@@@ -1278,49 -2149,1190 +2151,1235 @@@ mod tests 
                assert_eq!(route.paths[0][1].node_features.le_flags(), &[0; 0]); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][1].channel_features.le_flags(), &[0; 0]); // We can't learn any flags from invoices, sadly
        }
+       #[test]
+       fn available_amount_while_routing_test() {
+               // Tests whether we choose the correct available channel amount while routing.
+               let (secp_ctx, mut net_graph_msg_handler, chain_monitor, logger) = build_graph();
+               let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
+               // We will use a simple single-path route from
+               // our node to node2 via node0: channels {1, 3}.
+               // First disable all other paths.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 2,
+                       timestamp: 2,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 12,
+                       timestamp: 2,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Make the first channel (#1) very permissive,
+               // and we will be testing all limits on the second channel.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 1,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(1_000_000_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // First, let's see if routing works if we have absolutely no idea about the available amount.
+               // In this case, it should be set to 250_000 sats.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 3,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               {
+                       // Attempt to route more than available results in a failure.
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 250_000_001, 42, Arc::clone(&logger)) {
+                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+               {
+                       // Now, attempt to route an exact amount we have should be fine.
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 250_000_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 1);
+                       let path = route.paths.last().unwrap();
+                       assert_eq!(path.len(), 2);
+                       assert_eq!(path.last().unwrap().pubkey, nodes[2]);
+                       assert_eq!(path.last().unwrap().fee_msat, 250_000_000);
+               }
+               // Check that setting outbound_capacity_msat in first_hops limits the channels.
+               // Disable channel #1 and use another first hop.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 1,
+                       timestamp: 3,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(1_000_000_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Now, limit the first_hop by the outbound_capacity_msat of 200_000 sats.
+               let our_chans = vec![channelmanager::ChannelDetails {
+                       channel_id: [0; 32],
+                       short_channel_id: Some(42),
+                       remote_network_id: nodes[0].clone(),
+                       counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
+                       channel_value_satoshis: 0,
+                       user_id: 0,
+                       outbound_capacity_msat: 200_000_000,
+                       inbound_capacity_msat: 0,
+                       is_live: true,
+               }];
+               {
+                       // Attempt to route more than available results in a failure.
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], Some(&our_chans.iter().collect::<Vec<_>>()), &Vec::new(), 200_000_001, 42, Arc::clone(&logger)) {
+                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+               {
+                       // Now, attempt to route an exact amount we have should be fine.
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], Some(&our_chans.iter().collect::<Vec<_>>()), &Vec::new(), 200_000_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 1);
+                       let path = route.paths.last().unwrap();
+                       assert_eq!(path.len(), 2);
+                       assert_eq!(path.last().unwrap().pubkey, nodes[2]);
+                       assert_eq!(path.last().unwrap().fee_msat, 200_000_000);
+               }
+               // Enable channel #1 back.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 1,
+                       timestamp: 4,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(1_000_000_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Now let's see if routing works if we know only htlc_maximum_msat.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 3,
+                       timestamp: 3,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(15_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               {
+                       // Attempt to route more than available results in a failure.
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 15_001, 42, Arc::clone(&logger)) {
+                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+               {
+                       // Now, attempt to route an exact amount we have should be fine.
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 15_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 1);
+                       let path = route.paths.last().unwrap();
+                       assert_eq!(path.len(), 2);
+                       assert_eq!(path.last().unwrap().pubkey, nodes[2]);
+                       assert_eq!(path.last().unwrap().fee_msat, 15_000);
+               }
+               // Now let's see if routing works if we know only capacity from the UTXO.
+               // We can't change UTXO capacity on the fly, so we'll disable
+               // the existing channel and add another one with the capacity we need.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 3,
+                       timestamp: 4,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               let good_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2)
+               .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[0]).serialize())
+               .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[2]).serialize())
+               .push_opcode(opcodes::all::OP_PUSHNUM_2)
+               .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
+               *chain_monitor.utxo_ret.lock().unwrap() = Ok(TxOut { value: 15, script_pubkey: good_script.clone() });
+               net_graph_msg_handler.add_chain_access(Some(chain_monitor));
+               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 333);
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 333,
+                       timestamp: 1,
+                       flags: 0,
+                       cltv_expiry_delta: (3 << 8) | 1,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 333,
+                       timestamp: 1,
+                       flags: 1,
+                       cltv_expiry_delta: (3 << 8) | 2,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
+                       fee_base_msat: 100,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               {
+                       // Attempt to route more than available results in a failure.
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 15_001, 42, Arc::clone(&logger)) {
+                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+               {
+                       // Now, attempt to route an exact amount we have should be fine.
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 15_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 1);
+                       let path = route.paths.last().unwrap();
+                       assert_eq!(path.len(), 2);
+                       assert_eq!(path.last().unwrap().pubkey, nodes[2]);
+                       assert_eq!(path.last().unwrap().fee_msat, 15_000);
+               }
+               // Now let's see if routing chooses htlc_maximum_msat over UTXO capacity.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 333,
+                       timestamp: 6,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(10_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               {
+                       // Attempt to route more than available results in a failure.
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 10_001, 42, Arc::clone(&logger)) {
+                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+               {
+                       // Now, attempt to route an exact amount we have should be fine.
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 10_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 1);
+                       let path = route.paths.last().unwrap();
+                       assert_eq!(path.len(), 2);
+                       assert_eq!(path.last().unwrap().pubkey, nodes[2]);
+                       assert_eq!(path.last().unwrap().fee_msat, 10_000);
+               }
+       }
+       #[test]
+       fn available_liquidity_last_hop_test() {
+               // Check that available liquidity properly limits the path even when only
+               // one of the latter hops is limited.
+               let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
+               let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
+               // Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
+               // {12, 13, 11} have the capacities of 100, {6} has a capacity of 50.
+               // Total capacity: 50 sats.
+               // Disable other potential paths.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 2,
+                       timestamp: 2,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 7,
+                       timestamp: 2,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Limit capacities
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 12,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 13,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 6,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(50_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 11,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               {
+                       // Attempt to route more than available results in a failure.
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3], None, &Vec::new(), 60_000, 42, Arc::clone(&logger)) {
+                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+               {
+                       // Now, attempt to route 49 sats (just a bit below the capacity).
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3], None, &Vec::new(), 49_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 1);
+                       let mut total_amount_paid_msat = 0;
+                       for path in &route.paths {
+                               assert_eq!(path.len(), 4);
+                               assert_eq!(path.last().unwrap().pubkey, nodes[3]);
+                               total_amount_paid_msat += path.last().unwrap().fee_msat;
+                       }
+                       assert_eq!(total_amount_paid_msat, 49_000);
+               }
+               {
+                       // Attempt to route an exact amount is also fine
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3], None, &Vec::new(), 50_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 1);
+                       let mut total_amount_paid_msat = 0;
+                       for path in &route.paths {
+                               assert_eq!(path.len(), 4);
+                               assert_eq!(path.last().unwrap().pubkey, nodes[3]);
+                               total_amount_paid_msat += path.last().unwrap().fee_msat;
+                       }
+                       assert_eq!(total_amount_paid_msat, 50_000);
+               }
+       }
+       #[test]
+       fn ignore_fee_first_hop_test() {
+               let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
+               let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
+               // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50).
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 1,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 1_000_000,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 3,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(50_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               {
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 50_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 1);
+                       let mut total_amount_paid_msat = 0;
+                       for path in &route.paths {
+                               assert_eq!(path.len(), 2);
+                               assert_eq!(path.last().unwrap().pubkey, nodes[2]);
+                               total_amount_paid_msat += path.last().unwrap().fee_msat;
+                       }
+                       assert_eq!(total_amount_paid_msat, 50_000);
+               }
+       }
+       #[test]
+       fn simple_mpp_route_test() {
+               let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
+               let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
+               // We need a route consisting of 3 paths:
+               // From our node to node2 via node0, node7, node1 (three paths one hop each).
+               // To achieve this, the amount being transferred should be around
+               // the total capacity of these 3 paths.
+               // First, we set limits on these (previously unlimited) channels.
+               // Their aggregate capacity will be 50 + 60 + 180 = 290 sats.
+               // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50).
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 1,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 3,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(50_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Path via node7 is channels {12, 13}. Limit them to 60 and 60 sats
+               // (total limit 60).
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 12,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(60_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 13,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(60_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Path via node1 is channels {2, 4}. Limit them to 200 and 180 sats
+               // (total capacity 180 sats).
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 2,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(200_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 4,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(180_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               {
+                       // Attempt to route more than available results in a failure.
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 300_000, 42, Arc::clone(&logger)) {
+                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+               {
+                       // Now, attempt to route 250 sats (just a bit below the capacity).
+                       // Our algorithm should provide us with these 3 paths.
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 250_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 3);
+                       let mut total_amount_paid_msat = 0;
+                       for path in &route.paths {
+                               assert_eq!(path.len(), 2);
+                               assert_eq!(path.last().unwrap().pubkey, nodes[2]);
+                               total_amount_paid_msat += path.last().unwrap().fee_msat;
+                       }
+                       assert_eq!(total_amount_paid_msat, 250_000);
+               }
+               {
+                       // Attempt to route an exact amount is also fine
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 290_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 3);
+                       let mut total_amount_paid_msat = 0;
+                       for path in &route.paths {
+                               assert_eq!(path.len(), 2);
+                               assert_eq!(path.last().unwrap().pubkey, nodes[2]);
+                               total_amount_paid_msat += path.last().unwrap().fee_msat;
+                       }
+                       assert_eq!(total_amount_paid_msat, 290_000);
+               }
+       }
+       #[test]
+       fn long_mpp_route_test() {
+               let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
+               let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
+               // We need a route consisting of 3 paths:
+               // From our node to node3 via {node0, node2}, {node7, node2, node4} and {node7, node2}.
+               // Note that these paths overlap (channels 5, 12, 13).
+               // We will route 300 sats.
+               // Each path will have 100 sats capacity, those channels which
+               // are used twice will have 200 sats capacity.
+               // Disable other potential paths.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 2,
+                       timestamp: 2,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 7,
+                       timestamp: 2,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Path via {node0, node2} is channels {1, 3, 5}.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 1,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 3,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Capacity of 200 sats because this channel will be used by 3rd path as well.
+               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 5,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(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
+               // are also used for 3rd path. 100 sats for the rest. Total capacity: 100 sats.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 12,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(200_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 13,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(200_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 6,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 11,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Path via {node7, node2} is channels {12, 13, 5}.
+               // We already limited them to 200 sats (they are used twice for 100 sats).
+               // Nothing to do here.
+               {
+                       // Attempt to route more than available results in a failure.
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3], None, &Vec::new(), 350_000, 42, Arc::clone(&logger)) {
+                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+               {
+                       // Now, attempt to route 300 sats (exact amount we can route).
+                       // Our algorithm should provide us with these 3 paths, 100 sats each.
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3], None, &Vec::new(), 300_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 3);
+                       let mut total_amount_paid_msat = 0;
+                       for path in &route.paths {
+                               assert_eq!(path.last().unwrap().pubkey, nodes[3]);
+                               total_amount_paid_msat += path.last().unwrap().fee_msat;
+                       }
+                       assert_eq!(total_amount_paid_msat, 300_000);
+               }
+       }
+       #[test]
+       fn mpp_cheaper_route_test() {
+               let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
+               let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
+               // This test checks that if we have two cheaper paths and one more expensive path,
+               // so that liquidity-wise any 2 of 3 combination is sufficient,
+               // two cheaper paths will be taken.
+               // These paths have equal available liquidity.
+               // We need a combination of 3 paths:
+               // From our node to node3 via {node0, node2}, {node7, node2, node4} and {node7, node2}.
+               // Note that these paths overlap (channels 5, 12, 13).
+               // Each path will have 100 sats capacity, those channels which
+               // are used twice will have 200 sats capacity.
+               // Disable other potential paths.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 2,
+                       timestamp: 2,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 7,
+                       timestamp: 2,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Path via {node0, node2} is channels {1, 3, 5}.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 1,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 3,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Capacity of 200 sats because this channel will be used by 3rd path as well.
+               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 5,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(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
+               // are also used for 3rd path. 100 sats for the rest. Total capacity: 100 sats.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 12,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(200_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 13,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(200_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 6,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 1_000,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 11,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Path via {node7, node2} is channels {12, 13, 5}.
+               // We already limited them to 200 sats (they are used twice for 100 sats).
+               // Nothing to do here.
+               {
+                       // Now, attempt to route 180 sats.
+                       // Our algorithm should provide us with these 2 paths.
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3], None, &Vec::new(), 180_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 2);
+                       let mut total_value_transferred_msat = 0;
+                       let mut total_paid_msat = 0;
+                       for path in &route.paths {
+                               assert_eq!(path.last().unwrap().pubkey, nodes[3]);
+                               total_value_transferred_msat += path.last().unwrap().fee_msat;
+                               for hop in path {
+                                       total_paid_msat += hop.fee_msat;
+                               }
+                       }
+                       // If we paid fee, this would be higher.
+                       assert_eq!(total_value_transferred_msat, 180_000);
+                       let total_fees_paid = total_paid_msat - total_value_transferred_msat;
+                       assert_eq!(total_fees_paid, 0);
+               }
+       }
+       #[test]
+       fn fees_on_mpp_route_test() {
+               // This test makes sure that MPP algorithm properly takes into account
+               // fees charged on the channels, by making the fees impactful:
+               // if the fee is not properly accounted for, the behavior is different.
+               let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
+               let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
+               // We need a route consisting of 2 paths:
+               // From our node to node3 via {node0, node2} and {node7, node2, node4}.
+               // We will route 200 sats, Each path will have 100 sats capacity.
+               // This test is not particularly stable: e.g.,
+               // there's a way to route via {node0, node2, node4}.
+               // It works while pathfinding is deterministic, but can be broken otherwise.
+               // It's fine to ignore this concern for now.
+               // Disable other potential paths.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 2,
+                       timestamp: 2,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 7,
+                       timestamp: 2,
+                       flags: 2,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Path via {node0, node2} is channels {1, 3, 5}.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 1,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 3,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 5,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(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,
+               // we'll add absolute fee of 150 sats paid for the use channel 6 (paid to node2 on channel 13).
+               // Since channel 12 allows to deliver only 250 sats to channel 13, channel 13 can transfer only
+               // 100 sats (and pay 150 sats in fees for the use of channel 6),
+               // so no matter how large are other channels,
+               // the whole path will be limited by 100 sats with just these 2 conditions:
+               // - channel 12 capacity is 250 sats
+               // - fee for channel 6 is 150 sats
+               // Let's test this by enforcing these 2 conditions and removing other limits.
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 12,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(250_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 13,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 6,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
+                       fee_base_msat: 150_000,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 11,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               {
+                       // Attempt to route more than available results in a failure.
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3], None, &Vec::new(), 210_000, 42, Arc::clone(&logger)) {
+                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+               {
+                       // Now, attempt to route 200 sats (exact amount we can route).
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3], None, &Vec::new(), 200_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 2);
+                       let mut total_amount_paid_msat = 0;
+                       for path in &route.paths {
+                               assert_eq!(path.last().unwrap().pubkey, nodes[3]);
+                               total_amount_paid_msat += path.last().unwrap().fee_msat;
+                       }
+                       assert_eq!(total_amount_paid_msat, 200_000);
+               }
+       }
+       #[test]
+       fn drop_lowest_channel_mpp_route_test() {
+               // This test checks that low-capacity channel is dropped when after
+               // path finding we realize that we found more capacity than we need.
+               let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
+               let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
+               // We need a route consisting of 3 paths:
+               // From our node to node2 via node0, node7, node1 (three paths one hop each).
+               // The first and the second paths should be sufficient, but the third should be
+               // cheaper, so that we select it but drop later.
+               // First, we set limits on these (previously unlimited) channels.
+               // Their aggregate capacity will be 50 + 60 + 20 = 130 sats.
+               // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50);
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 1,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(100_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 3,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(50_000),
+                       fee_base_msat: 100,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Path via node7 is channels {12, 13}. Limit them to 60 and 60 sats (total limit 60);
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 12,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(60_000),
+                       fee_base_msat: 100,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 13,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(60_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               // Path via node1 is channels {2, 4}. Limit them to 20 and 20 sats (total capacity 20 sats).
+               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 2,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(20_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 4,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: 0,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(20_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               {
+                       // Attempt to route more than available results in a failure.
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 150_000, 42, Arc::clone(&logger)) {
+                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+               {
+                       // Now, attempt to route 125 sats (just a bit below the capacity of 3 channels).
+                       // Our algorithm should provide us with these 3 paths.
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 125_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 3);
+                       let mut total_amount_paid_msat = 0;
+                       for path in &route.paths {
+                               assert_eq!(path.len(), 2);
+                               assert_eq!(path.last().unwrap().pubkey, nodes[2]);
+                               total_amount_paid_msat += path.last().unwrap().fee_msat;
+                       }
+                       assert_eq!(total_amount_paid_msat, 125_000);
+               }
+               {
+                       // Attempt to route without the last small cheap channel
+                       let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, &Vec::new(), 90_000, 42, Arc::clone(&logger)).unwrap();
+                       assert_eq!(route.paths.len(), 2);
+                       let mut total_amount_paid_msat = 0;
+                       for path in &route.paths {
+                               assert_eq!(path.len(), 2);
+                               assert_eq!(path.last().unwrap().pubkey, nodes[2]);
+                               total_amount_paid_msat += path.last().unwrap().fee_msat;
+                       }
+                       assert_eq!(total_amount_paid_msat, 90_000);
+               }
+       }
  }
 +
 +#[cfg(all(test, feature = "unstable"))]
 +mod benches {
 +      use super::*;
 +      use util::logger::{Logger, Record};
 +
 +      use std::fs::File;
 +      use test::Bencher;
 +
 +      struct DummyLogger {}
 +      impl Logger for DummyLogger {
 +              fn log(&self, _record: &Record) {}
 +      }
 +
 +      #[bench]
 +      fn generate_routes(bench: &mut Bencher) {
 +              let mut d = File::open("net_graph-2021-02-12.bin").expect("Please fetch https://bitcoin.ninja/ldk-net_graph-879e309c128-2020-02-12.bin and place it at lightning/net_graph-2021-02-12.bin");
 +              let graph = NetworkGraph::read(&mut d).unwrap();
 +
 +              // First, get 100 (source, destination) pairs for which route-getting actually succeeds...
 +              let mut path_endpoints = Vec::new();
 +              let mut seed: usize = 0xdeadbeef;
 +              'load_endpoints: for _ in 0..100 {
 +                      loop {
 +                              seed *= 0xdeadbeef;
 +                              let src = graph.get_nodes().keys().skip(seed % graph.get_nodes().len()).next().unwrap();
 +                              seed *= 0xdeadbeef;
 +                              let dst = graph.get_nodes().keys().skip(seed % graph.get_nodes().len()).next().unwrap();
 +                              let amt = seed as u64 % 1_000_000;
 +                              if get_route(src, &graph, dst, None, &[], amt, 42, &DummyLogger{}).is_ok() {
 +                                      path_endpoints.push((src, dst, amt));
 +                                      continue 'load_endpoints;
 +                              }
 +                      }
 +              }
 +
 +              // ...then benchmark finding paths between the nodes we learned.
 +              let mut idx = 0;
 +              bench.iter(|| {
 +                      let (src, dst, amt) = path_endpoints[idx % path_endpoints.len()];
 +                      assert!(get_route(src, &graph, dst, None, &[], amt, 42, &DummyLogger{}).is_ok());
 +                      idx += 1;
 +              });
 +      }
 +}