-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
routing: routing may come up with suboptimal routes (weight function) #1358
Conversation
Please let me know what you think of this new style of describing the graph. If you agree with my view, I can also convert basic_graph.json to an in-code definition which I am sure will be much shorter. |
The set of json was added initially as when things were a bit more contained on testnet, we could use the output of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this PR! The prior weighting algorithm was thrown in just to start to take the fees into account, but had a major flaw as you've shown here (was originally meant to be temporary, but it was never re-visited).
IMO, the new weight function drastically improves the decisions that path finding algo will make when sending routes. We may want to tweak the risk factor later in the future, but I think the current value is a good starting point (although the code could add a bit more detail in the comments w.r.t to how you arrived at the current value).
@@ -26,6 +26,12 @@ const ( | |||
|
|||
// infinity is used as a starting distance in our shortest path search. | |||
infinity = math.MaxInt64 | |||
|
|||
// RiskFactorBillionths controls the influence of time lock delta |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the process used to arrive at this value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment added
routing/pathfind.go
Outdated
|
||
// The final component is then 1 plus the timelock delta. | ||
timeWeight := int64(1 + e.TimeLockDelta) | ||
// timeWeight is the penalty for the time lock delta of this channel. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
timeWeight -> timeLockPenalty
@@ -2,6 +2,7 @@ package routing | |||
|
|||
import ( | |||
"bytes" | |||
"crypto/sha256" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commit message nit on this: the title itself could use a bit more detail. Simply from "unit test added" one can't gain any knowledge w.r.t exactly what's being tested in the additional set of unit tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Squashed unit test commit. I prefer implementation and covering test to be part of the same commit. But otherwise valid point about commit message.
routing/pathfind_test.go
Outdated
Capacity btcutil.Amount | ||
} | ||
|
||
// parseTestGraph returns a fully populated ChannelGraph given a path to a JSON |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The godoc comment doesn't match the name of the function.
routing/pathfind_test.go
Outdated
aliasMap := make(map[string]*btcec.PublicKey) | ||
|
||
nodeIndex := byte(0) | ||
addAlias := func(alias string) (*channeldb.LightningNode, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function does much more than add an alias. Would recommend calling it something like: addNodeWithAlias
.
routing/pathfind_test.go
Outdated
} | ||
|
||
channelID++ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra new line here.
routing/pathfind_test.go
Outdated
func TestFindLowestFeePath(t *testing.T) { | ||
t.Parallel() | ||
|
||
var testChannels = []*testChannel{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: no need to add a var here, can simply assign with :=
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could also use a comment here explaining the rationale behind the set up: that roasbeef should favor sending through b instead of a.
routing/pathfind_test.go
Outdated
return graph, cleanUp, aliasMap, nil | ||
} | ||
|
||
func TestFindLowestFeePath(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing godoc string on the test itself.
routing/pathfind_test.go
Outdated
if err != nil { | ||
t.Fatalf("unable to find path: %v", err) | ||
} | ||
route, err := newRoute(paymentAmt, sourceVertex, path, startingHeight, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: should be folded similar to the findPath
method above.
In this commit, a new weight function is introduced. This will create a meaningful effect of time lock on route selection. Also, removes the squaring of the fee term. This led to suboptimal routes. Unit test added that covers the weight function and asserts that the lowest fee route is indeed returned.
@Roasbeef comments addressed and rebased. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🎉
Fixes #1346
This PR:
The reason for creating an alternative method to build the test graph is that the current json file contains info that is not relevant for the unit test (pubkeys, channel id, channel point, flags). This makes it harder to maintain and also more difficult to understand the structure.
In this PR these non-relevant properties are (deterministically) generated at run time.
Then there was still the choice whether to stick with json or move the graph definition to go code. In my opinion, expressing the graph in go code can make it easier to understand and shorter because several useful constructors can be defined (for example: symmetricTestChannel).
The shorter the graph definition is, the less effort it is to bring up a dedicated graph to test a specific scenario. I can imagine that the number of these scenarios will grow significantly. Not only because the routing algorithm is not that extensively unit tested currently (unit test added in #1321 was missing for example), but also because future extensions like AMP will need additional unit tests.
With regards to a single test graph for all tests vs special graphs for special tests, I think a mixture will emerge. Some scenarios are just quite difficult to fit (together) into a single graph. There is the option to modify the graph runtime, but I think this is makes it more difficult to understand what is happening.