X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Frouter.rs;h=aa1c3c1176c70e45d6db1b0a0ca903e2b7e470d0;hb=0882655680040a0226b1790b6558150324a288f4;hp=9f4b8ac3589a27ef7c713751eb1d98ad18596978;hpb=7b4b75301047b7c122fb1e893658384e726ec60c;p=rust-lightning diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 9f4b8ac3..aa1c3c11 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -24,7 +24,6 @@ use util::logger::Logger; use prelude::*; use alloc::collections::BinaryHeap; use core::cmp; -use std::collections::HashMap; use core::ops::Deref; /// A hop in a route @@ -50,13 +49,13 @@ pub struct RouteHop { } impl_writeable_tlv_based!(RouteHop, { - (0, pubkey), - (2, node_features), - (4, short_channel_id), - (6, channel_features), - (8, fee_msat), - (10, cltv_expiry_delta), -}, {}, {}); + (0, pubkey, required), + (2, node_features, required), + (4, short_channel_id, required), + (6, channel_features, required), + (8, fee_msat, required), + (10, cltv_expiry_delta, required), +}); /// A route directs a payment from the sender (us) to the recipient. If the recipient supports MPP, /// it can take multiple paths. Each path is composed of one or more hops through the network. @@ -84,7 +83,7 @@ impl Writeable for Route { hop.write(writer)?; } } - write_tlv_fields!(writer, {}, {}); + write_tlv_fields!(writer, {}); Ok(()) } } @@ -102,7 +101,7 @@ impl Readable for Route { } paths.push(hops); } - read_tlv_fields!(reader, {}, {}); + read_tlv_fields!(reader, {}); Ok(Route { paths }) } } @@ -169,7 +168,7 @@ struct DummyDirectionalChannelInfo { /// so that we can choose cheaper paths (as per Dijkstra's algorithm). /// Fee values should be updated only in the context of the whole path, see update_value_and_recompute_fees. /// These fee values are useful to choose hops as we traverse the graph "payee-to-payer". -#[derive(Clone)] +#[derive(Clone, Debug)] struct PathBuildingHop<'a> { // The RouteHintHop fields which will eventually be used if this hop is used in a final Route. // Note that node_features is calculated separately after our initial graph walk. @@ -507,6 +506,8 @@ pub fn get_route(our_node_id: &PublicKey, network: &NetworkGraph, paye // - when we want to stop looking for new paths. let mut already_collected_value_msat = 0; + log_trace!(logger, "Building path from {} (payee) to {} (us/payer) for value {} msat.", payee, our_node_id, final_value_msat); + macro_rules! add_entry { // Adds entry which goes from $src_node_id to $dest_node_id // over the channel with id $chan_id with fees described in @@ -892,6 +893,8 @@ pub fn get_route(our_node_id: &PublicKey, network: &NetworkGraph, paye } } + log_trace!(logger, "Starting main path collection loop with {} nodes pre-filled from first/last hops.", targets.len()); + // At this point, targets are filled with the data from first and // last hops communicated by the caller, and the payment receiver. let mut found_new_path = false; @@ -955,6 +958,9 @@ pub fn get_route(our_node_id: &PublicKey, network: &NetworkGraph, paye ordered_hops.last_mut().unwrap().0.hop_use_fee_msat = 0; ordered_hops.last_mut().unwrap().0.cltv_expiry_delta = final_cltv; + log_trace!(logger, "Found a path back to us from the target with {} hops contributing up to {} msat: {:?}", + ordered_hops.len(), value_contribution_msat, ordered_hops); + let mut payment_path = PaymentPath {hops: ordered_hops}; // We could have possibly constructed a slightly inconsistent path: since we reduce @@ -990,8 +996,9 @@ pub fn get_route(our_node_id: &PublicKey, network: &NetworkGraph, paye // If we weren't capped by hitting a liquidity limit on a channel in the path, // we'll probably end up picking the same path again on the next iteration. // Decrease the available liquidity of a hop in the middle of the path. - let victim_liquidity = bookkeeped_channels_liquidity_available_msat.get_mut( - &payment_path.hops[(payment_path.hops.len() - 1) / 2].0.short_channel_id).unwrap(); + let victim_scid = payment_path.hops[(payment_path.hops.len() - 1) / 2].0.short_channel_id; + log_trace!(logger, "Disabling channel {} for future path building iterations to avoid duplicates.", victim_scid); + let victim_liquidity = bookkeeped_channels_liquidity_available_msat.get_mut(&victim_scid).unwrap(); *victim_liquidity = 0; } @@ -1033,6 +1040,8 @@ pub fn get_route(our_node_id: &PublicKey, network: &NetworkGraph, paye // In the latter case, making another path finding attempt won't help, // because we deterministically terminated the search due to low liquidity. if already_collected_value_msat >= recommended_value_msat || !found_new_path { + log_trace!(logger, "Have now collected {} msat (seeking {} msat) in paths. Last path loop {} a new path.", + already_collected_value_msat, recommended_value_msat, if found_new_path { "found" } else { "did not find" }); break 'paths_collection; } else if found_new_path && already_collected_value_msat == final_value_msat && payment_paths.len() == 1 { // Further, if this was our first walk of the graph, and we weren't limited by an @@ -1041,8 +1050,10 @@ pub fn get_route(our_node_id: &PublicKey, network: &NetworkGraph, paye // potentially allowing us to pay fees to meet the htlc_minimum on the new path while // still keeping a lower total fee than this path. if !hit_minimum_limit { + log_trace!(logger, "Collected exactly our payment amount on the first pass, without hitting an htlc_minimum_msat limit, exiting."); break 'paths_collection; } + log_trace!(logger, "Collected our payment amount on the first pass, but running again to collect extra paths with a potentially higher limit."); path_value_msat = recommended_value_msat; } } @@ -1153,7 +1164,7 @@ pub fn get_route(our_node_id: &PublicKey, network: &NetworkGraph, paye } let route = Route { paths: selected_paths }; - log_trace!(logger, "Got route: {}", log_route!(route)); + log_info!(logger, "Got route to {}: {}", payee, log_route!(route)); Ok(route) } @@ -1631,6 +1642,10 @@ mod tests { user_id: 0, outbound_capacity_msat: 100000, inbound_capacity_msat: 100000, + to_self_reserve_satoshis: None, + to_remote_reserve_satoshis: 0, + confirmations_required: None, + spend_csv_on_our_commitment_funds: None, is_outbound: true, is_funding_locked: true, is_usable: true, is_public: true, counterparty_forwarding_info: None, @@ -1951,6 +1966,10 @@ mod tests { user_id: 0, outbound_capacity_msat: 250_000_000, inbound_capacity_msat: 0, + to_self_reserve_satoshis: None, + to_remote_reserve_satoshis: 0, + confirmations_required: None, + spend_csv_on_our_commitment_funds: None, is_outbound: true, is_funding_locked: true, is_usable: true, is_public: true, counterparty_forwarding_info: None, @@ -2001,6 +2020,10 @@ mod tests { user_id: 0, outbound_capacity_msat: 250_000_000, inbound_capacity_msat: 0, + to_self_reserve_satoshis: None, + to_remote_reserve_satoshis: 0, + confirmations_required: None, + spend_csv_on_our_commitment_funds: None, is_outbound: true, is_funding_locked: true, is_usable: true, is_public: true, counterparty_forwarding_info: None, @@ -2068,6 +2091,10 @@ mod tests { user_id: 0, outbound_capacity_msat: 250_000_000, inbound_capacity_msat: 0, + to_self_reserve_satoshis: None, + to_remote_reserve_satoshis: 0, + confirmations_required: None, + spend_csv_on_our_commitment_funds: None, is_outbound: true, is_funding_locked: true, is_usable: true, is_public: true, counterparty_forwarding_info: None, @@ -2207,6 +2234,10 @@ mod tests { user_id: 0, outbound_capacity_msat: 250_000_000, inbound_capacity_msat: 0, + to_self_reserve_satoshis: None, + to_remote_reserve_satoshis: 0, + confirmations_required: None, + spend_csv_on_our_commitment_funds: None, is_outbound: true, is_funding_locked: true, is_usable: true, is_public: true, counterparty_forwarding_info: None, @@ -2338,6 +2369,10 @@ mod tests { user_id: 0, outbound_capacity_msat: 100000, inbound_capacity_msat: 100000, + to_self_reserve_satoshis: None, + to_remote_reserve_satoshis: 0, + confirmations_required: None, + spend_csv_on_our_commitment_funds: None, is_outbound: true, is_funding_locked: true, is_usable: true, is_public: true, counterparty_forwarding_info: None, @@ -2472,6 +2507,10 @@ mod tests { user_id: 0, outbound_capacity_msat: 200_000_000, inbound_capacity_msat: 0, + to_self_reserve_satoshis: None, + to_remote_reserve_satoshis: 0, + confirmations_required: None, + spend_csv_on_our_commitment_funds: None, is_outbound: true, is_funding_locked: true, is_usable: true, is_public: true, counterparty_forwarding_info: None, @@ -3843,6 +3882,7 @@ mod tests { } } + #[cfg(not(feature = "no_std"))] pub(super) fn random_init_seed() -> u64 { // Because the default HashMap in std pulls OS randomness, we can use it as a (bad) RNG. use core::hash::{BuildHasher, Hasher}; @@ -3850,9 +3890,11 @@ mod tests { println!("Using seed of {}", seed); seed } + #[cfg(not(feature = "no_std"))] use util::ser::Readable; #[test] + #[cfg(not(feature = "no_std"))] fn generate_routes() { let mut d = match super::test_utils::get_route_file() { Ok(f) => f, @@ -3880,6 +3922,7 @@ mod tests { } #[test] + #[cfg(not(feature = "no_std"))] fn generate_routes_mpp() { let mut d = match super::test_utils::get_route_file() { Ok(f) => f, @@ -3907,7 +3950,7 @@ mod tests { } } -#[cfg(test)] +#[cfg(all(test, not(feature = "no_std")))] pub(crate) mod test_utils { use std::fs::File; /// Tries to open a network graph file, or panics with a URL to fetch it. @@ -3934,7 +3977,7 @@ pub(crate) mod test_utils { } } -#[cfg(all(test, feature = "unstable"))] +#[cfg(all(test, feature = "unstable", not(feature = "no_std")))] mod benches { use super::*; use util::logger::{Logger, Record};