Skip to content

Commit

Permalink
Refactor find_route for precise channel balance info
Browse files Browse the repository at this point in the history
  • Loading branch information
contrun committed Nov 6, 2024
1 parent 581cc25 commit 0a6a584
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 35 deletions.
145 changes: 111 additions & 34 deletions src/fiber/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,64 @@ pub struct ChannelUpdateInfo {
pub last_update_message: ChannelUpdate,
}

// All the channel information for a inbound payment.
pub struct InboundChannelInfo<'a> {
pub from: Pubkey,
pub capacity: u128,
pub udt_type_script: &'a Option<Script>,
pub channel_outpoint: OutPoint,
/// Directed information about a channel that is public and can be used for routing.
/// We normally get this information from the broadcasted channel update messages.
/// It normally contains imprecise information about the channel (e.g. the balance of
/// one party in a channel is not known, only the total capacity of the channel is known).
pub struct PublicChannelInfo {
// We may (if, for example, we own the channel) or we may not know the exact balance of the channel.
pub liquidity_info: LiquidityInfo,
pub htlc_expiry_delta: u64,
pub htlc_minimum_value: u128,
pub htlc_maximum_value: u128,
pub fee_rate: u64,
}

/// Directed information about a channel that is private and cannot be used for routing.
/// This channel is normally owned by the node itself and is used for receiving payments.
pub struct PrivateChannelInfo {
/// The precise balance of the channel.
pub balance: u128,
}

/// Directed information about a channel that can be either public or private.
pub enum PublicOrPrivateChannelInfo {
Public(PublicChannelInfo),
Private(PrivateChannelInfo),
}

/// All the channel information for a payment from `from` to `to`.
pub struct DirectedChannelInfo {
pub from: Pubkey,
pub to: Pubkey,
pub udt_type_script: Option<Script>,
pub channel_outpoint: OutPoint,
pub channel_info: PublicOrPrivateChannelInfo,
}

/// The liquidity (with direction) of a channel. This may be the upper bound of the liquidity of the channel
/// (normally obtained from broadcasted channel capacity) or the precise liquidity of the channel
/// (normally we get this information because this is a channel owned by ourselves).
#[derive(Debug)]
pub enum LiquidityInfo {
/// The upper bound of the liquidity of the channel. This is the maximum amount that can be sent through the channel.
/// Normally we can only send a fraction of this amount through the channel. This amount is normally obtained from
/// the channel update messages.
UpperBound(u128),
/// The precise liquidity of the channel. It is guaranteed that a payment of this amount can be sent through the channel.
/// We know this amount because we own the channel and we know the exact balance of the channel.
Precise(u128),
}

impl LiquidityInfo {
pub fn upper_bound(&self) -> u128 {
match self {
LiquidityInfo::UpperBound(upper_bound) => *upper_bound,
LiquidityInfo::Precise(precise) => *precise,
}
}
}

#[derive(Clone, Debug)]
pub struct NetworkGraph<S> {
source: Pubkey,
Expand Down Expand Up @@ -436,37 +482,43 @@ where
self.chain_hash == chain_hash
}

pub fn get_node_inbounds<'a>(
&'a self,
pub fn get_inbound_channel_info(
&self,
node_id: Pubkey,
) -> impl Iterator<Item = InboundChannelInfo<'a>> {
) -> impl Iterator<Item = DirectedChannelInfo> + '_ {
self.channels.values().filter_map(move |channel| {
if let Some(info) = channel.node1_to_node2.as_ref() {
if info.enabled && channel.node2() == node_id {
return Some(InboundChannelInfo {
return Some(DirectedChannelInfo {
from: channel.node1(),
capacity: channel.capacity(),
udt_type_script: &channel.announcement_msg.udt_type_script,
to: node_id,
udt_type_script: channel.announcement_msg.udt_type_script.clone(),
channel_outpoint: channel.out_point(),
htlc_expiry_delta: info.htlc_expiry_delta,
htlc_minimum_value: info.htlc_minimum_value,
htlc_maximum_value: info.htlc_maximum_value,
fee_rate: info.fee_rate,
channel_info: PublicOrPrivateChannelInfo::Public(PublicChannelInfo {
liquidity_info: LiquidityInfo::UpperBound(channel.capacity()),
htlc_expiry_delta: info.htlc_expiry_delta,
htlc_minimum_value: info.htlc_minimum_value,
htlc_maximum_value: info.htlc_maximum_value,
fee_rate: info.fee_rate,
}),
});
}
}

if let Some(info) = channel.node2_to_node1.as_ref() {
if info.enabled && channel.node1() == node_id {
return Some(InboundChannelInfo {
return Some(DirectedChannelInfo {
from: channel.node2(),
capacity: channel.capacity(),
udt_type_script: &channel.announcement_msg.udt_type_script,
to: node_id,
udt_type_script: channel.announcement_msg.udt_type_script.clone(),
channel_outpoint: channel.out_point(),
htlc_expiry_delta: info.htlc_expiry_delta,
htlc_minimum_value: info.htlc_minimum_value,
htlc_maximum_value: info.htlc_maximum_value,
fee_rate: info.fee_rate,
channel_info: PublicOrPrivateChannelInfo::Public(PublicChannelInfo {
liquidity_info: LiquidityInfo::UpperBound(channel.capacity()),
htlc_expiry_delta: info.htlc_expiry_delta,
htlc_minimum_value: info.htlc_minimum_value,
htlc_maximum_value: info.htlc_maximum_value,
fee_rate: info.fee_rate,
}),
});
}
}
Expand Down Expand Up @@ -670,20 +722,45 @@ where
while let Some(cur_hop) = nodes_heap.pop() {
nodes_visited += 1;

for inbound_channel_info in self.get_node_inbounds(cur_hop.node_id) {
for inbound_channel_info in self.get_inbound_channel_info(cur_hop.node_id) {
let from = inbound_channel_info.from;
let capacity = inbound_channel_info.capacity;
let channel_outpoint = inbound_channel_info.channel_outpoint;
let htlc_expiry_delta = inbound_channel_info.htlc_expiry_delta;
let htlc_minimum_value = inbound_channel_info.htlc_minimum_value;
let htlc_maximum_value = inbound_channel_info.htlc_maximum_value;
let fee_rate = inbound_channel_info.fee_rate;
let (
liquidity_info,
htlc_expiry_delta,
htlc_minimum_value,
htlc_maximum_value,
fee_rate,
) = match inbound_channel_info.channel_info {
PublicOrPrivateChannelInfo::Private(PrivateChannelInfo {
balance: liquidity,
}) => {
// Since this is a private channel, and the target is not the destination of this channel,
// we should skip this channel. Otherwise, we are forwarding payment over a private channel.
if target != cur_hop.node_id {
debug!(
"Found a private channel to {:?}, but it is not the target {:?}. Since we shouldn't forward payment over private channel, skipping",
inbound_channel_info.to,
target
);
continue;
}
(LiquidityInfo::Precise(liquidity), 0, 0, 0, 0)
}
PublicOrPrivateChannelInfo::Public(channel_info) => (
channel_info.liquidity_info,
channel_info.htlc_expiry_delta,
channel_info.htlc_minimum_value,
channel_info.htlc_maximum_value,
channel_info.fee_rate,
),
};

if from == target && !route_to_self {
continue;
}
// if charge inbound fees for exit hop
if &udt_type_script != inbound_channel_info.udt_type_script {
if udt_type_script != inbound_channel_info.udt_type_script {
continue;
}

Expand All @@ -706,13 +783,13 @@ where
}
// check to make sure the current hop can send the amount
// if `htlc_maximum_value` equals 0, it means there is no limit
if amount_to_send > capacity
if amount_to_send > liquidity_info.upper_bound()
|| (htlc_maximum_value != 0 && amount_to_send > htlc_maximum_value)
{
debug!(
"amount_to_send is greater than channel capacity: {:?} capacity: {:?}, htlc_max_value: {:?}",
"amount_to_send is greater than the liquidity that can be provided: {:?} capacity: {:?}, htlc_max_value: {:?}",
amount_to_send,
capacity,
liquidity_info,
htlc_maximum_value
);
continue;
Expand All @@ -732,7 +809,7 @@ where
from,
cur_hop.node_id,
amount_to_send,
capacity,
liquidity_info,
);

if probability < DEFAULT_MIN_PROBABILITY {
Expand Down
3 changes: 2 additions & 1 deletion src/fiber/path.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ckb_types::packed::OutPoint;

use super::graph::LiquidityInfo;
use super::types::Pubkey;
use std::cmp::Ordering;
use std::collections::BinaryHeap;
Expand Down Expand Up @@ -112,7 +113,7 @@ impl ProbabilityEvaluator {
_from: Pubkey,
_to: Pubkey,
_amount_sent: u128,
_capacity: u128,
_liquidity_info: LiquidityInfo,
) -> f64 {
//FIXME(yukang): to because
return 0.5;
Expand Down
9 changes: 9 additions & 0 deletions src/fiber/tests/fee.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use crate::fiber::fee::calculate_tlc_forward_fee;

#[test]
fn test_zero_tlc_forward_fee() {
let amount = 1000;
let fee_proportational_millionths = 0;
let fee = calculate_tlc_forward_fee(amount, fee_proportational_millionths);
assert_eq!(fee, 0);
}
1 change: 1 addition & 0 deletions src/fiber/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod channel;
mod fee;
mod graph;
mod hash_algorithm;
mod network;
Expand Down

0 comments on commit 0a6a584

Please sign in to comment.