This is not worth optimizing that I can see. Using a non-debug build I get
the following times for tests/test_askrene.py::test_real_data
Before:
143 seconds
After:
141 seconds.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
I added amount_msat_accumulate for the "a+=b" case, but I was struggling
with a name for the subtractive equivalent. After some prompting, ChatGPT
suggested deduct.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: askrene-bias-node: an RPC command to set a bias on node's outgoing or incoming channels.
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
We add one more field to biases: "timestamp".
With the timestamp variable old biases can be removed with the
askrene-age command.
Changelog-Added: Plugins: askrene channel biases now have an associated timestamp, and are timed out by askrene-age
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
We have another report of looping. This maxparts code is being completely
rewritten, but it's good to have a catchall for any other cases which might
emerge.
I had to make it customizable since our tests under valgrind are SLOW!
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1. We would find a flow.
2. refine_flow would reduce it so it doesn't deliver enough.
3. So we need to find another, but we are at the limit.
4. So we remove the flow we found.
5. Goto 1.
This can be fixed by disabling a channel which we caused us to reduce the flow,
so we should always make forward progress.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Plugins: `askrene` could enter an infinite loop when maxparts is restricted.
You can now simply add per-tal-object helpers for memleak, but our older pattern required
calling memleak functions explicitly during memleak handling. Hash tables in particular need
to be dynamically allocated (we override the allocators using htable_set_allocator and assume
this), so it makes sense to have a helper macro that does all three.
This eliminates a huge amount of code.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
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>
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>
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
Changelog-Added: askrene: add a new parameter maxparts to getroutes that limits the number of routes in the solution.
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
remove_flows is a helper function to remove flows from a set so that we
keep the number of flows limited.
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
We use a wrapper around the MCF solver that takes care of finding the
best linearization parameters and fixing the flow values to meet the
htlc_min and htlc_max constraints.
We have reworked the current implementation and made it a bit more
similar to renepay's version.
Out of 50000 simulated payment situations distributed accross payment
amounts of 1e2, 1e3, 1e4, 1e5 and 1e6 sats, we find that 133 failed
cases in the master branch turn to success with the current changes,
while only 3 success cases in the master are not solved by the changes.
master
+-------+------+
| S | F |
+---+-------+------+
| S | 46329 | 133 |
changes +---+-------+------+
| F | 3 | 3535 |
+---+-------+------+
Out of the 133 cases that flipped from failure to success the failed
reasons were:
122 -> "Could not find route without excessive cost"
5 -> "We couldn't quite afford it"
5 -> "Amount *msat below minimum"
1 -> tripped an HTLC min check
Changelog-None.
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
by a small amount if the deliver amount is less than the requested
amount by X.
This step saves runtime by avoiding calling an extra MCF
and it helps us solve a small percentage of cases where the only
available routes have HTLCmin that is bigger than X.
Changelog-None
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Disable channels with HTLC min violations so that we don't hit them
twice when computing routes.
Changelog-None
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Try a new way to refine flows,
ie. reduce excess due to MCF accuracy and HTLC max constraints
after hop amounts are computed with fees included.
Changelog-None.
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
From the multiple arcs that derive from the same channel we consider
only those with the smallest cost such that the payment amount and HTLC
max can fit in their combined capacity, ie. we prune high cost arcs that
surely will never be used by the optimal solution.
This reduces the number of arcs in the graph approximately from 8 arcs
per channel to approximately 2 arcs per channel.
No pruning.
amount: 100 1000 10000 100000 1000000
channels: 104741 106163 106607 106654 106666
arcs: 837928 849304 852856 853232 853328
Prune, limit the channel capacity by its HTLC max
amount: 100 1000 10000 100000 1000000
channels: 104741 106163 106607 106654 106666
arcs: 255502 259314 260538 260676 260704
Prune, limit the channel capacity to the payment amount
amount: 100 1000 10000 100000 1000000
channels: 104741 106163 106607 106654 106666
arcs: 209482 216270 228618 295450 432468
Prune, limit the channel capacity to the payment amount and its HTLC max
amount: 100 1000 10000 100000 1000000
channels: 104741 106163 106607 106654 106666
arcs: 209480 212324 213242 215726 228018
This produces a slight speedup for MCF computations:
Amount (sats) | speedup
-----------------------
100 | 1.89
1000 | 1.77
10000 | 1.25
100000 | 1.25
1000000 | 1.18
Changelog-None
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Changelog-Added: askrene: an optimal single-path solver has been added, it can be called using the developer option --dev_algorithm=single-path or by adding the layer "auto.no_mpp_support"
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
The single path solver uses the same probability cost and fee cost
estimation of minflow. Single path routes computed this way are
suboptimal with respect to the MCF solution but still are optimal among
any other single path. Computationally is way faster than MCF, therefore
for some trivial payments it should be prefered.
Changelog-None.
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Refactor MCF solver: remove structs linear_network and residual_network.
Prefer passing raw data to the helper functions.
Changelog-None
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
It was originally a wrapper for JSON param() results, but now it's a more
generic struct. So make it clear that the fields are not optional. This
means a manual assignment in the initial population of this struct, but
all the users are now far clearer.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Move the feature tuning algorithm to mcf.c, ie. the loops for searching
a good mu and delay_feefactor to satisfy the problem constraints.
We are looking to set the stage for an execution logic that allows for
multiple choices of routing algorithms, mainly for experimenting without
breaking the default working code.
Changelog-None
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Add log information about the runtime of getroutes.
Changelog-None: askrene: add runtime of getroutes to the logs
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Change order of operations to ensure that askrene-inform-channel with
inform=constrained computes the correct upper bound on the liquidity:
upperBound = reserves + amount - 1
With the previous order of operations in the case amount=0 we would get:
upperBound = reserves
instead of
upperBound = reserves - 1
Changelog-None
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
We cannot add new parameters in the middle, since we accept parameters by JSON
array as well as by dicts. In fact, this broke tests, but due to unrelated
breakage in the GitHub "Automerge" functionality, it got applied as
556e38c838 ("askrene-bias-channel: bias call add
up.").
Also add tests, and a better Changelog line.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `askrene-bias-channel` now has a `relative` option to add, rather than replace, a channel bias.
The channel bias feature is not being used yet by any plugin, so this
hopefully doesn't break any working code.
When askrene-bias-channel is called the bias quantity is added on top of
any previous biased already present on that channel instead of
overwriting it.
Changelog-Changed: askrene-bias-channel: bias call add up.
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
The parameter max_htlc_value_in_flight_msat stablished by peers on
channel opening (BOLT02) can now be retrived from the
gossmods_from_listpeerchannels API.
Adapted the corresponding callback functions in renepay and askrene to
take into account that value as a constraint to the value we can send
through a channel.
Changelog-Add: fetch max_htlc_value_in_flight_msat from gossmods_listpeerchannels API
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
This is an inefficient hack. Can you tell I really didn't want to
implement this? MPP was finalized in 2018 FFS.
We do this by adding another "auto" layer, which removes all too-small
channels, and then makes our MPP node pile all the funds into the largest
channel it chooses.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
In particular, if the total amount we're sending is less than the minimum amount
the channel insists on, we can eliminate it.
This fixes the problem that we're really trying to send a de-minumus
amount (rather than the more obscure case where we divide the amount
and then it is below the minimum).
After trying several other approaches, this was by far the cleanest!
Reported-by: https://github.com/JssDWt
Fixes: https://github.com/ElementsProject/lightning/issues/8045
Changelog-Fixed: xpay: don't simply give up if our total amount is less than htlc_minimum_msat on some channel.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
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>
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>