Skip to content

Commit 03bb808

Browse files
committed
Add methods to count total fees and total amount in a Route #999
* Added `get_total_fees` method to route, to calculate all the fees paid accross each path. * Added `get_total_amount` method to route, to calculate the total of actual amounts paid in each path.
1 parent 4368b56 commit 03bb808

File tree

1 file changed

+80
-1
lines changed

1 file changed

+80
-1
lines changed

lightning/src/routing/router.rs

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,26 @@ pub struct Route {
7171
pub paths: Vec<Vec<RouteHop>>,
7272
}
7373

74+
impl Route {
75+
/// Returns the total amount of fees paid on this Route.
76+
/// This doesn't include any extra payment made to the recipient,
77+
/// which can happen in excess of the amount passed to `get_route`'s `final_value_msat`.
78+
pub fn get_total_fees(&self) -> u64 {
79+
// Do not count last hop of each path since that's the full value of the payment
80+
return self.paths.iter()
81+
.flat_map(|path| path.split_last().unwrap().1)
82+
.map(|hop| &hop.fee_msat)
83+
.sum();
84+
}
85+
/// Returns the total amount paid on this Route, excluding the fees.
86+
pub fn get_total_amount(&self) -> u64 {
87+
return self.paths.iter()
88+
.map(|path| path.split_last().unwrap().0)
89+
.map(|hop| &hop.fee_msat)
90+
.sum();
91+
}
92+
}
93+
7494
const SERIALIZATION_VERSION: u8 = 1;
7595
const MIN_SERIALIZATION_VERSION: u8 = 1;
7696

@@ -1191,7 +1211,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
11911211

11921212
#[cfg(test)]
11931213
mod tests {
1194-
use routing::router::{get_route, Route, RouteHint, RouteHintHop, RoutingFees};
1214+
use routing::router::{get_route, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees};
11951215
use routing::network_graph::{NetworkGraph, NetGraphMsgHandler};
11961216
use chain::transaction::OutPoint;
11971217
use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
@@ -3425,6 +3445,7 @@ mod tests {
34253445
total_amount_paid_msat += path.last().unwrap().fee_msat;
34263446
}
34273447
assert_eq!(total_amount_paid_msat, 200_000);
3448+
assert_eq!(route.get_total_fees(), 150_000);
34283449
}
34293450

34303451
}
@@ -3831,6 +3852,64 @@ mod tests {
38313852
}
38323853
}
38333854

3855+
#[test]
3856+
fn total_fees_single_path() {
3857+
let route = Route {
3858+
paths: vec![vec![
3859+
RouteHop {
3860+
pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
3861+
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
3862+
short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
3863+
},
3864+
RouteHop {
3865+
pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
3866+
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
3867+
short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
3868+
},
3869+
RouteHop {
3870+
pubkey: PublicKey::from_slice(&hex::decode("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(),
3871+
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
3872+
short_channel_id: 0, fee_msat: 225, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
3873+
},
3874+
]],
3875+
};
3876+
3877+
assert_eq!(route.get_total_fees(), 250);
3878+
assert_eq!(route.get_total_amount(), 225);
3879+
}
3880+
3881+
#[test]
3882+
fn total_fees_multi_path() {
3883+
let route = Route {
3884+
paths: vec![vec![
3885+
RouteHop {
3886+
pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
3887+
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
3888+
short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
3889+
},
3890+
RouteHop {
3891+
pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
3892+
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
3893+
short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
3894+
},
3895+
],vec![
3896+
RouteHop {
3897+
pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
3898+
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
3899+
short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
3900+
},
3901+
RouteHop {
3902+
pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
3903+
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
3904+
short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
3905+
},
3906+
]],
3907+
};
3908+
3909+
assert_eq!(route.get_total_fees(), 200);
3910+
assert_eq!(route.get_total_amount(), 300);
3911+
}
3912+
38343913
#[cfg(not(feature = "no-std"))]
38353914
pub(super) fn random_init_seed() -> u64 {
38363915
// Because the default HashMap in std pulls OS randomness, we can use it as a (bad) RNG.

0 commit comments

Comments
 (0)