We used to not print what happened with an HTLC in the `pay`
plugin. This meant that to follow the HTLCs we'd have to map the `pay`
HTLCs to the `lightningd` HTLCs, and then trace that. BY having `pay`
print the outcome as it sees it, we can make that tracking much
simpler, even allowing for tooling to do it for us.
Changelog-None This is a log-only change
I'm not sure why this happens, and suspect it is caused by an issue elsewhere, so
add some verbose debugging, don't crash.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/8017
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
The updated API requires typed htables to explicitly state whether they
allow duplicates: for most cases we don't, but we've had issues in the
past.
This is a big patch, but mainly mechanical.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
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
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>
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>
It's undocumented and only used in one place, so we can change it (it
was new in 24.08).
We really want to be able to just handle a raw onionmessage: this allows
oblivious sending of messages, but also, in combination with the coming
onionmessage_forward_fail notification, allows us to connect then
reinject.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
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.
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.
```
error[E0277]: the trait bound `cln_rpc::model::requests::AskrenereserveRequest: From<pb::AskrenereserveRequest>` is not satisfied
--> cln-grpc/src/server.rs:3994:56
|
3994 | let req: requests::AskrenereserveRequest = req.into();
| ^^^^ the trait `From<pb::AskrenereserveRequest>` is not implemented for `cln_rpc::model::requests::AskrenereserveRequest`, which is required by `pb::AskrenereserveRequest: Into<_>`
|
= note: required for `pb::AskrenereserveRequest` to implement `Into<cln_rpc::model::requests::AskrenereserveRequest>`
error[E0277]: the trait bound `cln_rpc::model::requests::AskreneageRequest: From<pb::AskreneageRequest>` is not satisfied
--> cln-grpc/src/server.rs:4026:52
|
4026 | let req: requests::AskreneageRequest = req.into();
| ^^^^ the trait `From<pb::AskreneageRequest>` is not implemented for `cln_rpc::model::requests::AskreneageRequest`, which is required by `pb::AskreneageRequest: Into<_>`
|
= note: required for `pb::AskreneageRequest` to implement `Into<cln_rpc::model::requests::AskreneageRequest>`
error[E0277]: the trait bound `cln_rpc::model::requests::GetroutesRequest: From<pb::GetroutesRequest>` is not satisfied
--> cln-grpc/src/server.rs:4058:51
|
4058 | let req: requests::GetroutesRequest = req.into();
| ^^^^ the trait `From<pb::GetroutesRequest>` is not implemented for `cln_rpc::model::requests::GetroutesRequest`, which is required by `pb::GetroutesRequest: Into<_>`
|
= note: required for `pb::GetroutesRequest` to implement `Into<cln_rpc::model::requests::GetroutesRequest>`
error[E0277]: the trait bound `cln_rpc::model::requests::AskrenedisablenodeRequest: From<pb::AskrenedisablenodeRequest>` is not satisfied
--> cln-grpc/src/server.rs:4090:60
|
4090 | let req: requests::AskrenedisablenodeRequest = req.into();
| ^^^^ the trait `From<pb::AskrenedisablenodeRequest>` is not implemented for `cln_rpc::model::requests::AskrenedisablenodeRequest`, which is required by `pb::AskrenedisablenodeRequest: Into<_>`
|
= note: required for `pb::AskrenedisablenodeRequest` to implement `Into<cln_rpc::model::requests::AskrenedisablenodeRequest>`
error[E0277]: the trait bound `cln_rpc::model::requests::AskreneinformchannelRequest: From<pb::AskreneinformchannelRequest>` is not satisfied
--> cln-grpc/src/server.rs:4122:62
|
4122 | let req: requests::AskreneinformchannelRequest = req.into();
| ^^^^ the trait `From<pb::AskreneinformchannelRequest>` is not implemented for `cln_rpc::model::requests::AskreneinformchannelRequest`, which is required by `pb::AskreneinformchannelRequest: Into<_>`
|
= note: required for `pb::AskreneinformchannelRequest` to implement `Into<cln_rpc::model::requests::AskreneinformchannelRequest>`
error[E0277]: the trait bound `cln_rpc::model::requests::AskrenecreatechannelRequest: From<pb::AskrenecreatechannelRequest>` is not satisfied
--> cln-grpc/src/server.rs:4154:62
|
4154 | let req: requests::AskrenecreatechannelRequest = req.into();
| ^^^^ the trait `From<pb::AskrenecreatechannelRequest>` is not implemented for `cln_rpc::model::requests::AskrenecreatechannelRequest`, which is required by `pb::AskrenecreatechannelRequest: Into<_>`
|
= note: required for `pb::AskrenecreatechannelRequest` to implement `Into<cln_rpc::model::requests::AskrenecreatechannelRequest>`
error[E0277]: the trait bound `cln_rpc::model::requests::AskreneupdatechannelRequest: From<pb::AskreneupdatechannelRequest>` is not satisfied
--> cln-grpc/src/server.rs:4186:62
|
4186 | let req: requests::AskreneupdatechannelRequest = req.into();
| ^^^^ the trait `From<pb::AskreneupdatechannelRequest>` is not implemented for `cln_rpc::model::requests::AskreneupdatechannelRequest`, which is required by `pb::AskreneupdatechannelRequest: Into<_>`
|
= note: required for `pb::AskreneupdatechannelRequest` to implement `Into<cln_rpc::model::requests::AskreneupdatechannelRequest>`
error[E0277]: the trait bound `cln_rpc::model::requests::AskrenebiaschannelRequest: From<pb::AskrenebiaschannelRequest>` is not satisfied
--> cln-grpc/src/server.rs:4218:60
|
4218 | let req: requests::AskrenebiaschannelRequest = req.into();
| ^^^^ the trait `From<pb::AskrenebiaschannelRequest>` is not implemented for `cln_rpc::model::requests::AskrenebiaschannelRequest`, which is required by `pb::AskrenebiaschannelRequest: Into<_>`
|
= note: required for `pb::AskrenebiaschannelRequest` to implement `Into<cln_rpc::model::requests::AskrenebiaschannelRequest>`
error[E0277]: the trait bound `cln_rpc::model::requests::AskrenelistreservationsRequest: From<pb::AskrenelistreservationsRequest>` is not satisfied
--> cln-grpc/src/server.rs:4250:65
|
4250 | let req: requests::AskrenelistreservationsRequest = req.into();
| ^^^^ the trait `From<pb::AskrenelistreservationsRequest>` is not implemented for `cln_rpc::model::requests::AskrenelistreservationsRequest`, which is required by `pb::AskrenelistreservationsRequest: Into<_>`
|
= note: required for `pb::AskrenelistreservationsRequest` to implement `Into<cln_rpc::model::requests::AskrenelistreservationsRequest>`
error[E0277]: the trait bound `cln_rpc::model::requests::InjectpaymentonionRequest: From<pb::InjectpaymentonionRequest>` is not satisfied
--> cln-grpc/src/server.rs:4282:60
|
4282 | let req: requests::InjectpaymentonionRequest = req.into();
| ^^^^ the trait `From<pb::InjectpaymentonionRequest>` is not implemented for `cln_rpc::model::requests::InjectpaymentonionRequest`, which is required by `pb::InjectpaymentonionRequest: Into<_>`
|
= note: required for `pb::InjectpaymentonionRequest` to implement `Into<cln_rpc::model::requests::InjectpaymentonionRequest>`
error[E0277]: the trait bound `cln_rpc::model::requests::XpayRequest: From<pb::XpayRequest>` is not satisfied
--> cln-grpc/src/server.rs:4314:46
|
4314 | let req: requests::XpayRequest = req.into();
| ^^^^ the trait `From<pb::XpayRequest>` is not implemented for `cln_rpc::model::requests::XpayRequest`, which is required by `pb::XpayRequest: Into<_>`
|
= note: required for `pb::XpayRequest` to implement `Into<cln_rpc::model::requests::XpayRequest>`
```
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Using jsonrpc_request_sync, layers are loaded before we finish init,
so we never can be asked to create a layer before we've loaded it
(xpay creates a layer immediately on startup).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: persistent layers new this release.
Create lower-level versions of routines to create biases, layers,
constraints, etc and only save the ones called from the public APIs.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: persistent layers were only added in this release
They're not always 34 (aka '"'). This is a side-effect of ids
changing from u64 to strings quite a while ago.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
If we connected out, remember that address. We always remember the last
address, but that may be an incoming address. This is explicitly the last
outgoing address which worked.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
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.
The ratio of the median of the fees and probability cost is overall not
a bad factor to combine these two features. This is what the
test_real_data shows.
Changelog-None
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
The fee_fallback test would fail after fixing the computation of the
median. Now by we can restore it by making the probability cost factor
1000x higher than the ratio of the median. This shows how hard it is to
combine fee and probability costs and why is the current approach so
fragile.
Changelog-None
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Rusty: "We don't generally use NDEBUG in our code"
Instead use a compile time flag ASKRENE_UNITTEST to make checks on unit
tests that we don't normally need on release code.
Changelog-none
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
- use graph_max_num_arcs/nodes instead of tal_count in bound checks,
- don't use ccan/lqueue, use instead a minimalistic queue
implementation with an array,
- add missing const qualifiers to temporary tal allocators,
- check preconditions with assert,
- remove inline specifier for static functions,
Changelog-None
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
The calculation of the median values of probability and fee cost in the
linear approximation had a bug by counting on non-existing arcs.
Changelog-none: askrene: fix the median
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
We use an arc "array" in the graph structure, but not all arc indexes
correspond to real topological arcs. We must be careful when iterating
through all arcs, and check if they are enabled before making operations
on them.
Changelog-None: askrene: fix bug, not all arcs exists
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>