Skip to content

Commit 84ffb4c

Browse files
Add Path struct and use it everywhere instead of Vec<RouteHop>
1 parent 2e82123 commit 84ffb4c

17 files changed

+799
-697
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use lightning::util::errors::APIError;
5050
use lightning::util::logger::Logger;
5151
use lightning::util::config::UserConfig;
5252
use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer};
53-
use lightning::routing::router::{InFlightHtlcs, Route, RouteHop, RouteParameters, Router};
53+
use lightning::routing::router::{InFlightHtlcs, Path, Route, RouteHop, RouteParameters, Router};
5454

5555
use crate::utils::test_logger::{self, Output};
5656
use crate::utils::test_persister::TestPersister;
@@ -352,14 +352,14 @@ fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, p
352352
payment_id[0..8].copy_from_slice(&payment_idx.to_ne_bytes());
353353
*payment_idx += 1;
354354
if let Err(err) = source.send_payment(&Route {
355-
paths: vec![vec![RouteHop {
355+
paths: vec![Path { hops: vec![RouteHop {
356356
pubkey: dest.get_our_node_id(),
357357
node_features: dest.node_features(),
358358
short_channel_id: dest_chan_id,
359359
channel_features: dest.channel_features(),
360360
fee_msat: amt,
361361
cltv_expiry_delta: 200,
362-
}]],
362+
}], blinded_tail: None }],
363363
payment_params: None,
364364
}, payment_hash, &Some(payment_secret), PaymentId(payment_id)) {
365365
check_payment_err(err);
@@ -374,7 +374,7 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
374374
payment_id[0..8].copy_from_slice(&payment_idx.to_ne_bytes());
375375
*payment_idx += 1;
376376
if let Err(err) = source.send_payment(&Route {
377-
paths: vec![vec![RouteHop {
377+
paths: vec![Path { hops: vec![RouteHop {
378378
pubkey: middle.get_our_node_id(),
379379
node_features: middle.node_features(),
380380
short_channel_id: middle_chan_id,
@@ -388,7 +388,7 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
388388
channel_features: dest.channel_features(),
389389
fee_msat: amt,
390390
cltv_expiry_delta: 200,
391-
}]],
391+
}], blinded_tail: None }],
392392
payment_params: None,
393393
}, payment_hash, &Some(payment_secret), PaymentId(payment_id)) {
394394
check_payment_err(err);

lightning-invoice/src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1173,7 +1173,7 @@ mod test {
11731173
nodes[fwd_idx].node.process_pending_htlc_forwards();
11741174

11751175
let payment_preimage_opt = if user_generated_pmt_hash { None } else { Some(payment_preimage) };
1176-
expect_payment_claimable!(&nodes[fwd_idx], payment_hash, payment_secret, payment_amt, payment_preimage_opt, route.paths[0].last().unwrap().pubkey);
1176+
expect_payment_claimable!(&nodes[fwd_idx], payment_hash, payment_secret, payment_amt, payment_preimage_opt, route.paths[0].hops.last().unwrap().pubkey);
11771177
do_claim_payment_along_route(&nodes[0], &[&vec!(&nodes[fwd_idx])[..]], false, payment_preimage);
11781178
let events = nodes[0].node.get_and_clear_pending_events();
11791179
assert_eq!(events.len(), 2);

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,12 +1974,12 @@ fn test_path_paused_mpp() {
19741974
// Set us up to take multiple routes, one 0 -> 1 -> 3 and one 0 -> 2 -> 3:
19751975
let path = route.paths[0].clone();
19761976
route.paths.push(path);
1977-
route.paths[0][0].pubkey = nodes[1].node.get_our_node_id();
1978-
route.paths[0][0].short_channel_id = chan_1_id;
1979-
route.paths[0][1].short_channel_id = chan_3_id;
1980-
route.paths[1][0].pubkey = nodes[2].node.get_our_node_id();
1981-
route.paths[1][0].short_channel_id = chan_2_ann.contents.short_channel_id;
1982-
route.paths[1][1].short_channel_id = chan_4_id;
1977+
route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id();
1978+
route.paths[0].hops[0].short_channel_id = chan_1_id;
1979+
route.paths[0].hops[1].short_channel_id = chan_3_id;
1980+
route.paths[1].hops[0].pubkey = nodes[2].node.get_our_node_id();
1981+
route.paths[1].hops[0].short_channel_id = chan_2_ann.contents.short_channel_id;
1982+
route.paths[1].hops[1].short_channel_id = chan_4_id;
19831983

19841984
// Set it so that the first monitor update (for the path 0 -> 1 -> 3) succeeds, but the second
19851985
// (for the path 0 -> 2 -> 3) fails.

lightning/src/ln/channel.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6977,6 +6977,7 @@ mod tests {
69776977
use crate::chain::chaininterface::{FeeEstimator, LowerBoundedFeeEstimator, ConfirmationTarget};
69786978
use crate::chain::keysinterface::{ChannelSigner, InMemorySigner, EntropySource, SignerProvider};
69796979
use crate::chain::transaction::OutPoint;
6980+
use crate::routing::router::Path;
69806981
use crate::util::config::UserConfig;
69816982
use crate::util::enforcing_trait_impls::EnforcingSigner;
69826983
use crate::util::errors::APIError;
@@ -7154,7 +7155,7 @@ mod tests {
71547155
cltv_expiry: 200000000,
71557156
state: OutboundHTLCState::Committed,
71567157
source: HTLCSource::OutboundRoute {
7157-
path: Vec::new(),
7158+
path: Path { hops: Vec::new(), blinded_tail: None },
71587159
session_priv: SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
71597160
first_hop_htlc_msat: 548,
71607161
payment_id: PaymentId([42; 32]),

lightning/src/ln/channelmanager.rs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, No
4545
#[cfg(any(feature = "_test_utils", test))]
4646
use crate::ln::features::InvoiceFeatures;
4747
use crate::routing::gossip::NetworkGraph;
48-
use crate::routing::router::{DefaultRouter, InFlightHtlcs, PaymentParameters, Route, RouteHop, RouteParameters, RoutePath, Router};
48+
use crate::routing::router::{BlindedTail, DefaultRouter, InFlightHtlcs, Path, PaymentParameters, Route, RouteHop, RouteParameters, Router};
4949
use crate::routing::scoring::ProbabilisticScorer;
5050
use crate::ln::msgs;
5151
use crate::ln::onion_utils;
@@ -280,7 +280,7 @@ impl_writeable_tlv_based_enum!(SentHTLCId,
280280
pub(crate) enum HTLCSource {
281281
PreviousHopData(HTLCPreviousHopData),
282282
OutboundRoute {
283-
path: Vec<RouteHop>,
283+
path: Path,
284284
session_priv: SecretKey,
285285
/// Technically we can recalculate this from the route, but we cache it here to avoid
286286
/// doing a double-pass on route when we get a failure back
@@ -313,7 +313,7 @@ impl core::hash::Hash for HTLCSource {
313313
impl HTLCSource {
314314
pub fn dummy() -> Self {
315315
HTLCSource::OutboundRoute {
316-
path: Vec::new(),
316+
path: Path { hops: Vec::new(), blinded_tail: None },
317317
session_priv: SecretKey::from_slice(&[1; 32]).unwrap(),
318318
first_hop_htlc_msat: 0,
319319
payment_id: PaymentId([2; 32]),
@@ -2513,16 +2513,16 @@ where
25132513
}
25142514

25152515
#[cfg(test)]
2516-
pub(crate) fn test_send_payment_along_path(&self, path: &Vec<RouteHop>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>, session_priv_bytes: [u8; 32]) -> Result<(), APIError> {
2516+
pub(crate) fn test_send_payment_along_path(&self, path: &Path, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>, session_priv_bytes: [u8; 32]) -> Result<(), APIError> {
25172517
let _lck = self.total_consistency_lock.read().unwrap();
25182518
self.send_payment_along_path(path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv_bytes)
25192519
}
25202520

2521-
fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>, session_priv_bytes: [u8; 32]) -> Result<(), APIError> {
2521+
fn send_payment_along_path(&self, path: &Path, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>, session_priv_bytes: [u8; 32]) -> Result<(), APIError> {
25222522
// The top-level caller should hold the total_consistency_lock read lock.
25232523
debug_assert!(self.total_consistency_lock.try_write().is_err());
25242524

2525-
log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.first().unwrap().short_channel_id);
2525+
log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.first_hop_scid());
25262526
let prng_seed = self.entropy_source.get_secure_random_bytes();
25272527
let session_priv = SecretKey::from_slice(&session_priv_bytes[..]).expect("RNG is busted");
25282528

@@ -2535,7 +2535,7 @@ where
25352535
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, prng_seed, payment_hash);
25362536

25372537
let err: Result<(), _> = loop {
2538-
let (counterparty_node_id, id) = match self.short_to_chan_info.read().unwrap().get(&path.first().unwrap().short_channel_id) {
2538+
let (counterparty_node_id, id) = match self.short_to_chan_info.read().unwrap().get(&path.first_hop_scid()) {
25392539
None => return Err(APIError::ChannelUnavailable{err: "No channel available with first hop!".to_owned()}),
25402540
Some((cp_id, chan_id)) => (cp_id.clone(), chan_id.clone()),
25412541
};
@@ -2587,7 +2587,7 @@ where
25872587
return Ok(());
25882588
};
25892589

2590-
match handle_error!(self, err, path.first().unwrap().pubkey) {
2590+
match handle_error!(self, err, path.first_hop_node_id()) {
25912591
Ok(_) => unreachable!(),
25922592
Err(e) => {
25932593
Err(APIError::ChannelUnavailable { err: e.err })
@@ -6902,23 +6902,25 @@ impl Readable for HTLCSource {
69026902
let mut payment_id = None;
69036903
let mut payment_secret = None;
69046904
let mut payment_params: Option<PaymentParameters> = None;
6905+
let mut blinded_tail: Option<BlindedTail> = None;
69056906
read_tlv_fields!(reader, {
69066907
(0, session_priv, required),
69076908
(1, payment_id, option),
69086909
(2, first_hop_htlc_msat, required),
69096910
(3, payment_secret, option),
69106911
(4, path, vec_type),
69116912
(5, payment_params, (option: ReadableArgs, 0)),
6913+
(6, blinded_tail, option),
69126914
});
69136915
if payment_id.is_none() {
69146916
// For backwards compat, if there was no payment_id written, use the session_priv bytes
69156917
// instead.
69166918
payment_id = Some(PaymentId(*session_priv.0.unwrap().as_ref()));
69176919
}
6918-
if path.is_none() || path.as_ref().unwrap().is_empty() {
6920+
let path = path.unwrap_or(Vec::new());
6921+
if path.is_empty() && blinded_tail.is_none() {
69196922
return Err(DecodeError::InvalidValue);
69206923
}
6921-
let path = path.unwrap();
69226924
if let Some(params) = payment_params.as_mut() {
69236925
if params.final_cltv_expiry_delta == 0 {
69246926
params.final_cltv_expiry_delta = path.last().unwrap().cltv_expiry_delta;
@@ -6927,7 +6929,7 @@ impl Readable for HTLCSource {
69276929
Ok(HTLCSource::OutboundRoute {
69286930
session_priv: session_priv.0.unwrap(),
69296931
first_hop_htlc_msat,
6930-
path,
6932+
path: Path { hops: path, blinded_tail },
69316933
payment_id: payment_id.unwrap(),
69326934
payment_secret,
69336935
})
@@ -6949,8 +6951,9 @@ impl Writeable for HTLCSource {
69496951
(1, payment_id_opt, option),
69506952
(2, first_hop_htlc_msat, required),
69516953
(3, payment_secret, option),
6952-
(4, *path, vec_type),
6954+
(4, path.hops, vec_type),
69536955
(5, None::<PaymentParameters>, option), // payment_params in LDK versions prior to 0.0.115
6956+
(6, path.blinded_tail, option),
69546957
});
69556958
}
69566959
HTLCSource::PreviousHopData(ref field) => {
@@ -7612,12 +7615,12 @@ where
76127615
if id_to_peer.get(&monitor.get_funding_txo().0.to_channel_id()).is_none() {
76137616
for (htlc_source, (htlc, _)) in monitor.get_pending_or_resolved_outbound_htlcs() {
76147617
if let HTLCSource::OutboundRoute { payment_id, session_priv, path, payment_secret, .. } = htlc_source {
7615-
if path.is_empty() {
7618+
if path.len() == 0 {
76167619
log_error!(args.logger, "Got an empty path for a pending payment");
76177620
return Err(DecodeError::InvalidValue);
76187621
}
76197622

7620-
let path_amt = path.last().unwrap().fee_msat;
7623+
let path_amt = path.final_value_msat();
76217624
let mut session_priv_bytes = [0; 32];
76227625
session_priv_bytes[..].copy_from_slice(&session_priv[..]);
76237626
match pending_outbounds.pending_outbound_payments.lock().unwrap().entry(payment_id) {
@@ -7627,7 +7630,7 @@ where
76277630
if newly_added { "Added" } else { "Had" }, path_amt, log_bytes!(session_priv_bytes), log_bytes!(htlc.payment_hash.0));
76287631
},
76297632
hash_map::Entry::Vacant(entry) => {
7630-
let path_fee = path.get_path_fees();
7633+
let path_fee = path.fee_msat();
76317634
entry.insert(PendingOutboundPayment::Retryable {
76327635
retry_strategy: None,
76337636
attempts: PaymentAttempts::new(),
@@ -8130,15 +8133,15 @@ mod tests {
81308133
Event::PaymentPathSuccessful { payment_id: ref actual_payment_id, ref payment_hash, ref path } => {
81318134
assert_eq!(payment_id, *actual_payment_id);
81328135
assert_eq!(our_payment_hash, *payment_hash.as_ref().unwrap());
8133-
assert_eq!(route.paths[0], *path);
8136+
assert_eq!(route.paths[0].hops, *path);
81348137
},
81358138
_ => panic!("Unexpected event"),
81368139
}
81378140
match events[2] {
81388141
Event::PaymentPathSuccessful { payment_id: ref actual_payment_id, ref payment_hash, ref path } => {
81398142
assert_eq!(payment_id, *actual_payment_id);
81408143
assert_eq!(our_payment_hash, *payment_hash.as_ref().unwrap());
8141-
assert_eq!(route.paths[0], *path);
8144+
assert_eq!(route.paths[0].hops, *path);
81428145
},
81438146
_ => panic!("Unexpected event"),
81448147
}
@@ -8342,12 +8345,12 @@ mod tests {
83428345
let (mut route, payment_hash, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000);
83438346
let path = route.paths[0].clone();
83448347
route.paths.push(path);
8345-
route.paths[0][0].pubkey = nodes[1].node.get_our_node_id();
8346-
route.paths[0][0].short_channel_id = chan_1_id;
8347-
route.paths[0][1].short_channel_id = chan_3_id;
8348-
route.paths[1][0].pubkey = nodes[2].node.get_our_node_id();
8349-
route.paths[1][0].short_channel_id = chan_2_id;
8350-
route.paths[1][1].short_channel_id = chan_4_id;
8348+
route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id();
8349+
route.paths[0].hops[0].short_channel_id = chan_1_id;
8350+
route.paths[0].hops[1].short_channel_id = chan_3_id;
8351+
route.paths[1].hops[0].pubkey = nodes[2].node.get_our_node_id();
8352+
route.paths[1].hops[0].short_channel_id = chan_2_id;
8353+
route.paths[1].hops[1].short_channel_id = chan_4_id;
83518354

83528355
match nodes[0].node.send_payment(&route, payment_hash, &None, PaymentId(payment_hash.0)).unwrap_err() {
83538356
PaymentSendFailure::ParameterError(APIError::APIMisuseError { ref err }) => {

lightning/src/ln/functional_test_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,7 +2189,7 @@ pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route:
21892189
let route = get_route(origin_node, &payment_params, recv_value, TEST_FINAL_CLTV).unwrap();
21902190
assert_eq!(route.paths.len(), 1);
21912191
assert_eq!(route.paths[0].len(), expected_route.len());
2192-
for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) {
2192+
for (node, hop) in expected_route.iter().zip(route.paths[0].hops.iter()) {
21932193
assert_eq!(hop.pubkey, node.node.get_our_node_id());
21942194
}
21952195

@@ -2210,7 +2210,7 @@ pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou
22102210
None, recv_value, TEST_FINAL_CLTV, origin_node.logger, &scorer, &random_seed_bytes).unwrap();
22112211
assert_eq!(route.paths.len(), 1);
22122212
assert_eq!(route.paths[0].len(), expected_route.len());
2213-
for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) {
2213+
for (node, hop) in expected_route.iter().zip(route.paths[0].hops.iter()) {
22142214
assert_eq!(hop.pubkey, node.node.get_our_node_id());
22152215
}
22162216

0 commit comments

Comments
 (0)