routing: report failures to mission control directly
As there is no more state kept in the payment session, failure reporting can go straight to mission control.
This commit is contained in:
parent
dc13da5abb
commit
8055bcf2e0
@ -343,7 +343,7 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID,
|
|||||||
func (p *paymentLifecycle) handleSendError(sendErr error) error {
|
func (p *paymentLifecycle) handleSendError(sendErr error) error {
|
||||||
|
|
||||||
final, reason := p.router.processSendError(
|
final, reason := p.router.processSendError(
|
||||||
p.paySession, &p.attempt.Route, sendErr,
|
&p.attempt.Route, sendErr,
|
||||||
)
|
)
|
||||||
if !final {
|
if !final {
|
||||||
// Save the forwarding error so it can be returned if
|
// Save the forwarding error so it can be returned if
|
||||||
|
@ -16,27 +16,6 @@ type PaymentSession interface {
|
|||||||
// specified HTLC payment to the target node.
|
// specified HTLC payment to the target node.
|
||||||
RequestRoute(payment *LightningPayment,
|
RequestRoute(payment *LightningPayment,
|
||||||
height uint32, finalCltvDelta uint16) (*route.Route, error)
|
height uint32, finalCltvDelta uint16) (*route.Route, error)
|
||||||
|
|
||||||
// ReportVertexFailure reports to the PaymentSession that the passsed
|
|
||||||
// vertex failed to route the previous payment attempt. The
|
|
||||||
// PaymentSession will use this information to produce a better next
|
|
||||||
// route.
|
|
||||||
ReportVertexFailure(v route.Vertex)
|
|
||||||
|
|
||||||
// ReportEdgeFailure reports to the PaymentSession that the passed edge
|
|
||||||
// failed to route the previous payment attempt. A minimum penalization
|
|
||||||
// amount is included to attenuate the failure. This is set to a
|
|
||||||
// non-zero value for channel balance failures. The PaymentSession will
|
|
||||||
// use this information to produce a better next route.
|
|
||||||
ReportEdgeFailure(failedEdge edge, minPenalizeAmt lnwire.MilliSatoshi)
|
|
||||||
|
|
||||||
// ReportEdgePolicyFailure reports to the PaymentSession that we
|
|
||||||
// received a failure message that relates to a channel policy. For
|
|
||||||
// these types of failures, the PaymentSession can decide whether to to
|
|
||||||
// keep the edge included in the next attempted route. The
|
|
||||||
// PaymentSession will use this information to produce a better next
|
|
||||||
// route.
|
|
||||||
ReportEdgePolicyFailure(failedEdge edge)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// paymentSession is used during an HTLC routings session to prune the local
|
// paymentSession is used during an HTLC routings session to prune the local
|
||||||
@ -60,52 +39,6 @@ type paymentSession struct {
|
|||||||
pathFinder pathFinder
|
pathFinder pathFinder
|
||||||
}
|
}
|
||||||
|
|
||||||
// A compile time assertion to ensure paymentSession meets the PaymentSession
|
|
||||||
// interface.
|
|
||||||
var _ PaymentSession = (*paymentSession)(nil)
|
|
||||||
|
|
||||||
// ReportVertexFailure adds a vertex to the graph prune view after a client
|
|
||||||
// reports a routing failure localized to the vertex. The time the vertex was
|
|
||||||
// added is noted, as it'll be pruned from the shared view after a period of
|
|
||||||
// vertexDecay. However, the vertex will remain pruned for the *local* session.
|
|
||||||
// This ensures we don't retry this vertex during the payment attempt.
|
|
||||||
//
|
|
||||||
// NOTE: Part of the PaymentSession interface.
|
|
||||||
func (p *paymentSession) ReportVertexFailure(v route.Vertex) {
|
|
||||||
p.sessionSource.MissionControl.ReportVertexFailure(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReportEdgeFailure adds a channel to the graph prune view. The time the
|
|
||||||
// channel was added is noted, as it'll be pruned from the global view after a
|
|
||||||
// period of edgeDecay. However, the edge will remain pruned for the duration
|
|
||||||
// of the *local* session. This ensures that we don't flap by continually
|
|
||||||
// retrying an edge after its pruning has expired.
|
|
||||||
//
|
|
||||||
// TODO(roasbeef): also add value attempted to send and capacity of channel
|
|
||||||
//
|
|
||||||
// NOTE: Part of the PaymentSession interface.
|
|
||||||
func (p *paymentSession) ReportEdgeFailure(failedEdge edge,
|
|
||||||
minPenalizeAmt lnwire.MilliSatoshi) {
|
|
||||||
|
|
||||||
p.sessionSource.MissionControl.ReportEdgeFailure(
|
|
||||||
failedEdge, minPenalizeAmt,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReportEdgePolicyFailure handles a failure message that relates to a
|
|
||||||
// channel policy. For these types of failures, the policy is updated and we
|
|
||||||
// want to keep it included during path finding. This function does mark the
|
|
||||||
// edge as 'policy failed once'. The next time it fails, the whole node will be
|
|
||||||
// pruned. This is to prevent nodes from keeping us busy by continuously sending
|
|
||||||
// new channel updates.
|
|
||||||
//
|
|
||||||
// NOTE: Part of the PaymentSession interface.
|
|
||||||
//
|
|
||||||
// TODO(joostjager): Move this logic into global mission control.
|
|
||||||
func (p *paymentSession) ReportEdgePolicyFailure(failedEdge edge) {
|
|
||||||
p.sessionSource.MissionControl.ReportEdgePolicyFailure(failedEdge)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RequestRoute returns a route which is likely to be capable for successfully
|
// RequestRoute returns a route which is likely to be capable for successfully
|
||||||
// routing the specified HTLC payment to the target node. Initially the first
|
// routing the specified HTLC payment to the target node. Initially the first
|
||||||
// set of paths returned from this method may encounter routing failure along
|
// set of paths returned from this method may encounter routing failure along
|
||||||
|
@ -1875,8 +1875,8 @@ func (r *ChannelRouter) tryApplyChannelUpdate(rt *route.Route,
|
|||||||
// error type, this error is either the final outcome of the payment or we need
|
// error type, this error is either the final outcome of the payment or we need
|
||||||
// to continue with an alternative route. This is indicated by the boolean
|
// to continue with an alternative route. This is indicated by the boolean
|
||||||
// return value.
|
// return value.
|
||||||
func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
func (r *ChannelRouter) processSendError(rt *route.Route, sendErr error) (
|
||||||
rt *route.Route, sendErr error) (bool, channeldb.FailureReason) {
|
bool, channeldb.FailureReason) {
|
||||||
|
|
||||||
// If the failure message could not be decrypted, attribute the failure
|
// If the failure message could not be decrypted, attribute the failure
|
||||||
// to our own outgoing channel.
|
// to our own outgoing channel.
|
||||||
@ -1981,7 +1981,7 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// that sent us this error, as it doesn't now what the
|
// that sent us this error, as it doesn't now what the
|
||||||
// correct block height is.
|
// correct block height is.
|
||||||
case *lnwire.FailExpiryTooSoon:
|
case *lnwire.FailExpiryTooSoon:
|
||||||
paySession.ReportVertexFailure(failureVertex)
|
r.cfg.MissionControl.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If we hit an instance of onion payload corruption or an invalid
|
// If we hit an instance of onion payload corruption or an invalid
|
||||||
@ -2001,49 +2001,49 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// amount, we'll apply the new minimum amount and retry
|
// amount, we'll apply the new minimum amount and retry
|
||||||
// routing.
|
// routing.
|
||||||
case *lnwire.FailAmountBelowMinimum:
|
case *lnwire.FailAmountBelowMinimum:
|
||||||
paySession.ReportEdgePolicyFailure(failedEdge)
|
r.cfg.MissionControl.ReportEdgePolicyFailure(failedEdge)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If we get a failure due to a fee, we'll apply the
|
// If we get a failure due to a fee, we'll apply the
|
||||||
// new fee update, and retry our attempt using the
|
// new fee update, and retry our attempt using the
|
||||||
// newly updated fees.
|
// newly updated fees.
|
||||||
case *lnwire.FailFeeInsufficient:
|
case *lnwire.FailFeeInsufficient:
|
||||||
paySession.ReportEdgePolicyFailure(failedEdge)
|
r.cfg.MissionControl.ReportEdgePolicyFailure(failedEdge)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If we get the failure for an intermediate node that
|
// If we get the failure for an intermediate node that
|
||||||
// disagrees with our time lock values, then we'll
|
// disagrees with our time lock values, then we'll
|
||||||
// apply the new delta value and try it once more.
|
// apply the new delta value and try it once more.
|
||||||
case *lnwire.FailIncorrectCltvExpiry:
|
case *lnwire.FailIncorrectCltvExpiry:
|
||||||
paySession.ReportEdgePolicyFailure(failedEdge)
|
r.cfg.MissionControl.ReportEdgePolicyFailure(failedEdge)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// The outgoing channel that this node was meant to
|
// The outgoing channel that this node was meant to
|
||||||
// forward one is currently disabled, so we'll apply
|
// forward one is currently disabled, so we'll apply
|
||||||
// the update and continue.
|
// the update and continue.
|
||||||
case *lnwire.FailChannelDisabled:
|
case *lnwire.FailChannelDisabled:
|
||||||
paySession.ReportEdgeFailure(failedEdge, 0)
|
r.cfg.MissionControl.ReportEdgeFailure(failedEdge, 0)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// It's likely that the outgoing channel didn't have
|
// It's likely that the outgoing channel didn't have
|
||||||
// sufficient capacity, so we'll prune this edge for
|
// sufficient capacity, so we'll prune this edge for
|
||||||
// now, and continue onwards with our path finding.
|
// now, and continue onwards with our path finding.
|
||||||
case *lnwire.FailTemporaryChannelFailure:
|
case *lnwire.FailTemporaryChannelFailure:
|
||||||
paySession.ReportEdgeFailure(failedEdge, failedAmt)
|
r.cfg.MissionControl.ReportEdgeFailure(failedEdge, failedAmt)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If the send fail due to a node not having the
|
// If the send fail due to a node not having the
|
||||||
// required features, then we'll note this error and
|
// required features, then we'll note this error and
|
||||||
// continue.
|
// continue.
|
||||||
case *lnwire.FailRequiredNodeFeatureMissing:
|
case *lnwire.FailRequiredNodeFeatureMissing:
|
||||||
paySession.ReportVertexFailure(failureVertex)
|
r.cfg.MissionControl.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If the send fail due to a node not having the
|
// If the send fail due to a node not having the
|
||||||
// required features, then we'll note this error and
|
// required features, then we'll note this error and
|
||||||
// continue.
|
// continue.
|
||||||
case *lnwire.FailRequiredChannelFeatureMissing:
|
case *lnwire.FailRequiredChannelFeatureMissing:
|
||||||
paySession.ReportVertexFailure(failureVertex)
|
r.cfg.MissionControl.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If the next hop in the route wasn't known or
|
// If the next hop in the route wasn't known or
|
||||||
@ -2054,18 +2054,18 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// returning errors in order to attempt to black list
|
// returning errors in order to attempt to black list
|
||||||
// another node.
|
// another node.
|
||||||
case *lnwire.FailUnknownNextPeer:
|
case *lnwire.FailUnknownNextPeer:
|
||||||
paySession.ReportEdgeFailure(failedEdge, 0)
|
r.cfg.MissionControl.ReportEdgeFailure(failedEdge, 0)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If the node wasn't able to forward for which ever
|
// If the node wasn't able to forward for which ever
|
||||||
// reason, then we'll note this and continue with the
|
// reason, then we'll note this and continue with the
|
||||||
// routes.
|
// routes.
|
||||||
case *lnwire.FailTemporaryNodeFailure:
|
case *lnwire.FailTemporaryNodeFailure:
|
||||||
paySession.ReportVertexFailure(failureVertex)
|
r.cfg.MissionControl.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
case *lnwire.FailPermanentNodeFailure:
|
case *lnwire.FailPermanentNodeFailure:
|
||||||
paySession.ReportVertexFailure(failureVertex)
|
r.cfg.MissionControl.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If we crafted a route that contains a too long time
|
// If we crafted a route that contains a too long time
|
||||||
@ -2078,15 +2078,15 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// that as a hint during future path finding through
|
// that as a hint during future path finding through
|
||||||
// that node.
|
// that node.
|
||||||
case *lnwire.FailExpiryTooFar:
|
case *lnwire.FailExpiryTooFar:
|
||||||
paySession.ReportVertexFailure(failureVertex)
|
r.cfg.MissionControl.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If we get a permanent channel or node failure, then
|
// If we get a permanent channel or node failure, then
|
||||||
// we'll prune the channel in both directions and
|
// we'll prune the channel in both directions and
|
||||||
// continue with the rest of the routes.
|
// continue with the rest of the routes.
|
||||||
case *lnwire.FailPermanentChannelFailure:
|
case *lnwire.FailPermanentChannelFailure:
|
||||||
paySession.ReportEdgeFailure(failedEdge, 0)
|
r.cfg.MissionControl.ReportEdgeFailure(failedEdge, 0)
|
||||||
paySession.ReportEdgeFailure(edge{
|
r.cfg.MissionControl.ReportEdgeFailure(edge{
|
||||||
from: failedEdge.to,
|
from: failedEdge.to,
|
||||||
to: failedEdge.from,
|
to: failedEdge.from,
|
||||||
channel: failedEdge.channel,
|
channel: failedEdge.channel,
|
||||||
@ -2095,7 +2095,7 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
|
|
||||||
// Any other failure or an empty failure will get the node pruned.
|
// Any other failure or an empty failure will get the node pruned.
|
||||||
default:
|
default:
|
||||||
paySession.ReportVertexFailure(failureVertex)
|
r.cfg.MissionControl.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user