• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.18
/htlcswitch/failure.go
1
package htlcswitch
2

3
import (
4
        "bytes"
5
        "fmt"
6

7
        sphinx "github.com/lightningnetwork/lightning-onion"
8
        "github.com/lightningnetwork/lnd/htlcswitch/hop"
9
        "github.com/lightningnetwork/lnd/lnwire"
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 {
3✔
45
        return &LinkError{msg: msg}
3✔
46
}
3✔
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 {
3✔
52

3✔
53
        return &LinkError{
3✔
54
                msg:           msg,
3✔
55
                FailureDetail: detail,
3✔
56
        }
3✔
57
}
3✔
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 {
3✔
66
        return l.msg
3✔
67
}
3✔
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 {
3✔
73
        // If the link error has no failure detail, return the wire message's
3✔
74
        // error.
3✔
75
        if l.FailureDetail == nil {
6✔
76
                return l.msg.Error()
3✔
77
        }
3✔
78

79
        return l.FailureDetail.FailureString()
3✔
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. With
86
        // this information, the dispatcher of a payment can modify their set of
87
        // candidate routes in response to the type of failure extracted. Index
88
        // 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 {
3✔
104
        return f.msg
3✔
105
}
3✔
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 {
3✔
111
        return fmt.Sprintf(
3✔
112
                "%v@%v", f.msg, f.FailureSourceIdx,
3✔
113
        )
3✔
114
}
3✔
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 {
3✔
120

3✔
121
        return &ForwardingError{
3✔
122
                FailureSourceIdx: index,
3✔
123
                msg:              failure,
3✔
124
        }
3✔
125
}
3✔
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.
UNCOV
130
func NewUnknownForwardingError(index int) *ForwardingError {
×
UNCOV
131
        return &ForwardingError{
×
UNCOV
132
                FailureSourceIdx: index,
×
UNCOV
133
        }
×
UNCOV
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) {
3✔
179

3✔
180
        failure, err := s.OnionErrorDecrypter.DecryptError(reason)
3✔
181
        if err != nil {
3✔
UNCOV
182
                return nil, err
×
UNCOV
183
        }
×
184

185
        // Decode the failure. If an error occurs, we leave the failure message
186
        // field nil.
187
        r := bytes.NewReader(failure.Message)
3✔
188
        failureMsg, err := lnwire.DecodeFailure(r, 0)
3✔
189
        if err != nil {
3✔
UNCOV
190
                return NewUnknownForwardingError(failure.SenderIdx), nil
×
UNCOV
191
        }
×
192

193
        return NewForwardingError(failureMsg, failure.SenderIdx), nil
3✔
194
}
195

196
// A compile time check to ensure ErrorDecrypter implements the Deobfuscator
197
// interface.
198
var _ ErrorDecrypter = (*SphinxErrorDecrypter)(nil)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc