Skip to content

Commit 2d94401

Browse files
Implement sending keysend payments (to public nodes)
1 parent d32052f commit 2d94401

File tree

4 files changed

+68
-15
lines changed

4 files changed

+68
-15
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,15 +1718,15 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
17181718
}
17191719

17201720
// Only public for testing, this should otherwise never be called direcly
1721-
pub(crate) fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32) -> Result<(), APIError> {
1721+
pub(crate) fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, keysend_preimage: &Option<PaymentPreimage>) -> Result<(), APIError> {
17221722
log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.first().unwrap().short_channel_id);
17231723
let prng_seed = self.keys_manager.get_secure_random_bytes();
17241724
let session_priv_bytes = self.keys_manager.get_secure_random_bytes();
17251725
let session_priv = SecretKey::from_slice(&session_priv_bytes[..]).expect("RNG is busted");
17261726

17271727
let onion_keys = onion_utils::construct_onion_keys(&self.secp_ctx, &path, &session_priv)
17281728
.map_err(|_| APIError::RouteError{err: "Pubkey along hop was maliciously selected"})?;
1729-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(path, total_value, payment_secret, cur_height)?;
1729+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(path, total_value, payment_secret, cur_height, keysend_preimage)?;
17301730
if onion_utils::route_size_insane(&onion_payloads) {
17311731
return Err(APIError::RouteError{err: "Route size too large considering onion data"});
17321732
}
@@ -1835,6 +1835,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
18351835
/// bit set (either as required or as available). If multiple paths are present in the Route,
18361836
/// we assume the invoice had the basic_mpp feature set.
18371837
pub fn send_payment(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>) -> Result<(), PaymentSendFailure> {
1838+
self.send_payment_internal(route, payment_hash, payment_secret, None)
1839+
}
1840+
1841+
fn send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, keysend_preimage: Option<PaymentPreimage>) -> Result<(), PaymentSendFailure> {
18381842
if route.paths.len() < 1 {
18391843
return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "There must be at least one path to send over"}));
18401844
}
@@ -1868,7 +1872,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
18681872
let cur_height = self.best_block.read().unwrap().height() + 1;
18691873
let mut results = Vec::new();
18701874
for path in route.paths.iter() {
1871-
results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height));
1875+
results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height, &keysend_preimage));
18721876
}
18731877
let mut has_ok = false;
18741878
let mut has_err = false;
@@ -1892,6 +1896,28 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
18921896
}
18931897
}
18941898

1899+
/// Send a spontaneous payment, which is a payment that does not require the recipient to have
1900+
/// generated an invoice. Optionally, you may specify the preimage. If you do choose to specify
1901+
/// the preimage, it must be a cryptographically secure random value that no intermediate node
1902+
/// would be able to guess -- otherwise, an intermediate node may claim the payment and it will
1903+
/// never reach the recipient.
1904+
///
1905+
/// Similar to regular payments, you MUST NOT reuse a `payment_preimage` value. See
1906+
/// [`send_payment`] for more information about the risks of duplicate preimage usage.
1907+
///
1908+
/// [`send_payment`]: Self::send_payment
1909+
pub fn send_spontaneous_payment(&self, route: &Route, payment_preimage: Option<PaymentPreimage>) -> Result<PaymentHash, PaymentSendFailure> {
1910+
let preimage = match payment_preimage {
1911+
Some(p) => p,
1912+
None => PaymentPreimage(self.keys_manager.get_secure_random_bytes()),
1913+
};
1914+
let payment_hash = PaymentHash(Sha256::hash(&preimage.0).into_inner());
1915+
match self.send_payment_internal(route, payment_hash, &None, Some(preimage)) {
1916+
Ok(()) => Ok(payment_hash),
1917+
Err(e) => Err(e)
1918+
}
1919+
}
1920+
18951921
/// Handles the generation of a funding transaction, optionally (for tests) with a function
18961922
/// which checks the correctness of the funding transaction given the associated channel.
18971923
fn funding_transaction_generated_intern<FundingOutput: Fn(&Channel<Signer>, &Transaction) -> Result<OutPoint, APIError>>

lightning/src/ln/functional_tests.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,7 +1585,7 @@ fn test_fee_spike_violation_fails_htlc() {
15851585
let cur_height = nodes[1].node.best_block.read().unwrap().height() + 1;
15861586

15871587
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
1588-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3460001, &Some(payment_secret), cur_height).unwrap();
1588+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3460001, &Some(payment_secret), cur_height, &None).unwrap();
15891589
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
15901590
let msg = msgs::UpdateAddHTLC {
15911591
channel_id: chan.2,
@@ -1746,7 +1746,7 @@ fn test_chan_reserve_violation_inbound_htlc_outbound_channel() {
17461746
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
17471747
let cur_height = nodes[1].node.best_block.read().unwrap().height() + 1;
17481748
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
1749-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 1000, &Some(payment_secret), cur_height).unwrap();
1749+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 1000, &Some(payment_secret), cur_height, &None).unwrap();
17501750
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
17511751
let msg = msgs::UpdateAddHTLC {
17521752
channel_id: chan.2,
@@ -1872,7 +1872,7 @@ fn test_chan_reserve_violation_inbound_htlc_inbound_chan() {
18721872
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
18731873
let cur_height = nodes[0].node.best_block.read().unwrap().height() + 1;
18741874
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route_2.paths[0], &session_priv).unwrap();
1875-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route_2.paths[0], recv_value_2, &None, cur_height).unwrap();
1875+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route_2.paths[0], recv_value_2, &None, cur_height, &None).unwrap();
18761876
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash_1);
18771877
let msg = msgs::UpdateAddHTLC {
18781878
channel_id: chan.2,
@@ -3421,7 +3421,7 @@ fn fail_backward_pending_htlc_upon_channel_failure() {
34213421
let current_height = nodes[1].node.best_block.read().unwrap().height() + 1;
34223422
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
34233423
let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 50_000, TEST_FINAL_CLTV, &logger).unwrap();
3424-
let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route.paths[0], 50_000, &Some(payment_secret), current_height).unwrap();
3424+
let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route.paths[0], 50_000, &Some(payment_secret), current_height, &None).unwrap();
34253425
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
34263426
let onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
34273427

@@ -4191,7 +4191,7 @@ fn do_test_htlc_timeout(send_partial_mpp: bool) {
41914191
// Use the utility function send_payment_along_path to send the payment with MPP data which
41924192
// indicates there are more HTLCs coming.
41934193
let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match.
4194-
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200000, cur_height).unwrap();
4194+
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200000, cur_height, &None).unwrap();
41954195
check_added_monitors!(nodes[0], 1);
41964196
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
41974197
assert_eq!(events.len(), 1);
@@ -6817,7 +6817,7 @@ fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() {
68176817

68186818
let cur_height = nodes[0].node.best_block.read().unwrap().height() + 1;
68196819
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::signing_only(), &route.paths[0], &session_priv).unwrap();
6820-
let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3999999, &Some(our_payment_secret), cur_height).unwrap();
6820+
let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3999999, &Some(our_payment_secret), cur_height, &None).unwrap();
68216821
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash);
68226822

68236823
let mut msg = msgs::UpdateAddHTLC {
@@ -9594,8 +9594,35 @@ fn do_test_tx_confirmed_skipping_blocks_immediate_broadcast(test_height_before_t
95949594
expect_payment_failure_chan_update!(nodes[0], chan_announce.contents.short_channel_id, true);
95959595
}
95969596
}
9597+
95979598
#[test]
95989599
fn test_tx_confirmed_skipping_blocks_immediate_broadcast() {
95999600
do_test_tx_confirmed_skipping_blocks_immediate_broadcast(false);
96009601
do_test_tx_confirmed_skipping_blocks_immediate_broadcast(true);
96019602
}
9603+
9604+
#[test]
9605+
fn test_keysend_payments_to_public_node() {
9606+
let chanmon_cfgs = create_chanmon_cfgs(2);
9607+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
9608+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
9609+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
9610+
9611+
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
9612+
let network_graph = nodes[0].net_graph_msg_handler.network_graph.read().unwrap();
9613+
let payer_pubkey = nodes[0].node.get_our_node_id();
9614+
let payee_pubkey = nodes[1].node.get_our_node_id();
9615+
let route = get_route(&payer_pubkey, &network_graph, &payee_pubkey, None,
9616+
None, &vec![], 10000, 40,
9617+
nodes[0].logger).unwrap();
9618+
9619+
let test_preimage = PaymentPreimage([42; 32]);
9620+
let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage)).unwrap();
9621+
check_added_monitors!(nodes[0], 1);
9622+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
9623+
assert_eq!(events.len(), 1);
9624+
let event = events.pop().unwrap();
9625+
let path = vec![&nodes[1]];
9626+
pass_along_path(&nodes[0], &path, 10000, payment_hash, PaymentSecret([0; 32]), event, true, Some(test_preimage));
9627+
claim_payment(&nodes[0], &path, test_preimage);
9628+
}

lightning/src/ln/onion_route_tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ fn test_onion_failure() {
327327
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
328328
let cur_height = nodes[0].best_block_info().1 + 1;
329329
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
330-
let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height).unwrap();
330+
let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height, &None).unwrap();
331331
let mut new_payloads = Vec::new();
332332
for payload in onion_payloads.drain(..) {
333333
new_payloads.push(BogusOnionHopData::new(payload));
@@ -343,7 +343,7 @@ fn test_onion_failure() {
343343
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
344344
let cur_height = nodes[0].best_block_info().1 + 1;
345345
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
346-
let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height).unwrap();
346+
let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height, &None).unwrap();
347347
let mut new_payloads = Vec::new();
348348
for payload in onion_payloads.drain(..) {
349349
new_payloads.push(BogusOnionHopData::new(payload));
@@ -537,7 +537,7 @@ fn test_onion_failure() {
537537
let height = nodes[2].best_block_info().1;
538538
route.paths[0][1].cltv_expiry_delta += CLTV_FAR_FAR_AWAY + route.paths[0][0].cltv_expiry_delta + 1;
539539
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
540-
let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, height).unwrap();
540+
let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, height, &None).unwrap();
541541
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
542542
msg.cltv_expiry = htlc_cltv;
543543
msg.onion_routing_packet = onion_packet;

lightning/src/ln/onion_utils.rs

Lines changed: 3 additions & 3 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 ln::{PaymentHash, PaymentSecret};
10+
use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
1111
use ln::channelmanager::HTLCSource;
1212
use ln::msgs;
1313
use routing::router::RouteHop;
@@ -119,7 +119,7 @@ pub(super) fn construct_onion_keys<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T
119119
}
120120

121121
/// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
122-
pub(super) fn build_onion_payloads(path: &Vec<RouteHop>, total_msat: u64, payment_secret_option: &Option<PaymentSecret>, starting_htlc_offset: u32) -> Result<(Vec<msgs::OnionHopData>, u64, u32), APIError> {
122+
pub(super) fn build_onion_payloads(path: &Vec<RouteHop>, total_msat: u64, payment_secret_option: &Option<PaymentSecret>, starting_htlc_offset: u32, keysend_preimage: &Option<PaymentPreimage>) -> Result<(Vec<msgs::OnionHopData>, u64, u32), APIError> {
123123
let mut cur_value_msat = 0u64;
124124
let mut cur_cltv = starting_htlc_offset;
125125
let mut last_short_channel_id = 0;
@@ -141,7 +141,7 @@ pub(super) fn build_onion_payloads(path: &Vec<RouteHop>, total_msat: u64, paymen
141141
total_msat,
142142
})
143143
} else { None },
144-
keysend_preimage: None,
144+
keysend_preimage: *keysend_preimage,
145145
}
146146
} else {
147147
msgs::OnionHopDataFormat::NonFinalNode {

0 commit comments

Comments
 (0)