Skip to content

Commit 13aad6a

Browse files
Filter route hints for phantom invoices
Filter the route hints in `create_phantom_invoice` based on the following criteria: * Only one channel per real participating node in the phantom invoice * Always select the channel with the highest inbound capacity * Filter out channels with a lower inbound capacity than the invoice amt
1 parent 80731e8 commit 13aad6a

File tree

1 file changed

+34
-33
lines changed

1 file changed

+34
-33
lines changed

lightning-invoice/src/utils.rs

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -64,42 +64,43 @@ 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,
67+
// Filter one route hint per "real" node.
68+
let channel_pubkey_selector = |_channel: ChannelDetails| hint.real_node_pubkey.clone();
69+
let route_hint_from_channel = |channel: ChannelDetails, short_channel_id: u64, forwarding_info: CounterpartyForwardingInfo| {
70+
RouteHint(vec![
71+
RouteHintHop {
72+
src_node_id: channel.counterparty.node_id,
73+
short_channel_id,
74+
fees: RoutingFees {
75+
base_msat: forwarding_info.fee_base_msat,
76+
proportional_millionths: forwarding_info.fee_proportional_millionths,
77+
},
78+
cltv_expiry_delta: forwarding_info.cltv_expiry_delta,
79+
htlc_minimum_msat: None,
80+
htlc_maximum_msat: None,
81+
},
82+
RouteHintHop {
83+
src_node_id: hint.real_node_pubkey,
84+
short_channel_id: hint.phantom_scid,
85+
fees: RoutingFees {
86+
base_msat: 0,
87+
proportional_millionths: 0,
8788
},
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-
);
89+
cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA,
90+
htlc_minimum_msat: None,
91+
htlc_maximum_msat: None,}])
92+
};
93+
let route_hints = filter_channels(
94+
hint.channels.clone(),
95+
amt_msat,
96+
false,
97+
channel_pubkey_selector,
98+
route_hint_from_channel
99+
);
100+
for hint in route_hints {
101+
invoice = invoice.private_route(hint);
100102
}
101103
}
102-
103104
let raw_invoice = match invoice.build_raw() {
104105
Ok(inv) => inv,
105106
Err(e) => return Err(SignOrCreationError::CreationError(e))

0 commit comments

Comments
 (0)