routing+server: add new QueryBandwidth method to reduce outbound failures

In this commit, we introduce a new method to the channel router's config
struct: QueryBandwidth. This method allows the channel router to query
for the up-to-date available bandwidth of a particular link. In the case
that this link emanates from/to us, then we can query the switch to see
if the link is active (if not bandwidth is zero), and return the current
best estimate for the available bandwidth of the link. If the link,
isn't one of ours, then we can thread through the total maximal
capacity of the link.

In order to implement this, the missionControl struct will now query the
switch upon creation to obtain a fresh bandwidth snapshot. We take care
to do this in a distinct db transaction in order to now introduced a
circular waiting condition between the mutexes in bolt, and the channel
state machine.

The aim of this change is to reduce the number of unnecessary failures
during HTLC payment routing as we'll now skip any links that are
inactive, or just don't have enough bandwidth for the payment. Nodes
that have several hundred channels (all of which in various states of
activity and available bandwidth) should see a nice gain from this w.r.t
payment latency.
This commit is contained in:
Olaoluwa Osuntokun
2018-05-07 21:04:31 -07:00
parent c96d07c1ae
commit f494433cbf
6 changed files with 162 additions and 27 deletions

View File

@ -313,7 +313,7 @@ func TestBasicGraphPathFinding(t *testing.T) {
target := aliases["sophon"]
path, err := findPath(
nil, graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, paymentAmt,
ignoredEdges, paymentAmt, nil,
)
if err != nil {
t.Fatalf("unable to find path: %v", err)
@ -455,7 +455,7 @@ func TestBasicGraphPathFinding(t *testing.T) {
target = aliases["luoji"]
path, err = findPath(
nil, graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, paymentAmt,
ignoredEdges, paymentAmt, nil,
)
if err != nil {
t.Fatalf("unable to find route: %v", err)
@ -541,7 +541,7 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) {
// We should now be able to find a path from roasbeef to doge.
path, err := findPath(
nil, graph, additionalEdges, sourceNode, dogePubKey, nil, nil,
paymentAmt,
paymentAmt, nil,
)
if err != nil {
t.Fatalf("unable to find private path to doge: %v", err)
@ -578,6 +578,7 @@ func TestKShortestPathFinding(t *testing.T) {
target := aliases["luoji"]
paths, err := findPaths(
nil, graph, sourceNode, target, paymentAmt, 100,
nil,
)
if err != nil {
t.Fatalf("unable to find paths between roasbeef and "+
@ -629,7 +630,7 @@ func TestNewRoutePathTooLong(t *testing.T) {
target := aliases["ursula"]
_, err = findPath(
nil, graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, paymentAmt,
ignoredEdges, paymentAmt, nil,
)
if err != nil {
t.Fatalf("path should have been found")
@ -640,7 +641,7 @@ func TestNewRoutePathTooLong(t *testing.T) {
target = aliases["vincent"]
path, err := findPath(
nil, graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, paymentAmt,
ignoredEdges, paymentAmt, nil,
)
if err == nil {
t.Fatalf("should not have been able to find path, supposed to be "+
@ -682,7 +683,7 @@ func TestPathNotAvailable(t *testing.T) {
_, err = findPath(
nil, graph, nil, sourceNode, unknownNode, ignoredVertexes,
ignoredEdges, 100,
ignoredEdges, 100, nil,
)
if !IsError(err, ErrNoPathFound) {
t.Fatalf("path shouldn't have been found: %v", err)
@ -718,7 +719,7 @@ func TestPathInsufficientCapacity(t *testing.T) {
payAmt := lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin)
_, err = findPath(
nil, graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, payAmt,
ignoredEdges, payAmt, nil,
)
if !IsError(err, ErrNoPathFound) {
t.Fatalf("graph shouldn't be able to support payment: %v", err)
@ -748,7 +749,7 @@ func TestRouteFailMinHTLC(t *testing.T) {
payAmt := lnwire.MilliSatoshi(10)
_, err = findPath(
nil, graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, payAmt,
ignoredEdges, payAmt, nil,
)
if !IsError(err, ErrNoPathFound) {
t.Fatalf("graph shouldn't be able to support payment: %v", err)
@ -778,7 +779,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
payAmt := lnwire.NewMSatFromSatoshis(10000)
_, err = findPath(
nil, graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, payAmt,
ignoredEdges, payAmt, nil,
)
if err != nil {
t.Fatalf("unable to find path: %v", err)
@ -799,7 +800,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
// failure as it is no longer eligible.
_, err = findPath(
nil, graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, payAmt,
ignoredEdges, payAmt, nil,
)
if !IsError(err, ErrNoPathFound) {
t.Fatalf("graph shouldn't be able to support payment: %v", err)