/ htlcswitch / linkfailure.go
linkfailure.go
  1  package htlcswitch
  2  
  3  import "errors"
  4  
  5  var (
  6  	// ErrLinkShuttingDown signals that the link is shutting down.
  7  	ErrLinkShuttingDown = errors.New("link shutting down")
  8  
  9  	// ErrLinkFailedShutdown signals that a requested shutdown failed.
 10  	ErrLinkFailedShutdown = errors.New("link failed to shutdown")
 11  )
 12  
 13  // errorCode encodes the possible types of errors that will make us fail the
 14  // current link.
 15  type errorCode uint8
 16  
 17  const (
 18  	// ErrInternalError indicates that something internal in the link
 19  	// failed. In this case we will send a generic error to our peer.
 20  	ErrInternalError errorCode = iota
 21  
 22  	// ErrRemoteError indicates that our peer sent an error, prompting up
 23  	// to fail the link.
 24  	ErrRemoteError
 25  
 26  	// ErrRemoteUnresponsive indicates that our peer took too long to
 27  	// complete a commitment dance.
 28  	ErrRemoteUnresponsive
 29  
 30  	// ErrSyncError indicates that we failed synchronizing the state of the
 31  	// channel with our peer.
 32  	ErrSyncError
 33  
 34  	// ErrInvalidUpdate indicates that the peer send us an invalid update.
 35  	ErrInvalidUpdate
 36  
 37  	// ErrInvalidCommitment indicates that the remote peer sent us an
 38  	// invalid commitment signature.
 39  	ErrInvalidCommitment
 40  
 41  	// ErrInvalidRevocation indicates that the remote peer send us an
 42  	// invalid revocation message.
 43  	ErrInvalidRevocation
 44  
 45  	// ErrRecoveryError the channel was unable to be resumed, we need the
 46  	// remote party to force close the channel out on chain now as a
 47  	// result.
 48  	ErrRecoveryError
 49  
 50  	// ErrCircuitError indicates a duplicate keystone error was hit in the
 51  	// circuit map. This is non-fatal and will resolve itself (usually
 52  	// within several minutes).
 53  	ErrCircuitError
 54  
 55  	// ErrStfuViolation indicates that the quiescence protocol has been
 56  	// violated, either because Stfu has been sent/received at an invalid
 57  	// time, or that an update has been sent/received while the channel is
 58  	// quiesced.
 59  	ErrStfuViolation
 60  )
 61  
 62  // LinkFailureAction is an enum-like type that describes the action that should
 63  // be taken in response to a link failure.
 64  type LinkFailureAction uint8
 65  
 66  const (
 67  	// LinkFailureForceNone indicates no action is to be taken.
 68  	LinkFailureForceNone LinkFailureAction = iota
 69  
 70  	// LinkFailureForceClose indicates that the channel should be force
 71  	// closed.
 72  	LinkFailureForceClose
 73  
 74  	// LinkFailureDisconnect indicates that we should disconnect in an
 75  	// attempt to recycle the connection. This can be useful if we think a
 76  	// TCP connection or state machine is stalled.
 77  	LinkFailureDisconnect
 78  )
 79  
 80  // LinkFailureError encapsulates an error that will make us fail the current
 81  // link. It contains the necessary information needed to determine if we should
 82  // force close the channel in the process, and if any error data should be sent
 83  // to the peer.
 84  type LinkFailureError struct {
 85  	// code is the type of error this LinkFailureError encapsulates.
 86  	code errorCode
 87  
 88  	// FailureAction describes what we should do to fail the channel.
 89  	FailureAction LinkFailureAction
 90  
 91  	// PermanentFailure indicates whether this failure is permanent, and
 92  	// the channel should not be attempted loaded again.
 93  	PermanentFailure bool
 94  
 95  	// Warning denotes if this is a non-terminal error that doesn't warrant
 96  	// failing the channel all together.
 97  	Warning bool
 98  
 99  	// SendData is a byte slice that will be sent to the peer. If nil a
100  	// generic error will be sent.
101  	SendData []byte
102  }
103  
104  // A compile time check to ensure LinkFailureError implements the error
105  // interface.
106  var _ error = (*LinkFailureError)(nil)
107  
108  // Error returns a generic error for the LinkFailureError.
109  //
110  // NOTE: Part of the error interface.
111  func (e LinkFailureError) Error() string {
112  	switch e.code {
113  	case ErrInternalError:
114  		return "internal error"
115  	case ErrRemoteError:
116  		return "remote error"
117  	case ErrRemoteUnresponsive:
118  		return "remote unresponsive"
119  	case ErrSyncError:
120  		return "sync error"
121  	case ErrInvalidUpdate:
122  		return "invalid update"
123  	case ErrInvalidCommitment:
124  		return "invalid commitment"
125  	case ErrInvalidRevocation:
126  		return "invalid revocation"
127  	case ErrRecoveryError:
128  		return "unable to resume channel, recovery required"
129  	case ErrCircuitError:
130  		return "non-fatal circuit map error"
131  	case ErrStfuViolation:
132  		return "quiescence protocol executed improperly"
133  	default:
134  		return "unknown error"
135  	}
136  }
137  
138  // ShouldSendToPeer indicates whether we should send an error to the peer if
139  // the link fails with this LinkFailureError.
140  func (e LinkFailureError) ShouldSendToPeer() bool {
141  	switch e.code {
142  
143  	// Since sending an error can lead some nodes to force close the
144  	// channel, create a whitelist of the failures we want to send so that
145  	// newly added error codes aren't automatically sent to the remote peer.
146  	case
147  		ErrInternalError,
148  		ErrRemoteError,
149  		ErrSyncError,
150  		ErrInvalidUpdate,
151  		ErrInvalidCommitment,
152  		ErrInvalidRevocation,
153  		ErrRecoveryError:
154  
155  		return true
156  
157  	// In all other cases we will not attempt to send our peer an error.
158  	default:
159  		return false
160  	}
161  }