Skip to content

Commit 39643a5

Browse files
committed
add test for self-payment
1 parent d842a75 commit 39643a5

File tree

2 files changed

+69
-18
lines changed

2 files changed

+69
-18
lines changed

lightning/src/ln/payment_tests.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5259,3 +5259,55 @@ fn max_out_mpp_path() {
52595259
check_added_monitors(&nodes[0], 2); // one monitor update per MPP part
52605260
nodes[0].node.get_and_clear_pending_msg_events();
52615261
}
5262+
5263+
#[test]
5264+
fn test_self_payment() {
5265+
let chanmon_cfgs = create_chanmon_cfgs(2);
5266+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
5267+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
5268+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
5269+
5270+
let self_node = nodes[0].node.get_our_node_id();
5271+
let _other_node = nodes[1].node.get_our_node_id();
5272+
5273+
create_announced_chan_between_nodes(&nodes, 0, 1);
5274+
5275+
let amt_msat = 10_000;
5276+
let payment_params = PaymentParameters::from_node_id(self_node, TEST_FINAL_CLTV)
5277+
.with_bolt11_features(nodes[0].node.bolt11_invoice_features())
5278+
.unwrap();
5279+
let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
5280+
5281+
let preimage = Some(PaymentPreimage([42; 32]));
5282+
let onion = RecipientOnionFields::spontaneous_empty();
5283+
let retry = Retry::Attempts(0); // payment to self should not be retried , it should succeed in one go ideally
5284+
let id = PaymentId([42; 32]);
5285+
nodes[0].node.send_spontaneous_payment(preimage, onion, id, route_params, retry).unwrap();
5286+
5287+
check_added_monitors!(nodes[0], 0); // Self-payments don't add monitors since no actual channel update occurs
5288+
5289+
let events = nodes[0].node.get_and_clear_pending_events();
5290+
assert_eq!(events.len(), 2);
5291+
5292+
let mut claimable_found = false;
5293+
let mut sent_found = false;
5294+
5295+
for event in &events {
5296+
match event {
5297+
Event::PaymentClaimable { purpose, .. } => {
5298+
if let PaymentPurpose::SpontaneousPayment(_preimage) = purpose {
5299+
// For self-payments, we don't need to manually claim since the payment
5300+
// is automatically processed. The PaymentSent event is already generated.
5301+
claimable_found = true;
5302+
}
5303+
},
5304+
Event::PaymentSent { .. } => {
5305+
sent_found = true;
5306+
},
5307+
_ => panic!("Unexpected event: {:?}", event),
5308+
}
5309+
}
5310+
5311+
assert!(claimable_found, "Expected PaymentClaimable event");
5312+
assert!(sent_found, "Expected PaymentSent event");
5313+
}

lightning/src/routing/router.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ use crate::blinded_path::payment::{
1818
};
1919
use crate::blinded_path::{BlindedHop, Direction, IntroductionNode};
2020
use crate::crypto::chacha20::ChaCha20;
21+
use crate::io;
2122
use crate::ln::channel_state::ChannelDetails;
2223
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields, MIN_FINAL_CLTV_EXPIRY_DELTA};
2324
use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
2425
use crate::ln::onion_utils;
2526
use crate::offers::invoice::Bolt12Invoice;
2627
#[cfg(async_payments)]
2728
use crate::offers::static_invoice::StaticInvoice;
29+
use crate::prelude::*;
2830
use crate::routing::gossip::{
2931
DirectedChannelInfo, EffectiveCapacity, NetworkGraph, NodeId, ReadOnlyNetworkGraph,
3032
};
@@ -37,8 +39,6 @@ use crate::types::features::{
3739
use crate::types::payment::{PaymentHash, PaymentPreimage};
3840
use crate::util::logger::Logger;
3941
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
40-
use crate::io;
41-
use crate::prelude::*;
4242
use alloc::collections::BinaryHeap;
4343
use core::ops::Deref;
4444
use core::{cmp, fmt};
@@ -3726,23 +3726,22 @@ where L::Target: Logger {
37263726
Ok(route)
37273727
}
37283728

3729-
fn create_self_payment_route(our_node_pubkey: &PublicKey, route_params: &RouteParameters) -> Result<Route, &'static str> {
3729+
fn create_self_payment_route(
3730+
our_node_pubkey: &PublicKey, route_params: &RouteParameters,
3731+
) -> Result<Route, &'static str> {
37303732
let path = Path {
3731-
hops: vec![RouteHop {
3732-
pubkey: our_node_pubkey.clone(),
3733-
short_channel_id: 0 , // Dummy short_channel_id specifying self payment
3734-
fee_msat: 0, // Zero fees
3735-
cltv_expiry_delta: MIN_FINAL_CLTV_EXPIRY_DELTA.into(),
3736-
node_features: NodeFeatures::empty(),
3737-
channel_features: ChannelFeatures::empty(),
3738-
maybe_announced_channel: false,
3739-
}],
3740-
blinded_tail: None,
3741-
};
3742-
Ok(Route {
3743-
paths: vec![path],
3744-
route_params: Some(route_params.clone()),
3745-
})
3733+
hops: vec![RouteHop {
3734+
pubkey: our_node_pubkey.clone(),
3735+
short_channel_id: 0, // Dummy short_channel_id specifying self payment
3736+
fee_msat: route_params.final_value_msat, // last hop send the entire amount
3737+
cltv_expiry_delta: MIN_FINAL_CLTV_EXPIRY_DELTA.into(),
3738+
node_features: NodeFeatures::empty(),
3739+
channel_features: ChannelFeatures::empty(),
3740+
maybe_announced_channel: false,
3741+
}],
3742+
blinded_tail: None,
3743+
};
3744+
Ok(Route { paths: vec![path], route_params: Some(route_params.clone()) })
37463745
}
37473746

37483747
// When an adversarial intermediary node observes a payment, it may be able to infer its

0 commit comments

Comments
 (0)