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

lightningnetwork / lnd / 11170835610

03 Oct 2024 10:41PM UTC coverage: 49.188% (-9.6%) from 58.738%
11170835610

push

github

web-flow
Merge pull request #9154 from ziggie1984/master

multi: bump btcd version.

3 of 6 new or added lines in 6 files covered. (50.0%)

26110 existing lines in 428 files now uncovered.

97359 of 197934 relevant lines covered (49.19%)

1.04 hits per line

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

75.83
/htlcswitch/resolution_store.go
1
package htlcswitch
2

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

7
        "github.com/go-errors/errors"
8
        "github.com/lightningnetwork/lnd/channeldb"
9
        "github.com/lightningnetwork/lnd/contractcourt"
10
        "github.com/lightningnetwork/lnd/kvdb"
11
        "github.com/lightningnetwork/lnd/lnwire"
12
)
13

14
var (
15
        // resBucketKey is used for the root level bucket that stores the
16
        // CircuitKey -> ResolutionMsg mapping.
17
        resBucketKey = []byte("resolution-store-bucket-key")
18

19
        // errResMsgNotFound is used to let callers know that the resolution
20
        // message was not found for the given CircuitKey. This is used in the
21
        // checkResolutionMsg function.
22
        errResMsgNotFound = errors.New("resolution message not found")
23
)
24

25
// resolutionStore contains ResolutionMsgs received from the contractcourt. The
26
// Switch deletes these from the store when the underlying circuit has been
27
// removed via DeleteCircuits. If the circuit hasn't been deleted, the Switch
28
// will dispatch the ResolutionMsg to a link if this was a multi-hop HTLC or to
29
// itself if the Switch initiated the payment.
30
type resolutionStore struct {
31
        backend kvdb.Backend
32
}
33

34
func newResolutionStore(db kvdb.Backend) *resolutionStore {
2✔
35
        return &resolutionStore{
2✔
36
                backend: db,
2✔
37
        }
2✔
38
}
2✔
39

40
// addResolutionMsg persists a ResolutionMsg to the resolutionStore.
41
func (r *resolutionStore) addResolutionMsg(
42
        resMsg *contractcourt.ResolutionMsg) error {
2✔
43

2✔
44
        // The outKey will be the database key.
2✔
45
        outKey := &CircuitKey{
2✔
46
                ChanID: resMsg.SourceChan,
2✔
47
                HtlcID: resMsg.HtlcIndex,
2✔
48
        }
2✔
49

2✔
50
        var resBuf bytes.Buffer
2✔
51
        if err := serializeResolutionMsg(&resBuf, resMsg); err != nil {
2✔
52
                return err
×
53
        }
×
54

55
        err := kvdb.Update(r.backend, func(tx kvdb.RwTx) error {
4✔
56
                resBucket, err := tx.CreateTopLevelBucket(resBucketKey)
2✔
57
                if err != nil {
2✔
58
                        return err
×
59
                }
×
60

61
                return resBucket.Put(outKey.Bytes(), resBuf.Bytes())
2✔
62
        }, func() {})
2✔
63
        if err != nil {
2✔
64
                return err
×
65
        }
×
66

67
        return nil
2✔
68
}
69

70
// checkResolutionMsg returns nil if the resolution message is found in the
71
// store. It returns an error if no resolution message was found for the
72
// passed outKey or if a database error occurred.
73
func (r *resolutionStore) checkResolutionMsg(outKey *CircuitKey) error {
2✔
74
        err := kvdb.View(r.backend, func(tx kvdb.RTx) error {
4✔
75
                resBucket := tx.ReadBucket(resBucketKey)
2✔
76
                if resBucket == nil {
2✔
77
                        // Return an error if the bucket doesn't exist.
×
78
                        return errResMsgNotFound
×
79
                }
×
80

81
                msg := resBucket.Get(outKey.Bytes())
2✔
82
                if msg == nil {
2✔
UNCOV
83
                        // Return the not found error since no message exists
×
UNCOV
84
                        // for this CircuitKey.
×
UNCOV
85
                        return errResMsgNotFound
×
UNCOV
86
                }
×
87

88
                // Return nil to indicate that the message was found.
89
                return nil
2✔
90
        }, func() {})
2✔
91
        if err != nil {
2✔
UNCOV
92
                return err
×
UNCOV
93
        }
×
94

95
        return nil
2✔
96
}
97

98
// fetchAllResolutionMsg returns a slice of all stored ResolutionMsgs. This is
99
// used by the Switch on start-up.
100
func (r *resolutionStore) fetchAllResolutionMsg() (
101
        []*contractcourt.ResolutionMsg, error) {
2✔
102

2✔
103
        var msgs []*contractcourt.ResolutionMsg
2✔
104

2✔
105
        err := kvdb.View(r.backend, func(tx kvdb.RTx) error {
4✔
106
                resBucket := tx.ReadBucket(resBucketKey)
2✔
107
                if resBucket == nil {
4✔
108
                        return nil
2✔
109
                }
2✔
110

111
                return resBucket.ForEach(func(k, v []byte) error {
4✔
112
                        kr := bytes.NewReader(k)
2✔
113
                        outKey := &CircuitKey{}
2✔
114
                        if err := outKey.Decode(kr); err != nil {
2✔
115
                                return err
×
116
                        }
×
117

118
                        vr := bytes.NewReader(v)
2✔
119
                        resMsg, err := deserializeResolutionMsg(vr)
2✔
120
                        if err != nil {
2✔
121
                                return err
×
122
                        }
×
123

124
                        // Set the CircuitKey values on the ResolutionMsg.
125
                        resMsg.SourceChan = outKey.ChanID
2✔
126
                        resMsg.HtlcIndex = outKey.HtlcID
2✔
127

2✔
128
                        msgs = append(msgs, resMsg)
2✔
129
                        return nil
2✔
130
                })
131
        }, func() {
2✔
132
                msgs = nil
2✔
133
        })
2✔
134
        if err != nil {
2✔
135
                return nil, err
×
136
        }
×
137

138
        return msgs, nil
2✔
139
}
140

141
// deleteResolutionMsg removes a ResolutionMsg with the passed-in CircuitKey.
142
func (r *resolutionStore) deleteResolutionMsg(outKey *CircuitKey) error {
2✔
143
        err := kvdb.Update(r.backend, func(tx kvdb.RwTx) error {
4✔
144
                resBucket, err := tx.CreateTopLevelBucket(resBucketKey)
2✔
145
                if err != nil {
2✔
146
                        return err
×
147
                }
×
148

149
                return resBucket.Delete(outKey.Bytes())
2✔
150
        }, func() {})
2✔
151
        return err
2✔
152
}
153

154
// serializeResolutionMsg writes part of a ResolutionMsg to the passed
155
// io.Writer.
156
func serializeResolutionMsg(w io.Writer,
157
        resMsg *contractcourt.ResolutionMsg) error {
2✔
158

2✔
159
        isFail := resMsg.Failure != nil
2✔
160

2✔
161
        if err := channeldb.WriteElement(w, isFail); err != nil {
2✔
162
                return err
×
163
        }
×
164

165
        // If this is a failure message, then we're done serializing.
166
        if isFail {
4✔
167
                return nil
2✔
168
        }
2✔
169

170
        // Else this is a settle message, and we need to write the preimage.
171
        return channeldb.WriteElement(w, *resMsg.PreImage)
2✔
172
}
173

174
// deserializeResolutionMsg reads part of a ResolutionMsg from the passed
175
// io.Reader.
176
func deserializeResolutionMsg(r io.Reader) (*contractcourt.ResolutionMsg,
177
        error) {
2✔
178

2✔
179
        resMsg := &contractcourt.ResolutionMsg{}
2✔
180
        var isFail bool
2✔
181

2✔
182
        if err := channeldb.ReadElements(r, &isFail); err != nil {
2✔
183
                return nil, err
×
184
        }
×
185

186
        // If a failure resolution msg was stored, set the Failure field.
187
        if isFail {
4✔
188
                failureMsg := &lnwire.FailPermanentChannelFailure{}
2✔
189
                resMsg.Failure = failureMsg
2✔
190
                return resMsg, nil
2✔
191
        }
2✔
192

193
        var preimage [32]byte
2✔
194
        resMsg.PreImage = &preimage
2✔
195

2✔
196
        // Else this is a settle resolution msg and we will read the preimage.
2✔
197
        if err := channeldb.ReadElement(r, resMsg.PreImage); err != nil {
2✔
198
                return nil, err
×
199
        }
×
200

201
        return resMsg, nil
2✔
202
}
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