Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 53 additions & 49 deletions fuzz/src/invoice_request_deser.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,15 +10,22 @@
use crate::utils::test_logger;
use bitcoin::secp256k1::{self, Keypair, Parity, PublicKey, Secp256k1, SecretKey};
use core::convert::TryFrom;
use lightning::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
use lightning::blinded_path::payment::{
Bolt12OfferContext, ForwardNode, ForwardTlvs, PaymentConstraints, PaymentContext, PaymentRelay,
ReceiveTlvs,
};
use lightning::blinded_path::BlindedPath;
use lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA;
use lightning::ln::features::BlindedHopFeatures;
use lightning::ln::types::PaymentSecret;
use lightning::ln::PaymentHash;
use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
use lightning::offers::invoice_request::InvoiceRequest;
use lightning::offers::invoice::UnsignedBolt12Invoice;
use lightning::offers::invoice_request::{InvoiceRequest, InvoiceRequestFields};
use lightning::offers::offer::OfferId;
use lightning::offers::parse::Bolt12SemanticError;
use lightning::sign::EntropySource;
use lightning::util::ser::Writeable;
use lightning::util::string::UntrustedString;

#[inline]
pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
Expand DownExpand Up@@ -76,57 +83,54 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
invoice_request: &InvoiceRequest, secp_ctx: &Secp256k1<T>,
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
let entropy_source = Randomness {};
let intermediate_nodes = [
[
ForwardNode { node_id: pubkey(43), short_channel_id: None },
ForwardNode { node_id: pubkey(44), short_channel_id: None },
],
[
ForwardNode { node_id: pubkey(45), short_channel_id: None },
ForwardNode { node_id: pubkey(46), short_channel_id: None },
],
];
let paths = vec![
BlindedPath::new_for_message(
&intermediate_nodes[0],
pubkey(42),
MessageContext::Offers(OffersContext::Unknown {}),
&entropy_source,
secp_ctx,
)
.unwrap(),
BlindedPath::new_for_message(
&intermediate_nodes[1],
pubkey(42),
MessageContext::Offers(OffersContext::Unknown {}),
&entropy_source,
secp_ctx,
)
.unwrap(),
];

let payinfo = vec![
BlindedPayInfo {
fee_base_msat: 1,
fee_proportional_millionths: 1_000,
cltv_expiry_delta: 42,
htlc_minimum_msat: 100,
htlc_maximum_msat: 1_000_000_000_000,
features: BlindedHopFeatures::empty(),
let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext {
offer_id: OfferId([42; 32]),
invoice_request: InvoiceRequestFields {
payer_id: invoice_request.payer_id(),
quantity: invoice_request.quantity(),
payer_note_truncated: invoice_request
.payer_note()
.map(|s| UntrustedString(s.to_string())),
},
});
let payee_tlvs = ReceiveTlvs {
payment_secret: PaymentSecret([42; 32]),
payment_constraints: PaymentConstraints {
max_cltv_expiry: 1_000_000,
htlc_minimum_msat: 1,
},
BlindedPayInfo {
fee_base_msat: 1,
fee_proportional_millionths: 1_000,
cltv_expiry_delta: 42,
htlc_minimum_msat: 100,
htlc_maximum_msat: 1_000_000_000_000,
payment_context,
};
let intermediate_nodes = [ForwardNode {
tlvs: ForwardTlvs {
short_channel_id: 43,
payment_relay: PaymentRelay {
cltv_expiry_delta: 40,
fee_proportional_millionths: 1_000,
fee_base_msat: 1,
},
payment_constraints: PaymentConstraints {
max_cltv_expiry: payee_tlvs.payment_constraints.max_cltv_expiry + 40,
htlc_minimum_msat: 100,
},
features: BlindedHopFeatures::empty(),
},
];
node_id: pubkey(43),
htlc_maximum_msat: 1_000_000_000_000,
}];
let payment_path = BlindedPath::new_for_payment(
&intermediate_nodes,
pubkey(42),
payee_tlvs,
u64::MAX,
MIN_FINAL_CLTV_EXPIRY_DELTA,
&entropy_source,
secp_ctx,
)
.unwrap();

let payment_paths = payinfo.into_iter().zip(paths.into_iter()).collect();
let payment_hash = PaymentHash([42; 32]);
invoice_request.respond_with(payment_paths, payment_hash)?.build()
invoice_request.respond_with(vec![payment_path], payment_hash)?.build()
}

pub fn invoice_request_deser_test<Out: test_logger::Output>(data: &[u8], out: Out) {
Expand Down
3 changes: 2 additions & 1 deletion fuzz/src/onion_message.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -106,7 +106,8 @@ struct TestOffersMessageHandler {}

impl OffersMessageHandler for TestOffersMessageHandler {
fn handle_message(
&self, _message: OffersMessage, _context: OffersContext, _responder: Option<Responder>,
&self, _message: OffersMessage, _context: Option<OffersContext>,
_responder: Option<Responder>,
) -> ResponseInstruction<OffersMessage> {
ResponseInstruction::NoResponse
}
Expand Down
89 changes: 41 additions & 48 deletions fuzz/src/refund_deser.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,11 +10,16 @@
use crate::utils::test_logger;
use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1, SecretKey};
use core::convert::TryFrom;
use lightning::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
use lightning::blinded_path::payment::{
Bolt12RefundContext, ForwardNode, ForwardTlvs, PaymentConstraints, PaymentContext,
PaymentRelay, ReceiveTlvs,
};
use lightning::blinded_path::BlindedPath;
use lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA;
use lightning::ln::features::BlindedHopFeatures;
use lightning::ln::types::PaymentSecret;
use lightning::ln::PaymentHash;
use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
use lightning::offers::invoice::UnsignedBolt12Invoice;
use lightning::offers::parse::Bolt12SemanticError;
use lightning::offers::refund::Refund;
use lightning::sign::EntropySource;
Expand DownExpand Up@@ -65,57 +70,45 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
refund: &Refund, signing_pubkey: PublicKey, secp_ctx: &Secp256k1<T>,
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
let entropy_source = Randomness {};
let intermediate_nodes = [
[
ForwardNode { node_id: pubkey(43), short_channel_id: None },
ForwardNode { node_id: pubkey(44), short_channel_id: None },
],
[
ForwardNode { node_id: pubkey(45), short_channel_id: None },
ForwardNode { node_id: pubkey(46), short_channel_id: None },
],
];
let paths = vec![
BlindedPath::new_for_message(
&intermediate_nodes[0],
pubkey(42),
MessageContext::Offers(OffersContext::Unknown {}),
&entropy_source,
secp_ctx,
)
.unwrap(),
BlindedPath::new_for_message(
&intermediate_nodes[1],
pubkey(42),
MessageContext::Offers(OffersContext::Unknown {}),
&entropy_source,
secp_ctx,
)
.unwrap(),
];

let payinfo = vec![
BlindedPayInfo {
fee_base_msat: 1,
fee_proportional_millionths: 1_000,
cltv_expiry_delta: 42,
htlc_minimum_msat: 100,
htlc_maximum_msat: 1_000_000_000_000,
features: BlindedHopFeatures::empty(),
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
let payee_tlvs = ReceiveTlvs {
payment_secret: PaymentSecret([42; 32]),
payment_constraints: PaymentConstraints {
max_cltv_expiry: 1_000_000,
htlc_minimum_msat: 1,
},
BlindedPayInfo {
fee_base_msat: 1,
fee_proportional_millionths: 1_000,
cltv_expiry_delta: 42,
htlc_minimum_msat: 100,
htlc_maximum_msat: 1_000_000_000_000,
payment_context,
};
let intermediate_nodes = [ForwardNode {
tlvs: ForwardTlvs {
short_channel_id: 43,
payment_relay: PaymentRelay {
cltv_expiry_delta: 40,
fee_proportional_millionths: 1_000,
fee_base_msat: 1,
},
payment_constraints: PaymentConstraints {
max_cltv_expiry: payee_tlvs.payment_constraints.max_cltv_expiry + 40,
htlc_minimum_msat: 100,
},
features: BlindedHopFeatures::empty(),
},
];
node_id: pubkey(43),
htlc_maximum_msat: 1_000_000_000_000,
}];
let payment_path = BlindedPath::new_for_payment(
&intermediate_nodes,
pubkey(42),
payee_tlvs,
u64::MAX,
MIN_FINAL_CLTV_EXPIRY_DELTA,
&entropy_source,
secp_ctx,
)
.unwrap();

let payment_paths = payinfo.into_iter().zip(paths.into_iter()).collect();
let payment_hash = PaymentHash([42; 32]);
refund.respond_with(payment_paths, payment_hash, signing_pubkey)?.build()
refund.respond_with(vec![payment_path], payment_hash, signing_pubkey)?.build()
}

pub fn refund_deser_test<Out: test_logger::Output>(data: &[u8], out: Out) {
Expand Down
27 changes: 18 additions & 9 deletions lightning/src/blinded_path/message.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,7 @@ use crate::blinded_path::utils;
use crate::io;
use crate::io::Cursor;
use crate::ln::channelmanager::PaymentId;
use crate::ln::onion_utils;
use crate::ln::{PaymentHash, onion_utils};
use crate::offers::nonce::Nonce;
use crate::onion_message::packet::ControlTlvs;
use crate::sign::{NodeSigner, Recipient};
Expand DownExpand Up@@ -108,11 +108,6 @@ pub enum MessageContext {
/// [`OffersMessage`]: crate::onion_message::offers::OffersMessage
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum OffersContext {
/// Represents an unknown BOLT12 message context.
///
/// This variant is used when a message is sent without using a [`BlindedPath`] or over one
/// created prior to LDK version 0.0.124.
Unknown {},
/// Context used by a [`BlindedPath`] within an [`Offer`].
///
/// This variant is intended to be received when handling an [`InvoiceRequest`].
Expand DownExpand Up@@ -152,6 +147,18 @@ pub enum OffersContext {
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
nonce: Nonce,
},
/// Context used by a [`BlindedPath`] as a reply path for a [`Bolt12Invoice`].
///
/// This variant is intended to be received when handling an [`InvoiceError`].
///
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
/// [`InvoiceError`]: crate::offers::invoice_error::InvoiceError
InboundPayment {
/// The same payment hash as [`Bolt12Invoice::payment_hash`].
///
/// [`Bolt12Invoice::payment_hash`]: crate::offers::invoice::Bolt12Invoice::payment_hash
payment_hash: PaymentHash,
},
}

impl_writeable_tlv_based_enum!(MessageContext,
Expand All@@ -160,14 +167,16 @@ impl_writeable_tlv_based_enum!(MessageContext,
);

impl_writeable_tlv_based_enum!(OffersContext,
(0, Unknown) => {},
(1, InvoiceRequest) => {
(0, InvoiceRequest) => {
(0, nonce, required),
},
(2, OutboundPayment) => {
(1, OutboundPayment) => {
(0, payment_id, required),
(1, nonce, required),
},
(2, InboundPayment) => {
(0, payment_hash, required),
},
);

/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
Expand Down
8 changes: 4 additions & 4 deletions lightning/src/events/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -810,7 +810,7 @@ pub enum Event {
/// The context of the [`BlindedPath`] used to send the invoice.
///
/// [`BlindedPath`]: crate::blinded_path::BlindedPath
context: OffersContext,
context: Option<OffersContext>,
/// A responder for replying with an [`InvoiceError`] if needed.
///
/// `None` if the invoice wasn't sent with a reply path.
Expand DownExpand Up@@ -1658,7 +1658,7 @@ impl Writeable for Event {
write_tlv_fields!(writer, {
(0, payment_id, required),
(2, invoice, required),
(4, context, required),
(4, context, option),
(6, responder, option),
});
},
Expand DownExpand Up@@ -2113,13 +2113,13 @@ impl MaybeReadable for Event {
_init_and_read_len_prefixed_tlv_fields!(reader, {
(0, payment_id, required),
(2, invoice, required),
(4, context, required),
(4, context, option),
(6, responder, option),
});
Ok(Some(Event::InvoiceReceived {
payment_id: payment_id.0.unwrap(),
invoice: invoice.0.unwrap(),
context: context.0.unwrap(),
context,
responder,
}))
};
Expand Down
Loading