Skip to content

Commit 4aee13b

Browse files
Fix InflightHtlcs::process_path to process the whole Path
1 parent 7aba42b commit 4aee13b

File tree

3 files changed

+59
-8
lines changed

3 files changed

+59
-8
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5698,7 +5698,7 @@ where
56985698
for chan in peer_state.channel_by_id.values() {
56995699
for (htlc_source, _) in chan.inflight_htlc_sources() {
57005700
if let HTLCSource::OutboundRoute { path, .. } = htlc_source {
5701-
inflight_htlcs.process_path(&path.hops, self.get_our_node_id()); // fixed in upcoming commit
5701+
inflight_htlcs.process_path(path, self.get_our_node_id());
57025702
}
57035703
}
57045704
}

lightning/src/routing/router.rs

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -170,22 +170,33 @@ impl InFlightHtlcs {
170170
pub fn new() -> Self { InFlightHtlcs(HashMap::new()) }
171171

172172
/// Takes in a path with payer's node id and adds the path's details to `InFlightHtlcs`.
173-
pub fn process_path(&mut self, path: &[RouteHop], payer_node_id: PublicKey) {
174-
if path.is_empty() { return };
173+
pub fn process_path(&mut self, path: &Path, payer_node_id: PublicKey) {
174+
if path.len() == 0 { return };
175+
176+
let mut cumulative_msat = 0;
177+
if let Some(tail) = &path.blinded_tail {
178+
cumulative_msat += tail.final_value_msat + tail.fee_msat;
179+
self.0
180+
.entry((tail.intro_node_scid,
181+
NodeId::from_pubkey(&path.hops.last().map_or(payer_node_id, |hop| hop.pubkey)) <
182+
NodeId::from_pubkey(&tail.path.introduction_node_id)))
183+
.and_modify(|used_liquidity_msat| *used_liquidity_msat += cumulative_msat)
184+
.or_insert(cumulative_msat);
185+
}
186+
175187
// total_inflight_map needs to be direction-sensitive when keeping track of the HTLC value
176188
// that is held up. However, the `hops` array, which is a path returned by `find_route` in
177189
// the router excludes the payer node. In the following lines, the payer's information is
178190
// hardcoded with an inflight value of 0 so that we can correctly represent the first hop
179191
// in our sliding window of two.
180-
let reversed_hops_with_payer = path.iter().rev().skip(1)
192+
let reversed_hops_with_payer = path.hops.iter().rev().skip(1)
181193
.map(|hop| hop.pubkey)
182194
.chain(core::iter::once(payer_node_id));
183-
let mut cumulative_msat = 0;
184195

185196
// Taking the reversed vector from above, we zip it with just the reversed hops list to
186197
// work "backwards" of the given path, since the last hop's `fee_msat` actually represents
187198
// the total amount sent.
188-
for (next_hop, prev_hop) in path.iter().rev().zip(reversed_hops_with_payer) {
199+
for (next_hop, prev_hop) in path.hops.iter().rev().zip(reversed_hops_with_payer) {
189200
cumulative_msat += next_hop.fee_msat;
190201
self.0
191202
.entry((next_hop.short_channel_id, NodeId::from_pubkey(&prev_hop) < NodeId::from_pubkey(&next_hop.pubkey)))
@@ -2274,11 +2285,12 @@ fn build_route_from_hops_internal<L: Deref>(
22742285

22752286
#[cfg(test)]
22762287
mod tests {
2288+
use crate::blinded_path::BlindedPath;
22772289
use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, EffectiveCapacity};
22782290
use crate::routing::utxo::UtxoResult;
22792291
use crate::routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features,
2280-
Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees,
2281-
DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE};
2292+
BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop,
2293+
RoutingFees, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE};
22822294
use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
22832295
use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
22842296
use crate::chain::transaction::OutPoint;
@@ -5244,6 +5256,36 @@ mod tests {
52445256
assert_eq!(path, vec![2, 4, 7, 10]);
52455257
}
52465258

5259+
#[test]
5260+
fn blinded_path_inflight_processing() {
5261+
// Ensure we'll score the channel that's inbound to a blinded path's introduction node.
5262+
let mut inflight_htlcs = InFlightHtlcs::new();
5263+
let path = Path {
5264+
hops: vec![RouteHop {
5265+
pubkey: ln_test_utils::pubkey(42),
5266+
node_features: NodeFeatures::empty(),
5267+
short_channel_id: 42,
5268+
channel_features: ChannelFeatures::empty(),
5269+
fee_msat: 100,
5270+
cltv_expiry_delta: 0,
5271+
}],
5272+
blinded_tail: Some(BlindedTail {
5273+
path: BlindedPath {
5274+
introduction_node_id: ln_test_utils::pubkey(43),
5275+
blinding_point: ln_test_utils::pubkey(44),
5276+
blinded_hops: Vec::new(),
5277+
},
5278+
intro_node_scid: 43,
5279+
fee_msat: 1,
5280+
cltv_expiry_delta: 0,
5281+
final_value_msat: 200,
5282+
}),
5283+
};
5284+
inflight_htlcs.process_path(&path, ln_test_utils::pubkey(44));
5285+
assert_eq!(*inflight_htlcs.0.get(&(42, true)).unwrap(), 301);
5286+
assert_eq!(*inflight_htlcs.0.get(&(43, false)).unwrap(), 201);
5287+
}
5288+
52475289
struct BadChannelScorer {
52485290
short_channel_id: u64,
52495291
}

lightning/src/util/test_utils.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ use crate::chain::keysinterface::{InMemorySigner, Recipient, EntropySource, Node
6060
use std::time::{SystemTime, UNIX_EPOCH};
6161
use bitcoin::Sequence;
6262

63+
pub fn pubkey(byte: u8) -> PublicKey {
64+
let secp_ctx = Secp256k1::new();
65+
PublicKey::from_secret_key(&secp_ctx, &privkey(byte))
66+
}
67+
68+
pub fn privkey(byte: u8) -> SecretKey {
69+
SecretKey::from_slice(&[byte; 32]).unwrap()
70+
}
71+
6372
pub struct TestVecWriter(pub Vec<u8>);
6473
impl Writer for TestVecWriter {
6574
fn write_all(&mut self, buf: &[u8]) -> Result<(), io::Error> {

0 commit comments

Comments
 (0)