Skip to content

Commit

Permalink
Fuzz test blinded payment pathfinding
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinewallace committed Jul 25, 2023
1 parent d75ede5 commit e7d5950
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 7 deletions.
56 changes: 55 additions & 1 deletion fuzz/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -279,7 +282,7 @@ pub fn do_test<Out: test_logger::Output>(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();
Expand Down Expand Up @@ -316,6 +319,57 @@ pub fn do_test<Out: test_logger::Output>(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 _final_cltv_expiry_delta = slice_to_be32(get_slice!(4)); // for symmetry with non-blinded case
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::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
&logger, &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes);
}
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions lightning/src/blinded_path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,26 @@ 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<BlindedHop>,
pub blinded_hops: Vec<BlindedHop>,
}

/// Used to construct the blinded hops portion of a blinded path. These hops cannot be identified
/// by outside observers and thus can be used to hide the identity of the recipient.
#[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<u8>,
pub encrypted_payload: Vec<u8>,
}

impl BlindedPath {
Expand Down
3 changes: 2 additions & 1 deletion lightning/src/routing/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,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,
Expand Down

0 comments on commit e7d5950

Please sign in to comment.