@@ -22,6 +22,22 @@ const (
2222// the output of a SHA256 hash.
2323type Hash256 [sha256 .Size ]byte
2424
25+ // DecryptedError contains the decrypted error message and its sender.
26+ type DecryptedError struct {
27+ // Sender is the node that sent the error. Note that a node may occur in
28+ // the path multiple times. If that is the case, the sender pubkey does
29+ // not tell the caller on which visit the error occurred.
30+ Sender * btcec.PublicKey
31+
32+ // SenderIdx is the position of the error sending node in the path.
33+ // Index zero is the self node. SenderIdx allows to distinguish between
34+ // errors from nodes that occur in the path multiple times.
35+ SenderIdx int
36+
37+ // Message is the decrypted error message.
38+ Message []byte
39+ }
40+
2541// zeroHMAC is the special HMAC value that allows the final node to determine
2642// if it is the payment destination or not.
2743var zeroHMAC [HMACSize ]byte
@@ -171,11 +187,15 @@ const onionErrorLength = 2 + 2 + 256 + sha256.Size
171187// DecryptError attempts to decrypt the passed encrypted error response. The
172188// onion failure is encrypted in backward manner, starting from the node where
173189// error have occurred. As a result, in order to decrypt the error we need get
174- // all shared secret and apply decryption in the reverse order.
175- func (o * OnionErrorDecrypter ) DecryptError (encryptedData []byte ) (* btcec.PublicKey , []byte , error ) {
190+ // all shared secret and apply decryption in the reverse order. A structure is
191+ // returned that contains the decrypted error message and information on the
192+ // sender.
193+ func (o * OnionErrorDecrypter ) DecryptError (encryptedData []byte ) (
194+ * DecryptedError , error ) {
195+
176196 // Ensure the error message length is as expected.
177197 if len (encryptedData ) != onionErrorLength {
178- return nil , nil , fmt .Errorf ("invalid error length: " +
198+ return nil , fmt .Errorf ("invalid error length: " +
179199 "expected %v got %v" , onionErrorLength ,
180200 len (encryptedData ))
181201 }
@@ -186,7 +206,7 @@ func (o *OnionErrorDecrypter) DecryptError(encryptedData []byte) (*btcec.PublicK
186206 )
187207
188208 var (
189- sender * btcec. PublicKey
209+ sender int
190210 msg []byte
191211 dummySecret Hash256
192212 )
@@ -202,7 +222,7 @@ func (o *OnionErrorDecrypter) DecryptError(encryptedData []byte) (*btcec.PublicK
202222 // secret to continue decryption attempts to fill out the rest
203223 // of the loop. Otherwise, we'll use the next shared secret in
204224 // line.
205- if sender != nil || i > len (sharedSecrets )- 1 {
225+ if sender != 0 || i > len (sharedSecrets )- 1 {
206226 sharedSecret = dummySecret
207227 } else {
208228 sharedSecret = sharedSecrets [i ]
@@ -226,19 +246,23 @@ func (o *OnionErrorDecrypter) DecryptError(encryptedData []byte) (*btcec.PublicK
226246 // If the MAC matches up, then we've found the sender of the
227247 // error and have also obtained the fully decrypted message.
228248 realMac := h .Sum (nil )
229- if hmac .Equal (realMac , expectedMac ) && sender == nil {
230- sender = o . circuit . PaymentPath [ i ]
249+ if hmac .Equal (realMac , expectedMac ) && sender == 0 {
250+ sender = i + 1
231251 msg = data
232252 }
233253 }
234254
235- // If the sender pointer is still nil , then we haven't found the
236- // sender, meaning we've failed to decrypt.
237- if sender == nil {
238- return nil , nil , errors .New ("unable to retrieve onion failure" )
255+ // If the sender index is still zero , then we haven't found the sender,
256+ // meaning we've failed to decrypt.
257+ if sender == 0 {
258+ return nil , errors .New ("unable to retrieve onion failure" )
239259 }
240260
241- return sender , msg , nil
261+ return & DecryptedError {
262+ SenderIdx : sender ,
263+ Sender : o .circuit .PaymentPath [sender - 1 ],
264+ Message : msg ,
265+ }, nil
242266}
243267
244268// EncryptError is used to make data obfuscation using the generated shared
0 commit comments