Skip to content

Commit 0992808

Browse files
committed
f - add one more hop to blinded payment paths
1 parent ae6f47a commit 0992808

File tree

2 files changed

+71
-24
lines changed

2 files changed

+71
-24
lines changed

lightning/src/routing/gossip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,7 @@ impl<'a> DirectedChannelInfo<'a> {
10261026

10271027
/// Returns information for the direction.
10281028
#[inline]
1029-
pub(super) fn direction(&self) -> &'a ChannelUpdateInfo { self.direction }
1029+
pub(crate) fn direction(&self) -> &'a ChannelUpdateInfo { self.direction }
10301030

10311031
/// Returns the `node_id` of the source hop.
10321032
///

lightning/src/routing/router.rs

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
9090
&self, recipient: PublicKey, first_hops: Vec<ChannelDetails>, tlvs: ReceiveTlvs,
9191
amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1<T>
9292
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
93+
let recipient_node_id = NodeId::from_pubkey(&recipient);
94+
9395
// Limit the number of blinded paths that are computed.
9496
const MAX_PAYMENT_PATHS: usize = 3;
9597

@@ -98,37 +100,82 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
98100
const MIN_PEER_CHANNELS: usize = 3;
99101
let network_graph = self.network_graph.deref().read_only();
100102

101-
first_hops.into_iter()
102-
.filter(|details| details.is_public)
103+
first_hops.iter()
103104
.filter(|details| details.counterparty.features.supports_route_blinding())
104105
.filter(|details| amount_msats >= details.inbound_capacity_msat)
105106
.filter(|details| amount_msats >= details.inbound_htlc_minimum_msat.unwrap_or(0))
106107
.filter(|details| amount_msats <= details.inbound_htlc_maximum_msat.unwrap_or(0))
107-
.filter(|details| network_graph
108-
.node(&NodeId::from_pubkey(&details.counterparty.node_id))
109-
.map(|node_info| node_info.channels.len() >= MIN_PEER_CHANNELS)
110-
.unwrap_or(false)
108+
.map(|details| (details, NodeId::from_pubkey(&details.counterparty.node_id)))
109+
// Limit to counterparties with announced channels
110+
.filter_map(|(details, counterparty_node_id)|
111+
network_graph
112+
.node(&counterparty_node_id)
113+
.map(|info| &info.channels[..])
114+
.and_then(|channels| (channels.len() >= MIN_PEER_CHANNELS).then(|| channels))
115+
.map(|channels| (details, counterparty_node_id, channels))
116+
)
117+
// Pair counterparties with their other channels
118+
.flat_map(|(details, counterparty_node_id, counterparty_channels)|
119+
counterparty_channels
120+
.iter()
121+
.filter_map(|scid| network_graph.channels().get_key_value(scid))
122+
.filter_map(move |(scid, info)| info
123+
.as_directed_to(&counterparty_node_id)
124+
.map(|(info, source)| (source, *scid, info))
125+
)
126+
.filter(|(source, _, _)| **source != recipient_node_id)
127+
.filter(|(_, _, info)| amount_msats >= info.direction().htlc_minimum_msat)
128+
.filter(|(_, _, info)| amount_msats <= info.direction().htlc_maximum_msat)
129+
.map(move |(source, scid, info)| (source, scid, info, details))
111130
)
112-
.map(|details| {
113-
let short_channel_id = details.get_inbound_payment_scid().unwrap();
114-
let payment_relay: PaymentRelay = details.counterparty.forwarding_info.unwrap().into();
115-
let payment_constraints = PaymentConstraints {
116-
max_cltv_expiry: tlvs.payment_constraints.max_cltv_expiry
117-
+ payment_relay.cltv_expiry_delta as u32,
118-
htlc_minimum_msat: details.inbound_htlc_minimum_msat.unwrap_or(0),
131+
// Construct blinded paths where the counterparty's counterparty is the introduction
132+
// node:
133+
//
134+
// source --- info ---> counterparty --- details ---> recipient
135+
.map(|(introduction_node_id, scid, info, details)| {
136+
let counterparty_forward_node = {
137+
let short_channel_id = details.get_inbound_payment_scid().unwrap();
138+
let payment_relay: PaymentRelay =
139+
details.counterparty.forwarding_info.clone().unwrap().into();
140+
let payment_constraints = PaymentConstraints {
141+
max_cltv_expiry: payment_relay.cltv_expiry_delta as u32
142+
+ tlvs.payment_constraints.max_cltv_expiry,
143+
htlc_minimum_msat: details.inbound_htlc_minimum_msat.unwrap_or(0),
144+
};
145+
ForwardNode {
146+
tlvs: ForwardTlvs {
147+
short_channel_id,
148+
payment_relay,
149+
payment_constraints,
150+
features: BlindedHopFeatures::empty(),
151+
},
152+
node_id: details.counterparty.node_id,
153+
htlc_maximum_msat: details.inbound_htlc_maximum_msat.unwrap_or(0),
154+
}
119155
};
120-
let forward_node = ForwardNode {
121-
tlvs: ForwardTlvs {
122-
short_channel_id,
123-
payment_relay,
124-
payment_constraints,
125-
features: BlindedHopFeatures::empty(),
126-
},
127-
node_id: details.counterparty.node_id,
128-
htlc_maximum_msat: details.inbound_htlc_maximum_msat.unwrap_or(0),
156+
let introduction_forward_node = {
157+
let htlc_minimum_msat = info.direction().htlc_minimum_msat;
158+
let htlc_maximum_msat = info.direction().htlc_maximum_msat;
159+
let payment_relay: PaymentRelay = info.into();
160+
let payment_constraints = PaymentConstraints {
161+
max_cltv_expiry: payment_relay.cltv_expiry_delta as u32
162+
+ counterparty_forward_node.tlvs.payment_constraints.max_cltv_expiry,
163+
htlc_minimum_msat,
164+
};
165+
ForwardNode {
166+
tlvs: ForwardTlvs {
167+
short_channel_id: scid,
168+
payment_relay,
169+
payment_constraints,
170+
features: BlindedHopFeatures::empty(),
171+
},
172+
node_id: introduction_node_id.as_pubkey().unwrap(),
173+
htlc_maximum_msat,
174+
}
129175
};
130176
BlindedPath::new_for_payment(
131-
&[forward_node], recipient, tlvs.clone(), u64::MAX, entropy_source, secp_ctx
177+
&[introduction_forward_node, counterparty_forward_node], recipient,
178+
tlvs.clone(), u64::MAX, entropy_source, secp_ctx
132179
)
133180
})
134181
.take(MAX_PAYMENT_PATHS)

0 commit comments

Comments
 (0)