Commit graph

136 commits

Author SHA1 Message Date
Matt Corallo
b728216fd9 [router] Calc min-to-node fees based on min value, not est value
When walking the network graph to calculate a route, we always
calculate the minimum fee which is required to make one further
hop. This avoids some extra hop processing at the end of each path
selection loop (saving around 10% runtime in our benchmarks).

However, if we use the real value which we expect
to send over a channel in that calculation, we may find an
alternate path to the same node which is more expensive but
capacity-constrained, resulting in us considering it cheaper as the
relative fee paid will be lower.

Instead, we can use the `minimal_value_contribution_msat`, which is
a constant through an entire path finding iteration, as the amount,
preventing any basis change in the relative fee paid.
2021-04-06 21:41:45 -04:00
Matt Corallo
ed54379ee4 [router] Make Dijkstra's path scoring non-decreasing + consistent
Currently, the "best source" for a given node tracked during
Dijkstra's is updated with a different critera from the heap
sorting, resulting in loops in calculated paths.

This adds a test for the specific failure currently seen, utilizing
the new path-htlc-minimum tracking in the heap entries in place of
the per-hop htlc-minimum values which the MPP changeset partially
used.
2021-04-06 21:41:45 -04:00
Matt Corallo
16a6e9c5c8 [router] Avoid re-selecting the same path over and over again
If we walk the network graph and find a route that meets are
payment amount and has a liquidiy limit far in excess of our
payment amount, we may select the same path several times in the
main path-gathering loop.

Instead, if the path we selected was not limited by the available
liquidity, we set the middle hop in the path's liquidity available
to zero, disabling that channel in future path finding steps.
2021-04-06 21:41:45 -04:00
Matt Corallo
93311b3684 [router] Track full-path htlc-minimum-msat while graph-walking
Previously, we'd happily send funds through a path where, while
generating the path, in some middle hope we reduce the value being
sent to meet an htlc_maximum, making a later hop invalid due to it
no longer meeting its htlc_minimum. Instead, we need to track the
path's htlc-minimum while we're transiting the graph.
2021-04-06 21:41:45 -04:00
Matt Corallo
5c38e09b26 [router] Do not fail if we are exactly (or 3x) limited by a maximum
The new MPP routing algorithm attempts to build paths with a higher
value than our payment to find paths which may allow us to pay a
fee to meet an htlc_minimum limit. This is great if we're
min-bounded, however it results in us rejecting paths where we are
bounded by a maximum near the end of the path, with fees, and then
bounded by a minimum earlier in the path. Further, it means we will
not find the cheapest path where paths have a lower relative fee
but a higher absolute fee.

Instead, we calculate routes using the actual amount we wish to
send. To maintain the previous behavior of searching for cheaper
paths where we can "pay the difference" to meet an htlc_minimum, we
detect if we were minimum-bounded during graph walking and, if we
are, we walk the graph again with a higher value.
2021-04-06 21:41:45 -04:00
Matt Corallo
512642c32d Add comment in get_route describing our dijkstra's mods 2021-04-06 21:41:45 -04:00
Matt Corallo
32f6205848
Merge pull request #841 from valentinewallace/207-replacement
Expose counterparty forwarding info in ChannelDetails
2021-03-17 22:41:30 +00:00
Valentine Wallace
c318ad87e0
Expose counterparty forwarding info in ChannelDetails.
Useful for constructing route hints for private channels in invoices.

Co-authored-by: Valentine Wallace <vwallace@protonmail.com>
Co-authored-by: Antoine Riard <ariard@student.42.fr>
2021-03-17 17:36:26 -04:00
Matt Corallo
8799a2a044
Merge pull request #828 from bmancini55/reply_channel_range
Handle query_channel_range gossip queries
2021-03-17 20:35:03 +00:00
bmancini55
7b842b61f8 Simplify sequencing of handle_query_channel_range
Modify NetGraphMsgHandler::handle_query_channel_range to always use
first_blocknum=0 in replies. This is spec compliant after changes to
make sequence completion explicity using sync_complete.
2021-03-16 19:36:38 -04:00
bmancini55
7815965bf7 Comment cleanup for handling query_channel_range
Cleans up NetGraphMsgHandler::handle_query_channel_range
2021-03-16 19:36:30 -04:00
bmancini55
f4adb9f013 Use constant MAX_REPLY_SCID
Modifies NetGraphMsgHandler::handle_query_channel_range to use a constant
max value in replies. Modifies tests to generate 8000 channels instead
of making this value configurable.
2021-03-13 14:51:36 -05:00
bmancini55
deffb4a3d8 Clean up iteration in handle_query_channel_range
Refactor to use an enumerator in NetGraphMsgHandler::handle_query_channel_range
2021-03-09 16:30:52 -05:00
bmancini55
d5fd8d96e1 Improve short_channel_id utils
Modifies scid_from_parts to use u64 inputs allowing untruncated
validation. Adds public constants for limits.
2021-03-09 15:34:52 -05:00
Matt Corallo
b9fef85aa3 Split router benchmark into an MPP and a non-MPP route benchmark 2021-03-08 17:19:23 -05:00
Matt Corallo
ef0f249294 Disable MPP routing when the payee does not support it 2021-03-08 17:19:23 -05:00
Matt Corallo
9e57364a89 Add an Option<>al InvoiceFeatures object for the payee in get_route
We currently only use it to override the graph-specific features
returned in the route, though we should also use it to enable or
disable MPP.

Note that tests which relied on MPP behavior have had all of their
get_route calls upgraded to provide the MPP flag.
2021-03-08 17:19:23 -05:00
bmancini55
44ba52ccf1 Handle query_channel_range message from peer
Initial implementation of handling query_channel_range messages in
NetGraphMsgHandler.  Enqueues a sequence of reply message in the pending
message events buffer.
2021-03-05 17:14:35 -05:00
Jeffrey Czyz
a571ecccbc
Fix build warnings 2021-03-02 21:30:34 -08:00
Matt Corallo
4894d52d30 Merge pull request #646 from naumenkogs/2020-06-router-mpp
MPP on the router side
2021-03-02 20:33:08 -05:00
Gleb Naumenko
e0600e5b1e Don't underpay htlc_min due to path contribution
We could have possibly constructed a slightly inconsistent
path: since we reduce value being transferred all the way, we
could have violated htlc_minimum_msat on some channels
we already passed (assuming dest->source direction). Here,
we recompute the fees again, so that if that's the case, we
match the currently underpaid htlc_minimum_msat with fees.
2021-03-02 21:40:08 +02:00
Gleb Naumenko
18c7730040 Mind htlc_minimum_msat when truncating overpaid value
At truncating the overpaid value, if we fall below
htlc_minimum_msat, reach it by increasing fees.
2021-03-02 21:19:58 +02:00
Gleb Naumenko
ef12ceb8dd Use outbound_capacity_msat from first_hops for routing 2021-03-02 21:09:50 +02:00
Gleb Naumenko
db4721f3a7 Implement finding paths for MPP 2021-03-02 21:09:49 +02:00
Matt Corallo
4b04f3ff1e Allow cloning NetworkGraphs 2021-02-22 11:44:22 -05:00
Matt Corallo
8051fb0118 Standardize trait derives in network graph objects
In general, trivial structs that have no inner logic can/should
all derive, at least, `Clone, Debug, PartialEq`.
2021-02-22 11:44:22 -05:00
Matt Corallo
09f37ae89b
Merge pull request #797 from TheBlueMatt/2021-02-no-addr-order
Drop address ordering enforcement in NodeAnnouncement deser
2021-02-16 08:05:26 -08:00
Matt Corallo
2ae6b3fad4 Add a trivial benchmark of calculating routes on today's graph
Sadly rust upstream never really figured out the benchmark story,
and it looks like the API we use here may not be long for this
world. Luckily, we can switch to criterion with largely the same
API if that happens before upstream finishes ongoing work with the
custom test framework stuff.

Sadly, it requires fetching the current network graph, which I did
using Val's route-testing script written to test the MPP router.
2021-02-15 16:51:51 -05:00
Matt Corallo
d873e72789 Allow gossip messages to have 1KB of uninterpreted data and relay 2021-02-15 16:45:22 -05:00
Matt Corallo
75d71cead3 Add additional Clone derives
The only API change outside of additional derives is to change
the inner field in `DecodeError::Io()` to an `std::io::ErrorKind`
instead of an `std::io::Error`. While `std::io::Error` obviously
makes more sense in context, it doesn't support Clone, and the
inner error largely doesn't have a lot of value on its own.
2021-02-10 22:34:19 -05:00
Matt Corallo
89be6254ae
Merge pull request #790 from bmancini55/sync_complete
Interpret sync_complete in reply_channel_range
2021-02-04 09:18:52 -08:00
bmancini55
77690fada2 Interpret sync_complete in reply_channel_range
LN Spec PR #826 changes full_information to indicate completion of a
sequence of reply_channel_range messages.
2021-02-04 09:19:02 -05:00
Matt Corallo
ac078c103c [bindings] Don't require trait impl for-structs to have no generics
This (finally) exposes `ChannelManager`/`ChannelMonitor` _write
methods, which were (needlessly) excluded as the structs themselves
have generic parameters. Sadly, we also now need to parse
`(C-not exported)` doc comments on impl blocks as we otherwise try
to expose _write methods for `&Vec<RouteHop>`, which doesn't work
(and isn't particularly interesting for users anyway). We add such
doc comments there.
2021-02-03 10:11:28 -05:00
Matt Corallo
70440a529e [bindings] Use consistent imports for MessageSendEvents traits
Our bindings generator is braindead with respect to the idents
used in a trait definition - it treats them as if they were used
where the trait is being used, instead of where the trait is
defined. Thus, if the idents used in a trait definition are not
also imported the same in the files where the traits are used, we
will claim the idents are bogus.

I spent some time trying to track the TypeResolvers globally
through the entire conversion run so that we could use the original
file's TypeResolver later when using the trait, but it is somewhat
of a lifetime mess. While likely possible, import consistency is
generally the case anyway, so unless it becomes more of an issue in
the future, it likely makes the most sense to just keep imports
consistent.

This commit keeps imports consistent across trait definition files
around `MessageSendEvent` and `MessageSendEventsProvider`.
2021-02-01 16:52:57 -05:00
Gleb Naumenko
368c534679 Store available routing amounts per channel to use it in routing decisions 2020-12-24 13:04:47 +02:00
bmancini55
e0bb63bc60 Remove should_request_full_sync from RoutingMessageHandler
This method was used to set the initial_routing_sync flag when sending
an outbound Init message to a peer. Since we are now relying on
gossip_queries instead of initial_routing_sync, synchronization can be
fully encapsulate into RoutingMessageHandler via sync_routing_table.

This commit removes should_request_full_sync from the trait
RoutingMessageHandler. The implementation is still used in
NetGraphMsgHandler and has been converted into a private method instead
of a trait function.
2020-12-14 12:52:59 -05:00
bmancini55
e742894492 Change routing table sync to use gossip_queries
This commit changes outbound routing table sync to use gossip_queries
instead of the effectively deprecated initial_routing_sync feature.

This change removes setting of initial_routing_sync in our outbound Init
message. Instead we now call sync_routing_table after receiving an Init
message from a peer. If the peer supports gossip_queries and
should_request_full_sync returns true, we initiate a full gossip_queries
sync.
2020-12-14 12:52:54 -05:00
bmancini55
7a4a29ffe0 Pass Init message to sync_routing_table method
This commit modifies sync_routing_table in RoutingMessageHandler to
accept a reference to the Init message received by the peer. This allows
the method to use the Peer's features to drive the operations of the
gossip_queries routing table sync.
2020-12-09 15:02:32 -05:00
bmancini55
7e1e0ac97c Pass gossip_queries messages to handler via ownership
This change modifies gossip_queries methods in RoutingMessageHandler to
move the message instead of passing a reference. This allows the message
handler to be more efficient by not requiring a full copy of SCIDs
passed in messages.
2020-12-09 15:02:32 -05:00
bmancini55
14d4492b68 Refactor gossip_queries sync to be stateless
This commit simplifies the sync process for routing gossip messages. When
a sync is initiated, the process is handled statelessly by immediately
issuing SCID queries as channel range replies are received. This greatly
simplifies the state machine at the cost of fully validating and
conforming to the current spec.
2020-12-09 15:02:32 -05:00
bmancini55
d183b975da Add genesis block hash to NetworkGraph
This changes adds the genesis block hash as a BlockHash to the
NetworkGraph struct. Making the NetworkGraph aware allows the message
handler to validate the chain_hash for received messages. This change
also adds the hash value to the Writeable and Readable methods.
2020-12-09 15:02:32 -05:00
bmancini55
69da2daeae Implement gossip_queries sync methods in NetGraphMsgHandler
To perform a sync of routing gossip messages with a peer requires a two
step process where we first initiate a channel range query to discover
channels in a block range. Next we request the routing gossip messages
for discovered channels.

This code implements logic in NetGraphMsgHandler for performing these two
tasks while taking into account the specification and variance in
implementation.
2020-12-09 15:02:32 -05:00
bmancini55
55e5aafcfe Add gossip_queries methods to RoutingMessageHandler trait
Defines message handlers for gossip_queries messages in the RoutingMessageHandler
trait. The MessageSendEventsProvider supertrait is added to RoutingMessageHandler
so that the implementor can use SendMessageEvents to send messages to a
peer at the appropriate time.

The trait methods are stubbed in NetGraphMsgHandler which implements
RoutingMessageHandler and return a "not implemented" error.
2020-12-09 15:02:32 -05:00
Matt Corallo
3b6f7f1199 Split NetworkGraph message handling fns into unsigned and signed
This takes the now-public `NetworkGraph` message handling functions
and splits them all into two methods - one which takes a required
Secp256k1 context and verifies signatures and one which takes only
the unsigned part of the message and does not take a Secp256k1
context.

This both clarifies the public API as well as simplifies it, all
without duplicating code.

Finally, this adds an assertion in the Router fuzzer to make sure
the constants used for message deserialization are correct.
2020-11-24 16:33:33 -05:00
Matt Corallo
d9c03f26f9 Move UTXO-lookup into pub utility function from RoutingMsgHandler
This makes the public utility methods in `NetworkGraph` able to do
UTXO lookups ala `NetworkMsgHandler`'s `RoutingMessageHandler`
implementation, slightly simplifying the public interface.

We also take this opportunity to verify signatures before calling
out to UTXO lookups, under the "do actions in order of
cheapest-to-most-expensive to reduce DoS surface" principle.
2020-11-24 14:00:02 -05:00
Matt Corallo
fc7df54f8d
Merge pull request #748 from TheBlueMatt/2020-11-router-fuzzer
Make router_target a bit easier for fuzzers to explore and fix two found bugs
2020-11-24 08:36:14 -08:00
Matt Corallo
c53d8a3596 Expose manual-update methods in NetworkGraph.
These functions were created but previously not exported, however
they are useful if we want to skip signature checking when accepting
routing messages (which we really should be doing in the routing
fuzzer).
2020-11-24 11:04:11 -05:00
Matt Corallo
423073dfe5 [netgraph] Do not allow capacity_sats * 1000 to overflow-panic
In updating the router fuzzer, it discovered that a remote peer can
cause us to overflow while multiplying the channel capacity value.
Since the value should never exceed 21 million BTC, we just add a
check for that.
2020-11-23 13:52:51 -05:00
Matt Corallo
50b348c4fa [router] Fix + test routing via next/last-hop hints only
We had code in the router to support sending a payment via a single
hop across channels exclusively provided by the next-/last-hop hints.
However, in updating the fuzzer, I noted that this case not only
didn't work, but paniced in some cases.

Here, we both fix the panic, as well as write a new test which
ensures we don't break support for such routing in the future.
2020-11-23 13:52:51 -05:00
Matt Corallo
d737111044 derive(Clone) for several pub simple data structs.
There is no reason not to and Clone can be useful especially in the
bindings context.
2020-11-23 11:08:34 -05:00