Skip to content

Commit 1b7f453

Browse files
f check for invalid provided blinded payment TLVs
1 parent e29fa03 commit 1b7f453

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

lightning/src/blinded_path/mod.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,25 @@ impl BlindedPath {
8080
/// Create a blinded path for a payment, to be forwarded along `path`. The last node
8181
/// in `path` will be the destination node.
8282
///
83-
/// Errors if `path` is empty, a node id in `path` is invalid, or [`BlindedPayInfo`] calculation
84-
/// results in an integer overflow.
83+
/// Errors if:
84+
/// * `path` is empty
85+
/// * a node id in `path` is invalid
86+
/// * [`BlindedPayInfo`] calculation results in an integer overflow
87+
/// * the list of [`BlindedPaymentTlvs`] does not consist of 0 or more
88+
/// `BlindedPaymentTlvs::Forward` followed by 1 `BlindedPaymentTlvs::Receive`
8589
// TODO: make all payloads the same size with padding + add dummy hops
8690
pub fn new_for_payment<ES: EntropySource, T: secp256k1::Signing + secp256k1::Verification>(
8791
path: &[(PublicKey, BlindedPaymentTlvs)], entropy_source: &ES, secp_ctx: &Secp256k1<T>
8892
) -> Result<(BlindedPayInfo, Self), ()> {
8993
if path.len() < 1 { return Err(()) }
94+
let mut found_recv_payload = false;
95+
for (_, payload) in path.iter() {
96+
if let BlindedPaymentTlvs::Receive { .. } = payload {
97+
if found_recv_payload { return Err(()) }
98+
found_recv_payload = true;
99+
} else if found_recv_payload { return Err(()) }
100+
}
101+
90102
let blinding_secret_bytes = entropy_source.get_secure_random_bytes();
91103
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
92104

lightning/src/blinded_path/payment.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,13 @@ impl_writeable_msg!(PaymentConstraints, {
220220

221221
#[cfg(test)]
222222
mod tests {
223-
use bitcoin::secp256k1::PublicKey;
223+
use bitcoin::network::constants::Network;
224+
use bitcoin::secp256k1::{PublicKey, Secp256k1};
225+
use crate::blinded_path::BlindedPath;
224226
use crate::blinded_path::payment::{BlindedPaymentTlvs, PaymentConstraints, PaymentRelay};
225227
use crate::ln::PaymentSecret;
226228
use crate::ln::features::BlindedHopFeatures;
229+
use crate::util::test_utils;
227230

228231
#[test]
229232
fn compute_payinfo() {
@@ -285,4 +288,50 @@ mod tests {
285288
assert_eq!(blinded_payinfo.cltv_expiry_delta, 0);
286289
assert_eq!(blinded_payinfo.htlc_minimum_msat, 1);
287290
}
291+
292+
#[test]
293+
fn invalid_payloads() {
294+
let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap();
295+
let secp_ctx = Secp256k1::new();
296+
let keys_manager = test_utils::TestKeysInterface::new(&[42 as u8; 32], Network::Testnet);
297+
298+
let out_of_order_payloads_path = vec![(dummy_pk, BlindedPaymentTlvs::Receive {
299+
payment_secret: PaymentSecret([0; 32]),
300+
payment_constraints: PaymentConstraints {
301+
max_cltv_expiry: 0,
302+
htlc_minimum_msat: 1,
303+
},
304+
features: BlindedHopFeatures::empty(),
305+
}), (dummy_pk, BlindedPaymentTlvs::Forward {
306+
short_channel_id: 0,
307+
payment_relay: PaymentRelay {
308+
cltv_expiry_delta: 144,
309+
fee_proportional_millionths: 500,
310+
fee_base_msat: 100,
311+
},
312+
payment_constraints: PaymentConstraints {
313+
max_cltv_expiry: 0,
314+
htlc_minimum_msat: 100,
315+
},
316+
features: BlindedHopFeatures::empty(),
317+
})];
318+
assert!(BlindedPath::new_for_payment(&out_of_order_payloads_path[..], &keys_manager, &secp_ctx).is_err());
319+
320+
let multiple_recv_payloads_path = vec![(dummy_pk, BlindedPaymentTlvs::Receive {
321+
payment_secret: PaymentSecret([0; 32]),
322+
payment_constraints: PaymentConstraints {
323+
max_cltv_expiry: 0,
324+
htlc_minimum_msat: 1,
325+
},
326+
features: BlindedHopFeatures::empty(),
327+
}), (dummy_pk, BlindedPaymentTlvs::Receive {
328+
payment_secret: PaymentSecret([0; 32]),
329+
payment_constraints: PaymentConstraints {
330+
max_cltv_expiry: 0,
331+
htlc_minimum_msat: 1,
332+
},
333+
features: BlindedHopFeatures::empty(),
334+
})];
335+
assert!(BlindedPath::new_for_payment(&multiple_recv_payloads_path[..], &keys_manager, &secp_ctx).is_err());
336+
}
288337
}

0 commit comments

Comments
 (0)