Skip to content

Commit 607727f

Browse files
authored
Merge pull request #2146 from valentinewallace/2023-03-blinded-pathfinding-groundwork
Blinded pathfinding groundwork
2 parents bc54441 + b131634 commit 607727f

34 files changed

+1322
-967
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use lightning::util::errors::APIError;
5050
use lightning::util::logger::Logger;
5151
use lightning::util::config::UserConfig;
5252
use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer};
53-
use lightning::routing::router::{InFlightHtlcs, Route, RouteHop, RouteParameters, Router};
53+
use lightning::routing::router::{InFlightHtlcs, Path, Route, RouteHop, RouteParameters, Router};
5454

5555
use crate::utils::test_logger::{self, Output};
5656
use crate::utils::test_persister::TestPersister;
@@ -353,14 +353,14 @@ fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, p
353353
payment_id[0..8].copy_from_slice(&payment_idx.to_ne_bytes());
354354
*payment_idx += 1;
355355
if let Err(err) = source.send_payment_with_route(&Route {
356-
paths: vec![vec![RouteHop {
356+
paths: vec![Path { hops: vec![RouteHop {
357357
pubkey: dest.get_our_node_id(),
358358
node_features: dest.node_features(),
359359
short_channel_id: dest_chan_id,
360360
channel_features: dest.channel_features(),
361361
fee_msat: amt,
362362
cltv_expiry_delta: 200,
363-
}]],
363+
}], blinded_tail: None }],
364364
payment_params: None,
365365
}, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_id)) {
366366
check_payment_err(err);
@@ -375,7 +375,7 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
375375
payment_id[0..8].copy_from_slice(&payment_idx.to_ne_bytes());
376376
*payment_idx += 1;
377377
if let Err(err) = source.send_payment_with_route(&Route {
378-
paths: vec![vec![RouteHop {
378+
paths: vec![Path { hops: vec![RouteHop {
379379
pubkey: middle.get_our_node_id(),
380380
node_features: middle.node_features(),
381381
short_channel_id: middle_chan_id,
@@ -389,7 +389,7 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
389389
channel_features: dest.channel_features(),
390390
fee_msat: amt,
391391
cltv_expiry_delta: 200,
392-
}]],
392+
}], blinded_tail: None }],
393393
payment_params: None,
394394
}, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_id)) {
395395
check_payment_err(err);

fuzz/src/invoice_request_deser.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
use bitcoin::secp256k1::{KeyPair, Parity, PublicKey, Secp256k1, SecretKey, self};
1111
use crate::utils::test_logger;
1212
use core::convert::{Infallible, TryFrom};
13+
use lightning::blinded_path::BlindedPath;
1314
use lightning::chain::keysinterface::EntropySource;
1415
use lightning::ln::PaymentHash;
1516
use lightning::ln::features::BlindedHopFeatures;
1617
use lightning::offers::invoice::{BlindedPayInfo, UnsignedInvoice};
1718
use lightning::offers::invoice_request::InvoiceRequest;
1819
use lightning::offers::parse::SemanticError;
19-
use lightning::onion_message::BlindedPath;
2020
use lightning::util::ser::Writeable;
2121

2222
#[inline]
@@ -74,8 +74,8 @@ fn build_response<'a, T: secp256k1::Signing + secp256k1::Verification>(
7474
) -> Result<UnsignedInvoice<'a>, SemanticError> {
7575
let entropy_source = Randomness {};
7676
let paths = vec![
77-
BlindedPath::new(&[pubkey(43), pubkey(44), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
78-
BlindedPath::new(&[pubkey(45), pubkey(46), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
77+
BlindedPath::new_for_message(&[pubkey(43), pubkey(44), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
78+
BlindedPath::new_for_message(&[pubkey(45), pubkey(46), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
7979
];
8080

8181
let payinfo = vec![

fuzz/src/refund_deser.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey, self};
1111
use crate::utils::test_logger;
1212
use core::convert::{Infallible, TryFrom};
13+
use lightning::blinded_path::BlindedPath;
1314
use lightning::chain::keysinterface::EntropySource;
1415
use lightning::ln::PaymentHash;
1516
use lightning::ln::features::BlindedHopFeatures;
1617
use lightning::offers::invoice::{BlindedPayInfo, UnsignedInvoice};
1718
use lightning::offers::parse::SemanticError;
1819
use lightning::offers::refund::Refund;
19-
use lightning::onion_message::BlindedPath;
2020
use lightning::util::ser::Writeable;
2121

2222
#[inline]
@@ -63,8 +63,8 @@ fn build_response<'a, T: secp256k1::Signing + secp256k1::Verification>(
6363
) -> Result<UnsignedInvoice<'a>, SemanticError> {
6464
let entropy_source = Randomness {};
6565
let paths = vec![
66-
BlindedPath::new(&[pubkey(43), pubkey(44), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
67-
BlindedPath::new(&[pubkey(45), pubkey(46), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
66+
BlindedPath::new_for_message(&[pubkey(43), pubkey(44), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
67+
BlindedPath::new_for_message(&[pubkey(45), pubkey(46), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
6868
];
6969

7070
let payinfo = vec![

lightning-background-processor/src/lib.rs

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -241,26 +241,21 @@ fn update_scorer<'a, S: 'static + Deref<Target = SC> + Send + Sync, SC: 'a + Wri
241241
let mut score = scorer.lock();
242242
match event {
243243
Event::PaymentPathFailed { ref path, short_channel_id: Some(scid), .. } => {
244-
let path = path.iter().collect::<Vec<_>>();
245-
score.payment_path_failed(&path, *scid);
244+
score.payment_path_failed(path, *scid);
246245
},
247246
Event::PaymentPathFailed { ref path, payment_failed_permanently: true, .. } => {
248247
// Reached if the destination explicitly failed it back. We treat this as a successful probe
249248
// because the payment made it all the way to the destination with sufficient liquidity.
250-
let path = path.iter().collect::<Vec<_>>();
251-
score.probe_successful(&path);
249+
score.probe_successful(path);
252250
},
253251
Event::PaymentPathSuccessful { path, .. } => {
254-
let path = path.iter().collect::<Vec<_>>();
255-
score.payment_path_successful(&path);
252+
score.payment_path_successful(path);
256253
},
257254
Event::ProbeSuccessful { path, .. } => {
258-
let path = path.iter().collect::<Vec<_>>();
259-
score.probe_successful(&path);
255+
score.probe_successful(path);
260256
},
261257
Event::ProbeFailed { path, short_channel_id: Some(scid), .. } => {
262-
let path = path.iter().collect::<Vec<_>>();
263-
score.probe_failed(&path, *scid);
258+
score.probe_failed(path, *scid);
264259
},
265260
_ => {},
266261
}
@@ -767,7 +762,7 @@ mod tests {
767762
use lightning::ln::msgs::{ChannelMessageHandler, Init};
768763
use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler};
769764
use lightning::routing::gossip::{NetworkGraph, NodeId, P2PGossipSync};
770-
use lightning::routing::router::{DefaultRouter, RouteHop};
765+
use lightning::routing::router::{DefaultRouter, Path, RouteHop};
771766
use lightning::routing::scoring::{ChannelUsage, Score};
772767
use lightning::util::config::UserConfig;
773768
use lightning::util::ser::Writeable;
@@ -910,10 +905,10 @@ mod tests {
910905

911906
#[derive(Debug)]
912907
enum TestResult {
913-
PaymentFailure { path: Vec<RouteHop>, short_channel_id: u64 },
914-
PaymentSuccess { path: Vec<RouteHop> },
915-
ProbeFailure { path: Vec<RouteHop> },
916-
ProbeSuccess { path: Vec<RouteHop> },
908+
PaymentFailure { path: Path, short_channel_id: u64 },
909+
PaymentSuccess { path: Path },
910+
ProbeFailure { path: Path },
911+
ProbeSuccess { path: Path },
917912
}
918913

919914
impl TestScorer {
@@ -935,11 +930,11 @@ mod tests {
935930
&self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage
936931
) -> u64 { unimplemented!(); }
937932

938-
fn payment_path_failed(&mut self, actual_path: &[&RouteHop], actual_short_channel_id: u64) {
933+
fn payment_path_failed(&mut self, actual_path: &Path, actual_short_channel_id: u64) {
939934
if let Some(expectations) = &mut self.event_expectations {
940935
match expectations.pop_front().unwrap() {
941936
TestResult::PaymentFailure { path, short_channel_id } => {
942-
assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
937+
assert_eq!(actual_path, &path);
943938
assert_eq!(actual_short_channel_id, short_channel_id);
944939
},
945940
TestResult::PaymentSuccess { path } => {
@@ -955,14 +950,14 @@ mod tests {
955950
}
956951
}
957952

958-
fn payment_path_successful(&mut self, actual_path: &[&RouteHop]) {
953+
fn payment_path_successful(&mut self, actual_path: &Path) {
959954
if let Some(expectations) = &mut self.event_expectations {
960955
match expectations.pop_front().unwrap() {
961956
TestResult::PaymentFailure { path, .. } => {
962957
panic!("Unexpected payment path failure: {:?}", path)
963958
},
964959
TestResult::PaymentSuccess { path } => {
965-
assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
960+
assert_eq!(actual_path, &path);
966961
},
967962
TestResult::ProbeFailure { path } => {
968963
panic!("Unexpected probe failure: {:?}", path)
@@ -974,7 +969,7 @@ mod tests {
974969
}
975970
}
976971

977-
fn probe_failed(&mut self, actual_path: &[&RouteHop], _: u64) {
972+
fn probe_failed(&mut self, actual_path: &Path, _: u64) {
978973
if let Some(expectations) = &mut self.event_expectations {
979974
match expectations.pop_front().unwrap() {
980975
TestResult::PaymentFailure { path, .. } => {
@@ -984,15 +979,15 @@ mod tests {
984979
panic!("Unexpected payment path success: {:?}", path)
985980
},
986981
TestResult::ProbeFailure { path } => {
987-
assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
982+
assert_eq!(actual_path, &path);
988983
},
989984
TestResult::ProbeSuccess { path } => {
990985
panic!("Unexpected probe success: {:?}", path)
991986
}
992987
}
993988
}
994989
}
995-
fn probe_successful(&mut self, actual_path: &[&RouteHop]) {
990+
fn probe_successful(&mut self, actual_path: &Path) {
996991
if let Some(expectations) = &mut self.event_expectations {
997992
match expectations.pop_front().unwrap() {
998993
TestResult::PaymentFailure { path, .. } => {
@@ -1005,7 +1000,7 @@ mod tests {
10051000
panic!("Unexpected probe failure: {:?}", path)
10061001
},
10071002
TestResult::ProbeSuccess { path } => {
1008-
assert_eq!(actual_path, &path.iter().collect::<Vec<_>>()[..]);
1003+
assert_eq!(actual_path, &path);
10091004
}
10101005
}
10111006
}
@@ -1533,14 +1528,14 @@ mod tests {
15331528
let node_1_privkey = SecretKey::from_slice(&[42; 32]).unwrap();
15341529
let node_1_id = PublicKey::from_secret_key(&secp_ctx, &node_1_privkey);
15351530

1536-
let path = vec![RouteHop {
1531+
let path = Path { hops: vec![RouteHop {
15371532
pubkey: node_1_id,
15381533
node_features: NodeFeatures::empty(),
15391534
short_channel_id: scored_scid,
15401535
channel_features: ChannelFeatures::empty(),
15411536
fee_msat: 0,
15421537
cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA as u32,
1543-
}];
1538+
}], blinded_tail: None };
15441539

15451540
$nodes[0].scorer.lock().unwrap().expect(TestResult::PaymentFailure { path: path.clone(), short_channel_id: scored_scid });
15461541
$nodes[0].node.push_pending_event(Event::PaymentPathFailed {

lightning/src/onion_message/blinded_path.rs renamed to lightning/src/blinded_path/mod.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99

1010
//! Creating blinded paths and related utilities live here.
1111
12+
pub(crate) mod utils;
13+
1214
use bitcoin::hashes::{Hash, HashEngine};
1315
use bitcoin::hashes::sha256::Hash as Sha256;
1416
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
1517

1618
use crate::chain::keysinterface::{EntropySource, NodeSigner, Recipient};
17-
use super::packet::ControlTlvs;
18-
use super::utils;
19+
use crate::onion_message::ControlTlvs;
1920
use crate::ln::msgs::DecodeError;
2021
use crate::ln::onion_utils;
2122
use crate::util::chacha20poly1305rfc::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
@@ -26,18 +27,18 @@ use core::ops::Deref;
2627
use crate::io::{self, Cursor};
2728
use crate::prelude::*;
2829

29-
/// Onion messages can be sent and received to blinded paths, which serve to hide the identity of
30-
/// the recipient.
31-
#[derive(Clone, Debug, PartialEq)]
30+
/// Onion messages and payments can be sent and received to blinded paths, which serve to hide the
31+
/// identity of the recipient.
32+
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
3233
pub struct BlindedPath {
3334
/// To send to a blinded path, the sender first finds a route to the unblinded
3435
/// `introduction_node_id`, which can unblind its [`encrypted_payload`] to find out the onion
35-
/// message's next hop and forward it along.
36+
/// message or payment's next hop and forward it along.
3637
///
3738
/// [`encrypted_payload`]: BlindedHop::encrypted_payload
3839
pub(crate) introduction_node_id: PublicKey,
3940
/// Used by the introduction node to decrypt its [`encrypted_payload`] to forward the onion
40-
/// message.
41+
/// message or payment.
4142
///
4243
/// [`encrypted_payload`]: BlindedHop::encrypted_payload
4344
pub(crate) blinding_point: PublicKey,
@@ -47,7 +48,7 @@ pub struct BlindedPath {
4748

4849
/// Used to construct the blinded hops portion of a blinded path. These hops cannot be identified
4950
/// by outside observers and thus can be used to hide the identity of the recipient.
50-
#[derive(Clone, Debug, PartialEq)]
51+
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
5152
pub struct BlindedHop {
5253
/// The blinded node id of this hop in a blinded path.
5354
pub(crate) blinded_node_id: PublicKey,
@@ -58,12 +59,12 @@ pub struct BlindedHop {
5859
}
5960

6061
impl BlindedPath {
61-
/// Create a blinded path to be forwarded along `node_pks`. The last node pubkey in `node_pks`
62-
/// will be the destination node.
62+
/// Create a blinded path for an onion message, to be forwarded along `node_pks`. The last node
63+
/// pubkey in `node_pks` will be the destination node.
6364
///
6465
/// Errors if less than two hops are provided or if `node_pk`(s) are invalid.
6566
// TODO: make all payloads the same size with padding + add dummy hops
66-
pub fn new<ES: EntropySource, T: secp256k1::Signing + secp256k1::Verification>
67+
pub fn new_for_message<ES: EntropySource, T: secp256k1::Signing + secp256k1::Verification>
6768
(node_pks: &[PublicKey], entropy_source: &ES, secp_ctx: &Secp256k1<T>) -> Result<Self, ()>
6869
{
6970
if node_pks.len() < 2 { return Err(()) }
@@ -74,12 +75,13 @@ impl BlindedPath {
7475
Ok(BlindedPath {
7576
introduction_node_id,
7677
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
77-
blinded_hops: blinded_hops(secp_ctx, node_pks, &blinding_secret).map_err(|_| ())?,
78+
blinded_hops: blinded_message_hops(secp_ctx, node_pks, &blinding_secret).map_err(|_| ())?,
7879
})
7980
}
8081

81-
// Advance the blinded path by one hop, so make the second hop into the new introduction node.
82-
pub(super) fn advance_by_one<NS: Deref, T: secp256k1::Signing + secp256k1::Verification>
82+
// Advance the blinded onion message path by one hop, so make the second hop into the new
83+
// introduction node.
84+
pub(super) fn advance_message_path_by_one<NS: Deref, T: secp256k1::Signing + secp256k1::Verification>
8385
(&mut self, node_signer: &NS, secp_ctx: &Secp256k1<T>) -> Result<(), ()>
8486
where NS::Target: NodeSigner
8587
{
@@ -114,8 +116,8 @@ impl BlindedPath {
114116
}
115117
}
116118

117-
/// Construct blinded hops for the given `unblinded_path`.
118-
fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
119+
/// Construct blinded onion message hops for the given `unblinded_path`.
120+
fn blinded_message_hops<T: secp256k1::Signing + secp256k1::Verification>(
119121
secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], session_priv: &SecretKey
120122
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
121123
let mut blinded_hops = Vec::with_capacity(unblinded_path.len());

lightning/src/onion_message/utils.rs renamed to lightning/src/blinded_path/utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ use bitcoin::hashes::sha256::Hash as Sha256;
1515
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey, Scalar};
1616
use bitcoin::secp256k1::ecdh::SharedSecret;
1717

18+
use super::BlindedPath;
1819
use crate::ln::onion_utils;
19-
use super::blinded_path::BlindedPath;
20-
use super::messenger::Destination;
20+
use crate::onion_message::Destination;
2121

2222
use crate::prelude::*;
2323

2424
// TODO: DRY with onion_utils::construct_onion_keys_callback
2525
#[inline]
26-
pub(super) fn construct_keys_callback<T: secp256k1::Signing + secp256k1::Verification,
26+
pub(crate) fn construct_keys_callback<T: secp256k1::Signing + secp256k1::Verification,
2727
FType: FnMut(PublicKey, SharedSecret, PublicKey, [u8; 32], Option<PublicKey>, Option<Vec<u8>>)>(
2828
secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], destination: Option<Destination>,
2929
session_priv: &SecretKey, mut callback: FType

0 commit comments

Comments
 (0)