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

lightningnetwork / lnd / 12199391122

06 Dec 2024 01:10PM UTC coverage: 49.807% (-9.1%) from 58.933%
12199391122

push

github

web-flow
Merge pull request #9337 from Guayaba221/patch-1

chore: fix typo in ruby.md

100137 of 201051 relevant lines covered (49.81%)

2.07 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 {
4✔
35
        return &resolutionStore{
4✔
36
                backend: db,
4✔
37
        }
4✔
38
}
4✔
39

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

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

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

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

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

67
        return nil
4✔
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 {
4✔
74
        err := kvdb.View(r.backend, func(tx kvdb.RTx) error {
8✔
75
                resBucket := tx.ReadBucket(resBucketKey)
4✔
76
                if resBucket == nil {
4✔
77
                        // Return an error if the bucket doesn't exist.
×
78
                        return errResMsgNotFound
×
79
                }
×
80

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

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

95
        return nil
4✔
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) {
4✔
102

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

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

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

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

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

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

138
        return msgs, nil
4✔
139
}
140

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

149
                return resBucket.Delete(outKey.Bytes())
4✔
150
        }, func() {})
4✔
151
        return err
4✔
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 {
4✔
158

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

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

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

170
        // Else this is a settle message, and we need to write the preimage.
171
        return channeldb.WriteElement(w, *resMsg.PreImage)
4✔
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) {
4✔
178

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

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

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

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

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

201
        return resMsg, nil
4✔
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