routing: add new NewPaymentSessionFromRoutes function instead of interface
In this commit, we modify the recent refactoring of the mission control sub-system to overload the existing payment session, rather than create a brand new one. This allows us to re-use more of the existing logic, and also feedback into mission control the failures incurred by any user selected routes.
This commit is contained in:
parent
9f183dc08f
commit
0113035f6d
@ -1,6 +1,7 @@
|
|||||||
package routing
|
package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -71,8 +72,7 @@ type missionControl struct {
|
|||||||
// newMissionControl returns a new instance of missionControl.
|
// newMissionControl returns a new instance of missionControl.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef): persist memory
|
// TODO(roasbeef): persist memory
|
||||||
func newMissionControl(
|
func newMissionControl(g *channeldb.ChannelGraph, selfNode *channeldb.LightningNode,
|
||||||
g *channeldb.ChannelGraph, selfNode *channeldb.LightningNode,
|
|
||||||
qb func(*channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi) *missionControl {
|
qb func(*channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi) *missionControl {
|
||||||
|
|
||||||
return &missionControl{
|
return &missionControl{
|
||||||
@ -165,6 +165,9 @@ type paymentSession struct {
|
|||||||
bandwidthHints map[uint64]lnwire.MilliSatoshi
|
bandwidthHints map[uint64]lnwire.MilliSatoshi
|
||||||
|
|
||||||
mc *missionControl
|
mc *missionControl
|
||||||
|
|
||||||
|
haveRoutes bool
|
||||||
|
preBuiltRoutes []*Route
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPaymentSession creates a new payment session backed by the latest prune
|
// NewPaymentSession creates a new payment session backed by the latest prune
|
||||||
@ -240,6 +243,18 @@ func (m *missionControl) NewPaymentSession(routeHints [][]HopHint,
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPaymentSessionFromRoutes creates a new paymentSession instance that will
|
||||||
|
// skip all path finding, and will instead utilize a set of pre-built routes.
|
||||||
|
// This constructor allows callers to specify their own routes which can be
|
||||||
|
// used for things like channel rebalancing, and swaps.
|
||||||
|
func (m *missionControl) NewPaymentSessionFromRoutes(routes []*Route) *paymentSession {
|
||||||
|
return &paymentSession{
|
||||||
|
haveRoutes: true,
|
||||||
|
preBuiltRoutes: routes,
|
||||||
|
mc: m,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// generateBandwidthHints is a helper function that's utilized the main
|
// generateBandwidthHints is a helper function that's utilized the main
|
||||||
// findPath function in order to obtain hints from the lower layer w.r.t to the
|
// findPath function in order to obtain hints from the lower layer w.r.t to the
|
||||||
// available bandwidth of edges on the network. Currently, we'll only obtain
|
// available bandwidth of edges on the network. Currently, we'll only obtain
|
||||||
@ -326,9 +341,25 @@ func (p *paymentSession) ReportChannelFailure(e uint64) {
|
|||||||
func (p *paymentSession) RequestRoute(payment *LightningPayment,
|
func (p *paymentSession) RequestRoute(payment *LightningPayment,
|
||||||
height uint32, finalCltvDelta uint16) (*Route, error) {
|
height uint32, finalCltvDelta uint16) (*Route, error) {
|
||||||
|
|
||||||
// First, we'll obtain our current prune view snapshot. This view will
|
switch {
|
||||||
// only ever grow during the duration of this payment session, never
|
// If we have a set of pre-built routes, then we'll just pop off the
|
||||||
// shrinking.
|
// next route from the queue, and use it directly.
|
||||||
|
case p.haveRoutes && len(p.preBuiltRoutes) > 0:
|
||||||
|
nextRoute := p.preBuiltRoutes[0]
|
||||||
|
p.preBuiltRoutes[0] = nil // Set to nil to avoid GC leak.
|
||||||
|
p.preBuiltRoutes = p.preBuiltRoutes[1:]
|
||||||
|
|
||||||
|
return nextRoute, nil
|
||||||
|
|
||||||
|
// If we were instantiated with a set of pre-built routes, and we've
|
||||||
|
// run out, then we'll return a terminal error.
|
||||||
|
case p.haveRoutes && len(p.preBuiltRoutes) == 0:
|
||||||
|
return nil, fmt.Errorf("pre-built routes exhausted")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we actually need to perform path finding, so we'll obtain
|
||||||
|
// our current prune view snapshot. This view will only ever grow
|
||||||
|
// during the duration of this payment session, never shrinking.
|
||||||
pruneView := p.pruneViewSnapshot
|
pruneView := p.pruneViewSnapshot
|
||||||
|
|
||||||
log.Debugf("Mission Control session using prune view of %v "+
|
log.Debugf("Mission Control session using prune view of %v "+
|
||||||
@ -352,8 +383,9 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment,
|
|||||||
// With the next candidate path found, we'll attempt to turn this into
|
// With the next candidate path found, we'll attempt to turn this into
|
||||||
// a route by applying the time-lock and fee requirements.
|
// a route by applying the time-lock and fee requirements.
|
||||||
sourceVertex := Vertex(p.mc.selfNode.PubKeyBytes)
|
sourceVertex := Vertex(p.mc.selfNode.PubKeyBytes)
|
||||||
route, err := newRoute(payment.Amount, sourceVertex, path, height,
|
route, err := newRoute(
|
||||||
finalCltvDelta)
|
payment.Amount, sourceVertex, path, height, finalCltvDelta,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO(roasbeef): return which edge/vertex didn't work
|
// TODO(roasbeef): return which edge/vertex didn't work
|
||||||
// out
|
// out
|
||||||
|
@ -1532,37 +1532,6 @@ type LightningPayment struct {
|
|||||||
// TODO(roasbeef): add e2e message?
|
// TODO(roasbeef): add e2e message?
|
||||||
}
|
}
|
||||||
|
|
||||||
// PaymentSession imitates paymentSession created from mission control
|
|
||||||
// and enables SendPayment and SendToRoute to call sendPayment.
|
|
||||||
type PaymentSession interface {
|
|
||||||
RequestRoute(payment *LightningPayment, currentHeight uint32,
|
|
||||||
finalCLTVDelta uint16) (*Route, error)
|
|
||||||
|
|
||||||
ReportVertexFailure(Vertex)
|
|
||||||
ReportChannelFailure(chanID uint64)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendToRoutePaymentSession implements PaymentSession.
|
|
||||||
type sendToRoutePaymentSession struct {
|
|
||||||
currentRouteIndex int
|
|
||||||
routes []*Route
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *sendToRoutePaymentSession) RequestRoute(payment *LightningPayment,
|
|
||||||
currentHeight uint32, finalCLTVDelta uint16) (*Route, error) {
|
|
||||||
|
|
||||||
defer func() { s.currentRouteIndex++ }()
|
|
||||||
|
|
||||||
if s.currentRouteIndex < len(s.routes) {
|
|
||||||
return s.routes[s.currentRouteIndex], nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("unable to send payment along any of " +
|
|
||||||
"the given routes")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *sendToRoutePaymentSession) ReportVertexFailure(v Vertex) {}
|
|
||||||
func (s *sendToRoutePaymentSession) ReportChannelFailure(chanID uint64) {}
|
|
||||||
|
|
||||||
// SendPayment attempts to send a payment as described within the passed
|
// SendPayment attempts to send a payment as described within the passed
|
||||||
// LightningPayment. This function is blocking and will return either: when the
|
// LightningPayment. This function is blocking and will return either: when the
|
||||||
// payment is successful, or all candidates routes have been attempted and
|
// payment is successful, or all candidates routes have been attempted and
|
||||||
@ -1594,9 +1563,9 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, *Route
|
|||||||
func (r *ChannelRouter) SendToRoute(routes []*Route,
|
func (r *ChannelRouter) SendToRoute(routes []*Route,
|
||||||
payment *LightningPayment) ([32]byte, *Route, error) {
|
payment *LightningPayment) ([32]byte, *Route, error) {
|
||||||
|
|
||||||
paySession := &sendToRoutePaymentSession{
|
paySession := r.missionControl.NewPaymentSessionFromRoutes(
|
||||||
routes: routes,
|
routes,
|
||||||
}
|
)
|
||||||
|
|
||||||
return r.sendPayment(payment, paySession)
|
return r.sendPayment(payment, paySession)
|
||||||
}
|
}
|
||||||
@ -1609,7 +1578,7 @@ func (r *ChannelRouter) SendToRoute(routes []*Route,
|
|||||||
// within the network to reach the destination. Additionally, the payment
|
// within the network to reach the destination. Additionally, the payment
|
||||||
// preimage will also be returned.
|
// preimage will also be returned.
|
||||||
func (r *ChannelRouter) sendPayment(payment *LightningPayment,
|
func (r *ChannelRouter) sendPayment(payment *LightningPayment,
|
||||||
paySession PaymentSession) ([32]byte, *Route, error) {
|
paySession *paymentSession) ([32]byte, *Route, error) {
|
||||||
|
|
||||||
log.Tracef("Dispatching route for lightning payment: %v",
|
log.Tracef("Dispatching route for lightning payment: %v",
|
||||||
newLogClosure(func() string {
|
newLogClosure(func() string {
|
||||||
@ -1960,7 +1929,7 @@ func (r *ChannelRouter) sendPayment(payment *LightningPayment,
|
|||||||
// pruneVertexFailure will attempt to prune a vertex from the current available
|
// pruneVertexFailure will attempt to prune a vertex from the current available
|
||||||
// vertexes of the target payment session in response to an encountered routing
|
// vertexes of the target payment session in response to an encountered routing
|
||||||
// error.
|
// error.
|
||||||
func pruneVertexFailure(paySession PaymentSession, route *Route,
|
func pruneVertexFailure(paySession *paymentSession, route *Route,
|
||||||
errSource *btcec.PublicKey, nextNode bool) {
|
errSource *btcec.PublicKey, nextNode bool) {
|
||||||
|
|
||||||
// By default, we'll try to prune the node that actually sent us the
|
// By default, we'll try to prune the node that actually sent us the
|
||||||
@ -1986,7 +1955,7 @@ func pruneVertexFailure(paySession PaymentSession, route *Route,
|
|||||||
// pruneEdgeFailure will attempts to prune an edge from the current available
|
// pruneEdgeFailure will attempts to prune an edge from the current available
|
||||||
// edges of the target payment session in response to an encountered routing
|
// edges of the target payment session in response to an encountered routing
|
||||||
// error.
|
// error.
|
||||||
func pruneEdgeFailure(paySession PaymentSession, route *Route,
|
func pruneEdgeFailure(paySession *paymentSession, route *Route,
|
||||||
errSource *btcec.PublicKey) {
|
errSource *btcec.PublicKey) {
|
||||||
|
|
||||||
// As this error indicates that the target channel was unable to carry
|
// As this error indicates that the target channel was unable to carry
|
||||||
|
Loading…
Reference in New Issue
Block a user