Skip to content

Commit 7507af8

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 * Filter out channels with a lower inbound capacity than the invoice amt * If any private 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 52a9287 commit 7507af8

File tree

1 file changed

+24
-34
lines changed

1 file changed

+24
-34
lines changed

lightning-invoice/src/utils.rs

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -64,42 +64,32 @@ pub fn create_phantom_invoice<Signer: Sign, K: Deref>(
6464
}
6565

6666
for hint in phantom_route_hints {
67-
for channel in &hint.channels {
68-
let short_channel_id = match channel.short_channel_id {
69-
Some(id) => id,
70-
None => continue,
71-
};
72-
let forwarding_info = match &channel.counterparty.forwarding_info {
73-
Some(info) => info.clone(),
74-
None => continue,
75-
};
76-
invoice = invoice.private_route(RouteHint(vec![
77-
RouteHintHop {
78-
src_node_id: channel.counterparty.node_id,
79-
short_channel_id,
80-
fees: RoutingFees {
81-
base_msat: forwarding_info.fee_base_msat,
82-
proportional_millionths: forwarding_info.fee_proportional_millionths,
83-
},
84-
cltv_expiry_delta: forwarding_info.cltv_expiry_delta,
85-
htlc_minimum_msat: None,
86-
htlc_maximum_msat: None,
87-
},
88-
RouteHintHop {
89-
src_node_id: hint.real_node_pubkey,
90-
short_channel_id: hint.phantom_scid,
91-
fees: RoutingFees {
92-
base_msat: 0,
93-
proportional_millionths: 0,
94-
},
95-
cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA,
96-
htlc_minimum_msat: None,
97-
htlc_maximum_msat: None,
98-
}])
99-
);
67+
let (mut route_hints, has_private_channels) = filter_channels(
68+
hint.channels.clone(),
69+
amt_msat
70+
);
71+
72+
// If we have any private channels, 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 `hint.real_node_pubkey`
75+
// node by looking at our public channels.
76+
if has_private_channels && 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: hint.real_node_pubkey,
82+
short_channel_id: hint.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());
10091
}
10192
}
102-
10393
let raw_invoice = match invoice.build_raw() {
10494
Ok(inv) => inv,
10595
Err(e) => return Err(SignOrCreationError::CreationError(e))

0 commit comments

Comments
 (0)