Skip to content

Commit 3619a3b

Browse files
committed
Add create_blinded_payment_paths to Router
The Router trait is used to find a Route for paying a node. Expand the interface with a create_blinded_payment paths method for creating such paths to a recipient node. Provide an implementation for DefaultRouter that creates two-hop blinded paths where the recipient's peers serve as the introduction nodes.
1 parent 2cbc57c commit 3619a3b

File tree

4 files changed

+98
-6
lines changed

4 files changed

+98
-6
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use bitcoin::hashes::sha256d::Hash as Sha256dHash;
3131
use bitcoin::hash_types::{BlockHash, WPubkeyHash};
3232

3333
use lightning::blinded_path::BlindedPath;
34+
use lightning::blinded_path::payment::ReceiveTlvs;
3435
use lightning::chain;
3536
use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, chainmonitor, channelmonitor, Confirm, Watch};
3637
use lightning::chain::channelmonitor::{ChannelMonitor, MonitorEvent};
@@ -45,7 +46,7 @@ use lightning::ln::channel::FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
4546
use lightning::ln::msgs::{self, CommitmentUpdate, ChannelMessageHandler, DecodeError, UpdateAddHTLC, Init};
4647
use lightning::ln::script::ShutdownScript;
4748
use lightning::ln::functional_test_utils::*;
48-
use lightning::offers::invoice::UnsignedBolt12Invoice;
49+
use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
4950
use lightning::offers::invoice_request::UnsignedInvoiceRequest;
5051
use lightning::onion_message::{Destination, MessageRouter, OnionMessagePath};
5152
use lightning::util::test_channel_signer::{TestChannelSigner, EnforcementState};
@@ -101,6 +102,15 @@ impl Router for FuzzRouter {
101102
action: msgs::ErrorAction::IgnoreError
102103
})
103104
}
105+
106+
fn create_blinded_payment_paths<
107+
ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
108+
>(
109+
&self, _recipient: PublicKey, _first_hops: Vec<ChannelDetails>, _tlvs: ReceiveTlvs,
110+
_amount_msats: u64, _entropy_source: &ES, _secp_ctx: &Secp256k1<T>
111+
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
112+
unreachable!()
113+
}
104114
}
105115

106116
impl MessageRouter for FuzzRouter {

fuzz/src/full_stack.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use bitcoin::hashes::sha256d::Hash as Sha256dHash;
2929
use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
3030

3131
use lightning::blinded_path::BlindedPath;
32+
use lightning::blinded_path::payment::ReceiveTlvs;
3233
use lightning::chain;
3334
use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen};
3435
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
@@ -42,7 +43,7 @@ use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,Ig
4243
use lightning::ln::msgs::{self, DecodeError};
4344
use lightning::ln::script::ShutdownScript;
4445
use lightning::ln::functional_test_utils::*;
45-
use lightning::offers::invoice::UnsignedBolt12Invoice;
46+
use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
4647
use lightning::offers::invoice_request::UnsignedInvoiceRequest;
4748
use lightning::onion_message::{Destination, MessageRouter, OnionMessagePath};
4849
use lightning::routing::gossip::{P2PGossipSync, NetworkGraph};
@@ -144,6 +145,15 @@ impl Router for FuzzRouter {
144145
action: msgs::ErrorAction::IgnoreError
145146
})
146147
}
148+
149+
fn create_blinded_payment_paths<
150+
ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
151+
>(
152+
&self, _recipient: PublicKey, _first_hops: Vec<ChannelDetails>, _tlvs: ReceiveTlvs,
153+
_amount_msats: u64, _entropy_source: &ES, _secp_ctx: &Secp256k1<T>
154+
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
155+
unreachable!()
156+
}
147157
}
148158

149159
impl MessageRouter for FuzzRouter {

lightning/src/routing/router.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ use bitcoin::hashes::Hash;
1414
use bitcoin::hashes::sha256::Hash as Sha256;
1515

1616
use crate::blinded_path::{BlindedHop, BlindedPath};
17+
use crate::blinded_path::payment::{ForwardNode, ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs};
1718
use crate::ln::PaymentHash;
1819
use crate::ln::channelmanager::{ChannelDetails, PaymentId};
19-
use crate::ln::features::{Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures};
20+
use crate::ln::features::{BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures};
2021
use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
2122
use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice};
2223
use crate::onion_message::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath};
@@ -82,6 +83,57 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
8283
&random_seed_bytes
8384
)
8485
}
86+
87+
fn create_blinded_payment_paths<
88+
ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
89+
>(
90+
&self, recipient: PublicKey, first_hops: Vec<ChannelDetails>, tlvs: ReceiveTlvs,
91+
amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1<T>
92+
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
93+
// Limit the number of blinded paths that are computed.
94+
const MAX_PAYMENT_PATHS: usize = 3;
95+
96+
// Ensure peers have at least three channels so that it is more difficult to infer the
97+
// recipient's node_id.
98+
const MIN_PEER_CHANNELS: usize = 3;
99+
100+
let network_graph = self.network_graph.deref().read_only();
101+
first_hops.into_iter()
102+
.filter(|details| details.is_public)
103+
.filter(|details| details.counterparty.features.supports_route_blinding())
104+
.filter(|details| amount_msats <= details.inbound_capacity_msat)
105+
.filter(|details| amount_msats >= details.inbound_htlc_minimum_msat.unwrap_or(0))
106+
.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)
111+
)
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),
119+
};
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),
129+
};
130+
BlindedPath::new_for_payment(
131+
&[forward_node], recipient, tlvs.clone(), u64::MAX, entropy_source, secp_ctx
132+
)
133+
})
134+
.take(MAX_PAYMENT_PATHS)
135+
.collect()
136+
}
85137
}
86138

87139
impl< G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp<ScoreParams = SP>> MessageRouter for DefaultRouter<G, L, S, SP, Sc> where
@@ -129,6 +181,16 @@ pub trait Router: MessageRouter {
129181
) -> Result<Route, LightningError> {
130182
self.find_route(payer, route_params, first_hops, inflight_htlcs)
131183
}
184+
185+
/// Creates [`BlindedPath`]s for payment to the `recipient` node. The channels in `first_hops`
186+
/// are assumed to be with the `recipient`'s peers. The payment secret and any constraints are
187+
/// given in `tlvs`.
188+
fn create_blinded_payment_paths<
189+
ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
190+
>(
191+
&self, recipient: PublicKey, first_hops: Vec<ChannelDetails>, tlvs: ReceiveTlvs,
192+
amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1<T>
193+
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()>;
132194
}
133195

134196
/// [`ScoreLookUp`] implementation that factors in in-flight HTLC liquidity.

lightning/src/util/test_utils.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// licenses.
99

1010
use crate::blinded_path::BlindedPath;
11+
use crate::blinded_path::payment::ReceiveTlvs;
1112
use crate::chain;
1213
use crate::chain::WatchedOutput;
1314
use crate::chain::chaininterface;
@@ -23,13 +24,13 @@ use crate::sign;
2324
use crate::events;
2425
use crate::events::bump_transaction::{WalletSource, Utxo};
2526
use crate::ln::ChannelId;
26-
use crate::ln::channelmanager;
27+
use crate::ln::channelmanager::{ChannelDetails, self};
2728
use crate::ln::chan_utils::CommitmentTransaction;
2829
use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
2930
use crate::ln::{msgs, wire};
3031
use crate::ln::msgs::LightningError;
3132
use crate::ln::script::ShutdownScript;
32-
use crate::offers::invoice::UnsignedBolt12Invoice;
33+
use crate::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
3334
use crate::offers::invoice_request::UnsignedInvoiceRequest;
3435
use crate::onion_message::{Destination, MessageRouter, OnionMessagePath};
3536
use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, RoutingFees};
@@ -120,7 +121,7 @@ impl<'a> TestRouter<'a> {
120121

121122
impl<'a> Router for TestRouter<'a> {
122123
fn find_route(
123-
&self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&channelmanager::ChannelDetails]>,
124+
&self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>,
124125
inflight_htlcs: InFlightHtlcs
125126
) -> Result<Route, msgs::LightningError> {
126127
if let Some((find_route_query, find_route_res)) = self.next_routes.lock().unwrap().pop_front() {
@@ -190,6 +191,15 @@ impl<'a> Router for TestRouter<'a> {
190191
&[42; 32]
191192
)
192193
}
194+
195+
fn create_blinded_payment_paths<
196+
ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
197+
>(
198+
&self, _recipient: PublicKey, _first_hops: Vec<ChannelDetails>, _tlvs: ReceiveTlvs,
199+
_amount_msats: u64, _entropy_source: &ES, _secp_ctx: &Secp256k1<T>
200+
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
201+
unreachable!()
202+
}
193203
}
194204

195205
impl<'a> MessageRouter for TestRouter<'a> {

0 commit comments

Comments
 (0)