Skip to content

Commit ddaf22f

Browse files
Fail out-of-PaymentContext inbound keysends
Here we bubble up the payment context into PendingHTLCRouting::ReceiveKeysend and check it when receiving a spontaneous payment prior to generating a claimable event. Prior to this patch, we would have accepted out-of-context keysends sent over blinded paths taken from our BOLT 12 invoices. As a side effect of this, our blinded keysend success test cases now fail, so those tests are now removed. Their coverage is re-added in future commits when we add support for async receive, meaning we're able to receive blinded keysends in the correct payment context.
1 parent d5bb547 commit ddaf22f

File tree

4 files changed

+85
-172
lines changed

4 files changed

+85
-172
lines changed

Diff for: lightning/src/ln/async_payments_tests.rs

+1-168
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@
99

1010
use crate::blinded_path::message::{MessageContext, OffersContext};
1111
use crate::events::{Event, HTLCDestination, MessageSendEventsProvider, PaymentFailureReason};
12-
use crate::ln::blinded_payment_tests::{blinded_payment_path, get_blinded_route_parameters};
13-
use crate::ln::channelmanager;
12+
use crate::ln::blinded_payment_tests::get_blinded_route_parameters;
1413
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
1514
use crate::ln::functional_test_utils::*;
16-
use crate::ln::inbound_payment;
1715
use crate::ln::msgs::ChannelMessageHandler;
1816
use crate::ln::msgs::OnionMessageHandler;
1917
use crate::ln::offers_tests;
@@ -29,11 +27,8 @@ use crate::onion_message::messenger::{Destination, MessageRouter, MessageSendIns
2927
use crate::onion_message::offers::OffersMessage;
3028
use crate::onion_message::packet::ParsedOnionMessageContents;
3129
use crate::prelude::*;
32-
use crate::routing::router::{PaymentParameters, RouteParameters};
33-
use crate::sign::NodeSigner;
3430
use crate::types::features::Bolt12InvoiceFeatures;
3531
use crate::types::payment::{PaymentPreimage, PaymentSecret};
36-
use crate::util::config::UserConfig;
3732
use bitcoin::secp256k1;
3833
use bitcoin::secp256k1::Secp256k1;
3934

@@ -67,168 +62,6 @@ fn create_static_invoice<T: secp256k1::Signing + secp256k1::Verification>(
6762
(offer, static_invoice)
6863
}
6964

70-
#[test]
71-
fn blinded_keysend() {
72-
let chanmon_cfgs = create_chanmon_cfgs(3);
73-
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
74-
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
75-
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
76-
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
77-
let chan_upd_1_2 =
78-
create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0).0.contents;
79-
80-
let inbound_payment_key = nodes[2].keys_manager.get_inbound_payment_key();
81-
let payment_secret = inbound_payment::create_for_spontaneous_payment(
82-
&inbound_payment_key,
83-
None,
84-
u32::MAX,
85-
nodes[2].node.duration_since_epoch().as_secs(),
86-
None,
87-
)
88-
.unwrap();
89-
90-
let amt_msat = 5000;
91-
let keysend_preimage = PaymentPreimage([42; 32]);
92-
let route_params = get_blinded_route_parameters(
93-
amt_msat,
94-
payment_secret,
95-
1,
96-
1_0000_0000,
97-
nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(),
98-
&[&chan_upd_1_2],
99-
&chanmon_cfgs[2].keys_manager,
100-
);
101-
102-
let payment_hash = nodes[0]
103-
.node
104-
.send_spontaneous_payment(
105-
Some(keysend_preimage),
106-
RecipientOnionFields::spontaneous_empty(),
107-
PaymentId(keysend_preimage.0),
108-
route_params,
109-
Retry::Attempts(0),
110-
)
111-
.unwrap();
112-
check_added_monitors(&nodes[0], 1);
113-
114-
let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[2]]];
115-
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
116-
assert_eq!(events.len(), 1);
117-
118-
let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
119-
pass_along_path(
120-
&nodes[0],
121-
expected_route[0],
122-
amt_msat,
123-
payment_hash,
124-
Some(payment_secret),
125-
ev.clone(),
126-
true,
127-
Some(keysend_preimage),
128-
);
129-
claim_payment_along_route(ClaimAlongRouteArgs::new(
130-
&nodes[0],
131-
expected_route,
132-
keysend_preimage,
133-
));
134-
}
135-
136-
#[test]
137-
fn blinded_mpp_keysend() {
138-
let chanmon_cfgs = create_chanmon_cfgs(4);
139-
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
140-
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
141-
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
142-
143-
create_announced_chan_between_nodes(&nodes, 0, 1);
144-
create_announced_chan_between_nodes(&nodes, 0, 2);
145-
let chan_1_3 = create_announced_chan_between_nodes(&nodes, 1, 3);
146-
let chan_2_3 = create_announced_chan_between_nodes(&nodes, 2, 3);
147-
148-
let inbound_payment_key = nodes[3].keys_manager.get_inbound_payment_key();
149-
let payment_secret = inbound_payment::create_for_spontaneous_payment(
150-
&inbound_payment_key,
151-
None,
152-
u32::MAX,
153-
nodes[3].node.duration_since_epoch().as_secs(),
154-
None,
155-
)
156-
.unwrap();
157-
158-
let amt_msat = 15_000_000;
159-
let keysend_preimage = PaymentPreimage([42; 32]);
160-
let route_params = {
161-
let pay_params = PaymentParameters::blinded(vec![
162-
blinded_payment_path(
163-
payment_secret,
164-
1,
165-
1_0000_0000,
166-
vec![nodes[1].node.get_our_node_id(), nodes[3].node.get_our_node_id()],
167-
&[&chan_1_3.0.contents],
168-
&chanmon_cfgs[3].keys_manager,
169-
),
170-
blinded_payment_path(
171-
payment_secret,
172-
1,
173-
1_0000_0000,
174-
vec![nodes[2].node.get_our_node_id(), nodes[3].node.get_our_node_id()],
175-
&[&chan_2_3.0.contents],
176-
&chanmon_cfgs[3].keys_manager,
177-
),
178-
])
179-
.with_bolt12_features(channelmanager::provided_bolt12_invoice_features(
180-
&UserConfig::default(),
181-
))
182-
.unwrap();
183-
RouteParameters::from_payment_params_and_value(pay_params, amt_msat)
184-
};
185-
186-
let payment_hash = nodes[0]
187-
.node
188-
.send_spontaneous_payment(
189-
Some(keysend_preimage),
190-
RecipientOnionFields::spontaneous_empty(),
191-
PaymentId(keysend_preimage.0),
192-
route_params,
193-
Retry::Attempts(0),
194-
)
195-
.unwrap();
196-
check_added_monitors!(nodes[0], 2);
197-
198-
let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]];
199-
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
200-
assert_eq!(events.len(), 2);
201-
202-
let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
203-
pass_along_path(
204-
&nodes[0],
205-
expected_route[0],
206-
amt_msat,
207-
payment_hash.clone(),
208-
Some(payment_secret),
209-
ev.clone(),
210-
false,
211-
Some(keysend_preimage),
212-
);
213-
214-
let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
215-
pass_along_path(
216-
&nodes[0],
217-
expected_route[1],
218-
amt_msat,
219-
payment_hash.clone(),
220-
Some(payment_secret),
221-
ev.clone(),
222-
true,
223-
Some(keysend_preimage),
224-
);
225-
claim_payment_along_route(ClaimAlongRouteArgs::new(
226-
&nodes[0],
227-
expected_route,
228-
keysend_preimage,
229-
));
230-
}
231-
23265
#[test]
23366
fn invalid_keysend_payment_secret() {
23467
let chanmon_cfgs = create_chanmon_cfgs(3);

Diff for: lightning/src/ln/channelmanager.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,11 @@ pub enum PendingHTLCRouting {
240240
/// [`PaymentSecret`] and should verify it using our
241241
/// [`NodeSigner::get_inbound_payment_key`].
242242
has_recipient_created_payment_secret: bool,
243+
/// The context of the payment included by the recipient in a blinded path, or `None` if a
244+
/// blinded path was not used.
245+
///
246+
/// Used in part to determine the [`events::PaymentPurpose`].
247+
payment_context: Option<PaymentContext>,
243248
},
244249
}
245250

@@ -6051,15 +6056,16 @@ where
60516056
PendingHTLCRouting::ReceiveKeysend {
60526057
payment_data, payment_preimage, payment_metadata,
60536058
incoming_cltv_expiry, custom_tlvs, requires_blinded_error: _,
6054-
has_recipient_created_payment_secret,
6059+
has_recipient_created_payment_secret, payment_context,
60556060
} => {
60566061
let onion_fields = RecipientOnionFields {
60576062
payment_secret: payment_data.as_ref().map(|data| data.payment_secret),
60586063
payment_metadata,
60596064
custom_tlvs,
60606065
};
60616066
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage),
6062-
payment_data, None, None, onion_fields, has_recipient_created_payment_secret)
6067+
payment_data, payment_context, None, onion_fields,
6068+
has_recipient_created_payment_secret)
60636069
},
60646070
_ => {
60656071
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
@@ -6256,6 +6262,12 @@ where
62566262
check_total_value!(purpose);
62576263
},
62586264
OnionPayload::Spontaneous(preimage) => {
6265+
if payment_context.is_some() {
6266+
if !matches!(payment_context, Some(PaymentContext::AsyncBolt12Offer(_))) {
6267+
log_trace!(self.logger, "Failing new HTLC with payment_hash {}: received a keysend payment to a non-async payments context {:#?}", payment_hash, payment_context);
6268+
}
6269+
fail_htlc!(claimable_htlc, payment_hash);
6270+
}
62596271
let purpose = events::PaymentPurpose::SpontaneousPayment(preimage);
62606272
check_total_value!(purpose);
62616273
}
@@ -12452,6 +12464,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
1245212464
(4, payment_data, option), // Added in 0.0.116
1245312465
(5, custom_tlvs, optional_vec),
1245412466
(7, has_recipient_created_payment_secret, (default_value, false)),
12467+
(9, payment_context, option),
1245512468
},
1245612469
);
1245712470

Diff for: lightning/src/ln/offers_tests.rs

+68-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ use crate::blinded_path::IntroductionNode;
4747
use crate::blinded_path::message::BlindedMessagePath;
4848
use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext};
4949
use crate::blinded_path::message::{MessageContext, OffersContext};
50-
use crate::events::{ClosureReason, Event, MessageSendEventsProvider, PaymentFailureReason, PaymentPurpose};
51-
use crate::ln::channelmanager::{Bolt12PaymentError, MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, Retry, self};
50+
use crate::events::{ClosureReason, Event, HTLCDestination, MessageSendEventsProvider, PaymentFailureReason, PaymentPurpose};
51+
use crate::ln::channelmanager::{Bolt12PaymentError, MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry, self};
5252
use crate::types::features::Bolt12InvoiceFeatures;
5353
use crate::ln::functional_test_utils::*;
5454
use crate::ln::msgs::{ChannelMessageHandler, Init, NodeAnnouncement, OnionMessage, OnionMessageHandler, RoutingMessageHandler, SocketAddress, UnsignedGossipMessage, UnsignedNodeAnnouncement};
@@ -62,6 +62,7 @@ use crate::onion_message::messenger::{Destination, PeeledOnion, MessageSendInstr
6262
use crate::onion_message::offers::OffersMessage;
6363
use crate::onion_message::packet::ParsedOnionMessageContents;
6464
use crate::routing::gossip::{NodeAlias, NodeId};
65+
use crate::routing::router::{PaymentParameters, RouteParameters};
6566
use crate::sign::{NodeSigner, Recipient};
6667
use crate::util::ser::Writeable;
6768

@@ -2255,6 +2256,71 @@ fn fails_paying_invoice_with_unknown_required_features() {
22552256
}
22562257
}
22572258

2259+
#[test]
2260+
fn rejects_keysend_to_non_static_invoice_path() {
2261+
// Test that we'll fail a keysend payment that was sent over a non-static BOLT 12 invoice path.
2262+
let chanmon_cfgs = create_chanmon_cfgs(2);
2263+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
2264+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
2265+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
2266+
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
2267+
2268+
// First pay the offer and save the payment preimage and invoice.
2269+
let offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap();
2270+
let amt_msat = 5000;
2271+
let payment_id = PaymentId([1; 32]);
2272+
nodes[0].node.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), None).unwrap();
2273+
let invreq_om = nodes[0].onion_messenger.next_onion_message_for_peer(nodes[1].node.get_our_node_id()).unwrap();
2274+
nodes[1].onion_messenger.handle_onion_message(nodes[0].node.get_our_node_id(), &invreq_om);
2275+
let invoice_om = nodes[1].onion_messenger.next_onion_message_for_peer(nodes[0].node.get_our_node_id()).unwrap();
2276+
let invoice = extract_invoice(&nodes[0], &invoice_om).0;
2277+
nodes[0].onion_messenger.handle_onion_message(nodes[1].node.get_our_node_id(), &invoice_om);
2278+
2279+
route_bolt12_payment(&nodes[0], &[&nodes[1]], &invoice);
2280+
expect_recent_payment!(nodes[0], RecentPaymentDetails::Pending, payment_id);
2281+
2282+
let payment_preimage = match get_event!(nodes[1], Event::PaymentClaimable) {
2283+
Event::PaymentClaimable { purpose, .. } => purpose.preimage().unwrap(),
2284+
_ => panic!()
2285+
};
2286+
2287+
claim_payment(&nodes[0], &[&nodes[1]], payment_preimage);
2288+
expect_recent_payment!(&nodes[0], RecentPaymentDetails::Fulfilled, payment_id);
2289+
2290+
// Time out the payment from recent payments so we can attempt to pay it again via keysend.
2291+
for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS {
2292+
nodes[0].node.timer_tick_occurred();
2293+
nodes[1].node.timer_tick_occurred();
2294+
}
2295+
2296+
// Pay the invoice via keysend now that we have the preimage and make sure the recipient fails it
2297+
// due to incorrect payment context.
2298+
let pay_params = PaymentParameters::from_bolt12_invoice(&invoice);
2299+
let route_params = RouteParameters::from_payment_params_and_value(pay_params, amt_msat);
2300+
let keysend_payment_id = PaymentId([2; 32]);
2301+
let payment_hash = nodes[0].node.send_spontaneous_payment(
2302+
Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), keysend_payment_id,
2303+
route_params, Retry::Attempts(0)
2304+
).unwrap();
2305+
check_added_monitors!(nodes[0], 1);
2306+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
2307+
assert_eq!(events.len(), 1);
2308+
let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
2309+
let route: &[&[&Node]] = &[&[&nodes[1]]];
2310+
2311+
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
2312+
.with_payment_preimage(payment_preimage)
2313+
.expect_failure(HTLCDestination::FailedPayment { payment_hash });
2314+
do_pass_along_path(args);
2315+
let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
2316+
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
2317+
do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false);
2318+
expect_payment_failed_conditions(&nodes[0], payment_hash, true, PaymentFailedConditions::new());
2319+
nodes[1].logger.assert_log_contains(
2320+
"lightning::ln::channelmanager", "received a keysend payment to a non-async payments context", 1
2321+
);
2322+
}
2323+
22582324
#[test]
22592325
fn no_double_pay_with_stale_channelmanager() {
22602326
// This tests the following bug:

Diff for: lightning/src/ln/onion_payment.rs

+1
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ pub(super) fn create_recv_pending_htlc_info(
235235
custom_tlvs,
236236
requires_blinded_error,
237237
has_recipient_created_payment_secret,
238+
payment_context,
238239
}
239240
} else if let Some(data) = payment_data {
240241
PendingHTLCRouting::Receive {

0 commit comments

Comments
 (0)