routing: add additionalEdges field to a missionControl's paymentSession

In this commit, we introduce the ability for payment sessions to store
an additional set of edges that can be used to assist a payment in
successfully reaching its destination.
This commit is contained in:
Wilmer Paulino 2018-03-26 23:53:46 -04:00
parent 5ddee85479
commit 7965247db1
No known key found for this signature in database
GPG Key ID: 6DF57B9F9514972F
2 changed files with 57 additions and 4 deletions

@ -5,6 +5,8 @@ import (
"time"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/roasbeef/btcd/btcec"
)
const (
@ -148,20 +150,69 @@ func (m *missionControl) GraphPruneView() graphPruneView {
// and will now be pruned after a decay like the main view within mission
// control. We do this as we want to avoid the case where we continually try a
// bad edge or route multiple times in a session. This can lead to an infinite
// loop if payment attempts take long enough.
// loop if payment attempts take long enough. An additional set of edges can
// also be provided to assist in reaching the payment's destination.
type paymentSession struct {
pruneViewSnapshot graphPruneView
additionalEdges map[Vertex][]*channeldb.ChannelEdgePolicy
mc *missionControl
}
// NewPaymentSession creates a new payment session backed by the latest prune
// view from Mission Control.
func (m *missionControl) NewPaymentSession() *paymentSession {
// view from Mission Control. An optional set of routing hints can be provided
// in order to populate additional edges to explore when finding a path to the
// payment's destination.
func (m *missionControl) NewPaymentSession(routeHints [][]HopHint,
target *btcec.PublicKey) *paymentSession {
viewSnapshot := m.GraphPruneView()
edges := make(map[Vertex][]*channeldb.ChannelEdgePolicy)
// Traverse through all of the available hop hints and include them in
// our edges map, indexed by the public key of the channel's starting
// node.
for _, routeHint := range routeHints {
// If multiple hop hints are provided within a single route
// hint, we'll assume they must be chained together and sorted
// in forward order in order to reach the target successfully.
for i, hopHint := range routeHint {
// In order to determine the end node of this hint,
// we'll need to look at the next hint's start node. If
// we've reached the end of the hints list, we can
// assume we've reached the destination.
endNode := &channeldb.LightningNode{}
if i != len(routeHint)-1 {
endNode.AddPubKey(routeHint[i+1].NodeID)
} else {
endNode.AddPubKey(target)
}
// Finally, create the channel edge from the hop hint
// and add it to list of edges corresponding to the node
// at the start of the channel.
edge := &channeldb.ChannelEdgePolicy{
Node: endNode,
ChannelID: hopHint.ChannelID,
FeeBaseMSat: lnwire.MilliSatoshi(
hopHint.FeeBaseMSat,
),
FeeProportionalMillionths: lnwire.MilliSatoshi(
hopHint.FeeProportionalMillionths,
),
TimeLockDelta: hopHint.CLTVExpiryDelta,
}
v := NewVertex(hopHint.NodeID)
edges[v] = append(edges[v], edge)
}
}
return &paymentSession{
pruneViewSnapshot: viewSnapshot,
additionalEdges: edges,
mc: m,
}
}

@ -1554,7 +1554,9 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, *Route
// Before starting the HTLC routing attempt, we'll create a fresh
// payment session which will report our errors back to mission
// control.
paySession := r.missionControl.NewPaymentSession()
paySession := r.missionControl.NewPaymentSession(
payment.RouteHints, payment.Target,
)
// We'll continue until either our payment succeeds, or we encounter a
// critical error during path finding.