From 851ebf702410963ad5df95e823daf97ab7854fc4 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Tue, 20 Jun 2023 12:59:35 -0400 Subject: [PATCH] Fuzz test blinded payment pathfinding --- fuzz/src/router.rs | 55 ++++++++++++++++++++++++++++++- lightning/src/blinded_path/mod.rs | 10 +++--- lightning/src/routing/router.rs | 3 +- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/fuzz/src/router.rs b/fuzz/src/router.rs index cc0d47d1cdb..86a356a594f 100644 --- a/fuzz/src/router.rs +++ b/fuzz/src/router.rs @@ -11,9 +11,12 @@ use bitcoin::blockdata::script::Builder; use bitcoin::blockdata::transaction::TxOut; use bitcoin::hash_types::BlockHash; +use lightning::blinded_path::{BlindedHop, BlindedPath}; use lightning::chain::transaction::OutPoint; use lightning::ln::channelmanager::{self, ChannelDetails, ChannelCounterparty}; +use lightning::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures}; use lightning::ln::msgs; +use lightning::offers::invoice::BlindedPayInfo; use lightning::routing::gossip::{NetworkGraph, RoutingFees}; use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoLookupError, UtxoResult}; use lightning::routing::router::{find_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters}; @@ -279,7 +282,7 @@ pub fn do_test(data: &[u8], out: Out) { net_graph.channel_failed_permanent(short_channel_id); }, _ if node_pks.is_empty() => {}, - _ => { + x if x < 250 => { let mut first_hops_vec = Vec::new(); let first_hops = first_hops!(first_hops_vec); let mut last_hops = Vec::new(); @@ -316,6 +319,56 @@ pub fn do_test(data: &[u8], out: Out) { &logger, &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes); } }, + x => { + let mut first_hops_vec = Vec::new(); + let first_hops = first_hops!(first_hops_vec); + let mut last_hops = Vec::new(); + { + let count = get_slice!(1)[0]; + for _ in 0..count { + // Fetch values in the same order as above to improve coverage. + let intro_node_id = node_pks.iter().skip(slice_to_be16(get_slice!(2)) as usize % node_pks.len()).next().unwrap(); + let fee_base_msat = slice_to_be32(get_slice!(4)); + let fee_proportional_millionths = slice_to_be32(get_slice!(4)); + let cltv_expiry_delta = slice_to_be16(get_slice!(2)); + let htlc_minimum_msat = slice_to_be64(get_slice!(8)); + let payinfo = BlindedPayInfo { + fee_base_msat, + fee_proportional_millionths, + htlc_minimum_msat, + htlc_maximum_msat: htlc_minimum_msat.saturating_mul(100), + cltv_expiry_delta, + features: BlindedHopFeatures::empty(), + }; + let num_blinded_hops = x % 250; + let mut blinded_hops = Vec::new(); + for _ in 0..num_blinded_hops { + blinded_hops.push(BlindedHop { + blinded_node_id: PublicKey::from_slice(&[2; 33]).unwrap(), + encrypted_payload: Vec::new() + }); + } + last_hops.push((payinfo, BlindedPath { + introduction_node_id: *intro_node_id, + blinding_point: PublicKey::from_slice(&[2; 33]).unwrap(), + blinded_hops, + })); + } + } + let mut features = Bolt12InvoiceFeatures::empty(); + features.set_basic_mpp_optional(); + let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &net_graph, &logger); + let random_seed_bytes: [u8; 32] = [get_slice!(1)[0]; 32]; + let final_value_msat = slice_to_be64(get_slice!(8)); + let route_params = RouteParameters { + payment_params: PaymentParameters::blinded(last_hops.clone()) + .with_bolt12_features(features.clone()).unwrap(), + final_value_msat, + }; + let _ = find_route(&our_pubkey, &route_params, &net_graph, + first_hops.map(|c| c.iter().collect::>()).as_ref().map(|a| a.as_slice()), + &logger, &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes); + } } } } diff --git a/lightning/src/blinded_path/mod.rs b/lightning/src/blinded_path/mod.rs index 97d3a408cdb..dabfb79c755 100644 --- a/lightning/src/blinded_path/mod.rs +++ b/lightning/src/blinded_path/mod.rs @@ -36,14 +36,14 @@ pub struct BlindedPath { /// message or payment's next hop and forward it along. /// /// [`encrypted_payload`]: BlindedHop::encrypted_payload - pub(crate) introduction_node_id: PublicKey, + pub introduction_node_id: PublicKey, /// Used by the introduction node to decrypt its [`encrypted_payload`] to forward the onion /// message or payment. /// /// [`encrypted_payload`]: BlindedHop::encrypted_payload - pub(crate) blinding_point: PublicKey, + pub blinding_point: PublicKey, /// The hops composing the blinded path. - pub(crate) blinded_hops: Vec, + pub blinded_hops: Vec, } /// Used to construct the blinded hops portion of a blinded path. These hops cannot be identified @@ -51,11 +51,11 @@ pub struct BlindedPath { #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct BlindedHop { /// The blinded node id of this hop in a blinded path. - pub(crate) blinded_node_id: PublicKey, + pub blinded_node_id: PublicKey, /// The encrypted payload intended for this hop in a blinded path. // The node sending to this blinded path will later encode this payload into the onion packet for // this hop. - pub(crate) encrypted_payload: Vec, + pub encrypted_payload: Vec, } impl BlindedPath { diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 9242e98b1ab..b9d2d764f7a 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -653,7 +653,8 @@ impl PaymentParameters { .with_expiry_time(invoice.created_at().as_secs().saturating_add(invoice.relative_expiry().as_secs())) } - fn blinded(blinded_route_hints: Vec<(BlindedPayInfo, BlindedPath)>) -> Self { + /// Creates parameters for paying to a blinded payee from the provided blinded route hints. + pub fn blinded(blinded_route_hints: Vec<(BlindedPayInfo, BlindedPath)>) -> Self { Self { payee: Payee::Blinded { route_hints: blinded_route_hints, features: None }, expiry_time: None,