( $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,
+ }
}
}
}
use ln::router::{Router,NodeInfo,NetworkMap,ChannelInfo,DirectionalChannelInfo,RouteHint};
use ln::msgs::GlobalFeatures;
- use bitcoin::util::misc::hex_bytes;
use bitcoin::util::hash::Sha256dHash;
+ use hex;
+
use secp256k1::key::{PublicKey,SecretKey};
use secp256k1::Secp256k1;
#[test]
fn route_test() {
let secp_ctx = Secp256k1::new();
- let our_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap()).unwrap();
+ let our_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap()).unwrap();
let router = Router::new(our_id);
// Build network from our_id to node8:
// chan11 1-to-2: enabled, 0 fee
// chan11 2-to-1: enabled, 0 fee
- let node1 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0202020202020202020202020202020202020202020202020202020202020202").unwrap()[..]).unwrap()).unwrap();
- let node2 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0303030303030303030303030303030303030303030303030303030303030303").unwrap()[..]).unwrap()).unwrap();
- let node3 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0404040404040404040404040404040404040404040404040404040404040404").unwrap()[..]).unwrap()).unwrap();
- let node4 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0505050505050505050505050505050505050505050505050505050505050505").unwrap()[..]).unwrap()).unwrap();
- let node5 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0606060606060606060606060606060606060606060606060606060606060606").unwrap()[..]).unwrap()).unwrap();
- let node6 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0707070707070707070707070707070707070707070707070707070707070707").unwrap()[..]).unwrap()).unwrap();
- let node7 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0808080808080808080808080808080808080808080808080808080808080808").unwrap()[..]).unwrap()).unwrap();
- let node8 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0909090909090909090909090909090909090909090909090909090909090909").unwrap()[..]).unwrap()).unwrap();
+ let node1 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0202020202020202020202020202020202020202020202020202020202020202").unwrap()[..]).unwrap()).unwrap();
+ let node2 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0303030303030303030303030303030303030303030303030303030303030303").unwrap()[..]).unwrap()).unwrap();
+ let node3 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0404040404040404040404040404040404040404040404040404040404040404").unwrap()[..]).unwrap()).unwrap();
+ let node4 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0505050505050505050505050505050505050505050505050505050505050505").unwrap()[..]).unwrap()).unwrap();
+ let node5 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0606060606060606060606060606060606060606060606060606060606060606").unwrap()[..]).unwrap()).unwrap();
+ let node6 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0707070707070707070707070707070707070707070707070707070707070707").unwrap()[..]).unwrap()).unwrap();
+ let node7 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0808080808080808080808080808080808080808080808080808080808080808").unwrap()[..]).unwrap()).unwrap();
+ let node8 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0909090909090909090909090909090909090909090909090909090909090909").unwrap()[..]).unwrap()).unwrap();
let zero_hash = Sha256dHash::from_data(&[0; 32]);