Skip to content

Commit 1e65c4a

Browse files
feat: allow self payment
This PR solves issue #2462. If we asked to pay an invoice that we generated ourselves. We generate PaymentSent and PaymentClaimable event and mark the payment as fulfilled in our set of outbound payments. This PR is important because we realized users can easily screw up self payments when they implement it themselves. See here: https://lists.linuxfoundation.org/pipermail/lightning-dev/2023-June/003983.html
1 parent a37a16a commit 1e65c4a

File tree

3 files changed

+70
-22
lines changed

3 files changed

+70
-22
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ pub enum FailureCode {
401401
}
402402

403403
impl Into<u16> for FailureCode {
404-
fn into(self) -> u16 {
404+
fn into(self) -> u16 {
405405
match self {
406406
FailureCode::TemporaryNodeFailure => 0x2000 | 2,
407407
FailureCode::RequiredNodeFeatureMissing => 0x4000 | 0x2000 | 3,
@@ -3396,7 +3396,7 @@ where
33963396
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
33973397
self.pending_outbound_payments
33983398
.send_payment_with_route(route, payment_hash, recipient_onion, payment_id,
3399-
&self.entropy_source, &self.node_signer, best_block_height,
3399+
&self.entropy_source, &self.node_signer, best_block_height, &self.pending_events,
34003400
|args| self.send_payment_along_path(args))
34013401
}
34023402

@@ -3406,7 +3406,7 @@ where
34063406
let best_block_height = self.best_block.read().unwrap().height();
34073407
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
34083408
self.pending_outbound_payments
3409-
.send_payment(payment_hash, recipient_onion, payment_id, retry_strategy, route_params,
3409+
.send_payment(payment_hash,recipient_onion, payment_id, retry_strategy, route_params,
34103410
&self.router, self.list_usable_channels(), || self.compute_inflight_htlcs(),
34113411
&self.entropy_source, &self.node_signer, best_block_height, &self.logger,
34123412
&self.pending_events, |args| self.send_payment_along_path(args))
@@ -3418,7 +3418,7 @@ where
34183418
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
34193419
self.pending_outbound_payments.test_send_payment_internal(route, payment_hash, recipient_onion,
34203420
keysend_preimage, payment_id, recv_value_msat, onion_session_privs, &self.node_signer,
3421-
best_block_height, |args| self.send_payment_along_path(args))
3421+
best_block_height, &self.pending_events, |args| self.send_payment_along_path(args))
34223422
}
34233423

34243424
#[cfg(test)]
@@ -3482,7 +3482,7 @@ where
34823482
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
34833483
self.pending_outbound_payments.send_spontaneous_payment_with_route(
34843484
route, payment_preimage, recipient_onion, payment_id, &self.entropy_source,
3485-
&self.node_signer, best_block_height, |args| self.send_payment_along_path(args))
3485+
&self.node_signer, best_block_height, &self.pending_events, |args| self.send_payment_along_path(args))
34863486
}
34873487

34883488
/// Similar to [`ChannelManager::send_spontaneous_payment`], but will automatically find a route
@@ -3509,7 +3509,7 @@ where
35093509
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
35103510
self.pending_outbound_payments.send_probe(path, self.probing_cookie_secret,
35113511
&self.entropy_source, &self.node_signer, best_block_height,
3512-
|args| self.send_payment_along_path(args))
3512+
&self.pending_events, |args| self.send_payment_along_path(args))
35133513
}
35143514

35153515
/// Returns whether a payment with the given [`PaymentHash`] and [`PaymentId`] is, in fact, a
@@ -5708,7 +5708,7 @@ where
57085708

57095709
let per_peer_state = self.per_peer_state.read().unwrap();
57105710
let peer_state_mutex = per_peer_state.get(counterparty_node_id)
5711-
.ok_or_else(|| {
5711+
.ok_or_else(|| {
57125712
debug_assert!(false);
57135713
MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id.clone())
57145714
})?;

lightning/src/ln/outbound_payment.rs

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ use bitcoin::hashes::sha256::Hash as Sha256;
1414
use bitcoin::secp256k1::{self, Secp256k1, SecretKey};
1515

1616
use crate::sign::{EntropySource, NodeSigner, Recipient};
17-
use crate::events::{self, PaymentFailureReason};
17+
use crate::events::{self, PaymentFailureReason, Event, PaymentPurpose};
1818
use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
1919
use crate::ln::channelmanager::{ChannelDetails, EventCompletionAction, HTLCSource, PaymentId};
2020
use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason};
2121
use crate::offers::invoice::Bolt12Invoice;
22-
use crate::routing::router::{InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router};
22+
use crate::routing::router::{InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router, Payee};
2323
use crate::util::errors::APIError;
2424
use crate::util::logger::Logger;
2525
use crate::util::time::Time;
@@ -650,7 +650,7 @@ impl OutboundPayments {
650650
pub(super) fn send_payment_with_route<ES: Deref, NS: Deref, F>(
651651
&self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
652652
payment_id: PaymentId, entropy_source: &ES, node_signer: &NS, best_block_height: u32,
653-
send_payment_along_path: F
653+
pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>, send_payment_along_path: F
654654
) -> Result<(), PaymentSendFailure>
655655
where
656656
ES::Target: EntropySource,
@@ -659,7 +659,7 @@ impl OutboundPayments {
659659
{
660660
let onion_session_privs = self.add_new_pending_payment(payment_hash, recipient_onion.clone(), payment_id, None, route, None, None, entropy_source, best_block_height)?;
661661
self.pay_route_internal(route, payment_hash, recipient_onion, None, payment_id, None,
662-
onion_session_privs, node_signer, best_block_height, &send_payment_along_path)
662+
onion_session_privs, node_signer, best_block_height, pending_events, &send_payment_along_path)
663663
.map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e })
664664
}
665665

@@ -690,7 +690,8 @@ impl OutboundPayments {
690690
pub(super) fn send_spontaneous_payment_with_route<ES: Deref, NS: Deref, F>(
691691
&self, route: &Route, payment_preimage: Option<PaymentPreimage>,
692692
recipient_onion: RecipientOnionFields, payment_id: PaymentId, entropy_source: &ES,
693-
node_signer: &NS, best_block_height: u32, send_payment_along_path: F
693+
node_signer: &NS, best_block_height: u32, pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>,
694+
send_payment_along_path: F
694695
) -> Result<PaymentHash, PaymentSendFailure>
695696
where
696697
ES::Target: EntropySource,
@@ -704,7 +705,7 @@ impl OutboundPayments {
704705
payment_id, Some(preimage), &route, None, None, entropy_source, best_block_height)?;
705706

706707
match self.pay_route_internal(route, payment_hash, recipient_onion, Some(preimage),
707-
payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path
708+
payment_id, None, onion_session_privs, node_signer, best_block_height, pending_events, &send_payment_along_path
708709
) {
709710
Ok(()) => Ok(payment_hash),
710711
Err(e) => {
@@ -849,8 +850,9 @@ impl OutboundPayments {
849850
}
850851
}
851852

853+
let payer_pubkey = node_signer.get_node_id(Recipient::Node).unwrap();
852854
let route = router.find_route_with_id(
853-
&node_signer.get_node_id(Recipient::Node).unwrap(), &route_params,
855+
&payer_pubkey, &route_params,
854856
Some(&first_hops.iter().collect::<Vec<_>>()), inflight_htlcs(),
855857
payment_hash, payment_id,
856858
).map_err(|_| {
@@ -869,7 +871,7 @@ impl OutboundPayments {
869871
})?;
870872

871873
let res = self.pay_route_internal(&route, payment_hash, recipient_onion, keysend_preimage, payment_id, None,
872-
onion_session_privs, node_signer, best_block_height, &send_payment_along_path);
874+
onion_session_privs, node_signer, best_block_height, pending_events, &send_payment_along_path);
873875
log_info!(logger, "Sending payment with id {} and hash {} returned {:?}",
874876
payment_id, payment_hash, res);
875877
if let Err(e) = res {
@@ -1021,7 +1023,7 @@ impl OutboundPayments {
10211023
};
10221024
let res = self.pay_route_internal(&route, payment_hash, recipient_onion, keysend_preimage,
10231025
payment_id, Some(total_msat), onion_session_privs, node_signer, best_block_height,
1024-
&send_payment_along_path);
1026+
pending_events, &send_payment_along_path);
10251027
log_info!(logger, "Result retrying payment id {}: {:?}", &payment_id, res);
10261028
if let Err(e) = res {
10271029
self.handle_pay_route_err(e, payment_id, payment_hash, route, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path);
@@ -1107,7 +1109,7 @@ impl OutboundPayments {
11071109

11081110
pub(super) fn send_probe<ES: Deref, NS: Deref, F>(
11091111
&self, path: Path, probing_cookie_secret: [u8; 32], entropy_source: &ES, node_signer: &NS,
1110-
best_block_height: u32, send_payment_along_path: F
1112+
best_block_height: u32, pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>, send_payment_along_path: F
11111113
) -> Result<(PaymentHash, PaymentId), PaymentSendFailure>
11121114
where
11131115
ES::Target: EntropySource,
@@ -1131,7 +1133,7 @@ impl OutboundPayments {
11311133
entropy_source, best_block_height)?;
11321134

11331135
match self.pay_route_internal(&route, payment_hash, RecipientOnionFields::spontaneous_empty(),
1134-
None, payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path
1136+
None, payment_id, None, onion_session_privs, node_signer, best_block_height, pending_events, &send_payment_along_path
11351137
) {
11361138
Ok(()) => Ok((payment_hash, payment_id)),
11371139
Err(e) => {
@@ -1238,7 +1240,7 @@ impl OutboundPayments {
12381240
&self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
12391241
keysend_preimage: Option<PaymentPreimage>, payment_id: PaymentId, recv_value_msat: Option<u64>,
12401242
onion_session_privs: Vec<[u8; 32]>, node_signer: &NS, best_block_height: u32,
1241-
send_payment_along_path: &F
1243+
pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>, send_payment_along_path: &F
12421244
) -> Result<(), PaymentSendFailure>
12431245
where
12441246
NS::Target: NodeSigner,
@@ -1252,6 +1254,42 @@ impl OutboundPayments {
12521254
{
12531255
return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError{err: "Payment secret is required for multi-path payments".to_owned()}));
12541256
}
1257+
1258+
if let Some(path) = route.paths.get(0) {
1259+
// handle self payment if path doesn't have a blinded tail.
1260+
if path.blinded_tail.is_none() {
1261+
let last_hop = path.hops.last().unwrap();
1262+
if node_signer.get_node_id(Recipient::Node).unwrap() == last_hop.pubkey {
1263+
let payment_secret = match recipient_onion.payment_secret {
1264+
Some(secret) => secret,
1265+
None => PaymentSecret([0; 32])
1266+
};
1267+
1268+
let payment_preimage = PaymentPreimage([0; 32]);
1269+
let payment_purpose = PaymentPurpose::InvoicePayment {
1270+
payment_preimage: Some(payment_preimage),
1271+
payment_secret,
1272+
};
1273+
1274+
let mut pending_outbounds_lock = self.pending_outbound_payments.lock().unwrap();
1275+
let payment = pending_outbounds_lock.get_mut(&payment_id).unwrap();
1276+
payment.mark_fulfilled();
1277+
1278+
let mut pending_events_lock = pending_events.lock().unwrap();
1279+
pending_events_lock.push_back((Event::PaymentSent { payment_id: Some(payment_id), payment_preimage,
1280+
payment_hash, fee_paid_msat: None }, None));
1281+
let amt_to_receive = match &route.route_params {
1282+
Some(route_params) => route_params.final_value_msat,
1283+
None => if recv_value_msat.is_some() { recv_value_msat.unwrap() } else { 0 },
1284+
};
1285+
pending_events_lock.push_back((Event::PaymentClaimable { receiver_node_id: Some(last_hop.pubkey), payment_hash,
1286+
onion_fields: Some(recipient_onion), amount_msat: amt_to_receive, counterparty_skimmed_fee_msat: 0,
1287+
purpose: payment_purpose, via_channel_id: None, via_user_channel_id: None, claim_deadline: None }, None));
1288+
return Ok(());
1289+
}
1290+
}
1291+
}
1292+
12551293
let mut total_value = 0;
12561294
let our_node_id = node_signer.get_node_id(Recipient::Node).unwrap(); // TODO no unwrap
12571295
let mut path_errs = Vec::with_capacity(route.paths.len());
@@ -1346,15 +1384,15 @@ impl OutboundPayments {
13461384
&self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
13471385
keysend_preimage: Option<PaymentPreimage>, payment_id: PaymentId, recv_value_msat: Option<u64>,
13481386
onion_session_privs: Vec<[u8; 32]>, node_signer: &NS, best_block_height: u32,
1349-
send_payment_along_path: F
1387+
pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>, send_payment_along_path: F
13501388
) -> Result<(), PaymentSendFailure>
13511389
where
13521390
NS::Target: NodeSigner,
13531391
F: Fn(SendAlongPathArgs) -> Result<(), APIError>,
13541392
{
13551393
self.pay_route_internal(route, payment_hash, recipient_onion, keysend_preimage, payment_id,
13561394
recv_value_msat, onion_session_privs, node_signer, best_block_height,
1357-
&send_payment_along_path)
1395+
pending_events, &send_payment_along_path)
13581396
.map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e })
13591397
}
13601398

lightning/src/routing/router.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,17 @@ where L::Target: Logger {
14661466
let our_node_id = NodeId::from_pubkey(&our_node_pubkey);
14671467

14681468
if payee_node_id_opt.map_or(false, |payee| payee == our_node_id) {
1469-
return Err(LightningError{err: "Cannot generate a route to ourselves".to_owned(), action: ErrorAction::IgnoreError});
1469+
let dummy_path = Path { hops: vec![RouteHop {
1470+
pubkey: our_node_pubkey.clone(),
1471+
short_channel_id: 0,
1472+
node_features: NodeFeatures::empty(),
1473+
channel_features: ChannelFeatures::empty(),
1474+
fee_msat: 0,
1475+
cltv_expiry_delta: 0,
1476+
maybe_announced_channel: false,
1477+
1478+
}], blinded_tail: None };
1479+
return Ok(Route { paths: vec![dummy_path], route_params: Some(route_params.clone()) });
14701480
}
14711481

14721482
if final_value_msat > MAX_VALUE_MSAT {

0 commit comments

Comments
 (0)