github.com/decred/dcrlnd@v0.7.6/htlcswitch/failure.go (about) 1 package htlcswitch 2 3 import ( 4 "bytes" 5 "fmt" 6 7 "github.com/decred/dcrlnd/htlcswitch/hop" 8 "github.com/decred/dcrlnd/lnwire" 9 sphinx "github.com/decred/lightning-onion/v4" 10 ) 11 12 // ClearTextError is an interface which is implemented by errors that occur 13 // when we know the underlying wire failure message. These errors are the 14 // opposite to opaque errors which are onion-encrypted blobs only understandable 15 // to the initiating node. ClearTextErrors are used when we fail a htlc at our 16 // node, or one of our initiated payments failed and we can decrypt the onion 17 // encrypted error fully. 18 type ClearTextError interface { 19 error 20 21 // WireMessage extracts a valid wire failure message from an internal 22 // error which may contain additional metadata (which should not be 23 // exposed to the network). This value may be nil in the case where 24 // an unknown wire error is returned by one of our peers. 25 WireMessage() lnwire.FailureMessage 26 } 27 28 // LinkError is an implementation of the ClearTextError interface which 29 // represents failures that occur on our incoming or outgoing link. 30 type LinkError struct { 31 // msg returns the wire failure associated with the error. 32 // This value should *not* be nil, because we should always 33 // know the failure type for failures which occur at our own 34 // node. 35 msg lnwire.FailureMessage 36 37 // FailureDetail enriches the wire error with additional information. 38 FailureDetail 39 } 40 41 // NewLinkError returns a LinkError with the failure message provided. 42 // The failure message provided should *not* be nil, because we should 43 // always know the failure type for failures which occur at our own node. 44 func NewLinkError(msg lnwire.FailureMessage) *LinkError { 45 return &LinkError{msg: msg} 46 } 47 48 // NewDetailedLinkError returns a link error that enriches a wire message with 49 // a failure detail. 50 func NewDetailedLinkError(msg lnwire.FailureMessage, 51 detail FailureDetail) *LinkError { 52 53 return &LinkError{ 54 msg: msg, 55 FailureDetail: detail, 56 } 57 } 58 59 // WireMessage extracts a valid wire failure message from an internal 60 // error which may contain additional metadata (which should not be 61 // exposed to the network). This value should never be nil for LinkErrors, 62 // because we are the ones failing the htlc. 63 // 64 // Note this is part of the ClearTextError interface. 65 func (l *LinkError) WireMessage() lnwire.FailureMessage { 66 return l.msg 67 } 68 69 // Error returns the string representation of a link error. 70 // 71 // Note this is part of the ClearTextError interface. 72 func (l *LinkError) Error() string { 73 // If the link error has no failure detail, return the wire message's 74 // error. 75 if l.FailureDetail == nil { 76 return l.msg.Error() 77 } 78 79 return l.FailureDetail.FailureString() 80 } 81 82 // ForwardingError wraps an lnwire.FailureMessage in a struct that also 83 // includes the source of the error. 84 type ForwardingError struct { 85 // FailureSourceIdx is the index of the node that sent the failure. 86 // With this information, the dispatcher of a payment can modify their 87 // set of candidate routes in response to the type of failure 88 // extracted. Index zero is the self node. 89 FailureSourceIdx int 90 91 // msg is the wire message associated with the error. This value may 92 // be nil in the case where we fail to decode failure message sent by 93 // a peer. 94 msg lnwire.FailureMessage 95 } 96 97 // WireMessage extracts a valid wire failure message from an internal 98 // error which may contain additional metadata (which should not be 99 // exposed to the network). This value may be nil in the case where 100 // an unknown wire error is returned by one of our peers. 101 // 102 // Note this is part of the ClearTextError interface. 103 func (f *ForwardingError) WireMessage() lnwire.FailureMessage { 104 return f.msg 105 } 106 107 // Error implements the built-in error interface. We use this method to allow 108 // the switch or any callers to insert additional context to the error message 109 // returned. 110 func (f *ForwardingError) Error() string { 111 return fmt.Sprintf( 112 "%v@%v", f.msg, f.FailureSourceIdx, 113 ) 114 } 115 116 // NewForwardingError creates a new payment error which wraps a wire error 117 // with additional metadata. 118 func NewForwardingError(failure lnwire.FailureMessage, 119 index int) *ForwardingError { 120 121 return &ForwardingError{ 122 FailureSourceIdx: index, 123 msg: failure, 124 } 125 } 126 127 // NewUnknownForwardingError returns a forwarding error which has a nil failure 128 // message. This constructor should only be used in the case where we cannot 129 // decode the failure we have received from a peer. 130 func NewUnknownForwardingError(index int) *ForwardingError { 131 return &ForwardingError{ 132 FailureSourceIdx: index, 133 } 134 } 135 136 // ErrorDecrypter is an interface that is used to decrypt the onion encrypted 137 // failure reason an extra out a well formed error. 138 type ErrorDecrypter interface { 139 // DecryptError peels off each layer of onion encryption from the first 140 // hop, to the source of the error. A fully populated 141 // lnwire.FailureMessage is returned along with the source of the 142 // error. 143 DecryptError(lnwire.OpaqueReason) (*ForwardingError, error) 144 } 145 146 // UnknownEncrypterType is an error message used to signal that an unexpected 147 // EncrypterType was encountered during decoding. 148 type UnknownEncrypterType hop.EncrypterType 149 150 // Error returns a formatted error indicating the invalid EncrypterType. 151 func (e UnknownEncrypterType) Error() string { 152 return fmt.Sprintf("unknown error encrypter type: %d", e) 153 } 154 155 // OnionErrorDecrypter is the interface that provides onion level error 156 // decryption. 157 type OnionErrorDecrypter interface { 158 // DecryptError attempts to decrypt the passed encrypted error response. 159 // The onion failure is encrypted in backward manner, starting from the 160 // node where error have occurred. As a result, in order to decrypt the 161 // error we need get all shared secret and apply decryption in the 162 // reverse order. 163 DecryptError(encryptedData []byte) (*sphinx.DecryptedError, error) 164 } 165 166 // SphinxErrorDecrypter wraps the sphinx data SphinxErrorDecrypter and maps the 167 // returned errors to concrete lnwire.FailureMessage instances. 168 type SphinxErrorDecrypter struct { 169 OnionErrorDecrypter 170 } 171 172 // DecryptError peels off each layer of onion encryption from the first hop, to 173 // the source of the error. A fully populated lnwire.FailureMessage is returned 174 // along with the source of the error. 175 // 176 // NOTE: Part of the ErrorDecrypter interface. 177 func (s *SphinxErrorDecrypter) DecryptError(reason lnwire.OpaqueReason) ( 178 *ForwardingError, error) { 179 180 failure, err := s.OnionErrorDecrypter.DecryptError(reason) 181 if err != nil { 182 return nil, err 183 } 184 185 // Decode the failure. If an error occurs, we leave the failure message 186 // field nil. 187 r := bytes.NewReader(failure.Message) 188 failureMsg, err := lnwire.DecodeFailure(r, 0) 189 if err != nil { 190 return NewUnknownForwardingError(failure.SenderIdx), nil 191 } 192 193 return NewForwardingError(failureMsg, failure.SenderIdx), nil 194 } 195 196 // A compile time check to ensure ErrorDecrypter implements the Deobfuscator 197 // interface. 198 var _ ErrorDecrypter = (*SphinxErrorDecrypter)(nil)