Skip to content

Commit b74a06d

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 92000f6 commit b74a06d

File tree

1 file changed

+24
-33
lines changed

1 file changed

+24
-33
lines changed

lightning-invoice/src/utils.rs

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -67,39 +67,30 @@ pub fn create_phantom_invoice<Signer: Sign, K: Deref>(
6767
}
6868

6969
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-
);
70+
let mut route_hints = filter_channels(
71+
hint.channels.clone(),
72+
amt_msat
73+
);
74+
75+
// If we have any public channel, the route hints from `filter_channels` will be empty.
76+
// In that case we create a RouteHint on which we will push a single hop with the phantom
77+
// route into the invoice, and let the sender find the path to the `hint.real_node_pubkey`
78+
// node by looking at our public channels.
79+
if route_hints.is_empty(){
80+
route_hints.push(RouteHint(vec![]))
81+
}
82+
for mut route_hint in route_hints {
83+
route_hint.0.push(RouteHintHop {
84+
src_node_id: hint.real_node_pubkey,
85+
short_channel_id: hint.phantom_scid,
86+
fees: RoutingFees {
87+
base_msat: 0,
88+
proportional_millionths: 0,
89+
},
90+
cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA,
91+
htlc_minimum_msat: None,
92+
htlc_maximum_msat: None,});
93+
invoice = invoice.private_route(route_hint.clone());
10394
}
10495
}
10596

0 commit comments

Comments
 (0)