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

lightningnetwork / lnd / 12343072627

15 Dec 2024 11:09PM UTC coverage: 57.504% (-1.1%) from 58.636%
12343072627

Pull #9315

github

yyforyongyu
contractcourt: offer outgoing htlc one block earlier before its expiry

We need to offer the outgoing htlc one block earlier to make sure when
the expiry height hits, the sweeper will not miss sweeping it in the
same block. This also means the outgoing contest resolver now only does
one thing - watch for preimage spend till height expiry-1, which can
easily be moved into the timeout resolver instead in the future.
Pull Request #9315: Implement `blockbeat`

1445 of 2007 new or added lines in 26 files covered. (72.0%)

19246 existing lines in 249 files now uncovered.

102342 of 177975 relevant lines covered (57.5%)

24772.24 hits per line

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

85.45
/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 {
135✔
45
        return &LinkError{msg: msg}
135✔
46
}
135✔
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 {
77✔
52

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

79
        return l.FailureDetail.FailureString()
9✔
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 {
160✔
104
        return f.msg
160✔
105
}
160✔
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.
UNCOV
110
func (f *ForwardingError) Error() string {
×
UNCOV
111
        return fmt.Sprintf(
×
UNCOV
112
                "%v@%v", f.msg, f.FailureSourceIdx,
×
UNCOV
113
        )
×
UNCOV
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 {
139✔
120

139✔
121
        return &ForwardingError{
139✔
122
                FailureSourceIdx: index,
139✔
123
                msg:              failure,
139✔
124
        }
139✔
125
}
139✔
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 {
2✔
131
        return &ForwardingError{
2✔
132
                FailureSourceIdx: index,
2✔
133
        }
2✔
134
}
2✔
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 {
4✔
182
                return nil, err
1✔
183
        }
1✔
184

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

193
        return NewForwardingError(failureMsg, failure.SenderIdx), nil
1✔
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