Skip to content

Follow-ups to #3139 #3202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
102 changes: 53 additions & 49 deletions fuzz/src/invoice_request_deser.rs
Original file line number Diff line number Diff 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 Down Expand 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 number Diff line number Diff 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 number Diff line number Diff 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 Down Expand 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 number Diff line number Diff 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 Down Expand 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 Down Expand 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 number Diff line number Diff 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 Down Expand 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 Down Expand 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
Loading