pytest: use xpay, not pay in misc tests.

This usually means changing the error strings, where we test them, and
avoiding `paystatus`.

Other changes:
1. Completely get rid of `test_custom_notification_topics`: xpay tests do this
   already.
2. Add xpay wrapper to pyln-client so we can mix named and unnamed args.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2026-05-11 13:50:16 +09:30
parent 363a1778b8
commit 7f6a33394e
17 changed files with 190 additions and 203 deletions

View file

@ -1186,6 +1186,25 @@ class LightningRpc(UnixDomainSocketRpc):
}
return self.call("pay", payload)
def xpay(self, invstring, amount_msat=None, maxfee=None, retry_for=None,
partial_msat=None, maxdelay=None, payer_note=None, label=None, localinvreqid=None,
dev_use_shadow=None):
"""
Send payment specified by {invstring}.
"""
payload = {
"invstring": invstring,
"amount_msat": amount_msat,
"maxfee": maxfee,
"retry_for": retry_for,
"partial_msat": partial_msat,
"maxdelay": maxdelay,
"label": label,
"localinvreqid": localinvreqid,
"dev_use_shadow": dev_use_shadow,
}
return self.call("xpay", payload)
def openchannel_init(self, node_id, channel_amount, psbt, feerate=None, funding_feerate=None, announce=True, close_to=None, request_amt=None, channel_type=None):
"""Initiate an openchannel with a peer """
payload = {

View file

@ -82,7 +82,7 @@ def test_single_payment(node_factory, benchmark):
def do_pay(l1, l2):
invoice = l2.rpc.invoice(1000, 'invoice-{}'.format(random.random()), 'desc')['bolt11']
l1.rpc.pay(invoice)
l1.rpc.xpay(invoice)
benchmark(do_pay, l1, l2)
@ -92,7 +92,7 @@ def test_forward_payment(node_factory, benchmark):
def do_pay(src, dest):
invoice = dest.rpc.invoice(1000, 'invoice-{}'.format(random.random()), 'desc')['bolt11']
src.rpc.pay(invoice)
src.rpc.xpay(invoice)
benchmark(do_pay, l1, l3)
@ -102,7 +102,7 @@ def test_long_forward_payment(node_factory, benchmark):
def do_pay(src, dest):
invoice = dest.rpc.invoice(1000, 'invoice-{}'.format(random.random()), 'desc')['bolt11']
src.rpc.pay(invoice)
src.rpc.xpay(invoice)
benchmark(do_pay, nodes[0], nodes[-1])
@ -125,7 +125,7 @@ def test_pay(node_factory, benchmark):
invoices.append(invoice)
def do_pay(l1, l2):
l1.rpc.pay(invoices.pop())
l1.rpc.xpay(invoices.pop())
benchmark(do_pay, l1, l2)

View file

@ -684,7 +684,8 @@ def test_bookkeeping_descriptions(node_factory, bitcoind, chainparams):
bolt12_desc = 'test "bolt12" description, 🥰🪢'
offer = l1.rpc.call('offer', [100, bolt12_desc])
invoice = l2.rpc.call('fetchinvoice', {'offer': offer['bolt12']})
paid = l2.rpc.pay(invoice['invoice'])
payment_hash = l2.rpc.decode(invoice['invoice'])['invoice_payment_hash']
l2.rpc.xpay(invoice['invoice'])
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
wait_for(lambda: only_one(l2.rpc.listpeerchannels()['channels'])['htlcs'] == [])
l1_inc_ev = l1.rpc.bkpr_listincome()['income_events']
@ -693,12 +694,12 @@ def test_bookkeeping_descriptions(node_factory, bitcoind, chainparams):
l2.daemon.wait_for_log('coin_move .* [(]invoice[)] 0msat -100msat')
# Test paying an offer (bolt12) (rcvr)
inv = only_one([ev for ev in l1_inc_ev if 'payment_id' in ev and ev['payment_id'] == paid['payment_hash']])
inv = only_one([ev for ev in l1_inc_ev if 'payment_id' in ev and ev['payment_id'] == payment_hash])
assert inv['description'] == bolt12_desc
# Test paying an offer (bolt12) (sender)
l2_inc_ev = l2.rpc.bkpr_listincome()['income_events']
inv = only_one([ev for ev in l2_inc_ev if 'payment_id' in ev and ev['payment_id'] == paid['payment_hash'] and ev['tag'] == 'invoice'])
inv = only_one([ev for ev in l2_inc_ev if 'payment_id' in ev and ev['payment_id'] == payment_hash and ev['tag'] == 'invoice'])
assert inv['description'] == bolt12_desc
# Check the CSVs look groovy
@ -720,7 +721,7 @@ def test_bookkeeping_descriptions(node_factory, bitcoind, chainparams):
# Test that we can update the description, payment id
edited_desc_payid = 'edited payment_id description'
for node in [l1, l2]:
results = node.rpc.bkpr_editdescriptionbypaymentid(paid['payment_hash'], edited_desc_payid)
results = node.rpc.bkpr_editdescriptionbypaymentid(payment_hash, edited_desc_payid)
assert only_one(results['updated'])['description'] == edited_desc_payid
# Test that we can update the description, outpoint
@ -1245,7 +1246,7 @@ def test_bkpr_report_tags_and_fallback(node_factory):
l1, l2 = node_factory.line_graph(2, opts={'bkpr-currency': 'USD'})
inv = l2.rpc.invoice(100000, "test_bkpr_report_tags_and_fallback", 'desc with "quotes"')
l1.rpc.pay(inv["bolt11"])
l1.rpc.xpay(inv["bolt11"])
wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] == [])
res = l1.rpc.call(
@ -1332,7 +1333,7 @@ def test_bkpr_report_lightning_cli_csv(node_factory):
# Give desc something awkward so CSV escaping matters if it shows up.
inv = l2.rpc.invoice(100000, "test_bkpr_report_lightning_cli_csv", 'hello, "csv"')
l1.rpc.pay(inv["bolt11"])
l1.rpc.xpay(inv["bolt11"])
wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] == [])
# Single-column CSV is enough to validate the CLI path and escaping.

View file

@ -346,7 +346,7 @@ def test_lsps2_non_approved_zero_conf(node_factory, bitcoind):
)["bolt11"]
with pytest.raises(ValueError):
l3.rpc.pay(bolt11, amount_msat=10000000)
l3.rpc.xpay(bolt11, amount_msat=10000000)
# l1 shouldn't have a new channel.
chs = l1.rpc.listpeerchannels()["channels"]

View file

@ -306,8 +306,8 @@ def test_cln_plugin_reentrant(node_factory, executor):
i1 = l1.rpc.invoice(label='lbl1', amount_msat='42sat', description='desc')['bolt11']
i2 = l1.rpc.invoice(label='lbl2', amount_msat='31337sat', description='desc')['bolt11']
f1 = executor.submit(l2.rpc.pay, i1)
f2 = executor.submit(l2.rpc.pay, i2)
f1 = executor.submit(l2.rpc.xpay, i1)
f2 = executor.submit(l2.rpc.xpay, i2)
l1.daemon.wait_for_logs(["plugin-cln-plugin-reentrant: Holding on to incoming HTLC Object"] * 2)

View file

@ -857,7 +857,7 @@ def test_channel_lease_post_expiry(node_factory, bitcoind, chainparams):
# send some payments, mine a block or two
inv = l2.rpc.invoice(10**4, '1', 'no_1')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
# make sure it's completely resolved before we generate blocks,
# otherwise it can close HTLC!
@ -974,9 +974,9 @@ def test_channel_lease_unilat_closes(node_factory, bitcoind):
# send some payments, mine a block or two
inv = l2.rpc.invoice(10**4, '1', 'no_1')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
inv = l2.rpc.invoice(10**4, '3', 'no_3')
l3.rpc.pay(inv['bolt11'])
l3.rpc.xpay(inv['bolt11'])
bitcoind.generate_block(2)
sync_blockheight(bitcoind, [l1, l2, l3])
@ -1079,7 +1079,7 @@ def test_channel_lease_lessor_cheat(node_factory, bitcoind, chainparams):
wait_for(lambda: [c['active'] for c in l2.rpc.listchannels(l2.get_channel_scid(l1))['channels']] == [True, True])
# send some payments, mine a block or two
inv = l2.rpc.invoice(10**4, '1', 'no_1')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
bitcoind.generate_block(1)
@ -1094,7 +1094,7 @@ def test_channel_lease_lessor_cheat(node_factory, bitcoind, chainparams):
# push some money from l2->l1, so the commit counter advances
inv = l1.rpc.invoice(10**5, '2', 'no_2')
l2.rpc.pay(inv['bolt11'])
l2.rpc.xpay(inv['bolt11'])
# stop both nodes, roll back l2's database
l2.stop()
@ -1151,7 +1151,7 @@ def test_channel_lease_lessee_cheat(node_factory, bitcoind, chainparams):
wait_for(lambda: [c['active'] for c in l2.rpc.listchannels(l2.get_channel_scid(l1))['channels']] == [True, True])
# send some payments, mine a block or two
inv = l2.rpc.invoice(10**4, '1', 'no_1')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
bitcoind.generate_block(1)
@ -1166,7 +1166,7 @@ def test_channel_lease_lessee_cheat(node_factory, bitcoind, chainparams):
# push some money from l2->l1, so the commit counter advances
inv = l1.rpc.invoice(10**5, '2', 'no_2')
l2.rpc.pay(inv['bolt11'])
l2.rpc.xpay(inv['bolt11'])
# stop both nodes, roll back l1's database
l1.stop()
@ -1246,11 +1246,11 @@ def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams, anchors):
# push some money so that 1 + 4 can both send htlcs
inv = l2.rpc.invoice(10**9 // 2, '1', 'balancer')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
inv = l4.rpc.invoice(10**9 // 2, '1', 'balancer')
l2.rpc.pay(inv['bolt11'])
l2.rpc.xpay(inv['bolt11'])
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
# now we send one 'sticky' htlc: l4->l1
@ -1275,7 +1275,7 @@ def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams, anchors):
inv = l3.rpc.invoice(10**4, '1', 'push')
# Make sure gossipd in l2 knows it's active
wait_for(lambda: [c['active'] for c in l2.rpc.listchannels(l2.get_channel_scid(l3))['channels']] == [True, True])
l2.rpc.pay(inv['bolt11'])
l2.rpc.xpay(inv['bolt11'])
# stop both nodes, roll back l2's database
l2.stop()
@ -1439,10 +1439,10 @@ def test_penalty_htlc_tx_timeout(node_factory, bitcoind, chainparams, anchors):
# push some money so that 1 + 4 can both send htlcs
inv = l2.rpc.invoice(10**9 // 2, '1', 'balancer')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
inv = l4.rpc.invoice(10**9 // 2, '1', 'balancer')
l2.rpc.pay(inv['bolt11'])
l2.rpc.xpay(inv['bolt11'])
# now we send two 'sticky' htlcs, l1->l5 + l4->l1
amt = 10**8 // 2
@ -1476,7 +1476,7 @@ def test_penalty_htlc_tx_timeout(node_factory, bitcoind, chainparams, anchors):
inv = l3.rpc.invoice(10**4, '1', 'push')
# Make sure gossipd in l2 knows it's active
wait_for(lambda: [c['active'] for c in l2.rpc.listchannels(l2.get_channel_scid(l3))['channels']] == [True, True])
l2.rpc.pay(inv['bolt11'])
l2.rpc.xpay(inv['bolt11'])
# stop both nodes, roll back l2's database
l2.stop()
@ -3987,7 +3987,7 @@ def test_closing_tx_valid(node_factory, bitcoind):
def test_closing_minfee(node_factory, bitcoind):
l1, l2 = node_factory.line_graph(2, opts={'feerates': None})
l1.rpc.pay(l2.rpc.invoice(10000000, 'test', 'test')['bolt11'])
l1.rpc.xpay(l2.rpc.invoice(10000000, 'test', 'test')['bolt11'])
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
@ -4091,7 +4091,7 @@ def test_closing_cpfp(node_factory, bitcoind):
change = only_one(l1.rpc.listfunds()['outputs'])
# Make sure both sides have some output
l1.rpc.pay(l2.rpc.invoice(10000000, 'test', 'test')['bolt11'])
l1.rpc.xpay(l2.rpc.invoice(10000000, 'test', 'test')['bolt11'])
# Mutual close
close_txid = only_one(l1.rpc.close(l2.info['id'])['txids'])
@ -4199,7 +4199,7 @@ def test_anchorspend_using_to_remote(node_factory, bitcoind, anchors):
# l4 disconnects after receiving fulfill. It then unilaterally
# closes, l2 gets to-remote with its output.
l4.rpc.pay(l2.rpc.invoice(100000000, 'test', 'test')['bolt11'])
l4.rpc.xpay(l2.rpc.invoice(100000000, 'test', 'test')['bolt11'])
wait_for(lambda: only_one(l4.rpc.listpeerchannels()['channels'])['htlcs'] != [])
wait_for(lambda: only_one(l4.rpc.listpeers()['peers'])['connected'] is False)
@ -4221,7 +4221,7 @@ def test_anchorspend_using_to_remote(node_factory, bitcoind, anchors):
for n in (l1, l2, l3):
wait_for(lambda: len(n.rpc.listchannels()['channels']) == 4)
l3.rpc.pay(l2.rpc.invoice(200000000, 'test2', 'test2')['bolt11'])
l3.rpc.xpay(l2.rpc.invoice(200000000, 'test2', 'test2')['bolt11'])
wait_for(lambda: only_one(l2.rpc.listpeerchannels(l3.info['id'])['channels'])['htlcs'] == [])
# Get HTLC stuck, so l2 has reason to push commitment tx.
@ -4281,7 +4281,7 @@ def test_onchain_reestablish_reply(node_factory, bitcoind, executor):
# For l2->l2, try:
# 1. are not in the initial state, and
# 2. actually onchain.
l2.rpc.pay(l3.rpc.invoice(200000000, 'test', 'test')['bolt11'])
l2.rpc.xpay(l3.rpc.invoice(200000000, 'test', 'test')['bolt11'])
# We block l3 from seeing close, so it will try to reestablish.
def no_new_blocks(req):
@ -4376,7 +4376,7 @@ def test_reestablish_closed_channels(node_factory, bitcoind):
l2.daemon.rpcproxy.mock_rpc('getblockhash', no_new_blocks)
# Make a payment, make sure it's entirely finished before we close.
l1.rpc.pay(l2.rpc.invoice(200000000, 'test', 'test')['bolt11'])
l1.rpc.xpay(l2.rpc.invoice(200000000, 'test', 'test')['bolt11'])
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
# l1 closes, unilaterally.

View file

@ -1191,8 +1191,8 @@ def test_v2_open(node_factory, bitcoind, chainparams):
# Send a payment over the channel
p = l2.rpc.invoice(100000, 'testpayment', 'desc')
l1.rpc.pay(p['bolt11'])
result = l1.rpc.waitsendpay(p['payment_hash'])
l1.rpc.xpay(p['bolt11'])
result = only_one(l1.rpc.listsendpays(payment_hash=p['payment_hash'])['payments'])
assert(result['status'] == 'complete')
@ -1708,7 +1708,7 @@ def test_funding_close_upfront(node_factory, bitcoind):
# check that remote peer closing works as expected (and that remote's close_to works)
_fundchannel(l1, l2, amt_addr, addr)
# send some money to remote so that they have a closeout
l1.rpc.pay(l2.rpc.invoice((amt_addr // 2) * 1000, 'test_remote_close_to', 'desc')['bolt11'])
l1.rpc.xpay(l2.rpc.invoice((amt_addr // 2) * 1000, 'test_remote_close_to', 'desc')['bolt11'])
assert l2.rpc.listpeerchannels()['channels'][-1]['close_to_addr'] == remote_valid_addr
# The tx outputs must be one of the two permutations
assert _close(l2, l1) in ([addr, remote_valid_addr], [remote_valid_addr, addr])
@ -1857,7 +1857,7 @@ def test_multifunding_v1_v2_mixed(node_factory, bitcoind):
for ldest in [l2, l3, l4]:
inv = ldest.rpc.invoice(5000, 'inv', 'inv')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
@ -1899,12 +1899,12 @@ def test_multifunding_v2_exclusive(node_factory, bitcoind):
# For dual-funded channels, pay from accepter to initiator
for ldest in [l2, l3]:
inv = l1.rpc.invoice(5000, 'inv' + ldest.info['id'], 'inv')['bolt11']
ldest.rpc.pay(inv)
ldest.rpc.xpay(inv)
# Then pay other direction
for ldest in [l2, l3, l4]:
inv = ldest.rpc.invoice(10000, 'inv', 'inv')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
@pytest.mark.openchannel('v1')
@ -1935,7 +1935,7 @@ def test_multifunding_simple(node_factory, bitcoind):
for ldest in [l2, l3, l4]:
inv = ldest.rpc.invoice(5000, 'inv', 'inv')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
@pytest.mark.openchannel('v1')
@ -1994,7 +1994,7 @@ def test_multifunding_one(node_factory, bitcoind):
for ldest in [l2, l3]:
inv = ldest.rpc.invoice(5000, 'inv', 'inv')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
@pytest.mark.openchannel('v1')
@ -2231,7 +2231,7 @@ def test_multifunding_best_effort(node_factory, bitcoind):
# There should be working channels to l2 and l4.
for ldest in [l2, l4]:
inv = ldest.rpc.invoice(5000, 'i{}'.format(i), 'i{}'.format(i))['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
# Function to find the SCID of the channel that is
# currently open.
@ -2598,7 +2598,7 @@ def test_update_fee_dynamic(node_factory, bitcoind):
# It will send UPDATE_FEE when it tries to send HTLC.
inv = l2.rpc.invoice(5000, 'test_update_fee_dynamic', 'test_update_fee_dynamic')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
l2.daemon.wait_for_log('peer_in.*UPDATE_FEE')
@ -2610,7 +2610,7 @@ def test_update_fee_dynamic(node_factory, bitcoind):
time.sleep(2)
inv = l2.rpc.invoice(5000, 'test_update_fee_dynamic2', 'test_update_fee_dynamic2')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
# Won't update fee.
assert not l2.daemon.is_in_log('peer_in.*UPDATE_FEE',
@ -2621,7 +2621,7 @@ def test_update_fee_dynamic(node_factory, bitcoind):
# It will send UPDATE_FEE when it tries to send HTLC.
inv = l2.rpc.invoice(5000, 'test_update_fee_dynamic3', 'test_update_fee_dynamic')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
l2.daemon.wait_for_log('peer_in.*UPDATE_FEE')
@ -3264,7 +3264,7 @@ def test_fulfill_incoming_first(node_factory, bitcoind):
wait_for_announce=True)
# This succeeds.
l1.rpc.pay(l3.rpc.invoice(200000000, 'test_fulfill_incoming_first', 'desc')['bolt11'])
l1.rpc.xpay(l3.rpc.invoice(200000000, 'test_fulfill_incoming_first', 'desc')['bolt11'])
# l1 can shutdown, fine.
l1.rpc.close(l2.info['id'])
@ -3620,7 +3620,7 @@ def test_wumbo_channels(node_factory, bitcoind):
inv = l2.rpc.invoice(str(1 << 24) + "sat", "test_wumbo_channels", "wumbo payment")
assert 'warning_mpp' not in inv
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
# Done in a single shot!
assert len(l1.rpc.listsendpays()['payments']) == 1
@ -4144,7 +4144,7 @@ def test_multichan(node_factory, executor, bitcoind):
wait_for(lambda: only_one(l3.rpc.listpeers(l2.info['id'])['peers'])['connected'])
inv4 = l3.rpc.invoice(100000000, "invoice4", "invoice4")
l1.rpc.pay(inv4['bolt11'])
l1.rpc.xpay(inv4['bolt11'], dev_use_shadow=False)
# A good place to test listhtlcs!
wait_for(lambda: all([h['state'] == 'RCVD_REMOVE_ACK_REVOCATION' for h in l1.rpc.listhtlcs()['htlcs']]))
@ -4218,7 +4218,7 @@ def test_mutual_reconnect_race(node_factory, executor, bitcoind):
"desc"
)['bolt11']
try:
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
except RpcError:
pass
@ -4248,7 +4248,7 @@ def test_mutual_reconnect_race(node_factory, executor, bitcoind):
wait_for(lambda: only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['connected'])
inv = l2.rpc.invoice(100000000, "invoice4", "invoice4")
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
def test_no_reconnect_awating_unilateral(node_factory, bitcoind):

View file

@ -320,7 +320,7 @@ def test_bkpr_listaccountevents_currencyrate(node_factory, fake_rateserver):
l1, l2 = node_factory.line_graph(2, opts=opts)
inv = l2.rpc.invoice(100000, "test-bkpr-currency", "desc")
l1.rpc.pay(inv["bolt11"])
l1.rpc.xpay(inv["bolt11"])
# We want this event in the list, so wait until it's totally closed.
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
@ -353,7 +353,7 @@ def test_bkpr_listaccountevents_realtime(node_factory, fake_rateserver):
old_median = (fake_rateserver["state"]["fast"] + fake_rateserver["state"]["slow"]) / 2
inv = l2.rpc.invoice(100000, "test_bkpr_listaccountevents_realtime", "desc")
l1.rpc.pay(inv["bolt11"])
l1.rpc.xpay(inv["bolt11"])
# We want this event in the list, so wait until it's totally closed.
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
@ -391,7 +391,7 @@ def test_bkpr_currency_dynamic(node_factory, fake_rateserver):
median_rate = (fake_rateserver["state"]["fast"] + fake_rateserver["state"]["slow"]) / 2
inv1 = l2.rpc.invoice(100000, "test_bkpr_currency_dynamic_1", "desc")
l1.rpc.pay(inv1["bolt11"])
l1.rpc.xpay(inv1["bolt11"])
# We want this event in the list, so wait until it's totally closed.
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
@ -406,7 +406,7 @@ def test_bkpr_currency_dynamic(node_factory, fake_rateserver):
l1.rpc.setconfig("bkpr-currency", "USD")
inv2 = l2.rpc.invoice(100000, "test_bkpr_currency_dynamic_2", "desc")
l1.rpc.pay(inv2["bolt11"])
l1.rpc.xpay(inv2["bolt11"])
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
events = l1.rpc.bkpr_listaccountevents()["events"]
@ -422,7 +422,7 @@ def test_bkpr_currency_dynamic(node_factory, fake_rateserver):
l1.rpc.setconfig("bkpr-currency", "")
inv3 = l2.rpc.invoice(100000, "test_bkpr_currency_dynamic_3", "desc")
l1.rpc.pay(inv3["bolt11"])
l1.rpc.xpay(inv3["bolt11"])
# If we don't wait here, we can get a spurious error from
# cln-currencyrate as fixture gets torn down!
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
@ -455,7 +455,7 @@ def test_bkpr_currencyrate_persisted(node_factory, fake_rateserver):
old_median = (fake_rateserver["state"]["fast"] + fake_rateserver["state"]["slow"]) / 2
inv = l2.rpc.invoice(100000, "test_bkpr_currencyrate_persisted", "desc")
l1.rpc.pay(inv["bolt11"])
l1.rpc.xpay(inv["bolt11"])
# Make sure it's fully resolved so we get all events now.
wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] == [])
@ -476,7 +476,7 @@ def test_bkpr_currencyrate_persisted(node_factory, fake_rateserver):
# And we can add more.
inv2 = l2.rpc.invoice(100000, "test_bkpr_currencyrate_persisted2", "desc")
l1.rpc.pay(inv2["bolt11"])
l1.rpc.xpay(inv2["bolt11"])
wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] == [])
new_events = l1.rpc.bkpr_listaccountevents()["events"]
@ -524,7 +524,7 @@ def test_bkpr_currencyrate_warns_for_old_events(node_factory, fake_rateserver):
# 1. Create old events before bkpr-currency is enabled.
inv1 = l2.rpc.invoice(100000, "test_bkpr_currencyrate_warns_old_1", "desc")
l1.rpc.pay(inv1["bolt11"])
l1.rpc.xpay(inv1["bolt11"])
wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] == [])
events = l1.rpc.bkpr_listaccountevents()["events"]
assert events
@ -536,7 +536,7 @@ def test_bkpr_currencyrate_warns_for_old_events(node_factory, fake_rateserver):
# New events.
inv2 = l2.rpc.invoice(100000, "test_bkpr_currencyrate_warns_old_2", "desc")
l1.rpc.pay(inv2["bolt11"])
l1.rpc.xpay(inv2["bolt11"])
wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] == [])
# It does NOT complain about records before we set currency at all.
@ -552,7 +552,7 @@ def test_bkpr_currencyrate_warns_for_old_events(node_factory, fake_rateserver):
# 4. Create new events while bookkeeper is stopped, then let them go stale.
inv3 = l2.rpc.invoice(100000, "test_bkpr_currencyrate_warns_old_3", "desc")
l1.rpc.pay(inv3["bolt11"])
l1.rpc.xpay(inv3["bolt11"])
wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] == [])
time.sleep(61)
@ -592,7 +592,7 @@ def test_bkpr_currencyrate_ranges(node_factory, fake_rateserver):
time.sleep(1)
inv1 = l2.rpc.invoice(100000, "test_bkpr_currencyrate_ranges_1", "desc")
l1.rpc.pay(inv1["bolt11"])
l1.rpc.xpay(inv1["bolt11"])
wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] == [])
# Now we change the rate (and make sure time goes forward so it re-checks!)
@ -606,7 +606,7 @@ def test_bkpr_currencyrate_ranges(node_factory, fake_rateserver):
l1.connect(l2)
inv2 = l2.rpc.invoice(100000, "test_bkpr_currencyrate_ranges_2", "desc")
l1.rpc.pay(inv2["bolt11"])
l1.rpc.xpay(inv2["bolt11"])
wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] == [])
# Calling this here makes sure it's finished processing currencyrates

View file

@ -979,7 +979,7 @@ def test_report_routing_failure(node_factory, bitcoind):
# Test
inv = l4.rpc.invoice(1234567, 'inv', 'for testing')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
def test_query_short_channel_id(node_factory, bitcoind, chainparams):

View file

@ -141,7 +141,7 @@ def test_invoice_preimage(node_factory):
# Make invoice and pay it
inv = l2.rpc.invoice(amount_msat=123456, label="inv", description="?", preimage=invoice_preimage)
payment = l1.rpc.pay(inv['bolt11'])
payment = l1.rpc.xpay(inv['bolt11'])
# Check preimage was given.
payment_preimage = payment['payment_preimage']
@ -176,7 +176,7 @@ def test_invoice_routeboost(node_factory, bitcoind):
assert r['cltv_expiry_delta'] == 6
# Pay it (and make sure it's fully resolved before we take l2 offline!)
l2.rpc.pay(inv['bolt11'])
l2.rpc.xpay(inv['bolt11'])
wait_channel_quiescent(l2, l3)
# Due to reserve & fees, l2 doesn't have capacity to pay this.
@ -386,8 +386,8 @@ def test_invoice_expiry(node_factory, executor):
inv = l2.rpc.invoice(amount_msat=123000, label='test_pay', description='description', expiry=1)['bolt11']
time.sleep(2)
with pytest.raises(RpcError):
l1.rpc.pay(inv)
with pytest.raises(RpcError, match='Invoice expired [1-9] seconds ago'):
l1.rpc.xpay(inv)
invoices = l2.rpc.listinvoices('test_pay')['invoices']
assert len(invoices) == 1
@ -460,7 +460,7 @@ def test_waitinvoice(node_factory, executor):
time.sleep(1)
assert not f.done()
# Pay invoice 2
l1.rpc.pay(inv2['bolt11'])
l1.rpc.xpay(inv2['bolt11'])
# Waiter should stil be blocked
time.sleep(1)
assert not f.done()
@ -468,7 +468,7 @@ def test_waitinvoice(node_factory, executor):
r = executor.submit(l2.rpc.waitinvoice, 'inv2').result(timeout=5)
assert r['label'] == 'inv2'
# Pay invoice 1
l1.rpc.pay(inv1['bolt11'])
l1.rpc.xpay(inv1['bolt11'])
# Waiter for invoice 1 should now finish
r = f.result(timeout=5)
assert r['label'] == 'inv1'
@ -494,8 +494,8 @@ def test_waitanyinvoice(node_factory, executor):
assert not f.done()
# Now pay the first two invoices and make sure we notice
l1.rpc.pay(inv1['bolt11'])
l1.rpc.pay(inv2['bolt11'])
l1.rpc.xpay(inv1['bolt11'])
l1.rpc.xpay(inv2['bolt11'])
r = f.result(timeout=5)
assert r['label'] == 'inv1'
pay_index = r['pay_index']
@ -509,7 +509,7 @@ def test_waitanyinvoice(node_factory, executor):
f = executor.submit(l2.rpc.waitanyinvoice, pay_index)
time.sleep(1)
assert not f.done()
l1.rpc.pay(inv3['bolt11'])
l1.rpc.xpay(inv3['bolt11'])
r = f.result(timeout=5)
assert r['label'] == 'inv3'
pay_index = r['pay_index']
@ -521,7 +521,7 @@ def test_waitanyinvoice(node_factory, executor):
# If timeout is 0 but a paid invoice is available
# anyway, it should return successfully immediately.
l1.rpc.pay(inv4['bolt11'])
l1.rpc.xpay(inv4['bolt11'])
r = executor.submit(l2.rpc.waitanyinvoice, pay_index, 0).result(timeout=5)
assert r['label'] == 'inv4'
@ -556,13 +556,13 @@ def test_waitanyinvoice_reversed(node_factory, executor):
# Pay inv2, wait, pay inv1, wait
# Pay inv2
l1.rpc.pay(inv2['bolt11'])
l1.rpc.xpay(inv2['bolt11'])
# Wait - should not block, should return inv2
r = executor.submit(l2.rpc.waitanyinvoice).result(timeout=5)
assert r['label'] == 'inv2'
pay_index = r['pay_index']
# Pay inv1
l1.rpc.pay(inv1['bolt11'])
l1.rpc.xpay(inv1['bolt11'])
# Wait inv2 - should not block, should return inv1
r = executor.submit(l2.rpc.waitanyinvoice, pay_index).result(timeout=5)
assert r['label'] == 'inv1'
@ -602,7 +602,7 @@ def test_amountless_invoice(node_factory):
details = l1.rpc.decode(inv)
assert('msatoshi' not in details)
l1.rpc.pay(inv, amount_msat=1337)
l1.rpc.xpay(inv, amount_msat=1337)
i = l2.rpc.listinvoices()['invoices']
assert(len(i) == 1)
@ -692,7 +692,7 @@ def test_wait_invoices(node_factory, executor):
waitfut = executor.submit(l2.rpc.call, 'wait', {'subsystem': 'invoices', 'indexname': 'updated', 'nextvalue': 1})
l2.daemon.wait_for_log('waiting on invoices updated 1')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
waitres = waitfut.result(TIMEOUT)
assert waitres == {'subsystem': 'invoices',
'updated': 1,
@ -836,7 +836,7 @@ def test_listinvoices_index(node_factory):
# Pay 10 of them, in reverse order. These will be the last ones in the 'updated' index.
for i in range(70, 60, -1):
l1.rpc.pay(invs[i]['bolt11'])
l1.rpc.xpay(invs[i]['bolt11'])
# Make sure it's fully resolved!
wait_for(lambda: only_one(l2.rpc.listpeerchannels()['channels'])['htlcs'] == [])

View file

@ -453,20 +453,12 @@ def test_htlc_out_timeout(node_factory, bitcoind, executor):
inv = l2.rpc.invoice(amt, 'test_htlc_out_timeout', 'desc')['bolt11']
assert only_one(l2.rpc.listinvoices('test_htlc_out_timeout')['invoices'])['status'] == 'unpaid'
executor.submit(l1.dev_pay, inv, dev_use_shadow=False)
executor.submit(l1.rpc.xpay, inv)
# l1 will disconnect, and not reconnect.
l1.daemon.wait_for_log('dev_disconnect: -WIRE_REVOKE_AND_ACK')
# Takes 6 blocks to timeout (cltv-final + 1), but we also give grace period of 1 block.
# shadow route can add extra blocks!
status = only_one(l1.rpc.call('paystatus')['pay'])
if 'shadow' in status:
shadowlen = 6 * status['shadow'].count('Added 6 cltv delay for shadow')
else:
shadowlen = 0
bitcoind.generate_block(5 + 1 + shadowlen)
bitcoind.generate_block(5 + 1)
time.sleep(3)
assert not l1.daemon.is_in_log('hit deadline')
bitcoind.generate_block(1)
@ -533,19 +525,12 @@ def test_htlc_in_timeout(node_factory, bitcoind, executor):
inv = l2.rpc.invoice(amt, 'test_htlc_in_timeout', 'desc')['bolt11']
assert only_one(l2.rpc.listinvoices('test_htlc_in_timeout')['invoices'])['status'] == 'unpaid'
executor.submit(l1.dev_pay, inv, dev_use_shadow=False)
executor.submit(l1.rpc.xpay, inv)
# l1 will disconnect and not reconnect.
l1.daemon.wait_for_log('dev_disconnect: -WIRE_REVOKE_AND_ACK')
# Deadline HTLC expiry minus 1/2 cltv-expiry delta (rounded up) (== cltv - 3). cltv is 5+1.
# shadow route can add extra blocks!
status = only_one(l1.rpc.call('paystatus')['pay'])
if 'shadow' in status:
shadowlen = 6 * status['shadow'].count('Added 6 cltv delay for shadow')
else:
shadowlen = 0
bitcoind.generate_block(2 + shadowlen)
bitcoind.generate_block(2)
assert not l2.daemon.is_in_log('hit deadline')
bitcoind.generate_block(1)
@ -555,7 +540,7 @@ def test_htlc_in_timeout(node_factory, bitcoind, executor):
l2.daemon.wait_for_log(' to ONCHAIN')
l1.daemon.wait_for_log(' to ONCHAIN')
# L2 will collect HTLC (iff no shadow route)
# L2 will collect HTLC
_, txid, blocks = l2.wait_for_onchaind_tx('OUR_HTLC_SUCCESS_TX',
'OUR_UNILATERAL/THEIR_HTLC')
assert blocks == 0
@ -3102,11 +3087,11 @@ def test_emergencyrecoverpenaltytxn(node_factory, bitcoind):
stubs = l1.rpc.emergencyrecover()["stubs"]
assert l1.daemon.is_in_log('channel {} already exists!'.format(_['channel_id']))
l2.rpc.pay(l1.rpc.invoice(25000000, 'lbl1', 'desc1')['bolt11'])
l2.rpc.xpay(l1.rpc.invoice(25000000, 'lbl1', 'desc1')['bolt11'])
tx = l2.rpc.dev_sign_last_tx(l1.info['id'])['tx']
l2.rpc.pay(l1.rpc.invoice(25000000, 'lbl2', 'desc2')['bolt11'])
l2.rpc.xpay(l1.rpc.invoice(25000000, 'lbl2', 'desc2')['bolt11'])
l1.stop()
@ -3222,7 +3207,7 @@ def test_recover_plugin(node_factory, bitcoind):
# successful payments
i31 = l1.rpc.invoice(10000, 'i31', 'desc')
l2.rpc.pay(i31['bolt11'])
l2.rpc.xpay(i31['bolt11'])
# Now, move l2 back in time.
l2.stop()
@ -3396,7 +3381,7 @@ def test_listforwards_and_listhtlcs(node_factory, bitcoind):
# successful payments
i31 = l3.rpc.invoice(1000, 'i31', 'desc')
l1.rpc.pay(i31['bolt11'])
l1.rpc.xpay(i31['bolt11'])
# 1 htlc in, 1 htlc out.
assert len(l2.rpc.listhtlcs()['htlcs']) == 2
@ -3415,7 +3400,7 @@ def test_listforwards_and_listhtlcs(node_factory, bitcoind):
assert len(l2.rpc.listhtlcs(id=c12, index='updated', start=1, limit=1)['htlcs']) == 1
i41 = l4.rpc.invoice(2000, 'i41', 'desc')
l1.rpc.pay(i41['bolt11'])
l1.rpc.xpay(i41['bolt11'])
# failed payment
failed_inv = l3.rpc.invoice(4000, 'failed', 'desc')
@ -3585,7 +3570,7 @@ def test_listforwards_wait(node_factory, executor):
amt1 = 1000
inv1 = l3.rpc.invoice(amt1, 'inv1', 'desc')
l1.rpc.pay(inv1['bolt11'])
l1.rpc.xpay(inv1['bolt11'], dev_use_shadow=False)
waitres = waitcreate.result(TIMEOUT)
assert waitres == {'subsystem': 'forwards',
@ -3614,8 +3599,8 @@ def test_listforwards_wait(node_factory, executor):
l2.daemon.wait_for_logs(['waiting on forwards created 2', 'waiting on forwards updated 2'])
time.sleep(1)
with pytest.raises(RpcError, match="WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS"):
l1.rpc.pay(inv2['bolt11'])
with pytest.raises(RpcError, match="incorrect_or_unknown_payment_details"):
l1.rpc.xpay(inv2['bolt11'])
waitres = waitcreate.result(TIMEOUT)
assert waitres == {'subsystem': 'forwards',
@ -3708,8 +3693,8 @@ def test_listhtlcs_wait(node_factory, bitcoind, executor):
waitcreate = executor.submit(l2.rpc.wait, subsystem='htlcs', indexname='created', nextvalue=4)
l2.daemon.wait_for_log('waiting on htlcs created 4')
with pytest.raises(RpcError, match="WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS"):
l1.rpc.pay(inv2['bolt11'])
with pytest.raises(RpcError, match="incorrect_or_unknown_payment_details"):
l1.rpc.xpay(inv2['bolt11'], dev_use_shadow=False)
waitres = waitcreate.result(TIMEOUT)
assert waitres == {'subsystem': 'htlcs',
@ -3744,7 +3729,7 @@ def test_listforwards_ancient(node_factory, bitcoind):
amt1 = 1000
inv1 = l3.rpc.invoice(amt1, 'inv1', 'desc')
l1.rpc.pay(inv1['bolt11'])
l1.rpc.xpay(inv1['bolt11'])
forwards = l2.rpc.listforwards()['forwards']
assert len(forwards) == 1
@ -4889,7 +4874,7 @@ def test_preapprove_use(node_factory, bitcoind, xkeysend):
# This will fail at the preapprove step.
inv = l1.rpc.invoice(123000, 'label', 'description', 3700)['bolt11']
with pytest.raises(RpcError, match='invoice was declined'):
l2.rpc.pay(inv)
l2.rpc.xpay(inv)
# This will fail the same way
with pytest.raises(RpcError, match='invoice was declined'):

View file

@ -100,7 +100,7 @@ def test_multifunding_v2_best_effort(node_factory, bitcoind):
working_chans = [l4] if failed_sign else [l2, l4]
for ldest in working_chans:
inv = ldest.rpc.invoice(5000, 'i{}'.format(i), 'i{}'.format(i))['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
# Function to find the SCID of the channel that is
# currently open.
@ -653,7 +653,7 @@ def test_v2_rbf_liquidity_ad(node_factory, bitcoind, chainparams):
# send some payments, mine a block or two
inv = l2.rpc.invoice(10**4, '1', 'no_1')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
# l2 attempts to close a channel that it leased, should succeed
# (channel isnt leased)
@ -1646,7 +1646,7 @@ def test_zeroconf_open(bitcoind, node_factory):
l2alias = only_one(l2.rpc.listpeerchannels(l3.info['id'])['channels'])['alias']['local']
assert(hop['pubkey'] == l2.info['id']) # l2 is the entrypoint
assert(hop['short_channel_id'] == l2alias) # Alias has to make sense to entrypoint
l2.rpc.pay(inv)
l2.rpc.xpay(inv)
# Ensure lightningd knows about the balance change before
# attempting the other way around.
@ -1654,7 +1654,7 @@ def test_zeroconf_open(bitcoind, node_factory):
# Inverse payments should work too
inv = l2.rpc.invoice(10**5, 'lbl', 'desc')['bolt11']
l3.rpc.pay(inv)
l3.rpc.xpay(inv)
def test_zeroconf_public(bitcoind, node_factory, chainparams):
@ -1792,7 +1792,7 @@ def test_zeroconf_forward(node_factory, bitcoind):
# Make sure (esp in non-dev-mode) blockheights agree so we don't WIRE_EXPIRY_TOO_SOON...
sync_blockheight(bitcoind, [l1, l2, l3])
inv = l3.rpc.invoice(42 * 10**6, 'inv1', 'desc')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
# And now try the other way around: zeroconf channel first
# followed by a public one.
@ -1803,7 +1803,7 @@ def test_zeroconf_forward(node_factory, bitcoind):
wait_for(lambda: (p['htlcs'] == [] for p in l2.rpc.listpeerchannels()['channels']))
inv = l1.rpc.invoice(42, 'back1', 'desc')['bolt11']
l3.rpc.pay(inv)
l3.rpc.xpay(inv)
def test_zeroconf_refusal(bitcoind, node_factory, chainparams):
@ -2068,7 +2068,7 @@ def test_zeroconf_multichan_forward(node_factory):
l2.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_READY')
l3.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_READY')
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
for c in l2.rpc.listpeerchannels(l3.info['id'])['channels']:
if c['channel_id'] == zeroconf_cid:
@ -2683,10 +2683,10 @@ def test_multifunding_all_amount(node_factory, bitcoind):
wait_for(lambda: [c['state'] for c in (l1.rpc.listpeerchannels()['channels'])] == ['CHANNELD_NORMAL', 'CHANNELD_NORMAL'])
inv = l2.rpc.invoice(5000, 'i1', 'i1')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
inv2 = l3.rpc.invoice(100000, 'i2', 'i2')['bolt11']
l1.rpc.pay(inv2)
l1.rpc.xpay(inv2)
@pytest.mark.parametrize("dopay", [True, False]) # Whether to send a payment or not
@ -2735,7 +2735,7 @@ def test_zeroconf_forget(node_factory, bitcoind, dopay: bool):
# risking any of our funds.
if dopay:
inv = l2.rpc.invoice(1, "payme", "my stake in the unconfirmed channel")
l1.rpc.pay(inv["bolt11"])
l1.rpc.xpay(inv["bolt11"])
wait_for(lambda: only_one(l2.rpc.listpeerchannels()['channels'])['to_us_msat'] == 1)
# We need *another* channel to make it forget the first though! (One block later, otherwise

View file

@ -5001,13 +5001,20 @@ def test_pay_blockheight_mismatch(node_factory, bitcoind):
"""
send, direct, recv = node_factory.line_graph(3, wait_for_announce=True)
send, direct, recv = node_factory.line_graph(3,
wait_for_announce=True,
opts={'may_reconnect': True})
sync_blockheight(bitcoind, [send, recv])
height = bitcoind.rpc.getblockchaininfo()['blocks']
# Pin `send` at the current height. by not returning the next
# blockhash. This error is special-cased not to count as the
# backend failing since it is used to poll for the next block.
def mock_getblockhash(req):
# Allow old blocks, for restart.
if int(req['params'][0]) <= height:
return None
return {
"id": req['id'],
"error": {
@ -5020,6 +5027,10 @@ def test_pay_blockheight_mismatch(node_factory, bitcoind):
bitcoind.generate_block(100)
sync_blockheight(bitcoind, [recv])
# For xpay, it doesn't poll the blockheight, only handles case where
# it's behind at the start.
send.restart()
send.rpc.connect(direct.info['id'], 'localhost', direct.port)
inv = recv.rpc.invoice(42, 'lbl', 'desc')['bolt11']
send.rpc.pay(inv)

View file

@ -669,7 +669,7 @@ def test_invoice_payment_hook(node_factory):
# This one works
inv1 = l2.rpc.invoice(1230, 'label', 'description', preimage='1' * 64)
l1.rpc.pay(inv1['bolt11'])
l1.rpc.xpay(inv1['bolt11'])
l2.daemon.wait_for_log('label=label')
l2.daemon.wait_for_log('msat=')
@ -677,11 +677,8 @@ def test_invoice_payment_hook(node_factory):
# This one will be rejected.
inv2 = l2.rpc.invoice(1230, 'label2', 'description', preimage='0' * 64)
with pytest.raises(RpcError):
l1.rpc.pay(inv2['bolt11'])
pstatus = l1.rpc.call('paystatus', [inv2['bolt11']])['pay'][0]
assert pstatus['attempts'][-1]['failure']['data']['failcodename'] == 'WIRE_TEMPORARY_NODE_FAILURE'
with pytest.raises(RpcError, match=r'Unexpected error \(temporary_node_failure\) from final node'):
l1.rpc.xpay(inv2['bolt11'])
l2.daemon.wait_for_log('label=label2')
l2.daemon.wait_for_log('msat=')
@ -697,7 +694,7 @@ def test_invoice_payment_hook_hold(node_factory, executor):
inv1 = l2.rpc.invoice(1230, 'label', 'description', preimage='1' * 64)
# This should block.
f = executor.submit(l1.rpc.pay, inv1['bolt11'])
f = executor.submit(l1.rpc.xpay, inv1['bolt11'])
time.sleep(5)
assert not f.done()
@ -1220,8 +1217,8 @@ def test_htlc_accepted_hook_fail(node_factory):
# Now try with forwarded HTLCs: l2 should still fail them
# This must fail
inv = l3.rpc.invoice(1000, "lbl", "desc")['bolt11']
with pytest.raises(RpcError):
l1.rpc.pay(inv)
with pytest.raises(RpcError, match=r"We got a weird error \(temporary_node_failure\) for the invoice's route hint"):
l1.rpc.xpay(inv)
# And the invoice must still be unpaid
inv = l3.rpc.listinvoices("lbl")['invoices']
@ -1238,7 +1235,7 @@ def test_htlc_accepted_hook_resolve(node_factory):
], wait_for_announce=True)
inv = l3.rpc.invoice(amount_msat=1000, label="lbl", description="desc", preimage="00" * 32)['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
# And the invoice must still be unpaid
inv = l3.rpc.listinvoices("lbl")['invoices']
@ -1255,7 +1252,7 @@ def test_htlc_accepted_hook_direct_restart(node_factory, executor):
])
i1 = l2.rpc.invoice(amount_msat=1000, label="direct", description="desc")['bolt11']
f1 = executor.submit(l1.rpc.pay, i1)
f1 = executor.submit(l1.rpc.xpay, i1)
l2.daemon.wait_for_log(r'Holding onto an incoming htlc for 10 seconds')
@ -1940,7 +1937,7 @@ def test_hook_chaining(node_factory):
inv = l2.rpc.invoice(123, 'odd', "Odd payment handled by the first plugin",
preimage="AA" * 32)['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
# The first plugin will handle this, the second one should not be called.
assert(l2.daemon.is_in_log(
@ -1956,7 +1953,7 @@ def test_hook_chaining(node_factory):
inv = l2.rpc.invoice(
123, 'even', "Even payment handled by the second plugin", preimage="BB" * 32
)['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
assert(l2.daemon.is_in_log(
r'plugin-hook-chain-odd.py: htlc_accepted called for payment_hash {}'.format(hash2)
))
@ -1968,7 +1965,7 @@ def test_hook_chaining(node_factory):
# by the internal invoice handling.
inv = l2.rpc.invoice(123, 'neither', "Neither plugin handles this",
preimage="CC" * 32)['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
assert(l2.daemon.is_in_log(
r'plugin-hook-chain-odd.py: htlc_accepted called for payment_hash {}'.format(hash3)
))
@ -2255,7 +2252,7 @@ def test_hook_crash(node_factory, executor, bitcoind):
futures = []
for n in nodes:
inv = n.rpc.invoice(123, "lbl", "desc")['bolt11']
futures.append(executor.submit(l1.rpc.pay, inv))
futures.append(executor.submit(l1.rpc.xpay, inv))
for n in nodes:
n.daemon.wait_for_logs([
@ -2298,14 +2295,14 @@ def test_replacement_payload(node_factory):
# Replace with an invalid payload.
l2.rpc.call('setpayload', ['0000'])
inv = l2.rpc.invoice(123, 'test_replacement_payload', 'test_replacement_payload')['bolt11']
with pytest.raises(RpcError, match=r"WIRE_INVALID_ONION_PAYLOAD \(reply from remote\)"):
l1.rpc.pay(inv)
with pytest.raises(RpcError, match=r"Unexpected error \(invalid_onion_payload\) from final node"):
l1.rpc.xpay(inv)
# Replace with valid payload, but corrupt payment_secret
l2.rpc.call('setpayload', ['corrupt_secret'])
with pytest.raises(RpcError, match=r"WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS \(reply from remote\)"):
l1.rpc.pay(inv)
with pytest.raises(RpcError, match=r"Destination said it doesn't know invoice: incorrect_or_unknown_payment_details"):
l1.rpc.xpay(inv)
assert l2.daemon.wait_for_log("Attempt to pay.*with wrong payment_secret")
@ -2329,12 +2326,12 @@ def test_watchtower(node_factory, bitcoind, directory, chainparams):
channel_id = l1.rpc.listpeerchannels()['channels'][0]['channel_id']
# Force a new commitment
l1.rpc.pay(l2.rpc.invoice(25000000, 'lbl1', 'desc1')['bolt11'])
l1.rpc.xpay(l2.rpc.invoice(25000000, 'lbl1', 'desc1')['bolt11'])
tx = l1.rpc.dev_sign_last_tx(l2.info['id'])['tx']
# Now make sure it is out of date
l1.rpc.pay(l2.rpc.invoice(25000000, 'lbl2', 'desc2')['bolt11'])
l1.rpc.xpay(l2.rpc.invoice(25000000, 'lbl2', 'desc2')['bolt11'])
# l2 stops watching the chain, allowing the watchtower to react
l2.stop()
@ -2610,15 +2607,15 @@ def test_htlc_accepted_hook_crash(node_factory, executor):
# This should still succeed
f = executor.submit(l1.rpc.pay, i)
f = executor.submit(l1.rpc.xpay, i)
l2.daemon.wait_for_log(r'Crashing on purpose...')
l2.daemon.wait_for_log(
r'Hook handler for htlc_accepted failed with an exception.'
)
with pytest.raises(RpcError, match=r'failed: WIRE_TEMPORARY_NODE_FAILURE'):
f.result(10)
with pytest.raises(RpcError, match=r'Unexpected error \(temporary_node_failure\) from final node: disabling'):
f.result(TIMEOUT)
def test_notify(node_factory):
@ -2693,17 +2690,17 @@ def test_htlc_accepted_hook_failmsg(node_factory):
# First let's test the newer failure_message, which should get passed
# through without being mapped.
tests = {
'2002': 'WIRE_TEMPORARY_NODE_FAILURE',
'400F' + 12 * '00': 'WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS',
'4009': 'WIRE_REQUIRED_CHANNEL_FEATURE_MISSING',
'4016' + 3 * '00': 'WIRE_INVALID_ONION_PAYLOAD',
'2002': 'temporary_node_failure',
'400F' + 12 * '00': 'incorrect_or_unknown_payment_details',
'4009': 'required_channel_feature_missing',
'4016' + 3 * '00': 'invalid_onion_payload',
}
for failmsg, expected in tests.items():
l2.rpc.setfailmsg(msg=failmsg)
inv = l2.rpc.invoice(42, 'failmsg{}'.format(failmsg), '')['bolt11']
with pytest.raises(RpcError, match=r'failcodename.: .{}.'.format(expected)):
l1.rpc.pay(inv)
with pytest.raises(RpcError, match=expected):
l1.rpc.xpay(inv)
def test_htlc_accepted_hook_customtlvs(node_factory):
@ -2718,14 +2715,14 @@ def test_htlc_accepted_hook_customtlvs(node_factory):
single_tlv = "fe00010001012a" # represents type: 65537, lenght: 1, value: 42
l2.rpc.setcustomtlvs(tlvs=single_tlv)
inv = l3.rpc.invoice(1000, 'customtlvs-singletlv', '')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
l3.daemon.wait_for_log(f"called htlc accepted hook with extra_tlvs: {single_tlv}")
# Mutliple tlvs - Check that we recieve multiple extra tlvs at l3 attached by l2.
multi_tlv = "fdffff012afe00010001020539" # represents type: 65535, length: 1, value: 42 and type: 65537, length: 2, value: 1337
l2.rpc.setcustomtlvs(tlvs=multi_tlv)
inv = l3.rpc.invoice(1000, 'customtlvs-multitlvs', '')['bolt11']
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
l3.daemon.wait_for_log(f"called htlc accepted hook with extra_tlvs: {multi_tlv}")
@ -2825,7 +2822,7 @@ def test_htlc_accepted_hook_failonion(node_factory):
l2.rpc.setfailonion('0' * (292 * 2))
inv = l2.rpc.invoice(42, 'failonion000', '')['bolt11']
with pytest.raises(RpcError):
l1.rpc.pay(inv)
l1.rpc.xpay(inv)
@pytest.mark.slow_test # VALGRIND running generally too slow to trigger race we need.
@ -2867,14 +2864,14 @@ def test_htlc_accepted_hook_fwdto(node_factory):
l1, l2, l3 = node_factory.line_graph(3, opts=[{}, {'plugin': plugin}, {}], wait_for_announce=True)
# Add some balance
l1.rpc.pay(l2.rpc.invoice(10**9 // 2, 'balance', '')['bolt11'])
l1.rpc.xpay(l2.rpc.invoice(10**9 // 2, 'balance', '')['bolt11'])
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
# make it forward back down same channel.
l2.rpc.setfwdto(only_one(l1.rpc.listpeerchannels()['channels'])['channel_id'])
inv = l3.rpc.invoice(42, 'fwdto', '')['bolt11']
with pytest.raises(RpcError, match="WIRE_INVALID_ONION_HMAC"):
l1.rpc.pay(inv)
with pytest.raises(RpcError, match=r"Unexpected error \(invalid_onion_hmac\) from intermediate node: disabling the invoice's route hint"):
l1.rpc.xpay(inv)
assert l2.rpc.listforwards()['forwards'][0]['out_channel'] == only_one(l1.rpc.listpeerchannels()['channels'])['short_channel_id']
@ -2954,32 +2951,6 @@ def test_self_disable(node_factory):
l1.rpc.plugin_start(p2, selfdisable=True)
def test_custom_notification_topics(node_factory):
plugin = os.path.join(
os.path.dirname(__file__), "plugins", "custom_notifications.py"
)
l1, l2 = node_factory.line_graph(2, opts=[{'plugin': plugin}, {}])
l1.rpc.emit()
l1.daemon.wait_for_log("Got a custom notification Hello world from plugin custom_notifications.py")
inv = l2.rpc.invoice(42, "lbl", "desc")['bolt11']
l1.rpc.pay(inv)
l1.daemon.wait_for_log(r'Got a pay_success notification from plugin pay for payment_hash [0-9a-f]{64}')
# And now make sure that we drop unannounced notifications
l1.rpc.faulty_emit()
l1.daemon.wait_for_log(
r"Plugin attempted to send a notification to topic .* not forwarding"
)
time.sleep(1)
assert not l1.daemon.is_in_log(r'Got the ididntannouncethis event')
# The plugin just dist what previously was a fatal mistake (emit
# an unknown notification), make sure we didn't kill it.
assert str(plugin) in [p['name'] for p in l1.rpc.plugin_list()['plugins']]
def test_restart_on_update(node_factory):
"""Tests if plugin rescan restarts modified plugins
"""
@ -3292,12 +3263,12 @@ def test_autoclean(node_factory):
# Reconnect, l1 pays invoice, we test paid expiry.
l2.rpc.connect(l3.info['id'], 'localhost', l3.port)
l1.rpc.pay(inv4['bolt11'])
l1.rpc.xpay(inv4['bolt11'])
# We manually delete inv5 so we can have l1 fail a payment.
l3.rpc.delinvoice('inv5', 'unpaid')
with pytest.raises(RpcError, match='WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS'):
l1.rpc.pay(inv5['bolt11'])
with pytest.raises(RpcError, match="Destination said it doesn't know invoice: incorrect_or_unknown_payment_details"):
l1.rpc.xpay(inv5['bolt11'])
assert l3.rpc.autoclean_status()['autoclean']['paidinvoices']['enabled'] is False
assert l3.rpc.autoclean_status()['autoclean']['paidinvoices']['cleaned'] == 0
@ -3373,10 +3344,10 @@ def test_autoclean_once(node_factory):
inv2 = l3.rpc.invoice(amount_msat=12300, label='inv2', description='description4')
inv3 = l3.rpc.invoice(amount_msat=12300, label='inv3', description='description5')
l1.rpc.pay(inv2['bolt11'])
l1.rpc.xpay(inv2['bolt11'])
l3.rpc.delinvoice('inv3', 'unpaid')
with pytest.raises(RpcError, match='WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS'):
l1.rpc.pay(inv3['bolt11'])
with pytest.raises(RpcError, match="Destination said it doesn't know invoice: incorrect_or_unknown_payment_details"):
l1.rpc.xpay(inv3['bolt11'])
# Default status
default_status = {'autoclean': {'failedpays': {'enabled': False,
@ -4242,12 +4213,12 @@ def test_sql(node_factory, bitcoind):
wait_for(lambda: l2.rpc.listnodes(l1.info['id'])['nodes'] != [])
# This should create a forward through l2
l1.rpc.pay(l3.rpc.invoice(amount_msat=12300, label='inv1', description='description')['bolt11'])
l1.rpc.xpay(l3.rpc.invoice(amount_msat=12300, label='inv1', description='description')['bolt11'])
# Very rough checks of other list commands (make sure l2 has one of each)
l2.rpc.offer(1, 'desc')
l2.rpc.invoice(1, 'label', 'desc')
l2.rpc.pay(l3.rpc.invoice(amount_msat=12300, label='inv2', description='description')['bolt11'])
l2.rpc.xpay(l3.rpc.invoice(amount_msat=12300, label='inv2', description='description')['bolt11'])
# And I need at least one HTLC in-flight so listpeers.channels.htlcs isn't empty:
l3.rpc.plugin_start(os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py'))
@ -4370,7 +4341,7 @@ def test_sql(node_factory, bitcoind):
# Test json functions
scidl1l3, _ = l1.fundchannel(l3)
l1.rpc.pay(l3.rpc.invoice(amount_msat=1000000, label='inv1000', description='description 1000 msat')['bolt11'])
l1.rpc.xpay(l3.rpc.invoice(amount_msat=1000000, label='inv1000', description='description 1000 msat')['bolt11'])
# Two channels, l1->l3 *may* have an HTLC in flight.
ret = l1.rpc.sql("SELECT json_object('peer_id', hex(pc.peer_id), 'alias', alias, 'scid', short_channel_id, 'htlcs',"

View file

@ -566,7 +566,7 @@ def make_chans(node_factory, qty=2, fundamount=1000000, balanced=True):
nodes[i].daemon.wait_for_log(' to CHANNELD_NORMAL')
if balanced:
inv = nodes[i + 1].rpc.invoice(1000 * fundamount // 2, 'balance', 'balance')
nodes[i].rpc.pay(inv['bolt11'])
nodes[i].rpc.xpay(inv['bolt11'])
chanids.insert(0, nodes[1].get_channel_id(nodes[0]))
if qty > 1:

View file

@ -40,7 +40,7 @@ def test_splice(node_factory, bitcoind):
l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
inv = l2.rpc.invoice(10**2, '3', 'no_3')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
# Check that the splice doesn't generate a unilateral close transaction
time.sleep(5)
@ -114,10 +114,10 @@ def test_two_chan_splice_in(node_factory, bitcoind):
l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
inv = l2.rpc.invoice(10**2, '1', 'no_1')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
inv = l3.rpc.invoice(10**2, '2', 'no_2')
l2.rpc.pay(inv['bolt11'])
l2.rpc.xpay(inv['bolt11'])
@pytest.mark.openchannel('v1')
@ -146,7 +146,7 @@ def test_splice_rbf(node_factory, bitcoind):
assert result['txid'] in list(mempool.keys())
inv = l2.rpc.invoice(10**2, '1', 'no_1')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
funds_result = l1.rpc.addpsbtoutput(100000)
@ -162,7 +162,7 @@ def test_splice_rbf(node_factory, bitcoind):
l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_AWAITING_SPLICE')
inv = l2.rpc.invoice(10**2, '2', 'no_2')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
# Make sure l1 doesn't unilateral close if HTLC hasn't completely settled before deadline.
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['htlcs'] == [])
@ -173,7 +173,7 @@ def test_splice_rbf(node_factory, bitcoind):
l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
inv = l2.rpc.invoice(10**2, '3', 'no_3')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
# Check that the splice doesn't generate a unilateral close transaction
time.sleep(5)
@ -335,7 +335,7 @@ def test_splice_out(node_factory, bitcoind):
l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
inv = l2.rpc.invoice(10**2, '3', 'no_3')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
# Check that the splice doesn't generate a unilateral close transaction
time.sleep(5)
@ -392,7 +392,7 @@ def test_invalid_splice(node_factory, bitcoind):
l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
inv = l2.rpc.invoice(10**2, '3', 'no_3')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
# Check that the splice doesn't generate a unilateral close transaction
time.sleep(5)
@ -443,7 +443,7 @@ def test_commit_crash_splice(node_factory, bitcoind):
assert l1.db_query("SELECT count(*) as c FROM channel_funding_inflights;")[0]['c'] == 0
inv = l2.rpc.invoice(10**2, '3', 'no_3')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
# Check that the splice doesn't generate a unilateral close transaction
time.sleep(5)
@ -459,7 +459,7 @@ def test_splice_stuck_htlc(node_factory, bitcoind, executor):
l3.rpc.dev_ignore_htlcs(id=l2.info['id'], ignore=True)
inv = l3.rpc.invoice(10000000, '1', 'no_1')
executor.submit(l1.rpc.pay, inv['bolt11'])
executor.submit(l1.rpc.xpay, inv['bolt11'])
l3.daemon.wait_for_log('their htlc 0 dev_ignore_htlcs')
# Now we should have a stuck invoice between l1 -> l2

View file

@ -59,7 +59,7 @@ def test_splice_disconnect_sig(node_factory, bitcoind):
l2.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
inv = l2.rpc.invoice(10**2, '3', 'no_3')
l1.rpc.pay(inv['bolt11'])
l1.rpc.xpay(inv['bolt11'])
# Check that the splice doesn't generate a unilateral close transaction
time.sleep(5)