routing: define payment result
This commit groups together all payment result data. It is a preparation for historical payment results being retrieved from the database.
This commit is contained in:
parent
1507ff6590
commit
9e26f0d079
@ -147,6 +147,17 @@ type MissionControlChannelSnapshot struct {
|
|||||||
SuccessProb float64
|
SuccessProb float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// paymentResult is the information that becomes available when a payment
|
||||||
|
// attempt completes.
|
||||||
|
type paymentResult struct {
|
||||||
|
id uint64
|
||||||
|
timeFwd, timeReply time.Time
|
||||||
|
route *route.Route
|
||||||
|
success bool
|
||||||
|
failureSourceIdx *int
|
||||||
|
failure lnwire.FailureMessage
|
||||||
|
}
|
||||||
|
|
||||||
// NewMissionControl returns a new instance of missionControl.
|
// NewMissionControl returns a new instance of missionControl.
|
||||||
func NewMissionControl(cfg *MissionControlConfig) *MissionControl {
|
func NewMissionControl(cfg *MissionControlConfig) *MissionControl {
|
||||||
log.Debugf("Instantiating mission control with config: "+
|
log.Debugf("Instantiating mission control with config: "+
|
||||||
@ -399,25 +410,33 @@ func (m *MissionControl) ReportPaymentFail(paymentID uint64, rt *route.Route,
|
|||||||
|
|
||||||
timestamp := m.now()
|
timestamp := m.now()
|
||||||
|
|
||||||
|
// TODO(joostjager): Use actual payment initiation time for timeFwd.
|
||||||
|
result := &paymentResult{
|
||||||
|
success: false,
|
||||||
|
timeFwd: timestamp,
|
||||||
|
timeReply: timestamp,
|
||||||
|
id: paymentID,
|
||||||
|
failureSourceIdx: failureSourceIdx,
|
||||||
|
failure: failure,
|
||||||
|
route: rt,
|
||||||
|
}
|
||||||
|
|
||||||
// Apply result to update mission control state.
|
// Apply result to update mission control state.
|
||||||
return m.applyPaymentResult(
|
return m.applyPaymentResult(result)
|
||||||
timestamp, paymentID, rt, failureSourceIdx, failure,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyPaymentResult applies a payment result as input for future probability
|
// applyPaymentResult applies a payment result as input for future probability
|
||||||
// estimates. It returns a bool indicating whether this error is a final error
|
// estimates. It returns a bool indicating whether this error is a final error
|
||||||
// and no further payment attempts need to be made.
|
// and no further payment attempts need to be made.
|
||||||
func (m *MissionControl) applyPaymentResult(timeReply time.Time,
|
func (m *MissionControl) applyPaymentResult(result *paymentResult) (
|
||||||
paymentID uint64, rt *route.Route, failureSourceIdx *int,
|
bool, channeldb.FailureReason) {
|
||||||
failureMessage lnwire.FailureMessage) (bool, channeldb.FailureReason) {
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
failureSourceIdxInt int
|
failureSourceIdxInt int
|
||||||
failure lnwire.FailureMessage
|
failure lnwire.FailureMessage
|
||||||
)
|
)
|
||||||
|
|
||||||
if failureSourceIdx == nil {
|
if result.failureSourceIdx == nil {
|
||||||
// If the failure message could not be decrypted, attribute the
|
// If the failure message could not be decrypted, attribute the
|
||||||
// failure to our own outgoing channel.
|
// failure to our own outgoing channel.
|
||||||
//
|
//
|
||||||
@ -425,24 +444,24 @@ func (m *MissionControl) applyPaymentResult(timeReply time.Time,
|
|||||||
failureSourceIdxInt = 0
|
failureSourceIdxInt = 0
|
||||||
failure = lnwire.NewTemporaryChannelFailure(nil)
|
failure = lnwire.NewTemporaryChannelFailure(nil)
|
||||||
} else {
|
} else {
|
||||||
failureSourceIdxInt = *failureSourceIdx
|
failureSourceIdxInt = *result.failureSourceIdx
|
||||||
failure = failureMessage
|
failure = result.failure
|
||||||
}
|
}
|
||||||
|
|
||||||
var failureVertex route.Vertex
|
var failureVertex route.Vertex
|
||||||
|
|
||||||
if failureSourceIdxInt > 0 {
|
if failureSourceIdxInt > 0 {
|
||||||
failureVertex = rt.Hops[failureSourceIdxInt-1].PubKeyBytes
|
failureVertex = result.route.Hops[failureSourceIdxInt-1].PubKeyBytes
|
||||||
} else {
|
} else {
|
||||||
failureVertex = rt.SourcePubKey
|
failureVertex = result.route.SourcePubKey
|
||||||
}
|
}
|
||||||
log.Tracef("Node %x (index %v) reported failure when sending htlc",
|
log.Tracef("Node %x (index %v) reported failure when sending htlc",
|
||||||
failureVertex, failureSourceIdx)
|
failureVertex, result.failureSourceIdx)
|
||||||
|
|
||||||
// Always determine chan id ourselves, because a channel update with id
|
// Always determine chan id ourselves, because a channel update with id
|
||||||
// may not be available.
|
// may not be available.
|
||||||
failedEdge, failedAmt := getFailedEdge(
|
failedEdge, failedAmt := getFailedEdge(
|
||||||
rt, failureSourceIdxInt,
|
result.route, failureSourceIdxInt,
|
||||||
)
|
)
|
||||||
|
|
||||||
switch failure.(type) {
|
switch failure.(type) {
|
||||||
@ -501,7 +520,7 @@ func (m *MissionControl) applyPaymentResult(timeReply time.Time,
|
|||||||
// 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:
|
||||||
m.reportVertexFailure(timeReply, failureVertex)
|
m.reportVertexFailure(result.timeReply, 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
|
||||||
@ -521,49 +540,49 @@ func (m *MissionControl) applyPaymentResult(timeReply time.Time,
|
|||||||
// 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:
|
||||||
m.reportEdgePolicyFailure(timeReply, failedEdge)
|
m.reportEdgePolicyFailure(result.timeReply, 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:
|
||||||
m.reportEdgePolicyFailure(timeReply, failedEdge)
|
m.reportEdgePolicyFailure(result.timeReply, 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:
|
||||||
m.reportEdgePolicyFailure(timeReply, failedEdge)
|
m.reportEdgePolicyFailure(result.timeReply, 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:
|
||||||
m.reportEdgeFailure(timeReply, failedEdge, 0)
|
m.reportEdgeFailure(result.timeReply, 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:
|
||||||
m.reportEdgeFailure(timeReply, failedEdge, failedAmt)
|
m.reportEdgeFailure(result.timeReply, 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:
|
||||||
m.reportVertexFailure(timeReply, failureVertex)
|
m.reportVertexFailure(result.timeReply, 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:
|
||||||
m.reportVertexFailure(timeReply, failureVertex)
|
m.reportVertexFailure(result.timeReply, 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
|
||||||
@ -574,18 +593,18 @@ func (m *MissionControl) applyPaymentResult(timeReply time.Time,
|
|||||||
// 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:
|
||||||
m.reportEdgeFailure(timeReply, failedEdge, 0)
|
m.reportEdgeFailure(result.timeReply, 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:
|
||||||
m.reportVertexFailure(timeReply, failureVertex)
|
m.reportVertexFailure(result.timeReply, failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
case *lnwire.FailPermanentNodeFailure:
|
case *lnwire.FailPermanentNodeFailure:
|
||||||
m.reportVertexFailure(timeReply, failureVertex)
|
m.reportVertexFailure(result.timeReply, 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
|
||||||
@ -598,15 +617,15 @@ func (m *MissionControl) applyPaymentResult(timeReply time.Time,
|
|||||||
// 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:
|
||||||
m.reportVertexFailure(timeReply, failureVertex)
|
m.reportVertexFailure(result.timeReply, 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:
|
||||||
m.reportEdgeFailure(timeReply, failedEdge, 0)
|
m.reportEdgeFailure(result.timeReply, failedEdge, 0)
|
||||||
m.reportEdgeFailure(timeReply, edge{
|
m.reportEdgeFailure(result.timeReply, edge{
|
||||||
from: failedEdge.to,
|
from: failedEdge.to,
|
||||||
to: failedEdge.from,
|
to: failedEdge.from,
|
||||||
channel: failedEdge.channel,
|
channel: failedEdge.channel,
|
||||||
@ -615,7 +634,7 @@ func (m *MissionControl) applyPaymentResult(timeReply time.Time,
|
|||||||
|
|
||||||
// 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:
|
||||||
m.reportVertexFailure(timeReply, failureVertex)
|
m.reportVertexFailure(result.timeReply, failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user