Commit Graph

132 Commits

Author SHA1 Message Date
ZmnSCPxj jxPCSnmZ 0eb1e7e0ca plugins/libplugin-pay.c: Add new payee_incoming_limit to limit number of HTLCs based on payee connectivity.
Fixes: #3926

(probably)

Changelog-Fixed: pay: Also limit the number of splits if the payee seems to have a low number of channels that can enter it, given the max-concurrent-htlcs limit.
2020-09-10 16:50:52 +09:30
ZmnSCPxj jxPCSnmZ deced56344 plugins/libplugin-pay.c: Add facility to have paymods request lowering of the estimated max HTLCs. 2020-09-10 16:50:52 +09:30
ZmnSCPxj jxPCSnmZ d15717b576 plugins/libplugin-pay.c: Keep p->invoice->routes valid when the routehints paymod mutates it.
The routehints paymod shares the storage of the array d->routehints and
p->invoice->routes, but once it operates, it possibly leaves it as a stale
pointer to memory it used to have.

Since other paymods may be interested in the invoice details, including
the routehints in the invoice, we should ensure the p->invoice->routes
remains valid whenever we try mutating that array.
2020-09-10 16:50:52 +09:30
Rusty Russell 191355e0e7 pay: fix handling of legacy vs tlv encoding.
As revealed by the failure of tests in #3936, where we ended up trying
to send a partial payment using legacy style, we are not handling
style properly.

1. BOLT9 has features, so we can *know* that the destination supports
   MPP.  We may not have seen a node_announcement.
2. We can't assume that nodes inside routehints support TLV.
3. We can't assume direct peers support TLV.

The keysend code tried to fix this up, so I'm not sure that this caused
the issue in #3968, though.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `pay` will now make reliable multi-part payments to nodes it doesn't have a node_announcement for.
2020-09-10 16:50:32 +09:30
Rusty Russell 0c7d04bd98 libplugin-pay: fix default CLTV.
This was changed recently, but without a bolt quote, we didn't find
this.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-09-02 06:59:13 +09:30
Rusty Russell 8150d28575 Makefile: use generic rules to make spec-derived sources.
Now we use the same Makefile rules for all CSV->C generation.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-08-31 21:33:26 -05:00
ZmnSCPxj jxPCSnmZ 932709cad9 plugins/libplugin-pay.c: Micro-optimize start_block sampling.
Using `waitblockheight 0` is a very slightly faster query than `getinfo`.
Also, avoid querying blockheight for child payments (allow `waitblockheight`
paymod to provide the blockheight returned from the `waitblockheight`, and
just resample the starting blockheight from the parent).

Changelog-None: pointless micro-optimization
2020-08-28 16:40:27 +02:00
ZmnSCPxj jxPCSnmZ 05daa8e5f3 plugins/libplugin-pay.c: Micro-optimization of plugin_is_finished.
This was checked with `gcc -S -O2` to see how an optimized build
would compile the function.
The original code completed calls into each child (and the `.s`
file showed that GCC 9.x was not smart enough to do early-out).

This modification explicitly does early-out, and avoids call-return
stack overhead for the common case where a payment is an ancestor
of a long line of single-child payments due to retrying.

Changelog-None: pointless micro-optimization
2020-08-28 16:40:27 +02:00
Rusty Russell 496c0dd1e6 common/random_select: central place for reservoir sampling.
Turns out we can make quite a simple API out of it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-08-28 10:56:50 +09:30
Rusty Russell 12d0d5c185 amount: cleanup usage.
We've got some recently-added primitives which help.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-08-27 18:16:28 +02:00
Christian Decker 21d87f7075 pay: Implement simple presplit fix for ludicrous amounts
This is the simplest possible fix: increase the target amount until we get
the desired number of parts, while still bucketizing payments together that
are in approximately the same size.

The current logic puts all payments that are in the range x < amount <= 16*x
in the same bucket, making them harder to distinguish.

Changelog-Fixed: pay: The `presplit` modifier now supports large payments without exhausting the available HTLCs.
2020-08-27 10:19:21 +09:30
ZmnSCPxj jxPCSnmZ 128adf0938 plugins/libplugin-pay.c: Round-robin routehints when splitting.
This improves the success rate of `test_mpp_interference_2`, though
still not quite up to the level that we can remove `@flaky` from it.
2020-08-26 09:29:46 +09:30
ZmnSCPxj jxPCSnmZ c27d7a3110 plugins/libplugin-pay.c: Store the route description, and re-report on failure. 2020-08-25 12:17:18 +02:00
ZmnSCPxj jxPCSnmZ 6468616c02 plugins/libplugin-pay.c: Propagate local_id from parent to child payment object. 2020-08-25 12:17:18 +02:00
ZmnSCPxj jxPCSnmZ d8678467fa plugins/libplugin-pay.c: Show routes being tried, also print updates to channel hints not just initial creations. 2020-08-25 12:17:18 +02:00
ZmnSCPxj jxPCSnmZ d89c77c0ce plugins/libplugin-pay.c: Describe the bits of unrecognized failure codes. 2020-08-25 12:17:18 +02:00
ZmnSCPxj jxPCSnmZ 0d2d85ab5f plugins/libplugin-pay.c: Also print events that create new sub-payments. 2020-08-25 12:17:18 +02:00
ZmnSCPxj jxPCSnmZ 98583e84b5 plugins/libplugin-pay.c: Give cmd id and partid for each log message.
Changelog-None: internal debugging

Makes it easier to debug payments with tons of splits.
2020-08-25 12:17:18 +02:00
ZmnSCPxj jxPCSnmZ f81611e551 plugins/libplugin-pay.c: Make sure blockheight disagreement does not prevent all future progress.
Blockheight disagreement is signalled with a permanent failure at the
end node, but is actually a transient failure.
2020-08-13 12:50:16 +02:00
Christian Decker 8769f9ed93 pay: Fix final TLV payload if not going through MPP modifiers
Reported-by: ZmnSCPxj
Signed-off-by: Christian Decker <@cdecker>

Changelog-Fixed: pay: Correct a case where we put the sub-payment value instead of the *total* value in the `total_msat` field of a multi-part payment.
2020-08-13 12:50:16 +02:00
ZmnSCPxj jxPCSnmZ 0279be1d13 plugins/libplugin-pay.c: Be less aggressive with advancing through routehints.
Only advance through routehints if no route was found at all, or if the
estimated capacity at the routehint is lower than the amount that we
have to send through the routehint.

Changelog-Fixed: pay: Be less aggressive with forgetting routehints.
2020-08-13 12:50:16 +02:00
Christian Decker 894c886bdd pay: Inherit payment label to all children 2020-08-12 19:10:48 +02:00
Christian Decker 0dcd974d97 pytest: Reproduce #3915 2020-08-12 19:10:48 +02:00
Vincenzo Palazzo 1521c29fcf listpays mod 1: add destination inside the response when bolt11 is null
Changelog-Added: JSON-RPC: `listpays` now lists the `destination` if it was provided (e.g., via the `pay` plugin or `keysend` plugin)
2020-08-09 16:03:03 +02:00
Rusty Russell fa829f23db amount: add amount_msat_scale, amount_msat_ratio, amount_{msat,sat}_div
It's not all that rare to do these operations, and requiring annotations
for it is a little painful.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-08-06 09:36:47 +09:30
ZmnSCPxj jxPCSnmZ 094eac4e95 plugins/libplugin-pay.c: Properly handle exclusions for routehints with two hops or more.
Arguably a low-priority bug since no current node ever generates routehints longer
than one hop.

However, it is possible as an edge case, if the destination is directly accessible
*and* supports multiple channels, that we route through the destination, one of the
*other* channels it has not in the routehint, to the entry point, and then through
the routehint.

This change removes the risk of the above edge case.

Changelog-None: arguably a low-priority bug.
2020-08-03 15:20:29 +09:30
Christian Decker a456d08ad0 pay: Be less aggressive when estimating channel capacity
We'd previously take the failed attempt and estimate the failing channel's
capacity at 3/4 of the attempted amount, which is rather aggressive. This
reduces this aggressiveness to use the exact amount tried, but excluding on
equality. This still skips attempting the same route with the same amount, but
also permits attempts that are in the range [3/4, 1] of the failed attempt
amount to still be attempted.
2020-08-03 12:15:08 +09:30
Christian Decker d7cca0781d jsonrpc: Add `msatoshi` argument to `sendonion` to annotate
While not directly necessary, it still feeds the `listpays` result, and so we
should pass it along if we can, so we don't have to rely solely on the
`amount_sent` field, which includes the fees.

Reported-by: Rusty Russell <@rustyrussell>
2020-07-28 16:17:39 +09:30
Vincent 81fd552e84 plugins/pay: hand bolt11 arg to sendonion if we have one (i.e. for `pay`)
[ Extracted into standalone patch and comment added by RR ]
2020-07-27 13:11:14 +02:00
Christian Decker 15d1a190a0 pay: Remove duplicate message field
jsonrpc_stream_fail already adds a message field.
2020-07-24 11:35:49 +02:00
Christian Decker 85ec438d34 paymod: Routehintmod signals that we can retry if getroute fails
The shortcut in the retry_mod that we can skip retrying if getroute fails or
we have no result is only valid if the parameters don't change. As we iterate
through the routehints the parameters change, and so we must signal to the
retry_mod that it can retry even in those cases.
2020-07-24 11:35:49 +02:00
Christian Decker 52a8b8f9e7 paymod: Update step before creating child payments
The child payments will sometimes depend on the step of the parent, and making
sure that the parent state is correct before we create the children is
therefore important.
2020-07-24 11:35:49 +02:00
Rusty Russell 2556df5f7c plugins/pay: Exclude the entrypoint to a routehint to avoid cycles
This uses @cdecker's idea of excluding the routehinted channel from the route,
and also consumes the route hints as it goes so that it makes progress.

I don't know if this is correct, but it reliably passes tests/test_pay.py::test_tlv_or_legacy
now.
2020-07-24 11:35:49 +02:00
Christian Decker 56dd18e01e paymod: Iterate through the routehints in order
We store an offset of the current routehint in the modifier data. It gets
incremented on retry, and it gets reset to 0 on split. This is because once we
split we have a different amount and a previously unusable routehint becomes
usable again.
2020-07-24 11:35:49 +02:00
Christian Decker 1e28d661fd paymod: Move application of routehints into its own function
We have two places we need to do that now: in the root payment after we
checked if the destination is reachable, and in any other payment directly in
the initialization-step callback.
2020-07-24 11:35:49 +02:00
Christian Decker 282f19d560 paymod: Simplify routehint data initialization
It was spread over the step callback, but we only need to initialize the
routehints array there, child-payments can just inherit most of the information.
2020-07-24 11:35:49 +02:00
Christian Decker b78aa3fb25 paymod: Check if destination is reachable at all directly at startup
This does two things: it checks if the destination of the payment is at all
reachable without routehints, and if it is it adds a direct attempt as option
to the routehints in the form of a NULL routehint. It also simplifies the
selection of the routehint since the direct case is no longer special, instead
we just return a NULL routehint as if it were a normal routehint.
2020-07-24 11:35:49 +02:00
Rusty Russell 497b18ba33 paymod: fix typo which can cause memory overrun.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-07-23 14:57:29 +02:00
Christian Decker 6ada56ca7c paymod: Always initialize p->route
We're using it in a couple of places to see if we even performed the attempt,
so we need to make sure it's initialized.
2020-07-23 10:14:21 +09:30
Christian Decker 899a2e64b0 paymod: Randomly select a routehint, or none at random
The adaptive MPP test was showing an issue with always using a routehint, even
when it wasn't necessary: we would insist on routhing to the entrypoint of the
routehint, even through the actual destination. If a channel on that loop
would result being over capacity we'd slam below 0, and then increase again by
unapplying the route. The solution really is not to insist on routing through
a routehint, so we implement random skipping of routehints, and we rotate them
if we have multiples.
2020-07-23 10:14:21 +09:30
Christian Decker 534536b242 paymod: Consolidate channel_hint creation in channel_hints_update
As the hints get new fields added it is easy to forget to amend one of the
places we create them, since we already have an update method let's use that
to handle all additions to the array of known channel hints.
2020-07-23 10:14:21 +09:30
Christian Decker e76bf541ad paymod: Fix the routehints being lost when retrying
We were removing the current hint from the list and not inheriting the current
routehint, so we'd be forgetting a hint at each retry. Now we keep the array
unchanged in the root, and simply skip the ones that are not usable given the
current information we have about the channels (in the form of channel_hints).

Fixes #3861
2020-07-23 10:14:21 +09:30
Christian Decker d289ee64a1 paymod: Add the courtesy +1 to the CLTVs to allow for a new block
This may be related to the issue #3862, however the water was muddied by it
being the wrong error to return, and the node should not expect this courtesy
feature to be present at all...
2020-07-23 10:14:21 +09:30
Christian Decker e92787a0e2 paymod: Teach the adaptive splitter to respect the HTLC limit
There is little point in trying to split if the resulting HTLCs exceed the
maximum number of HTLCs we can add to our channels. So abort if a split would
result in more HTLCs than our channels can support.
2020-07-23 10:14:21 +09:30
Christian Decker acdd9b8762 paymod: Teach the presplit modifier to respect the chan HTLC limit
The presplit modifier could end up exceeding the maximum number of HTLCs we
can add to a channel right out the gate, so we switch to a dynamic presplit if
that is the case. The presplit will now at most use 1/3rd of the available
HTLCs on the channels if the normal split would exceed the number of availabe
HTLCs. And we also abort early if we don't have a sufficient HTLCs available.
2020-07-23 10:14:21 +09:30
Christian Decker a1dc9cbd97 paymod: Track how many HTLCs each channel can still add
It turns out that by aggressively splitting payments we may end up exhausting
the number of HTLCs we can add to a channel quickly. By tracking the number of
HTLCs we can still add, and excluding the channels to which we cannot add any
more we increase the route diversity, and avoid quickly exhausting the HTLC
budget.

In the next commit we'll also implement an early abort if we've exhausted all
channels, so we don't end up splitting indefinitely and we can also optimize
the initial split to not run afoul of that limit.
2020-07-23 10:14:21 +09:30
Vincent 54888d454b Fixed assertion in pay plugin
This PR includes the fix discussed on PR #3855. This fix was tested with the use case described inside the issue and worked.

Fixes: #3855

Changelog-None
2020-07-23 10:14:21 +09:30
Rusty Russell 178415aca7 pay: handle returned errors more gracefully.
The code had incorrect assertions, partially because it didn't clearly
distinguish errors from the final node (which, barring blockheight issues,
mean a complete failre) and intermediate nodes.

In particular, we can't trust the *values*, so we need to distinguish
these by the *sender*.

If a route is of length 2 (A, B):
- erring_index == 0 means us complaining about channel A.
- erring_index == 1 means A.node complaining about channel B.
- erring_index == 2 means the final destination node B.node.

This is particularly of note because Travis does NOT run test_pay_routeboost!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-07-23 10:14:21 +09:30
Rusty Russell a849e5f4bd pay: fix problematic sharing of shadow route data.
Because listchannels responses are async, with mpp we can end up
fighting over use of the parent's data giving results from incorrect
final CLTVs to assertion failures like below:

```
pay: plugins/libplugin-pay.c:1964: shadow_route_listchannels: Assertion `amount_msat_greater_eq(p->constraints.fee_budget, d->constraints.fee_budget)' failed.
pay: FATAL SIGNAL 6 (version v0.9.0rc2-11-g29d32e0-modded)
0x563129eb6a15 send_backtrace
	common/daemon.c:38
0x563129eb6abf crashdump
	common/daemon.c:51
0x7fe37c8b920f ???
	???:0
0x7fe37c8b918b ???
	???:0
0x7fe37c898858 ???
	???:0
0x7fe37c898728 ???
	???:0
0x7fe37c8a9f35 ???
	???:0
0x563129ea5c63 shadow_route_listchannels
	plugins/libplugin-pay.c:1964
0x563129e9c56a handle_rpc_reply
	plugins/libplugin.c:547
0x563129e9cbfa rpc_read_response_one
	plugins/libplugin.c:662
0x563129e9ccf0 rpc_conn_read_response
	plugins/libplugin.c:681
0x563129ece660 next_plan
	ccan/ccan/io/io.c:59
0x563129ecf245 do_plan
	ccan/ccan/io/io.c:407
0x563129ecf287 io_ready
	ccan/ccan/io/io.c:417
0x563129ed151f io_loop
	ccan/ccan/io/poll.c:445
0x563129e9ef03 plugin_main
	plugins/libplugin.c:1284
0x563129e9b099 main
	plugins/pay.c:2010
0x7fe37c89a0b2 ???
	???:0
0x563129e9452d ???
	???:0
0xffffffffffffffff ???
	???:0
```
2020-07-23 10:14:21 +09:30
Christian Decker f950153f98 paymod: Fix the adaptive splitter partitioning
We were using the current constraints, including any shadow route and other
modifications, when computing the remainder that the second child should
use. Instead we should use the `start_constraints` on the parent payment,
which is a copy of `constraints` created in `payment_start` exactly for this
purpose.

Also added an assert for the invariant on the multiplier.
2020-07-23 10:14:21 +09:30