mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 09:53:54 +01:00
87a486f1f9
This allows Switch-initiated payments to be failed back if they don't make it into a commitment. Prior to this commit, a Switch-initiated HTLC could get "lost" meaning the circuit wouldn't get deleted except if conditions were "right" and the network result store would never be made aware of the HTLC's fate. Switch-initiated HTLC's are now passed to the link's mailbox to ensure they can be failed back. This change also special-cases the ErrDuplicateKeystone error from OpenCircuits(...) so that callers of updateCommitTx() in the link don't send an Error to the peer if they encounter the keystone error. With the first async change, the keystone error should now always be recoverable.
133 lines
3.8 KiB
Go
133 lines
3.8 KiB
Go
package htlcswitch
|
|
|
|
import "github.com/go-errors/errors"
|
|
|
|
var (
|
|
// ErrLinkShuttingDown signals that the link is shutting down.
|
|
ErrLinkShuttingDown = errors.New("link shutting down")
|
|
|
|
// ErrLinkFailedShutdown signals that a requested shutdown failed.
|
|
ErrLinkFailedShutdown = errors.New("link failed to shutdown")
|
|
)
|
|
|
|
// errorCode encodes the possible types of errors that will make us fail the
|
|
// current link.
|
|
type errorCode uint8
|
|
|
|
const (
|
|
// ErrInternalError indicates that something internal in the link
|
|
// failed. In this case we will send a generic error to our peer.
|
|
ErrInternalError errorCode = iota
|
|
|
|
// ErrRemoteError indicates that our peer sent an error, prompting up
|
|
// to fail the link.
|
|
ErrRemoteError
|
|
|
|
// ErrRemoteUnresponsive indicates that our peer took too long to
|
|
// complete a commitment dance.
|
|
ErrRemoteUnresponsive
|
|
|
|
// ErrSyncError indicates that we failed synchronizing the state of the
|
|
// channel with our peer.
|
|
ErrSyncError
|
|
|
|
// ErrInvalidUpdate indicates that the peer send us an invalid update.
|
|
ErrInvalidUpdate
|
|
|
|
// ErrInvalidCommitment indicates that the remote peer sent us an
|
|
// invalid commitment signature.
|
|
ErrInvalidCommitment
|
|
|
|
// ErrInvalidRevocation indicates that the remote peer send us an
|
|
// invalid revocation message.
|
|
ErrInvalidRevocation
|
|
|
|
// ErrRecoveryError the channel was unable to be resumed, we need the
|
|
// remote party to force close the channel out on chain now as a
|
|
// result.
|
|
ErrRecoveryError
|
|
|
|
// ErrCircuitError indicates a duplicate keystone error was hit in the
|
|
// circuit map. This is non-fatal and will resolve itself (usually
|
|
// within several minutes).
|
|
ErrCircuitError
|
|
)
|
|
|
|
// LinkFailureError encapsulates an error that will make us fail the current
|
|
// link. It contains the necessary information needed to determine if we should
|
|
// force close the channel in the process, and if any error data should be sent
|
|
// to the peer.
|
|
type LinkFailureError struct {
|
|
// code is the type of error this LinkFailureError encapsulates.
|
|
code errorCode
|
|
|
|
// ForceClose indicates whether we should force close the channel
|
|
// because of this error.
|
|
ForceClose bool
|
|
|
|
// PermanentFailure indicates whether this failure is permanent, and
|
|
// the channel should not be attempted loaded again.
|
|
PermanentFailure bool
|
|
|
|
// SendData is a byte slice that will be sent to the peer. If nil a
|
|
// generic error will be sent.
|
|
SendData []byte
|
|
}
|
|
|
|
// A compile time check to ensure LinkFailureError implements the error
|
|
// interface.
|
|
var _ error = (*LinkFailureError)(nil)
|
|
|
|
// Error returns a generic error for the LinkFailureError.
|
|
//
|
|
// NOTE: Part of the error interface.
|
|
func (e LinkFailureError) Error() string {
|
|
switch e.code {
|
|
case ErrInternalError:
|
|
return "internal error"
|
|
case ErrRemoteError:
|
|
return "remote error"
|
|
case ErrRemoteUnresponsive:
|
|
return "remote unresponsive"
|
|
case ErrSyncError:
|
|
return "sync error"
|
|
case ErrInvalidUpdate:
|
|
return "invalid update"
|
|
case ErrInvalidCommitment:
|
|
return "invalid commitment"
|
|
case ErrInvalidRevocation:
|
|
return "invalid revocation"
|
|
case ErrRecoveryError:
|
|
return "unable to resume channel, recovery required"
|
|
case ErrCircuitError:
|
|
return "non-fatal circuit map error"
|
|
default:
|
|
return "unknown error"
|
|
}
|
|
}
|
|
|
|
// ShouldSendToPeer indicates whether we should send an error to the peer if
|
|
// the link fails with this LinkFailureError.
|
|
func (e LinkFailureError) ShouldSendToPeer() bool {
|
|
switch e.code {
|
|
|
|
// Since sending an error can lead some nodes to force close the
|
|
// channel, create a whitelist of the failures we want to send so that
|
|
// newly added error codes aren't automatically sent to the remote peer.
|
|
case
|
|
ErrInternalError,
|
|
ErrRemoteError,
|
|
ErrSyncError,
|
|
ErrInvalidUpdate,
|
|
ErrInvalidCommitment,
|
|
ErrInvalidRevocation,
|
|
ErrRecoveryError:
|
|
|
|
return true
|
|
|
|
// In all other cases we will not attempt to send our peer an error.
|
|
default:
|
|
return false
|
|
}
|
|
}
|