Skip to content

Commit b12f984

Browse files
Add utilities for getting a path's final value and cltv delta
1 parent 48f5302 commit b12f984

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
@@ -7025,7 +7025,7 @@ impl Readable for HTLCSource {
70257025
let path = path.unwrap();
70267026
if let Some(params) = payment_params.as_mut() {
70277027
if params.final_cltv_expiry_delta == 0 {
7028-
params.final_cltv_expiry_delta = path.last().unwrap().cltv_expiry_delta;
7028+
params.final_cltv_expiry_delta = path.final_cltv_expiry_delta();
70297029
}
70307030
}
70317031
Ok(HTLCSource::OutboundRoute {
@@ -7725,7 +7725,7 @@ where
77257725
return Err(DecodeError::InvalidValue);
77267726
}
77277727

7728-
let path_amt = path.last().unwrap().fee_msat;
7728+
let path_amt = path.final_value_msat();
77297729
let mut session_priv_bytes = [0; 32];
77307730
session_priv_bytes[..].copy_from_slice(&session_priv[..]);
77317731
match pending_outbounds.pending_outbound_payments.lock().unwrap().entry(payment_id) {
@@ -7735,7 +7735,7 @@ where
77357735
if newly_added { "Added" } else { "Had" }, path_amt, log_bytes!(session_priv_bytes), log_bytes!(htlc.payment_hash.0));
77367736
},
77377737
hash_map::Entry::Vacant(entry) => {
7738-
let path_fee = path.get_path_fees();
7738+
let path_fee = path.fee_msat();
77397739
entry.insert(PendingOutboundPayment::Retryable {
77407740
retry_strategy: None,
77417741
attempts: PaymentAttempts::new(),

lightning/src/ln/outbound_payment.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,9 @@ impl PendingOutboundPayment {
172172
if remove_res {
173173
if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self {
174174
let path = path.expect("Fulfilling a payment should always come with a path");
175-
let path_last_hop = path.last().expect("Outbound payments must have had a valid path");
176-
*pending_amt_msat -= path_last_hop.fee_msat;
175+
*pending_amt_msat -= path.final_value_msat();
177176
if let Some(fee_msat) = pending_fee_msat.as_mut() {
178-
*fee_msat -= path.get_path_fees();
177+
*fee_msat -= path.fee_msat();
179178
}
180179
}
181180
}
@@ -193,10 +192,9 @@ impl PendingOutboundPayment {
193192
};
194193
if insert_res {
195194
if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self {
196-
let path_last_hop = path.last().expect("Outbound payments must have had a valid path");
197-
*pending_amt_msat += path_last_hop.fee_msat;
195+
*pending_amt_msat += path.final_value_msat();
198196
if let Some(fee_msat) = pending_fee_msat.as_mut() {
199-
*fee_msat += path.get_path_fees();
197+
*fee_msat += path.fee_msat();
200198
}
201199
}
202200
}
@@ -756,7 +754,7 @@ impl OutboundPayments {
756754
PendingOutboundPayment::Retryable {
757755
total_msat, keysend_preimage, payment_secret, payment_metadata, pending_amt_msat, ..
758756
} => {
759-
let retry_amt_msat: u64 = route.paths.iter().map(|path| path.last().unwrap().fee_msat).sum();
757+
let retry_amt_msat = route.get_total_amount();
760758
if retry_amt_msat + *pending_amt_msat > *total_msat * (100 + RETRY_OVERFLOW_PERCENTAGE) / 100 {
761759
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);
762760
abandon_with_entry!(payment, PaymentFailureReason::UnexpectedError);
@@ -1008,7 +1006,7 @@ impl OutboundPayments {
10081006
continue 'path_check;
10091007
}
10101008
}
1011-
total_value += path.last().unwrap().fee_msat;
1009+
total_value += path.final_value_msat();
10121010
path_errs.push(Ok(()));
10131011
}
10141012
if path_errs.iter().any(|e| e.is_err()) {
@@ -1056,7 +1054,7 @@ impl OutboundPayments {
10561054
has_err = true;
10571055
has_ok = true;
10581056
} else if res.is_err() {
1059-
pending_amt_unsent += path.last().unwrap().fee_msat;
1057+
pending_amt_unsent += path.final_value_msat();
10601058
}
10611059
}
10621060
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+
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)