Skip to content

Commit 4a3b1af

Browse files
committed
Add FinalOnionHopData to ReceiveKeysend
This is needed to communicate `total_msat` to the recipient so they know to wait for more payment parts before claiming. f - make payment secret preimage
1 parent 8f88966 commit 4a3b1af

File tree

2 files changed

+20
-65
lines changed

2 files changed

+20
-65
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 13 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ pub(super) enum PendingHTLCRouting {
111111
phantom_shared_secret: Option<[u8; 32]>,
112112
},
113113
ReceiveKeysend {
114+
payment_data: Option<msgs::FinalOnionHopData>,
114115
payment_preimage: PaymentPreimage,
115116
payment_metadata: Option<Vec<u8>>,
116117
incoming_cltv_expiry: u32, // Used to track when we should expire pending HTLCs that go unclaimed
@@ -2285,20 +2286,7 @@ where
22852286
});
22862287
},
22872288
msgs::OnionHopDataFormat::FinalNode { payment_data, keysend_preimage, payment_metadata } => {
2288-
if payment_data.is_some() && keysend_preimage.is_some() {
2289-
return Err(ReceiveError {
2290-
err_code: 0x4000|22,
2291-
err_data: Vec::new(),
2292-
msg: "We don't support MPP keysend payments",
2293-
});
2294-
} else if let Some(data) = payment_data {
2295-
PendingHTLCRouting::Receive {
2296-
payment_data: data,
2297-
payment_metadata,
2298-
incoming_cltv_expiry: hop_data.outgoing_cltv_value,
2299-
phantom_shared_secret,
2300-
}
2301-
} else if let Some(payment_preimage) = keysend_preimage {
2289+
if let Some(payment_preimage) = keysend_preimage {
23022290
// We need to check that the sender knows the keysend preimage before processing this
23032291
// payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
23042292
// could discover the final destination of X, by probing the adjacent nodes on the route
@@ -2312,12 +2300,19 @@ where
23122300
msg: "Payment preimage didn't match payment hash",
23132301
});
23142302
}
2315-
23162303
PendingHTLCRouting::ReceiveKeysend {
2304+
payment_data,
23172305
payment_preimage,
23182306
payment_metadata,
23192307
incoming_cltv_expiry: hop_data.outgoing_cltv_value,
23202308
}
2309+
} else if let Some(data) = payment_data {
2310+
PendingHTLCRouting::Receive {
2311+
payment_data: data,
2312+
payment_metadata,
2313+
incoming_cltv_expiry: hop_data.outgoing_cltv_value,
2314+
phantom_shared_secret,
2315+
}
23212316
} else {
23222317
return Err(ReceiveError {
23232318
err_code: 0x4000|0x2000|3,
@@ -3435,10 +3430,10 @@ where
34353430
(incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data },
34363431
Some(payment_data), phantom_shared_secret, onion_fields)
34373432
},
3438-
PendingHTLCRouting::ReceiveKeysend { payment_preimage, payment_metadata, incoming_cltv_expiry } => {
3433+
PendingHTLCRouting::ReceiveKeysend { payment_data, payment_preimage, payment_metadata, incoming_cltv_expiry } => {
34393434
let onion_fields = RecipientOnionFields { payment_secret: None, payment_metadata };
34403435
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage),
3441-
None, None, onion_fields)
3436+
payment_data, None, onion_fields)
34423437
},
34433438
_ => {
34443439
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
@@ -6850,6 +6845,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
68506845
},
68516846
(2, ReceiveKeysend) => {
68526847
(0, payment_preimage, required),
6848+
(1, payment_data, option),
68536849
(2, incoming_cltv_expiry, required),
68546850
(3, payment_metadata, option),
68556851
},
@@ -8443,52 +8439,6 @@ mod tests {
84438439
nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Payment preimage didn't match payment hash", 1);
84448440
}
84458441

8446-
#[test]
8447-
fn test_keysend_msg_with_secret_err() {
8448-
// Test that we error as expected if we receive a keysend payment that includes a payment secret.
8449-
let chanmon_cfgs = create_chanmon_cfgs(2);
8450-
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
8451-
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
8452-
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
8453-
8454-
let payer_pubkey = nodes[0].node.get_our_node_id();
8455-
let payee_pubkey = nodes[1].node.get_our_node_id();
8456-
8457-
let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
8458-
let route_params = RouteParameters {
8459-
payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
8460-
final_value_msat: 10_000,
8461-
};
8462-
let network_graph = nodes[0].network_graph.clone();
8463-
let first_hops = nodes[0].node.list_usable_channels();
8464-
let scorer = test_utils::TestScorer::new();
8465-
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
8466-
let route = find_route(
8467-
&payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
8468-
nodes[0].logger, &scorer, &random_seed_bytes
8469-
).unwrap();
8470-
8471-
let test_preimage = PaymentPreimage([42; 32]);
8472-
let test_secret = PaymentSecret([43; 32]);
8473-
let payment_hash = PaymentHash(Sha256::hash(&test_preimage.0).into_inner());
8474-
let session_privs = nodes[0].node.test_add_new_pending_payment(payment_hash,
8475-
RecipientOnionFields::secret_only(test_secret), PaymentId(payment_hash.0), &route).unwrap();
8476-
nodes[0].node.test_send_payment_internal(&route, payment_hash,
8477-
RecipientOnionFields::secret_only(test_secret), Some(test_preimage),
8478-
PaymentId(payment_hash.0), None, session_privs).unwrap();
8479-
check_added_monitors!(nodes[0], 1);
8480-
8481-
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
8482-
assert_eq!(updates.update_add_htlcs.len(), 1);
8483-
assert!(updates.update_fulfill_htlcs.is_empty());
8484-
assert!(updates.update_fail_htlcs.is_empty());
8485-
assert!(updates.update_fail_malformed_htlcs.is_empty());
8486-
assert!(updates.update_fee.is_none());
8487-
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
8488-
8489-
nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "We don't support MPP keysend payments", 1);
8490-
}
8491-
84928442
#[test]
84938443
fn test_multi_hop_missing_secret() {
84948444
let chanmon_cfgs = create_chanmon_cfgs(4);

lightning/src/ln/onion_utils.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// You may not use this file except in accordance with one or both of these
88
// licenses.
99

10-
use crate::ln::{PaymentHash, PaymentPreimage};
10+
use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
1111
use crate::ln::channelmanager::{HTLCSource, RecipientOnionFields};
1212
use crate::ln::msgs;
1313
use crate::ln::wire::Encode;
@@ -169,7 +169,12 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o
169169
payment_secret: secret,
170170
total_msat,
171171
})
172-
} else { None },
172+
} else if keysend_preimage.is_some() && value_msat < total_msat {
173+
Some(msgs::FinalOnionHopData {
174+
payment_secret: PaymentSecret(keysend_preimage.unwrap().0),
175+
total_msat,
176+
})
177+
} else { None }, // For probing
173178
payment_metadata: recipient_onion.payment_metadata.take(),
174179
keysend_preimage: *keysend_preimage,
175180
}

0 commit comments

Comments
 (0)