Skip to content

Commit 3c4f14b

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.
1 parent d5d3af0 commit 3c4f14b

File tree

2 files changed

+18
-59
lines changed

2 files changed

+18
-59
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 12 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ pub(super) enum PendingHTLCRouting {
110110
phantom_shared_secret: Option<[u8; 32]>,
111111
},
112112
ReceiveKeysend {
113+
payment_data: Option<msgs::FinalOnionHopData>,
113114
payment_preimage: PaymentPreimage,
114115
incoming_cltv_expiry: u32, // Used to track when we should expire pending HTLCs that go unclaimed
115116
},
@@ -2155,19 +2156,7 @@ where
21552156
});
21562157
},
21572158
msgs::OnionHopDataFormat::FinalNode { payment_data, keysend_preimage } => {
2158-
if payment_data.is_some() && keysend_preimage.is_some() {
2159-
return Err(ReceiveError {
2160-
err_code: 0x4000|22,
2161-
err_data: Vec::new(),
2162-
msg: "We don't support MPP keysend payments",
2163-
});
2164-
} else if let Some(data) = payment_data {
2165-
PendingHTLCRouting::Receive {
2166-
payment_data: data,
2167-
incoming_cltv_expiry: hop_data.outgoing_cltv_value,
2168-
phantom_shared_secret,
2169-
}
2170-
} else if let Some(payment_preimage) = keysend_preimage {
2159+
if let Some(payment_preimage) = keysend_preimage {
21712160
// We need to check that the sender knows the keysend preimage before processing this
21722161
// payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
21732162
// could discover the final destination of X, by probing the adjacent nodes on the route
@@ -2183,9 +2172,16 @@ where
21832172
}
21842173

21852174
PendingHTLCRouting::ReceiveKeysend {
2175+
payment_data,
21862176
payment_preimage,
21872177
incoming_cltv_expiry: hop_data.outgoing_cltv_value,
21882178
}
2179+
} else if let Some(data) = payment_data {
2180+
PendingHTLCRouting::Receive {
2181+
payment_data: data,
2182+
incoming_cltv_expiry: hop_data.outgoing_cltv_value,
2183+
phantom_shared_secret,
2184+
}
21892185
} else {
21902186
return Err(ReceiveError {
21912187
err_code: 0x4000|0x2000|3,
@@ -3288,8 +3284,8 @@ where
32883284
let _legacy_hop_data = Some(payment_data.clone());
32893285
(incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data }, Some(payment_data), phantom_shared_secret)
32903286
},
3291-
PendingHTLCRouting::ReceiveKeysend { payment_preimage, incoming_cltv_expiry } =>
3292-
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage), None, None),
3287+
PendingHTLCRouting::ReceiveKeysend { payment_data, payment_preimage, incoming_cltv_expiry } =>
3288+
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage), payment_data, None),
32933289
_ => {
32943290
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
32953291
}
@@ -6724,6 +6720,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
67246720
},
67256721
(2, ReceiveKeysend) => {
67266722
(0, payment_preimage, required),
6723+
(1, payment_data, option),
67276724
(2, incoming_cltv_expiry, required),
67286725
},
67296726
;);
@@ -8283,49 +8280,6 @@ mod tests {
82838280
nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Payment preimage didn't match payment hash", 1);
82848281
}
82858282

8286-
#[test]
8287-
fn test_keysend_msg_with_secret_err() {
8288-
// Test that we error as expected if we receive a keysend payment that includes a payment secret.
8289-
let chanmon_cfgs = create_chanmon_cfgs(2);
8290-
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
8291-
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
8292-
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
8293-
8294-
let payer_pubkey = nodes[0].node.get_our_node_id();
8295-
let payee_pubkey = nodes[1].node.get_our_node_id();
8296-
8297-
let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
8298-
let route_params = RouteParameters {
8299-
payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
8300-
final_value_msat: 10_000,
8301-
};
8302-
let network_graph = nodes[0].network_graph.clone();
8303-
let first_hops = nodes[0].node.list_usable_channels();
8304-
let scorer = test_utils::TestScorer::new();
8305-
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
8306-
let route = find_route(
8307-
&payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
8308-
nodes[0].logger, &scorer, &random_seed_bytes
8309-
).unwrap();
8310-
8311-
let test_preimage = PaymentPreimage([42; 32]);
8312-
let test_secret = PaymentSecret([43; 32]);
8313-
let payment_hash = PaymentHash(Sha256::hash(&test_preimage.0).into_inner());
8314-
let session_privs = nodes[0].node.test_add_new_pending_payment(payment_hash, Some(test_secret), PaymentId(payment_hash.0), &route).unwrap();
8315-
nodes[0].node.test_send_payment_internal(&route, payment_hash, &Some(test_secret), Some(test_preimage), PaymentId(payment_hash.0), None, session_privs).unwrap();
8316-
check_added_monitors!(nodes[0], 1);
8317-
8318-
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
8319-
assert_eq!(updates.update_add_htlcs.len(), 1);
8320-
assert!(updates.update_fulfill_htlcs.is_empty());
8321-
assert!(updates.update_fail_htlcs.is_empty());
8322-
assert!(updates.update_fail_malformed_htlcs.is_empty());
8323-
assert!(updates.update_fee.is_none());
8324-
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
8325-
8326-
nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "We don't support MPP keysend payments", 1);
8327-
}
8328-
83298283
#[test]
83308284
fn test_multi_hop_missing_secret() {
83318285
let chanmon_cfgs = create_chanmon_cfgs(4);

lightning/src/ln/onion_utils.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,12 @@ pub(super) fn build_onion_payloads(path: &Vec<RouteHop>, total_msat: u64, paymen
169169
payment_secret: payment_secret.clone(),
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([0u8; 32]),
175+
total_msat,
176+
})
177+
} else { None }, // For probing
173178
keysend_preimage: *keysend_preimage,
174179
}
175180
} else {

0 commit comments

Comments
 (0)