Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions lightningd/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -1485,9 +1485,22 @@ static struct command_result *self_payment(struct lightningd *ld,
const u8 *payment_metadata)
{
struct wallet_payment *payment;
const struct wallet_payment *prev_payment;
const struct invoice_details *inv;
u64 inv_dbid;
const char *err;
struct command_result *ret;
assert(partid == 0);

/* Reconcile this with previous attempts */
ret = check_progress(ld, cmd, rhash, msat, msat, partid, groupid,
&ld->our_nodeid, &prev_payment);
if (ret)
return ret;

/* Previous payment success is defined to be idempotent */
if (prev_payment)
return sendpay_success(cmd, prev_payment, NULL);

payment = wallet_add_payment(tmpctx,
ld->wallet,
Expand Down
46 changes: 39 additions & 7 deletions tests/test_pay.py
Original file line number Diff line number Diff line change
Expand Up @@ -5738,23 +5738,55 @@ def test_self_sendpay(node_factory):

# Bad payment_secret
with pytest.raises(RpcError, match="Attempt to pay .* with wrong payment_secret"):
l1.rpc.sendpay([], inv['payment_hash'], label='selfpay-badimage', bolt11=inv['bolt11'], payment_secret='00' * 32, amount_msat='100000sat')
l1.rpc.sendpay([], inv['payment_hash'], label='selfpay-badimage',
bolt11=inv['bolt11'], payment_secret='00' * 32,
amount_msat='100000sat', groupid=1111)

# retry with the same partid and groupid
with pytest.raises(RpcError, match=f"There already is a payment with payment_hash={inv['payment_hash']}, groupid=1111, partid=0."):
l1.rpc.sendpay([], inv['payment_hash'], label='selfpay-badimage',
bolt11=inv['bolt11'], payment_secret='00' * 32,
amount_msat='100000sat', groupid=1111)

# Expired
time.sleep(2)
with pytest.raises(RpcError, match="Already paid or expired invoice"):
l1.rpc.sendpay([], inv_expires['payment_hash'], label='selfpay-badimage', bolt11=inv_expires['bolt11'], payment_secret=inv['payment_secret'], amount_msat='1btc')

# This one works!
l1.rpc.sendpay([], inv['payment_hash'], label='selfpay', bolt11=inv['bolt11'], payment_secret=inv['payment_secret'], amount_msat='100000sat')
self_groupid = 0
l1.rpc.sendpay([], inv['payment_hash'], label='selfpay',
bolt11=inv['bolt11'], payment_secret=inv['payment_secret'],
amount_msat='100000sat', groupid=self_groupid)

# from sendpay documentation:
# Calls to sendpay with the same payment_hash, amount_msat,
# and destination as a previous successful payment
# (even if a different route or partid) will return immediately with success.
l1.rpc.sendpay([], inv['payment_hash'], label='selfpay',
bolt11=inv['bolt11'],
payment_secret=inv['payment_secret'],
amount_msat='100000sat')

# same groupid and same partid
l1.rpc.sendpay([], inv['payment_hash'], label='selfpay',
bolt11=inv['bolt11'],
payment_secret=inv['payment_secret'],
amount_msat='100000sat',
groupid=self_groupid)

# a different amount
with pytest.raises(RpcError, match="Already succeeded with amount 100000000msat"):
l1.rpc.sendpay([], inv['payment_hash'], label='selfpay',
bolt11=inv['bolt11'],
payment_secret=inv['payment_secret'],
amount_msat='200000sat')

assert only_one(l1.rpc.listinvoices(payment_hash=inv['payment_hash'])['invoices'])['status'] == 'paid'
# Only one is complete.
assert [p['status'] for p in l1.rpc.listsendpays()['payments'] if p['status'] != 'failed'] == ['complete']

# Can't pay paid one already paid!
with pytest.raises(RpcError, match="Already paid or expired invoice"):
l1.rpc.sendpay([], inv['payment_hash'], label='selfpay', bolt11=inv['bolt11'], payment_secret=inv['payment_secret'], amount_msat='100000sat')
# We have succeeded several calls to sendpay for the same invoice but only
# one payment was executed and recorded.
assert [p['status'] for p in l1.rpc.listsendpays()['payments'] if p['status'] != 'failed'] == ['complete']


def test_strip_lightning_suffix_from_inv(node_factory):
Expand Down