53 Commits

Author SHA1 Message Date
nazarevsky
bcdce8f40d cln-rpc: update schema, update proto for xpay payer_note field 2025-12-18 12:47:06 -08:00
nazarevsky
66ce41d584 xpay: add payer_note field
Changelog-Added: Add 'payer-note' field to the 'xpay' RPC call.
2025-12-18 12:47:06 -08:00
wqxoxo
3c08a8bdb9 xpay: fix misleading "route hint" label in error messages
describe_scidd() was labeling any channel as "the invoice's route hint"
when there was a single-hop route hint, even if the error occurred on
an unrelated intermediate channel.

Now we check the channel actually matches the route hint's
short_channel_id before using that label.

Fixes: #8252
Changelog-Fixed: xpay: error messages no longer incorrectly label intermediate channels as "the invoice's route hint".
2025-11-29 08:33:37 +10:30
Rusty Russell
9961f6bf0e xpay: use filtering on rpc_command so we only get called on "pay".
tests/test_coinmoves.py::test_generate_coinmoves (2,000,000, sqlite3):
	Time (from start to end of l2 node):	 135 seconds **WAS 227**
	Worst latency:				 12.1 seconds **WAS 62.4**

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-11-20 16:30:50 +10:30
Rusty Russell
73147dafe2 xpay: restrict maxparts to 6 for non-public nodes, but remove it if we can't route.
This attempts to solve a problem we have with Phoenix clients:

	This payment has been split in two many parts by the sender: 31 parts vs max 6 parts allowed for on-the-fly funding.

The problem is that we don't have any way in bolt11 or bolt12 to
specify the maximum number of HTLCs.

As a workaround, we start by restricting askrene to 6 parts if the
node is not openly reachable, and if it struggles, we remove the
restriction.  This would work much better if askrene handled maxparts
more completely!

See-Also: https://github.com/ElementsProject/lightning/issues/8331
Changelog-Fixed: `xpay` will not try to send too many HTLCs through unknown channels (6, as that is Phoenix's limit) unless it has no choice
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-11-17 19:46:00 +10:30
Rusty Russell
e5b68cada7 xpay: don't place global reservations on generated channels.
We generate fake scids for routehints and blinded paths.  But then we were
placing reservations on them as if they were global.  If there are two xpays
going at once these reservations will clash, even though the same scid refers
to different channels.

Reported-by: @Lagrang3
Changelog-Fixed: xpay: fixed theoretical clash with simultanous payments via routehints and blinded paths.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-11-17 13:52:54 +10:30
Rusty Russell
8b9020d7b9 global: use clock_time in place of time_now().
Except for tracing, that sticks with time_now().

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-11-13 21:21:29 +10:30
Rusty Russell
add398f5ea xpay: wait, if final node gives us an indication we're behind on blockheight.
This doesn't happen much in real life, but it's certainly possible, so do what pay does here.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/8612
Changelog-Added: `xpay` will now wait if it suspects a payment failure is due to a height disagreement with the final node.
2025-11-13 15:15:57 +10:30
Rusty Russell
f6a4e79420 global: remove unnecessary includes from headers.
Each header should only include the other headers it needs to compile;
`devtools/reduce-includes.sh */*.h` does this.  The C files then need
additional includes if they don't compile.

And remove the entirely useless wire/onion_wire.h, which only serves to include wire/onion_wiregen.h.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-23 06:44:04 +10:30
Rusty Russell
65d997842e Makefiles: remove redundant dependencies, and have objects depend on their Makefile.
1. $(JSMN_OBJS) is not set anywhere.
2. You don't need to depend on CCAN_HEADERS, COMMON_HEADERS or JSMN_HEADERS: the top level Makefile has all object depedning on it.
3. Similarly, CCAN_OBJS.
4. Every object file should be rebuilt if its Makefile changes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-23 06:44:04 +10:30
Rusty Russell
e120f87083 Makefile: create a library containing common, wire and bitcoin objects.
This means we don't have to manually choose what to link against,
which is much of the complexity of our Makefiles: the compiler will
automatically use any object files it needs to link.

We already do this for ccan as libccan.a, now we have libcommon.a.

We don't link against it for *everything*, as some tests require their own
versions.

Notes:
1. I get rid of the weird plugins/test/Makefile2 (accidental commit?)
2. Many tests change due to update-mocks.
3. In some places I added the missing dependency on the Makefile itself, though most are in the next
   patch.

Before:
	Total program size:     221366528
	Total tests size:       364243856

After:
	Total program size:     190733656
	Total tests size:       337880888

Build time from make clean (RUST=0) (includes building external libs):

Before:
	real    0m38.227000-44.245000(41.8222+/-1.6)s
	user    3m2.105000-33.696000(23.1442+/-8.4)s
	sys     0m35.054000-42.269000(39.7231+/-2)s
After:
	real    0m38.944000-40.416000(40.1131+/-0.4)s
	user    3m6.790000-17.159000(15.0571+/-2.8)s
	sys     0m35.304000-37.336000(36.8942+/-0.57)s

Build time after touch config.vars (RUST=0):

Before:
	real    0m18.928000-22.776000(21.5084+/-1.1)s
	user    2m8.613000-36.567000(27.7281+/-7.7)s
	sys     0m20.458000-23.436000(22.3963+/-0.77)s

After:
	real    0m19.831000-21.862000(21.5528+/-0.58)s
	user    2m15.361000-30.731000(28.4798+/-4.4)s
	sys     0m21.056000-22.339000(22.0346+/-0.35)s

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

rusty@rusty-Framework:~/devel/cvs/lightni
2025-10-23 06:44:04 +10:30
Rusty Russell
54444e4337 BOLT12: Update recurrence to latest spec draft.
Changes:
* Fields renumbered to their draft values + billion.
* offer_recurrence now comes in compulsory or optional (backwards compat) flavors.
* `proportional_amount` is now inside `offer_recurrence_base` not `offer_recurrence_paywindow`.
* New field `invreq_recurrence_cancel`.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: Draft specification for recurring offers changed: old recurring offers will no longer work.
2025-10-01 15:31:30 +09:30
Rusty Russell
3c3788a241 pytest: fix test_xpay_fake_channeld flake
Also, resulting log was huge, so suppress log level (will probably speed test)

```
2025-09-02T06:01:39.4881086Z >       l1.rpc.plugin_start(os.path.join(os.getcwd(), 'plugins/cln-askrene'))
2025-09-02T06:01:39.4881090Z 
2025-09-02T06:01:39.4881174Z tests/test_xpay.py:279: 
...
2025-09-02T06:01:39.4883193Z >           self.sock.connect(str(self.path))
2025-09-02T06:01:39.4883340Z E           ConnectionRefusedError: [Errno 111] Connection refused
...
2025-09-02T06:01:41.7767610Z lightningd-1 2025-09-02T06:01:27.235Z **BROKEN** plugin-cln-xpay: askrene-age failed with {"code":-4, "message":"Plugin terminated before replying to RPC call."}
2025-09-02T06:01:41.7768127Z lightningd-1 2025-09-02T06:01:27.305Z INFO    plugin-cln-xpay: Killing plugin: exited during normal operation
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-09-30 11:37:31 +09:30
Rusty Russell
6799dbe656 xpay: add option to pay bip353.
Changelog-Added: JSON-RPC: `xpay` can now directly pay a BIP353 address, like `₿rusty@rustcorp.com.au`.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-18 14:57:46 +09:30
Rusty Russell
103a49ef51 xpay: support paying a (simple) bolt12 offer directly.
fetchinvoice is still good for detailed diagnostics and handling
recurring invoices and alternate currencies, but this covers the
"throw some sats" case well.

Changelog-Added: JSON-RPC: `xpay` can now pay a simple offer directly, rather than requiring fetchinvoice first.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-18 14:57:46 +09:30
Lagrang3
1830c0e2e1 xpay: add developer option dev_maxparts
dev_maxparts limits the number of pending routes allowed at any given
time.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-08-15 16:13:19 +09:30
Rusty Russell
e24bd9685a xpay: add pay_part_start and pay_part_end notifications.
Requested-by: Michael at Boltz
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: Plugins: `xpay` now publishes `pay_part_start` and `pay_part_end` notifications on every payment send attempt.
2025-08-14 16:52:44 +09:30
Rusty Russell
09e03e98ef deprecations: update v25.11 to v25.12.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-06-24 09:57:24 +09:30
Rusty Russell
2408233b2e pay: use correct CLTV values for blinded paths.
We added twice, which caused spurious failures in real-world cases.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Reported-by: https://github.com/hMsats
Fixes: https://github.com/ElementsProject/lightning/issues/8119
Changelog-Fixed: `xpay` would double the CLTV values in blinded paths, sometimes causing spurious failures.
2025-02-26 14:26:47 -06:00
Rusty Russell
da793e66b9 xpay: rename payment_failed to payment_give_up
Eduardo points out that payment_failed kind of over-promises: it may
actually not fail the payment now (with slow mode).

It's more an indiciation that we're not trying any more payment parts,
so rename it to payment_give_up.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-20 20:22:54 -06:00
Rusty Russell
43e59a6774 pytest: test xpay gracefully handles failure after success.
We can create this scenario by having one path force close.  We take
the opportunity to log this, even in non-slow-mode, since it's interesting
(not our bug, but someone just lost money!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-20 20:22:54 -06:00
Rusty Russell
f168cb5949 xpay: add xpay-slow-mode to force waiting for all parts before returning.
This was requested by Michael of Boltz; it's mainly useful if you plan to
try failed payments on a *different* node.  In that case, there's a
theoretical possibility that slow parts of this payment could combine with
that from a different node and overpay.

We don't allow this from the same node, already.

Changelog-Added: xpay: `xpay-slow-mode` makes xpay wait for all parts of a payment to complete before returning success or failure.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-20 20:22:54 -06:00
Rusty Russell
db1e26eb67 xpay: refactor payment_succeeded.
1. Don't rely on the current attempt, make caller calculate total.
2. Save preimage inside attempt, for slow mode.
3. Hoist it higher in the file.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-20 20:22:54 -06:00
Lagrang3
f5c8934e22 xpay: reduce log entries on rpc_command hook
Don't print unnecessary log entries every time we receive an rpc_command
hook event. Only log when `pay` is called.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-19 16:17:44 -06:00
Rusty Russell
c718e35359 xpay: in future, don't MPP to pay bolt12 invoices unless invoice explicitly says so.
We don't want to enable this yet, since we only just fixed CLN this release!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 22:17:21 +10:30
Rusty Russell
4ed709f9ec xpay: avoid MPP if invoice does not allow it.
This is deeply annoying, and we may have to support this properly
(using a separate algorithm entirely) if other implementations don't
fix their crap.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Plugins: xpay: suppress multi-part payment if invoice doesn't allow it (please, fix your nodes!)
2025-02-14 22:17:21 +10:30
Rusty Russell
c3362b057c BOLT12: remove -offers from bolt12 quotes, update them.
Typo fixes and wording changes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
fdfc7ce62f gossmap: add (and use) logging hook.
Default goes to stderr for LOG_UNUSUAL and higher.

We have to whitelist more cases in map_catchup so we don't spam the logs
with perfectly-expected (but ignored) messages though.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Lagrang3
21195be3f7 xpay-handle-pay: don't assume bolt11 is non NULL
Changelog-None: xpay-handle-pay: don't assume bolt11 param is non NULL

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-06 12:46:38 -06:00
Lagrang3
a272258fb6 xpay-handle-pay: bugfix, handle null parameters
Changelog-Fixed: xpay-handle-pay: handle null parameters passed in the "param" list.

Reported-by: @hMsats
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-06 12:46:38 -06:00
Rusty Russell
43130a33be xpay: make sure we report if we ever try to call getroutes with 0msat.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-28 10:53:22 +10:30
Rusty Russell
fd7ac4e05b xpay: refuse request to pay 0msat.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: JSON-RPC: `xpay` will refuse to make a 0msat payment (0msat invoice, partial payment, or manually-set on amountless invoice).
Fixes: https://github.com/ElementsProject/lightning/issues/8016
2025-01-28 10:53:22 +10:30
michael1011
060368bb0a xpay: add maxdelay parameter
Changelog-Added: Plugins: `xpay` now supports a `maxdelay` parameter for better `xpay-handle-pay` compatibility.
2025-01-22 12:19:47 -08:00
Rusty Russell
d7adf06dfe xpay: created_at response from pay compatibility is a number, not integer.
Reported-by: @hMsats
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-18 14:04:14 +10:30
Rusty Russell
3e9a4fc750 xpay: simplify printing of destination.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-18 14:04:14 +10:30
Lagrang3
545220dfbc xpay: add destination to output
Changelog-Add: xpay: add destination to xpay success output when xpay-handle-pay is active.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-12-18 14:04:14 +10:30
Rusty Russell
d26ea6673d xpay: more accurately reflect pay when xpay-handle-pay is set.
Note that the slight code reorder changes the JSON order, which is generally
undefined, but our doc checker is very strict!

Changelog-Changed: `xpay` now gives the same JSON success return as documented by `pay` when `xpay-handle-pay` is set.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/7923
2024-12-17 15:49:03 +10:30
Rusty Russell
428c76068c xpay: emulate maxfeepercent and exemptfee when xpay-handle-pay used
maxfeepercent is use by Zeus, so let's make that work.

maxfee is more precise, so it's the only xpay option (maxfee was added
to pay later).

[ Fix to ppm logic by Lagrang3, thanks! --RR ]

Fixes: https://github.com/ElementsProject/lightning/issues/7926
Changelog-Changed: JSON-RPC: With `xpay-handle-pay` set, xpay will now be used even if `pay` uses maxfeeprecent or exemptfee parameters (e.g. Zeus)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-17 10:54:31 +10:30
Rusty Russell
cf22762c8f xpay: tell injectpaymentonion what the amount being delivered to destination is.
This means that it gets shown in listsendpays: omitting this broke spark, apparently!

Changelog-Changed: `xpay` now populates more fields, so `listsendpays` and `listpays` show `destination` and `amount_msat` fields for xpay payments.
Fixes: https://github.com/ElementsProject/lightning/issues/7881
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-17 08:14:45 +10:30
Marcel Hernandez
d6bd61157e Changelog-Fixed: xpay no longer logs "Got command" at info level. 2024-12-15 21:53:43 +10:30
Rusty Russell
113156858b xpay: don't excees maxfee *overall*.
We were handing "maxfee" to every getroutes call, even if we had already
used some of the fees.

Reported-by: @daywalker90
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: xpay is new this release.
2024-12-02 14:31:11 +10:30
Rusty Russell
b8e5b122d2 decode: don't fail to decode just because a bolt12 invoice has expired.
In fact, there are several places where we try to decode old invoices,
and they should all work.  The only place we should enforce expiration is
when we're going to pay.

This also revealed that xpay wasn't checking bolt11 expiries!

Reported-by: hMsats
Fixes: https://github.com/ElementsProject/lightning/issues/7869
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: JSON-RPC: `decode` refused to decode expired bolt12 invoices.
2024-11-30 13:17:55 +01:00
Rusty Russell
90ab9325a1 xpay: give an additional block "slack" for CLTV values.
pay does this, xpay does not.  Which means if a block comes in (or you're behind),
you get gratuitous failures:

```
    def test_xpay_simple(node_factory):
        l1, l2, l3, l4 = node_factory.get_nodes(4, opts={'may_reconnect': True})
        node_factory.join_nodes([l1, l2, l3], wait_for_announce=True)
        node_factory.join_nodes([l3, l4], announce_channels=False)

        # BOLT 11, direct peer
        b11 = l2.rpc.invoice('10000msat', 'test_xpay_simple', 'test_xpay_simple bolt11')['bolt11']
>       ret = l1.rpc.xpay(b11)

tests/test_xpay.py:148:
...
        if not isinstance(resp, dict):
            raise TypeError("Malformed response, response is not a dictionary %s." % resp)
        elif "error" in resp:
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: xpay, payload: ('lnbcrt100n1pn5qu7csp53rp0mfwtfsyyy8gzsggepnxgslyalwvz3jkg9ptmqq452ln2nmgqpp58ak9nmfz9l93r0fpm266ewyjrhurhatrs05nda0r03p82cykp0vsdp9w3jhxazl0pcxz72lwd5k6urvv5sxymmvwscnzxqyjw5qcqp99qxpqysgqa798258yppu2tlfj8herr3zuz0zgux79zvtx6z57cmfzs2wdesmr4nvnkcmyssyu6k64ud54eg0v45c3mcw342jj6uy7tu202p6klrcp6ljc9w',), error: {'code': 203, 'message': "Destination said it doesn't know invoice: incorrect_or_unknown_payment_details"}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: xpay is new this release.
2024-11-23 10:20:30 +10:30
Rusty Russell
1380d36898 xpay: don't try to timeout things until after we have created xpay layer.
```
lightningd-1 2024-11-19T05:21:16.313Z DEBUG   lightningd: Looking for [askrene,layers]
lightningd-1 2024-11-19T05:21:16.314Z DEBUG   lightningd: Got [askrene,layers,xpay]
lightningd-1 2024-11-19T05:21:16.314Z DEBUG   lightningd: Printing
lightningd-1 2024-11-19T05:21:16.315Z **BROKEN** plugin-cln-xpay: askrene-age failed with {\"code\":-32602,\"message\":\"layer: Unknown layer: invalid token '\\\"xpay\\\"'\"}
lightningd-1 2024-11-19T05:21:16.318Z DEBUG   plugin-cln-askrene: datastore = {\"datastore\":[{\"key\":[\"askrene\",\"layers\",\"xpay\"],\"generation\":13,\"hex\":\"000300001000003f47af0100000000673c1fea010000000000d1b0d4000003000000000ce5066e0000000000673c1fea010000000000d1b0d400000300001000001a47050000000000673c1fea010000000000d1b0d400000300003f00005a72b40100000000673c1fea010000000000d1b0d400000300000000005a07e80100000000673c1fea010000000000d1b0d400000300001a0000e3564c0100000000673c1fea010000000000d1b0d40000030000e3000db69cf50000000000673c1fea0001000000000100637e\"}]}
lightningd-1 2024-11-19T05:21:16.318Z DEBUG   plugin-cln-askrene: Loaded level xpay (203 bytes)
lightningd-1 2024-11-19T05:21:16.391Z INFO    plugin-cln-xpay: Killing plugin: exited during normal operation
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-19 17:51:18 +10:30
Rusty Russell
05fbcb4d9b xpay: make sure to call preapproveinvoice!
This is required for VLS which wants to know (and potentially decline) invoices
we're trying to pay.

As a nice side effect, our "check" command for xpay now does much more thorough
checking of arguments.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
2c15dc0e5b xpay: make self-pay work.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
229fc3f2b4 xpay: make the xpay layer persistent.
As the first user of a persistent layer, this tripped tests which
assumed the datastore would be empty!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
41e15b1ac9 xpay: age the "xpay" layer so we forget information older than 1 hour.
1 hour is what mpay uses, so stick with that for now.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
c715253af7 xpay: option to steal easy commands from pay.
Note: won't work with grpc (or probably other tools), since the output
is different.  But good for testing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: Config: option `xpay-handle-pay` can be used to call xpay when pay is used in many cases (but output is different from pay!)
2024-11-18 11:03:26 +10:30
Rusty Russell
64c1522597 xpay: don't use rpc_scan or jsonrpc_request_sync.
These will deadlock once we hook into rpc_command, so avoid them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30