Merge pull request #3843 from carlaKC/htlcnotifier-0-switcherrors
[htlcnotifier 1/4]: Introduce Internal Errors
This commit is contained in:
12 files changed
+422
-237
No files matched your search
@@ -35,12 +35,12 @@ func (m *mockPaymentAttemptDispatcher) SendHTLC(firstHop lnwire.ShortChannelID,
|
||||
var result *htlcswitch.PaymentResult
|
||||
preimage, err := m.onPayment(firstHop)
|
||||
if err != nil {
|
||||
fwdErr, ok := err.(*htlcswitch.ForwardingError)
|
||||
rtErr, ok := err.(htlcswitch.ClearTextError)
|
||||
if !ok {
|
||||
return err
|
||||
}
|
||||
result = &htlcswitch.PaymentResult{
|
||||
Error: fwdErr,
|
||||
Error: rtErr,
|
||||
}
|
||||
} else {
|
||||
result = &htlcswitch.PaymentResult{Preimage: preimage}
|
||||
|
||||
+22
-7
@@ -1905,18 +1905,33 @@ func (r *ChannelRouter) processSendError(paymentID uint64, rt *route.Route,
|
||||
|
||||
return reportFail(nil, nil)
|
||||
}
|
||||
// If an internal, non-forwarding error occurred, we can stop
|
||||
// trying.
|
||||
fErr, ok := sendErr.(*htlcswitch.ForwardingError)
|
||||
|
||||
// If the error is a ClearTextError, we have received a valid wire
|
||||
// failure message, either from our own outgoing link or from a node
|
||||
// down the route. If the error is not related to the propagation of
|
||||
// our payment, we can stop trying because an internal error has
|
||||
// occurred.
|
||||
rtErr, ok := sendErr.(htlcswitch.ClearTextError)
|
||||
if !ok {
|
||||
return &internalErrorReason
|
||||
}
|
||||
|
||||
failureMessage := fErr.FailureMessage
|
||||
failureSourceIdx := fErr.FailureSourceIdx
|
||||
// failureSourceIdx is the index of the node that the failure occurred
|
||||
// at. If the ClearTextError received is not a ForwardingError the
|
||||
// payment error occurred at our node, so we leave this value as 0
|
||||
// to indicate that the failure occurred locally. If the error is a
|
||||
// ForwardingError, it did not originate at our node, so we set
|
||||
// failureSourceIdx to the index of the node where the failure occurred.
|
||||
failureSourceIdx := 0
|
||||
source, ok := rtErr.(*htlcswitch.ForwardingError)
|
||||
if ok {
|
||||
failureSourceIdx = source.FailureSourceIdx
|
||||
}
|
||||
|
||||
// Apply channel update if the error contains one. For unknown
|
||||
// failures, failureMessage is nil.
|
||||
// Extract the wire failure and apply channel update if it contains one.
|
||||
// If we received an unknown failure message from a node along the
|
||||
// route, the failure message will be nil.
|
||||
failureMessage := rtErr.WireMessage()
|
||||
if failureMessage != nil {
|
||||
err := r.tryApplyChannelUpdate(
|
||||
rt, failureSourceIdx, failureMessage,
|
||||
|
||||
+57
-61
@@ -288,11 +288,12 @@ func TestSendPaymentRouteFailureFallback(t *testing.T) {
|
||||
|
||||
roasbeefSongoku := lnwire.NewShortChanIDFromInt(12345)
|
||||
if firstHop == roasbeefSongoku {
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
// TODO(roasbeef): temp node failure should be?
|
||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||
}
|
||||
return [32]byte{}, htlcswitch.NewForwardingError(
|
||||
// TODO(roasbeef): temp node failure
|
||||
// should be?
|
||||
&lnwire.FailTemporaryChannelFailure{},
|
||||
1,
|
||||
)
|
||||
}
|
||||
|
||||
return preImage, nil
|
||||
@@ -420,12 +421,12 @@ func TestChannelUpdateValidation(t *testing.T) {
|
||||
// The unsigned channel update is attached to the failure message.
|
||||
ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcher).setPaymentResult(
|
||||
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
FailureMessage: &lnwire.FailFeeInsufficient{
|
||||
return [32]byte{}, htlcswitch.NewForwardingError(
|
||||
&lnwire.FailFeeInsufficient{
|
||||
Update: errChanUpdate,
|
||||
},
|
||||
}
|
||||
1,
|
||||
)
|
||||
})
|
||||
|
||||
// The payment parameter is mostly redundant in SendToRoute. Can be left
|
||||
@@ -542,16 +543,15 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
|
||||
|
||||
roasbeefSongoku := lnwire.NewShortChanIDFromInt(chanID)
|
||||
if firstHop == roasbeefSongoku {
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
|
||||
// Within our error, we'll add a channel update
|
||||
// which is meant to reflect he new fee
|
||||
// schedule for the node/channel.
|
||||
FailureMessage: &lnwire.FailFeeInsufficient{
|
||||
return [32]byte{}, htlcswitch.NewForwardingError(
|
||||
// Within our error, we'll add a
|
||||
// channel update which is meant to
|
||||
// reflect the new fee schedule for the
|
||||
// node/channel.
|
||||
&lnwire.FailFeeInsufficient{
|
||||
Update: errChanUpdate,
|
||||
},
|
||||
}
|
||||
}, 1,
|
||||
)
|
||||
}
|
||||
|
||||
return preImage, nil
|
||||
@@ -646,12 +646,11 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
|
||||
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
||||
|
||||
if firstHop == roasbeefSongoku {
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
FailureMessage: &lnwire.FailExpiryTooSoon{
|
||||
return [32]byte{}, htlcswitch.NewForwardingError(
|
||||
&lnwire.FailExpiryTooSoon{
|
||||
Update: errChanUpdate,
|
||||
},
|
||||
}
|
||||
}, 1,
|
||||
)
|
||||
}
|
||||
|
||||
return preImage, nil
|
||||
@@ -700,12 +699,11 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
|
||||
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
||||
|
||||
if firstHop == roasbeefSongoku {
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
FailureMessage: &lnwire.FailIncorrectCltvExpiry{
|
||||
return [32]byte{}, htlcswitch.NewForwardingError(
|
||||
&lnwire.FailIncorrectCltvExpiry{
|
||||
Update: errChanUpdate,
|
||||
},
|
||||
}
|
||||
}, 1,
|
||||
)
|
||||
}
|
||||
|
||||
return preImage, nil
|
||||
@@ -763,20 +761,19 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
||||
// We'll first simulate an error from the first
|
||||
// hop to simulate the channel from songoku to
|
||||
// sophon not having enough capacity.
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||
}
|
||||
return [32]byte{}, htlcswitch.NewForwardingError(
|
||||
&lnwire.FailTemporaryChannelFailure{},
|
||||
1,
|
||||
)
|
||||
}
|
||||
|
||||
// Next, we'll create an error from phan nuwen to
|
||||
// indicate that the sophon node is not longer online,
|
||||
// which should prune out the rest of the routes.
|
||||
if firstHop == roasbeefPhanNuwen {
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
||||
}
|
||||
return [32]byte{}, htlcswitch.NewForwardingError(
|
||||
&lnwire.FailUnknownNextPeer{}, 1,
|
||||
)
|
||||
}
|
||||
|
||||
return preImage, nil
|
||||
@@ -805,10 +802,10 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
||||
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
||||
|
||||
if firstHop == roasbeefSongoku {
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
||||
}
|
||||
failure := htlcswitch.NewForwardingError(
|
||||
&lnwire.FailUnknownNextPeer{}, 1,
|
||||
)
|
||||
return [32]byte{}, failure
|
||||
}
|
||||
|
||||
return preImage, nil
|
||||
@@ -851,10 +848,10 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
||||
// We'll first simulate an error from the first
|
||||
// outgoing link to simulate the channel from luo ji to
|
||||
// roasbeef not having enough capacity.
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||
}
|
||||
return [32]byte{}, htlcswitch.NewForwardingError(
|
||||
&lnwire.FailTemporaryChannelFailure{},
|
||||
1,
|
||||
)
|
||||
}
|
||||
return preImage, nil
|
||||
})
|
||||
@@ -2539,9 +2536,7 @@ func TestUnknownErrorSource(t *testing.T) {
|
||||
// couldn't be decoded (FailureMessage is nil).
|
||||
if firstHop.ToUint64() == 2 {
|
||||
return [32]byte{},
|
||||
&htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
}
|
||||
htlcswitch.NewUnknownForwardingError(1)
|
||||
}
|
||||
|
||||
// Otherwise the payment succeeds.
|
||||
@@ -3105,10 +3100,10 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
||||
// called, and we respond with a forwarding error
|
||||
case sendToSwitchResultFailure:
|
||||
select {
|
||||
case sendResult <- &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||
}:
|
||||
case sendResult <- htlcswitch.NewForwardingError(
|
||||
&lnwire.FailTemporaryChannelFailure{},
|
||||
1,
|
||||
):
|
||||
case <-time.After(1 * time.Second):
|
||||
t.Fatalf("unable to send result")
|
||||
}
|
||||
@@ -3129,12 +3124,14 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
||||
// to be called, and we respond with a forwarding
|
||||
// error, indicating that the router should retry.
|
||||
case getPaymentResultFailure:
|
||||
failure := htlcswitch.NewForwardingError(
|
||||
&lnwire.FailTemporaryChannelFailure{},
|
||||
1,
|
||||
)
|
||||
|
||||
select {
|
||||
case getPaymentResult <- &htlcswitch.PaymentResult{
|
||||
Error: &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||
},
|
||||
Error: failure,
|
||||
}:
|
||||
case <-time.After(1 * time.Second):
|
||||
t.Fatalf("unable to get result")
|
||||
@@ -3302,12 +3299,11 @@ func TestSendToRouteStructuredError(t *testing.T) {
|
||||
// The unsigned channel update is attached to the failure message.
|
||||
ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcher).setPaymentResult(
|
||||
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
FailureSourceIdx: 1,
|
||||
FailureMessage: &lnwire.FailFeeInsufficient{
|
||||
return [32]byte{}, htlcswitch.NewForwardingError(
|
||||
&lnwire.FailFeeInsufficient{
|
||||
Update: lnwire.ChannelUpdate{},
|
||||
},
|
||||
}
|
||||
}, 1,
|
||||
)
|
||||
})
|
||||
|
||||
// The payment parameter is mostly redundant in SendToRoute. Can be left
|
||||
@@ -3324,7 +3320,7 @@ func TestSendToRouteStructuredError(t *testing.T) {
|
||||
t.Fatalf("expected forwarding error")
|
||||
}
|
||||
|
||||
if _, ok := fErr.FailureMessage.(*lnwire.FailFeeInsufficient); !ok {
|
||||
if _, ok := fErr.WireMessage().(*lnwire.FailFeeInsufficient); !ok {
|
||||
t.Fatalf("expected fee insufficient error")
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user