X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Frouter.rs;h=23360d74b62e8a304b8203e454dc9bc52a0b1831;hb=refs%2Fheads%2F2018-07-announce-bug;hp=9e3272c13e260dc565eb2e6fe6935e674e6bbcaf;hpb=fa9715dccf3ac3a151a910f2c825a599d1503312;p=rust-lightning diff --git a/src/ln/router.rs b/src/ln/router.rs index 9e3272c1..23360d74 100644 --- a/src/ln/router.rs +++ b/src/ln/router.rs @@ -21,7 +21,7 @@ pub struct RouteHop { /// The fee taken on this hop. For the last hop, this should be the full value of the payment. pub fee_msat: u64, /// The CLTV delta added for this hop. For the last hop, this should be the full CLTV value - /// expected at the destination, NOT a delta. + /// expected at the destination, in excess of the current block height. pub cltv_expiry_delta: u32, } @@ -403,7 +403,18 @@ impl Router { let mut first_hop_targets = HashMap::with_capacity(if first_hops.is_some() { first_hops.as_ref().unwrap().len() } else { 0 }); if let Some(hops) = first_hops { for chan in hops { - first_hop_targets.insert(chan.remote_network_id, chan.short_channel_id.expect("first_hops should be filled in with usable channels, not pending ones")); + let short_channel_id = chan.short_channel_id.expect("first_hops should be filled in with usable channels, not pending ones"); + if chan.remote_network_id == *target { + return Ok(Route { + hops: vec![RouteHop { + pubkey: chan.remote_network_id, + short_channel_id, + fee_msat: final_value_msat, + cltv_expiry_delta: final_cltv, + }], + }); + } + first_hop_targets.insert(chan.remote_network_id, short_channel_id); } if first_hop_targets.is_empty() { return Err(HandleError{err: "Cannot route when there are no outbound routes away from us", action: None}); @@ -417,39 +428,43 @@ impl Router { ( $chan_id: expr, $dest_node_id: expr, $directional_info: expr, $starting_fee_msat: expr ) => { //TODO: Explore simply adding fee to hit htlc_minimum_msat if $starting_fee_msat as u64 + final_value_msat > $directional_info.htlc_minimum_msat { - let new_fee = $directional_info.fee_base_msat as u64 + ($starting_fee_msat + final_value_msat) * ($directional_info.fee_proportional_millionths as u64) / 1000000; - let mut total_fee = $starting_fee_msat as u64; - let mut hm_entry = dist.entry(&$directional_info.src_node_id); - let old_entry = hm_entry.or_insert_with(|| { - let node = network.nodes.get(&$directional_info.src_node_id).unwrap(); - (u64::max_value(), - node.lowest_inbound_channel_fee_base_msat as u64, - node.lowest_inbound_channel_fee_proportional_millionths as u64, - RouteHop { - pubkey: PublicKey::new(), - short_channel_id: 0, - fee_msat: 0, - cltv_expiry_delta: 0, - }) - }); - if $directional_info.src_node_id != network.our_node_id { - // Ignore new_fee for channel-from-us as we assume all channels-from-us - // will have the same effective-fee - total_fee += new_fee; - total_fee += old_entry.2 * (final_value_msat + total_fee) / 1000000 + old_entry.1; - } - let new_graph_node = RouteGraphNode { - pubkey: $directional_info.src_node_id, - lowest_fee_to_peer_through_node: total_fee, - }; - if old_entry.0 > total_fee { - targets.push(new_graph_node); - old_entry.0 = total_fee; - old_entry.3 = RouteHop { - pubkey: $dest_node_id.clone(), - short_channel_id: $chan_id.clone(), - fee_msat: new_fee, // This field is ignored on the last-hop anyway - cltv_expiry_delta: $directional_info.cltv_expiry_delta as u32, + let proportional_fee_millions = ($starting_fee_msat + final_value_msat).checked_mul($directional_info.fee_proportional_millionths as u64); + if let Some(new_fee) = proportional_fee_millions.and_then(|part| { + ($directional_info.fee_base_msat as u64).checked_add(part / 1000000) }) + { + let mut total_fee = $starting_fee_msat as u64; + let hm_entry = dist.entry(&$directional_info.src_node_id); + let old_entry = hm_entry.or_insert_with(|| { + let node = network.nodes.get(&$directional_info.src_node_id).unwrap(); + (u64::max_value(), + node.lowest_inbound_channel_fee_base_msat as u64, + node.lowest_inbound_channel_fee_proportional_millionths as u64, + RouteHop { + pubkey: PublicKey::new(), + short_channel_id: 0, + fee_msat: 0, + cltv_expiry_delta: 0, + }) + }); + if $directional_info.src_node_id != network.our_node_id { + // Ignore new_fee for channel-from-us as we assume all channels-from-us + // will have the same effective-fee + total_fee += new_fee; + total_fee += old_entry.2 * (final_value_msat + total_fee) / 1000000 + old_entry.1; + } + let new_graph_node = RouteGraphNode { + pubkey: $directional_info.src_node_id, + lowest_fee_to_peer_through_node: total_fee, + }; + if old_entry.0 > total_fee { + targets.push(new_graph_node); + old_entry.0 = total_fee; + old_entry.3 = RouteHop { + pubkey: $dest_node_id.clone(), + short_channel_id: $chan_id.clone(), + fee_msat: new_fee, // This field is ignored on the last-hop anyway + cltv_expiry_delta: $directional_info.cltv_expiry_delta as u32, + } } } }