routing/router: add SendToRoute

This commit is contained in:
t4sk 2018-01-30 15:03:29 +07:00 committed by Olaoluwa Osuntokun
parent 6ddd7b4d0d
commit 53eb396ae9

@ -1532,6 +1532,37 @@ 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
@ -1540,6 +1571,46 @@ type LightningPayment struct {
// 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) ([32]byte, *Route, error) { func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, *Route, error) {
// Before starting the HTLC routing attempt, we'll create a fresh
// payment session which will report our errors back to mission
// control.
paySession, err := r.missionControl.NewPaymentSession(
payment.RouteHints, payment.Target,
)
if err != nil {
return [32]byte{}, nil, err
}
return r.sendPayment(payment, paySession)
}
// SendToRoute attempts to send a payment as described within the passed
// LightningPayment through the provided routes. This function is blocking
// and will return either: when the payment is successful, or all routes
// have been attempted and resulted in a failed payment. If the payment
// succeeds, then a non-nil Route will be returned which describes the
// path the successful payment traversed within the network to reach the
// destination. Additionally, the payment preimage will also be returned.
func (r *ChannelRouter) SendToRoute(routes []*Route,
payment *LightningPayment) ([32]byte, *Route, error) {
paySession := &sendToRoutePaymentSession{
routes: routes,
}
return r.sendPayment(payment, paySession)
}
// sendPayment attempts to send a payment as described within the passed
// LightningPayment. This function is blocking and will return either: when the
// payment is successful, or all candidates routes have been attempted and
// resulted in a failed payment. If the payment succeeds, then a non-nil Route
// will be returned which describes the path the successful payment traversed
// within the network to reach the destination. Additionally, the payment
// preimage will also be returned.
func (r *ChannelRouter) sendPayment(payment *LightningPayment,
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 {
// Remove the public key curve parameters when logging // Remove the public key curve parameters when logging
@ -1569,7 +1640,7 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, *Route
// calculate the required HTLC time locks within the route. // calculate the required HTLC time locks within the route.
_, currentHeight, err := r.cfg.Chain.GetBestBlock() _, currentHeight, err := r.cfg.Chain.GetBestBlock()
if err != nil { if err != nil {
return preImage, nil, err return [32]byte{}, nil, err
} }
var finalCLTVDelta uint16 var finalCLTVDelta uint16
@ -1588,17 +1659,6 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, *Route
timeoutChan := time.After(payAttemptTimeout) timeoutChan := time.After(payAttemptTimeout)
// Before starting the HTLC routing attempt, we'll create a fresh
// payment session which will report our errors back to mission
// control.
paySession, err := r.missionControl.NewPaymentSession(
payment.RouteHints, payment.Target,
)
if err != nil {
return preImage, nil, fmt.Errorf("unable to create payment "+
"session: %v", err)
}
// We'll continue until either our payment succeeds, or we encounter a // We'll continue until either our payment succeeds, or we encounter a
// critical error during path finding. // critical error during path finding.
for { for {
@ -1623,10 +1683,6 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, *Route
// are expiring. // are expiring.
} }
// We'll kick things off by requesting a new route from mission
// control, which will incorporate the current best known state
// of the channel graph and our past HTLC routing
// successes/failures.
route, err := paySession.RequestRoute( route, err := paySession.RequestRoute(
payment, uint32(currentHeight), finalCLTVDelta, payment, uint32(currentHeight), finalCLTVDelta,
) )
@ -1904,7 +1960,7 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, *Route
// 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
@ -1930,7 +1986,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