Skip to content

Commit e7d5950

Browse files
Fuzz test blinded payment pathfinding
1 parent d75ede5 commit e7d5950

File tree

3 files changed

+62
-7
lines changed

3 files changed

+62
-7
lines changed

fuzz/src/router.rs

+55-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@ use bitcoin::blockdata::script::Builder;
1111
use bitcoin::blockdata::transaction::TxOut;
1212
use bitcoin::hash_types::BlockHash;
1313

14+
use lightning::blinded_path::{BlindedHop, BlindedPath};
1415
use lightning::chain::transaction::OutPoint;
1516
use lightning::ln::channelmanager::{self, ChannelDetails, ChannelCounterparty};
17+
use lightning::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures};
1618
use lightning::ln::msgs;
19+
use lightning::offers::invoice::BlindedPayInfo;
1720
use lightning::routing::gossip::{NetworkGraph, RoutingFees};
1821
use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoLookupError, UtxoResult};
1922
use lightning::routing::router::{find_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
@@ -279,7 +282,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
279282
net_graph.channel_failed_permanent(short_channel_id);
280283
},
281284
_ if node_pks.is_empty() => {},
282-
_ => {
285+
x if x < 250 => {
283286
let mut first_hops_vec = Vec::new();
284287
let first_hops = first_hops!(first_hops_vec);
285288
let mut last_hops = Vec::new();
@@ -316,6 +319,57 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
316319
&logger, &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes);
317320
}
318321
},
322+
x => {
323+
let mut first_hops_vec = Vec::new();
324+
let first_hops = first_hops!(first_hops_vec);
325+
let mut last_hops = Vec::new();
326+
{
327+
let count = get_slice!(1)[0];
328+
for _ in 0..count {
329+
// Fetch values in the same order as above to improve coverage.
330+
let intro_node_id = node_pks.iter().skip(slice_to_be16(get_slice!(2)) as usize % node_pks.len()).next().unwrap();
331+
let fee_base_msat = slice_to_be32(get_slice!(4));
332+
let fee_proportional_millionths = slice_to_be32(get_slice!(4));
333+
let cltv_expiry_delta = slice_to_be16(get_slice!(2));
334+
let htlc_minimum_msat = slice_to_be64(get_slice!(8));
335+
let payinfo = BlindedPayInfo {
336+
fee_base_msat,
337+
fee_proportional_millionths,
338+
htlc_minimum_msat,
339+
htlc_maximum_msat: htlc_minimum_msat.saturating_mul(100),
340+
cltv_expiry_delta,
341+
features: BlindedHopFeatures::empty(),
342+
};
343+
let num_blinded_hops = x % 250;
344+
let mut blinded_hops = Vec::new();
345+
for _ in 0..num_blinded_hops {
346+
blinded_hops.push(BlindedHop {
347+
blinded_node_id: PublicKey::from_slice(&[2; 33]).unwrap(),
348+
encrypted_payload: Vec::new()
349+
});
350+
}
351+
last_hops.push((payinfo, BlindedPath {
352+
introduction_node_id: *intro_node_id,
353+
blinding_point: PublicKey::from_slice(&[2; 33]).unwrap(),
354+
blinded_hops,
355+
}));
356+
}
357+
}
358+
let mut features = Bolt12InvoiceFeatures::empty();
359+
features.set_basic_mpp_optional();
360+
let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &net_graph, &logger);
361+
let random_seed_bytes: [u8; 32] = [get_slice!(1)[0]; 32];
362+
let final_value_msat = slice_to_be64(get_slice!(8));
363+
let _final_cltv_expiry_delta = slice_to_be32(get_slice!(4)); // for symmetry with non-blinded case
364+
let route_params = RouteParameters {
365+
payment_params: PaymentParameters::blinded(last_hops.clone())
366+
.with_bolt12_features(features.clone()).unwrap(),
367+
final_value_msat,
368+
};
369+
let _ = find_route(&our_pubkey, &route_params, &net_graph,
370+
first_hops.map(|c| c.iter().collect::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
371+
&logger, &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes);
372+
}
319373
}
320374
}
321375
}

lightning/src/blinded_path/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -36,26 +36,26 @@ pub struct BlindedPath {
3636
/// message or payment's next hop and forward it along.
3737
///
3838
/// [`encrypted_payload`]: BlindedHop::encrypted_payload
39-
pub(crate) introduction_node_id: PublicKey,
39+
pub introduction_node_id: PublicKey,
4040
/// Used by the introduction node to decrypt its [`encrypted_payload`] to forward the onion
4141
/// message or payment.
4242
///
4343
/// [`encrypted_payload`]: BlindedHop::encrypted_payload
44-
pub(crate) blinding_point: PublicKey,
44+
pub blinding_point: PublicKey,
4545
/// The hops composing the blinded path.
46-
pub(crate) blinded_hops: Vec<BlindedHop>,
46+
pub blinded_hops: Vec<BlindedHop>,
4747
}
4848

4949
/// Used to construct the blinded hops portion of a blinded path. These hops cannot be identified
5050
/// by outside observers and thus can be used to hide the identity of the recipient.
5151
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
5252
pub struct BlindedHop {
5353
/// The blinded node id of this hop in a blinded path.
54-
pub(crate) blinded_node_id: PublicKey,
54+
pub blinded_node_id: PublicKey,
5555
/// The encrypted payload intended for this hop in a blinded path.
5656
// The node sending to this blinded path will later encode this payload into the onion packet for
5757
// this hop.
58-
pub(crate) encrypted_payload: Vec<u8>,
58+
pub encrypted_payload: Vec<u8>,
5959
}
6060

6161
impl BlindedPath {

lightning/src/routing/router.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,8 @@ impl PaymentParameters {
656656
.with_expiry_time(invoice.created_at().as_secs().saturating_add(invoice.relative_expiry().as_secs()))
657657
}
658658

659-
fn blinded(blinded_route_hints: Vec<(BlindedPayInfo, BlindedPath)>) -> Self {
659+
/// Creates parameters for paying to a blinded payee from the provided blinded route hints.
660+
pub fn blinded(blinded_route_hints: Vec<(BlindedPayInfo, BlindedPath)>) -> Self {
660661
Self {
661662
payee: Payee::Blinded { route_hints: blinded_route_hints, features: None },
662663
expiry_time: None,

0 commit comments

Comments
 (0)