Skip to content

Commit 7b457e0

Browse files
Add utilities for getting a path's final value and cltv delta
1 parent 51b4555 commit 7b457e0

File tree

4 files changed

+59
-37
lines changed

4 files changed

+59
-37
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6895,7 +6895,7 @@ impl Readable for HTLCSource {
68956895
let path = path.unwrap();
68966896
if let Some(params) = payment_params.as_mut() {
68976897
if params.final_cltv_expiry_delta == 0 {
6898-
params.final_cltv_expiry_delta = path.last().unwrap().cltv_expiry_delta;
6898+
params.final_cltv_expiry_delta = path.final_cltv_expiry_delta();
68996899
}
69006900
}
69016901
Ok(HTLCSource::OutboundRoute {
@@ -7590,7 +7590,7 @@ where
75907590
return Err(DecodeError::InvalidValue);
75917591
}
75927592

7593-
let path_amt = path.last().unwrap().fee_msat;
7593+
let path_amt = path.final_value_msat();
75947594
let mut session_priv_bytes = [0; 32];
75957595
session_priv_bytes[..].copy_from_slice(&session_priv[..]);
75967596
match pending_outbounds.pending_outbound_payments.lock().unwrap().entry(payment_id) {
@@ -7600,7 +7600,7 @@ where
76007600
if newly_added { "Added" } else { "Had" }, path_amt, log_bytes!(session_priv_bytes), log_bytes!(htlc.payment_hash.0));
76017601
},
76027602
hash_map::Entry::Vacant(entry) => {
7603-
let path_fee = path.get_path_fees();
7603+
let path_fee = path.fee_msat();
76047604
entry.insert(PendingOutboundPayment::Retryable {
76057605
retry_strategy: None,
76067606
attempts: PaymentAttempts::new(),

lightning/src/ln/outbound_payment.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,9 @@ impl PendingOutboundPayment {
171171
if remove_res {
172172
if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self {
173173
let path = path.expect("Fulfilling a payment should always come with a path");
174-
let path_last_hop = path.last().expect("Outbound payments must have had a valid path");
175-
*pending_amt_msat -= path_last_hop.fee_msat;
174+
*pending_amt_msat -= path.final_value_msat();
176175
if let Some(fee_msat) = pending_fee_msat.as_mut() {
177-
*fee_msat -= path.get_path_fees();
176+
*fee_msat -= path.fee_msat();
178177
}
179178
}
180179
}
@@ -192,10 +191,9 @@ impl PendingOutboundPayment {
192191
};
193192
if insert_res {
194193
if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self {
195-
let path_last_hop = path.last().expect("Outbound payments must have had a valid path");
196-
*pending_amt_msat += path_last_hop.fee_msat;
194+
*pending_amt_msat += path.final_value_msat();
197195
if let Some(fee_msat) = pending_fee_msat.as_mut() {
198-
*fee_msat += path.get_path_fees();
196+
*fee_msat += path.fee_msat();
199197
}
200198
}
201199
}
@@ -723,7 +721,7 @@ impl OutboundPayments {
723721
PendingOutboundPayment::Retryable {
724722
total_msat, keysend_preimage, payment_secret, pending_amt_msat, ..
725723
} => {
726-
let retry_amt_msat: u64 = route.paths.iter().map(|path| path.last().unwrap().fee_msat).sum();
724+
let retry_amt_msat = route.get_total_amount();
727725
if retry_amt_msat + *pending_amt_msat > *total_msat * (100 + RETRY_OVERFLOW_PERCENTAGE) / 100 {
728726
log_error!(logger, "retry_amt_msat of {} will put pending_amt_msat (currently: {}) more than 10% over total_payment_amt_msat of {}", retry_amt_msat, pending_amt_msat, total_msat);
729727
abandon_with_entry!(payment, PaymentFailureReason::UnexpectedError);
@@ -961,7 +959,7 @@ impl OutboundPayments {
961959
continue 'path_check;
962960
}
963961
}
964-
total_value += path.last().unwrap().fee_msat;
962+
total_value += path.final_value_msat();
965963
path_errs.push(Ok(()));
966964
}
967965
if path_errs.iter().any(|e| e.is_err()) {
@@ -1009,7 +1007,7 @@ impl OutboundPayments {
10091007
has_err = true;
10101008
has_ok = true;
10111009
} else if res.is_err() {
1012-
pending_amt_unsent += path.last().unwrap().fee_msat;
1010+
pending_amt_unsent += path.final_value_msat();
10131011
}
10141012
}
10151013
if has_err && has_ok {

lightning/src/routing/router.rs

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -261,17 +261,43 @@ pub struct Route {
261261
pub payment_params: Option<PaymentParameters>,
262262
}
263263

264+
// This trait is deleted in the next commit
264265
pub(crate) trait RoutePath {
265266
/// Gets the fees for a given path, excluding any excess paid to the recipient.
266-
fn get_path_fees(&self) -> u64;
267+
fn fee_msat(&self) -> u64;
268+
269+
/// Gets the total amount paid on this path, excluding the fees.
270+
fn final_value_msat(&self) -> u64;
271+
272+
/// Gets the final hop's CLTV expiry delta.
273+
fn final_cltv_expiry_delta(&self) -> u32;
267274
}
268275
impl RoutePath for Vec<RouteHop> {
269-
fn get_path_fees(&self) -> u64 {
276+
fn fee_msat(&self) -> u64 {
270277
// Do not count last hop of each path since that's the full value of the payment
271278
self.split_last().map(|(_, path_prefix)| path_prefix).unwrap_or(&[])
272279
.iter().map(|hop| &hop.fee_msat)
273280
.sum()
274281
}
282+
fn final_value_msat(&self) -> u64 {
283+
self.last().map_or(0, |hop| hop.fee_msat)
284+
}
285+
fn final_cltv_expiry_delta(&self) -> u32 {
286+
self.last().map_or(0, |hop| hop.cltv_expiry_delta)
287+
}
288+
}
289+
impl RoutePath for &[&RouteHop] {
290+
fn fee_msat(&self) -> u64 {
291+
self.split_last().map(|(_, path_prefix)| path_prefix).unwrap_or(&[])
292+
.iter().map(|hop| &hop.fee_msat)
293+
.sum()
294+
}
295+
fn final_value_msat(&self) -> u64 {
296+
self.last().map_or(0, |hop| hop.fee_msat)
297+
}
298+
fn final_cltv_expiry_delta(&self) -> u32 {
299+
self.last().map_or(0, |hop| hop.cltv_expiry_delta)
300+
}
275301
}
276302

277303
impl Route {
@@ -280,15 +306,13 @@ impl Route {
280306
/// This doesn't include any extra payment made to the recipient, which can happen in excess of
281307
/// the amount passed to [`find_route`]'s `params.final_value_msat`.
282308
pub fn get_total_fees(&self) -> u64 {
283-
self.paths.iter().map(|path| path.get_path_fees()).sum()
309+
self.paths.iter().map(|path| path.fee_msat()).sum()
284310
}
285311

286312
/// Returns the total amount paid on this [`Route`], excluding the fees. Might be more than
287313
/// requested if we had to reach htlc_minimum_msat.
288314
pub fn get_total_amount(&self) -> u64 {
289-
return self.paths.iter()
290-
.map(|path| path.split_last().map(|(hop, _)| hop.fee_msat).unwrap_or(0))
291-
.sum();
315+
return self.paths.iter().map(|path|path.final_value_msat()).sum()
292316
}
293317
}
294318

@@ -2183,7 +2207,7 @@ mod tests {
21832207
use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, EffectiveCapacity};
21842208
use crate::routing::utxo::UtxoResult;
21852209
use crate::routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features,
2186-
PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees,
2210+
PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, RoutePath,
21872211
DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE};
21882212
use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
21892213
use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
@@ -3487,7 +3511,7 @@ mod tests {
34873511
let path = route.paths.last().unwrap();
34883512
assert_eq!(path.len(), 2);
34893513
assert_eq!(path.last().unwrap().pubkey, nodes[2]);
3490-
assert_eq!(path.last().unwrap().fee_msat, 250_000_000);
3514+
assert_eq!(path.final_value_msat(), 250_000_000);
34913515
}
34923516

34933517
// Check that setting next_outbound_htlc_limit_msat in first_hops limits the channels.
@@ -3523,7 +3547,7 @@ mod tests {
35233547
let path = route.paths.last().unwrap();
35243548
assert_eq!(path.len(), 2);
35253549
assert_eq!(path.last().unwrap().pubkey, nodes[2]);
3526-
assert_eq!(path.last().unwrap().fee_msat, 200_000_000);
3550+
assert_eq!(path.final_value_msat(), 200_000_000);
35273551
}
35283552

35293553
// Enable channel #1 back.
@@ -3570,7 +3594,7 @@ mod tests {
35703594
let path = route.paths.last().unwrap();
35713595
assert_eq!(path.len(), 2);
35723596
assert_eq!(path.last().unwrap().pubkey, nodes[2]);
3573-
assert_eq!(path.last().unwrap().fee_msat, 15_000);
3597+
assert_eq!(path.final_value_msat(), 15_000);
35743598
}
35753599

35763600
// Now let's see if routing works if we know only capacity from the UTXO.
@@ -3641,7 +3665,7 @@ mod tests {
36413665
let path = route.paths.last().unwrap();
36423666
assert_eq!(path.len(), 2);
36433667
assert_eq!(path.last().unwrap().pubkey, nodes[2]);
3644-
assert_eq!(path.last().unwrap().fee_msat, 15_000);
3668+
assert_eq!(path.final_value_msat(), 15_000);
36453669
}
36463670

36473671
// Now let's see if routing chooses htlc_maximum_msat over UTXO capacity.
@@ -3673,7 +3697,7 @@ mod tests {
36733697
let path = route.paths.last().unwrap();
36743698
assert_eq!(path.len(), 2);
36753699
assert_eq!(path.last().unwrap().pubkey, nodes[2]);
3676-
assert_eq!(path.last().unwrap().fee_msat, 10_000);
3700+
assert_eq!(path.final_value_msat(), 10_000);
36773701
}
36783702
}
36793703

@@ -3786,7 +3810,7 @@ mod tests {
37863810
for path in &route.paths {
37873811
assert_eq!(path.len(), 4);
37883812
assert_eq!(path.last().unwrap().pubkey, nodes[3]);
3789-
total_amount_paid_msat += path.last().unwrap().fee_msat;
3813+
total_amount_paid_msat += path.final_value_msat();
37903814
}
37913815
assert_eq!(total_amount_paid_msat, 49_000);
37923816
}
@@ -3799,7 +3823,7 @@ mod tests {
37993823
for path in &route.paths {
38003824
assert_eq!(path.len(), 4);
38013825
assert_eq!(path.last().unwrap().pubkey, nodes[3]);
3802-
total_amount_paid_msat += path.last().unwrap().fee_msat;
3826+
total_amount_paid_msat += path.final_value_msat();
38033827
}
38043828
assert_eq!(total_amount_paid_msat, 50_000);
38053829
}
@@ -3847,7 +3871,7 @@ mod tests {
38473871
for path in &route.paths {
38483872
assert_eq!(path.len(), 2);
38493873
assert_eq!(path.last().unwrap().pubkey, nodes[2]);
3850-
total_amount_paid_msat += path.last().unwrap().fee_msat;
3874+
total_amount_paid_msat += path.final_value_msat();
38513875
}
38523876
assert_eq!(total_amount_paid_msat, 50_000);
38533877
}
@@ -3993,7 +4017,7 @@ mod tests {
39934017
for path in &route.paths {
39944018
assert_eq!(path.len(), 2);
39954019
assert_eq!(path.last().unwrap().pubkey, nodes[2]);
3996-
total_amount_paid_msat += path.last().unwrap().fee_msat;
4020+
total_amount_paid_msat += path.final_value_msat();
39974021
}
39984022
assert_eq!(total_amount_paid_msat, 250_000);
39994023
}
@@ -4007,7 +4031,7 @@ mod tests {
40074031
for path in &route.paths {
40084032
assert_eq!(path.len(), 2);
40094033
assert_eq!(path.last().unwrap().pubkey, nodes[2]);
4010-
total_amount_paid_msat += path.last().unwrap().fee_msat;
4034+
total_amount_paid_msat += path.final_value_msat();
40114035
}
40124036
assert_eq!(total_amount_paid_msat, 290_000);
40134037
}
@@ -4171,7 +4195,7 @@ mod tests {
41714195
let mut total_amount_paid_msat = 0;
41724196
for path in &route.paths {
41734197
assert_eq!(path.last().unwrap().pubkey, nodes[3]);
4174-
total_amount_paid_msat += path.last().unwrap().fee_msat;
4198+
total_amount_paid_msat += path.final_value_msat();
41754199
}
41764200
assert_eq!(total_amount_paid_msat, 300_000);
41774201
}
@@ -4333,7 +4357,7 @@ mod tests {
43334357
let mut total_paid_msat = 0;
43344358
for path in &route.paths {
43354359
assert_eq!(path.last().unwrap().pubkey, nodes[3]);
4336-
total_value_transferred_msat += path.last().unwrap().fee_msat;
4360+
total_value_transferred_msat += path.final_value_msat();
43374361
for hop in path {
43384362
total_paid_msat += hop.fee_msat;
43394363
}
@@ -4510,7 +4534,7 @@ mod tests {
45104534
let mut total_amount_paid_msat = 0;
45114535
for path in &route.paths {
45124536
assert_eq!(path.last().unwrap().pubkey, nodes[3]);
4513-
total_amount_paid_msat += path.last().unwrap().fee_msat;
4537+
total_amount_paid_msat += path.final_value_msat();
45144538
}
45154539
assert_eq!(total_amount_paid_msat, 200_000);
45164540
assert_eq!(route.get_total_fees(), 150_000);
@@ -4737,7 +4761,7 @@ mod tests {
47374761
for path in &route.paths {
47384762
assert_eq!(path.len(), 2);
47394763
assert_eq!(path.last().unwrap().pubkey, nodes[2]);
4740-
total_amount_paid_msat += path.last().unwrap().fee_msat;
4764+
total_amount_paid_msat += path.final_value_msat();
47414765
}
47424766
assert_eq!(total_amount_paid_msat, 125_000);
47434767
}
@@ -4750,7 +4774,7 @@ mod tests {
47504774
for path in &route.paths {
47514775
assert_eq!(path.len(), 2);
47524776
assert_eq!(path.last().unwrap().pubkey, nodes[2]);
4753-
total_amount_paid_msat += path.last().unwrap().fee_msat;
4777+
total_amount_paid_msat += path.final_value_msat();
47544778
}
47554779
assert_eq!(total_amount_paid_msat, 90_000);
47564780
}

lightning/src/routing/scoring.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
5757
use crate::ln::msgs::DecodeError;
5858
use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId};
59-
use crate::routing::router::RouteHop;
59+
use crate::routing::router::{RouteHop, RoutePath};
6060
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
6161
use crate::util::logger::Logger;
6262
use crate::util::time::Time;
@@ -1234,7 +1234,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
12341234
}
12351235

12361236
fn payment_path_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) {
1237-
let amount_msat = path.split_last().map(|(hop, _)| hop.fee_msat).unwrap_or(0);
1237+
let amount_msat = path.final_value_msat();
12381238
log_trace!(self.logger, "Scoring path through to SCID {} as having failed at {} msat", short_channel_id, amount_msat);
12391239
let network_graph = self.network_graph.read_only();
12401240
for (hop_idx, hop) in path.iter().enumerate() {
@@ -1273,7 +1273,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
12731273
}
12741274

12751275
fn payment_path_successful(&mut self, path: &[&RouteHop]) {
1276-
let amount_msat = path.split_last().map(|(hop, _)| hop.fee_msat).unwrap_or(0);
1276+
let amount_msat = path.final_value_msat();
12771277
log_trace!(self.logger, "Scoring path through SCID {} as having succeeded at {} msat.",
12781278
path.split_last().map(|(hop, _)| hop.short_channel_id).unwrap_or(0), amount_msat);
12791279
let network_graph = self.network_graph.read_only();

0 commit comments

Comments
 (0)