Skip to content

Commit 85e5e6a

Browse files
authored
Merge pull request #3202 from jkczyz/2024-07-blinded-path-auth-follow-up
Follow-ups to #3139
2 parents 8c1b3d1 + 8834336 commit 85e5e6a

17 files changed

+299
-205
lines changed

fuzz/src/invoice_request_deser.rs

+53-49
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,22 @@
1010
use crate::utils::test_logger;
1111
use bitcoin::secp256k1::{self, Keypair, Parity, PublicKey, Secp256k1, SecretKey};
1212
use core::convert::TryFrom;
13-
use lightning::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
13+
use lightning::blinded_path::payment::{
14+
Bolt12OfferContext, ForwardNode, ForwardTlvs, PaymentConstraints, PaymentContext, PaymentRelay,
15+
ReceiveTlvs,
16+
};
1417
use lightning::blinded_path::BlindedPath;
18+
use lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA;
1519
use lightning::ln::features::BlindedHopFeatures;
20+
use lightning::ln::types::PaymentSecret;
1621
use lightning::ln::PaymentHash;
17-
use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
18-
use lightning::offers::invoice_request::InvoiceRequest;
22+
use lightning::offers::invoice::UnsignedBolt12Invoice;
23+
use lightning::offers::invoice_request::{InvoiceRequest, InvoiceRequestFields};
24+
use lightning::offers::offer::OfferId;
1925
use lightning::offers::parse::Bolt12SemanticError;
2026
use lightning::sign::EntropySource;
2127
use lightning::util::ser::Writeable;
28+
use lightning::util::string::UntrustedString;
2229

2330
#[inline]
2431
pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
@@ -76,57 +83,54 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
7683
invoice_request: &InvoiceRequest, secp_ctx: &Secp256k1<T>,
7784
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
7885
let entropy_source = Randomness {};
79-
let intermediate_nodes = [
80-
[
81-
ForwardNode { node_id: pubkey(43), short_channel_id: None },
82-
ForwardNode { node_id: pubkey(44), short_channel_id: None },
83-
],
84-
[
85-
ForwardNode { node_id: pubkey(45), short_channel_id: None },
86-
ForwardNode { node_id: pubkey(46), short_channel_id: None },
87-
],
88-
];
89-
let paths = vec![
90-
BlindedPath::new_for_message(
91-
&intermediate_nodes[0],
92-
pubkey(42),
93-
MessageContext::Offers(OffersContext::Unknown {}),
94-
&entropy_source,
95-
secp_ctx,
96-
)
97-
.unwrap(),
98-
BlindedPath::new_for_message(
99-
&intermediate_nodes[1],
100-
pubkey(42),
101-
MessageContext::Offers(OffersContext::Unknown {}),
102-
&entropy_source,
103-
secp_ctx,
104-
)
105-
.unwrap(),
106-
];
107-
108-
let payinfo = vec![
109-
BlindedPayInfo {
110-
fee_base_msat: 1,
111-
fee_proportional_millionths: 1_000,
112-
cltv_expiry_delta: 42,
113-
htlc_minimum_msat: 100,
114-
htlc_maximum_msat: 1_000_000_000_000,
115-
features: BlindedHopFeatures::empty(),
86+
let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext {
87+
offer_id: OfferId([42; 32]),
88+
invoice_request: InvoiceRequestFields {
89+
payer_id: invoice_request.payer_id(),
90+
quantity: invoice_request.quantity(),
91+
payer_note_truncated: invoice_request
92+
.payer_note()
93+
.map(|s| UntrustedString(s.to_string())),
94+
},
95+
});
96+
let payee_tlvs = ReceiveTlvs {
97+
payment_secret: PaymentSecret([42; 32]),
98+
payment_constraints: PaymentConstraints {
99+
max_cltv_expiry: 1_000_000,
100+
htlc_minimum_msat: 1,
116101
},
117-
BlindedPayInfo {
118-
fee_base_msat: 1,
119-
fee_proportional_millionths: 1_000,
120-
cltv_expiry_delta: 42,
121-
htlc_minimum_msat: 100,
122-
htlc_maximum_msat: 1_000_000_000_000,
102+
payment_context,
103+
};
104+
let intermediate_nodes = [ForwardNode {
105+
tlvs: ForwardTlvs {
106+
short_channel_id: 43,
107+
payment_relay: PaymentRelay {
108+
cltv_expiry_delta: 40,
109+
fee_proportional_millionths: 1_000,
110+
fee_base_msat: 1,
111+
},
112+
payment_constraints: PaymentConstraints {
113+
max_cltv_expiry: payee_tlvs.payment_constraints.max_cltv_expiry + 40,
114+
htlc_minimum_msat: 100,
115+
},
123116
features: BlindedHopFeatures::empty(),
124117
},
125-
];
118+
node_id: pubkey(43),
119+
htlc_maximum_msat: 1_000_000_000_000,
120+
}];
121+
let payment_path = BlindedPath::new_for_payment(
122+
&intermediate_nodes,
123+
pubkey(42),
124+
payee_tlvs,
125+
u64::MAX,
126+
MIN_FINAL_CLTV_EXPIRY_DELTA,
127+
&entropy_source,
128+
secp_ctx,
129+
)
130+
.unwrap();
126131

127-
let payment_paths = payinfo.into_iter().zip(paths.into_iter()).collect();
128132
let payment_hash = PaymentHash([42; 32]);
129-
invoice_request.respond_with(payment_paths, payment_hash)?.build()
133+
invoice_request.respond_with(vec![payment_path], payment_hash)?.build()
130134
}
131135

132136
pub fn invoice_request_deser_test<Out: test_logger::Output>(data: &[u8], out: Out) {

fuzz/src/onion_message.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ struct TestOffersMessageHandler {}
106106

107107
impl OffersMessageHandler for TestOffersMessageHandler {
108108
fn handle_message(
109-
&self, _message: OffersMessage, _context: OffersContext, _responder: Option<Responder>,
109+
&self, _message: OffersMessage, _context: Option<OffersContext>,
110+
_responder: Option<Responder>,
110111
) -> ResponseInstruction<OffersMessage> {
111112
ResponseInstruction::NoResponse
112113
}

fuzz/src/refund_deser.rs

+41-48
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@
1010
use crate::utils::test_logger;
1111
use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1, SecretKey};
1212
use core::convert::TryFrom;
13-
use lightning::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
13+
use lightning::blinded_path::payment::{
14+
Bolt12RefundContext, ForwardNode, ForwardTlvs, PaymentConstraints, PaymentContext,
15+
PaymentRelay, ReceiveTlvs,
16+
};
1417
use lightning::blinded_path::BlindedPath;
18+
use lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA;
1519
use lightning::ln::features::BlindedHopFeatures;
20+
use lightning::ln::types::PaymentSecret;
1621
use lightning::ln::PaymentHash;
17-
use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
22+
use lightning::offers::invoice::UnsignedBolt12Invoice;
1823
use lightning::offers::parse::Bolt12SemanticError;
1924
use lightning::offers::refund::Refund;
2025
use lightning::sign::EntropySource;
@@ -65,57 +70,45 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
6570
refund: &Refund, signing_pubkey: PublicKey, secp_ctx: &Secp256k1<T>,
6671
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
6772
let entropy_source = Randomness {};
68-
let intermediate_nodes = [
69-
[
70-
ForwardNode { node_id: pubkey(43), short_channel_id: None },
71-
ForwardNode { node_id: pubkey(44), short_channel_id: None },
72-
],
73-
[
74-
ForwardNode { node_id: pubkey(45), short_channel_id: None },
75-
ForwardNode { node_id: pubkey(46), short_channel_id: None },
76-
],
77-
];
78-
let paths = vec![
79-
BlindedPath::new_for_message(
80-
&intermediate_nodes[0],
81-
pubkey(42),
82-
MessageContext::Offers(OffersContext::Unknown {}),
83-
&entropy_source,
84-
secp_ctx,
85-
)
86-
.unwrap(),
87-
BlindedPath::new_for_message(
88-
&intermediate_nodes[1],
89-
pubkey(42),
90-
MessageContext::Offers(OffersContext::Unknown {}),
91-
&entropy_source,
92-
secp_ctx,
93-
)
94-
.unwrap(),
95-
];
96-
97-
let payinfo = vec![
98-
BlindedPayInfo {
99-
fee_base_msat: 1,
100-
fee_proportional_millionths: 1_000,
101-
cltv_expiry_delta: 42,
102-
htlc_minimum_msat: 100,
103-
htlc_maximum_msat: 1_000_000_000_000,
104-
features: BlindedHopFeatures::empty(),
73+
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
74+
let payee_tlvs = ReceiveTlvs {
75+
payment_secret: PaymentSecret([42; 32]),
76+
payment_constraints: PaymentConstraints {
77+
max_cltv_expiry: 1_000_000,
78+
htlc_minimum_msat: 1,
10579
},
106-
BlindedPayInfo {
107-
fee_base_msat: 1,
108-
fee_proportional_millionths: 1_000,
109-
cltv_expiry_delta: 42,
110-
htlc_minimum_msat: 100,
111-
htlc_maximum_msat: 1_000_000_000_000,
80+
payment_context,
81+
};
82+
let intermediate_nodes = [ForwardNode {
83+
tlvs: ForwardTlvs {
84+
short_channel_id: 43,
85+
payment_relay: PaymentRelay {
86+
cltv_expiry_delta: 40,
87+
fee_proportional_millionths: 1_000,
88+
fee_base_msat: 1,
89+
},
90+
payment_constraints: PaymentConstraints {
91+
max_cltv_expiry: payee_tlvs.payment_constraints.max_cltv_expiry + 40,
92+
htlc_minimum_msat: 100,
93+
},
11294
features: BlindedHopFeatures::empty(),
11395
},
114-
];
96+
node_id: pubkey(43),
97+
htlc_maximum_msat: 1_000_000_000_000,
98+
}];
99+
let payment_path = BlindedPath::new_for_payment(
100+
&intermediate_nodes,
101+
pubkey(42),
102+
payee_tlvs,
103+
u64::MAX,
104+
MIN_FINAL_CLTV_EXPIRY_DELTA,
105+
&entropy_source,
106+
secp_ctx,
107+
)
108+
.unwrap();
115109

116-
let payment_paths = payinfo.into_iter().zip(paths.into_iter()).collect();
117110
let payment_hash = PaymentHash([42; 32]);
118-
refund.respond_with(payment_paths, payment_hash, signing_pubkey)?.build()
111+
refund.respond_with(vec![payment_path], payment_hash, signing_pubkey)?.build()
119112
}
120113

121114
pub fn refund_deser_test<Out: test_logger::Output>(data: &[u8], out: Out) {

lightning/src/blinded_path/message.rs

+18-9
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::blinded_path::utils;
2121
use crate::io;
2222
use crate::io::Cursor;
2323
use crate::ln::channelmanager::PaymentId;
24-
use crate::ln::onion_utils;
24+
use crate::ln::{PaymentHash, onion_utils};
2525
use crate::offers::nonce::Nonce;
2626
use crate::onion_message::packet::ControlTlvs;
2727
use crate::sign::{NodeSigner, Recipient};
@@ -108,11 +108,6 @@ pub enum MessageContext {
108108
/// [`OffersMessage`]: crate::onion_message::offers::OffersMessage
109109
#[derive(Clone, Debug, Eq, PartialEq)]
110110
pub enum OffersContext {
111-
/// Represents an unknown BOLT12 message context.
112-
///
113-
/// This variant is used when a message is sent without using a [`BlindedPath`] or over one
114-
/// created prior to LDK version 0.0.124.
115-
Unknown {},
116111
/// Context used by a [`BlindedPath`] within an [`Offer`].
117112
///
118113
/// This variant is intended to be received when handling an [`InvoiceRequest`].
@@ -152,6 +147,18 @@ pub enum OffersContext {
152147
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
153148
nonce: Nonce,
154149
},
150+
/// Context used by a [`BlindedPath`] as a reply path for a [`Bolt12Invoice`].
151+
///
152+
/// This variant is intended to be received when handling an [`InvoiceError`].
153+
///
154+
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
155+
/// [`InvoiceError`]: crate::offers::invoice_error::InvoiceError
156+
InboundPayment {
157+
/// The same payment hash as [`Bolt12Invoice::payment_hash`].
158+
///
159+
/// [`Bolt12Invoice::payment_hash`]: crate::offers::invoice::Bolt12Invoice::payment_hash
160+
payment_hash: PaymentHash,
161+
},
155162
}
156163

157164
impl_writeable_tlv_based_enum!(MessageContext,
@@ -160,14 +167,16 @@ impl_writeable_tlv_based_enum!(MessageContext,
160167
);
161168

162169
impl_writeable_tlv_based_enum!(OffersContext,
163-
(0, Unknown) => {},
164-
(1, InvoiceRequest) => {
170+
(0, InvoiceRequest) => {
165171
(0, nonce, required),
166172
},
167-
(2, OutboundPayment) => {
173+
(1, OutboundPayment) => {
168174
(0, payment_id, required),
169175
(1, nonce, required),
170176
},
177+
(2, InboundPayment) => {
178+
(0, payment_hash, required),
179+
},
171180
);
172181

173182
/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.

lightning/src/events/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ pub enum Event {
810810
/// The context of the [`BlindedPath`] used to send the invoice.
811811
///
812812
/// [`BlindedPath`]: crate::blinded_path::BlindedPath
813-
context: OffersContext,
813+
context: Option<OffersContext>,
814814
/// A responder for replying with an [`InvoiceError`] if needed.
815815
///
816816
/// `None` if the invoice wasn't sent with a reply path.
@@ -1658,7 +1658,7 @@ impl Writeable for Event {
16581658
write_tlv_fields!(writer, {
16591659
(0, payment_id, required),
16601660
(2, invoice, required),
1661-
(4, context, required),
1661+
(4, context, option),
16621662
(6, responder, option),
16631663
});
16641664
},
@@ -2113,13 +2113,13 @@ impl MaybeReadable for Event {
21132113
_init_and_read_len_prefixed_tlv_fields!(reader, {
21142114
(0, payment_id, required),
21152115
(2, invoice, required),
2116-
(4, context, required),
2116+
(4, context, option),
21172117
(6, responder, option),
21182118
});
21192119
Ok(Some(Event::InvoiceReceived {
21202120
payment_id: payment_id.0.unwrap(),
21212121
invoice: invoice.0.unwrap(),
2122-
context: context.0.unwrap(),
2122+
context,
21232123
responder,
21242124
}))
21252125
};

0 commit comments

Comments
 (0)