Skip to content

Commit 43cc81c

Browse files
Filter route hints for phantom invoices
Filter the route hints in `create_phantom_invoice` based on the following criteria: * Only one channel for every counterparty node per phantom payment-receiving node in the invoice * Always select the channel with the highest inbound capacity * For each payment-receiving node, filter out channels with a lower inbound capacity than the invoice amount, if any channel exists with enough capacity to cover the invoice amount * If any public channels exists for a payment-receiving node, push a single RouteHintHop with the phantom route and let the sender find the path to the payment-receiving node through the public channels.
1 parent eae5086 commit 43cc81c

File tree

1 file changed

+22
-34
lines changed

1 file changed

+22
-34
lines changed

lightning-invoice/src/utils.rs

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -66,40 +66,28 @@ pub fn create_phantom_invoice<Signer: Sign, K: Deref>(
6666
invoice = invoice.amount_milli_satoshis(amt);
6767
}
6868

69-
for hint in phantom_route_hints {
70-
for channel in &hint.channels {
71-
let short_channel_id = match channel.get_inbound_payment_scid() {
72-
Some(id) => id,
73-
None => continue,
74-
};
75-
let forwarding_info = match &channel.counterparty.forwarding_info {
76-
Some(info) => info.clone(),
77-
None => continue,
78-
};
79-
invoice = invoice.private_route(RouteHint(vec![
80-
RouteHintHop {
81-
src_node_id: channel.counterparty.node_id,
82-
short_channel_id,
83-
fees: RoutingFees {
84-
base_msat: forwarding_info.fee_base_msat,
85-
proportional_millionths: forwarding_info.fee_proportional_millionths,
86-
},
87-
cltv_expiry_delta: forwarding_info.cltv_expiry_delta,
88-
htlc_minimum_msat: None,
89-
htlc_maximum_msat: None,
90-
},
91-
RouteHintHop {
92-
src_node_id: hint.real_node_pubkey,
93-
short_channel_id: hint.phantom_scid,
94-
fees: RoutingFees {
95-
base_msat: 0,
96-
proportional_millionths: 0,
97-
},
98-
cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA,
99-
htlc_minimum_msat: None,
100-
htlc_maximum_msat: None,
101-
}])
102-
);
69+
for PhantomRouteHints { channels, phantom_scid, real_node_pubkey } in phantom_route_hints {
70+
let mut route_hints = filter_channels(channels, amt_msat);
71+
72+
// If we have any public channel, the route hints from `filter_channels` will be empty.
73+
// In that case we create a RouteHint on which we will push a single hop with the phantom
74+
// route into the invoice, and let the sender find the path to the `real_node_pubkey`
75+
// node by looking at our public channels.
76+
if route_hints.is_empty() {
77+
route_hints.push(RouteHint(vec![]))
78+
}
79+
for mut route_hint in route_hints {
80+
route_hint.0.push(RouteHintHop {
81+
src_node_id: real_node_pubkey,
82+
short_channel_id: phantom_scid,
83+
fees: RoutingFees {
84+
base_msat: 0,
85+
proportional_millionths: 0,
86+
},
87+
cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA,
88+
htlc_minimum_msat: None,
89+
htlc_maximum_msat: None,});
90+
invoice = invoice.private_route(route_hint.clone());
10391
}
10492
}
10593

0 commit comments

Comments
 (0)