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

lightningnetwork / lnd / 13408822928

19 Feb 2025 08:59AM UTC coverage: 41.123% (-17.7%) from 58.794%
13408822928

Pull #9521

github

web-flow
Merge d2f397b3c into 0e8786348
Pull Request #9521: unit: remove GOACC, use Go 1.20 native coverage functionality

92496 of 224923 relevant lines covered (41.12%)

18825.83 hits per line

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

71.81
/channeldb/waitingproof.go
1
package channeldb
2

3
import (
4
        "bytes"
5
        "encoding/binary"
6
        "fmt"
7
        "io"
8
        "sync"
9

10
        "github.com/go-errors/errors"
11
        "github.com/lightningnetwork/lnd/kvdb"
12
        "github.com/lightningnetwork/lnd/lnwire"
13
)
14

15
var (
16
        // waitingProofsBucketKey byte string name of the waiting proofs store.
17
        waitingProofsBucketKey = []byte("waitingproofs")
18

19
        // ErrWaitingProofNotFound is returned if waiting proofs haven't been
20
        // found by db.
21
        ErrWaitingProofNotFound = errors.New("waiting proofs haven't been " +
22
                "found")
23

24
        // ErrWaitingProofAlreadyExist is returned if waiting proofs haven't been
25
        // found by db.
26
        ErrWaitingProofAlreadyExist = errors.New("waiting proof with such " +
27
                "key already exist")
28
)
29

30
// WaitingProofStore is the bold db map-like storage for half announcement
31
// signatures. The one responsibility of this storage is to be able to
32
// retrieve waiting proofs after client restart.
33
type WaitingProofStore struct {
34
        // cache is used in order to reduce the number of redundant get
35
        // calls, when object isn't stored in it.
36
        cache map[WaitingProofKey]struct{}
37
        db    kvdb.Backend
38
        mu    sync.RWMutex
39
}
40

41
// NewWaitingProofStore creates new instance of proofs storage.
42
func NewWaitingProofStore(db kvdb.Backend) (*WaitingProofStore, error) {
1✔
43
        s := &WaitingProofStore{
1✔
44
                db: db,
1✔
45
        }
1✔
46

1✔
47
        if err := s.ForAll(func(proof *WaitingProof) error {
1✔
48
                s.cache[proof.Key()] = struct{}{}
×
49
                return nil
×
50
        }, func() {
1✔
51
                s.cache = make(map[WaitingProofKey]struct{})
1✔
52
        }); err != nil && err != ErrWaitingProofNotFound {
1✔
53
                return nil, err
×
54
        }
×
55

56
        return s, nil
1✔
57
}
58

59
// Add adds new waiting proof in the storage.
60
func (s *WaitingProofStore) Add(proof *WaitingProof) error {
1✔
61
        s.mu.Lock()
1✔
62
        defer s.mu.Unlock()
1✔
63

1✔
64
        err := kvdb.Update(s.db, func(tx kvdb.RwTx) error {
2✔
65
                var err error
1✔
66
                var b bytes.Buffer
1✔
67

1✔
68
                // Get or create the bucket.
1✔
69
                bucket, err := tx.CreateTopLevelBucket(waitingProofsBucketKey)
1✔
70
                if err != nil {
1✔
71
                        return err
×
72
                }
×
73

74
                // Encode the objects and place it in the bucket.
75
                if err := proof.Encode(&b); err != nil {
1✔
76
                        return err
×
77
                }
×
78

79
                key := proof.Key()
1✔
80

1✔
81
                return bucket.Put(key[:], b.Bytes())
1✔
82
        }, func() {})
1✔
83
        if err != nil {
1✔
84
                return err
×
85
        }
×
86

87
        // Knowing that the write succeeded, we can now update the in-memory
88
        // cache with the proof's key.
89
        s.cache[proof.Key()] = struct{}{}
1✔
90

1✔
91
        return nil
1✔
92
}
93

94
// Remove removes the proof from storage by its key.
95
func (s *WaitingProofStore) Remove(key WaitingProofKey) error {
1✔
96
        s.mu.Lock()
1✔
97
        defer s.mu.Unlock()
1✔
98

1✔
99
        if _, ok := s.cache[key]; !ok {
1✔
100
                return ErrWaitingProofNotFound
×
101
        }
×
102

103
        err := kvdb.Update(s.db, func(tx kvdb.RwTx) error {
2✔
104
                // Get or create the top bucket.
1✔
105
                bucket := tx.ReadWriteBucket(waitingProofsBucketKey)
1✔
106
                if bucket == nil {
1✔
107
                        return ErrWaitingProofNotFound
×
108
                }
×
109

110
                return bucket.Delete(key[:])
1✔
111
        }, func() {})
1✔
112
        if err != nil {
1✔
113
                return err
×
114
        }
×
115

116
        // Since the proof was successfully deleted from the store, we can now
117
        // remove it from the in-memory cache.
118
        delete(s.cache, key)
1✔
119

1✔
120
        return nil
1✔
121
}
122

123
// ForAll iterates thought all waiting proofs and passing the waiting proof
124
// in the given callback.
125
func (s *WaitingProofStore) ForAll(cb func(*WaitingProof) error,
126
        reset func()) error {
2✔
127

2✔
128
        return kvdb.View(s.db, func(tx kvdb.RTx) error {
4✔
129
                bucket := tx.ReadBucket(waitingProofsBucketKey)
2✔
130
                if bucket == nil {
3✔
131
                        return ErrWaitingProofNotFound
1✔
132
                }
1✔
133

134
                // Iterate over objects buckets.
135
                return bucket.ForEach(func(k, v []byte) error {
1✔
136
                        // Skip buckets fields.
×
137
                        if v == nil {
×
138
                                return nil
×
139
                        }
×
140

141
                        r := bytes.NewReader(v)
×
142
                        proof := &WaitingProof{}
×
143
                        if err := proof.Decode(r); err != nil {
×
144
                                return err
×
145
                        }
×
146

147
                        return cb(proof)
×
148
                })
149
        }, reset)
150
}
151

152
// Get returns the object which corresponds to the given index.
153
func (s *WaitingProofStore) Get(key WaitingProofKey) (*WaitingProof, error) {
2✔
154
        var proof *WaitingProof
2✔
155

2✔
156
        s.mu.RLock()
2✔
157
        defer s.mu.RUnlock()
2✔
158

2✔
159
        if _, ok := s.cache[key]; !ok {
3✔
160
                return nil, ErrWaitingProofNotFound
1✔
161
        }
1✔
162

163
        err := kvdb.View(s.db, func(tx kvdb.RTx) error {
2✔
164
                bucket := tx.ReadBucket(waitingProofsBucketKey)
1✔
165
                if bucket == nil {
1✔
166
                        return ErrWaitingProofNotFound
×
167
                }
×
168

169
                // Iterate over objects buckets.
170
                v := bucket.Get(key[:])
1✔
171
                if v == nil {
1✔
172
                        return ErrWaitingProofNotFound
×
173
                }
×
174

175
                r := bytes.NewReader(v)
1✔
176
                return proof.Decode(r)
1✔
177
        }, func() {
1✔
178
                proof = &WaitingProof{}
1✔
179
        })
1✔
180

181
        return proof, err
1✔
182
}
183

184
// WaitingProofKey is the proof key which uniquely identifies the waiting
185
// proof object. The goal of this key is distinguish the local and remote
186
// proof for the same channel id.
187
type WaitingProofKey [9]byte
188

189
// WaitingProof is the storable object, which encapsulate the half proof and
190
// the information about from which side this proof came. This structure is
191
// needed to make channel proof exchange persistent, so that after client
192
// restart we may receive remote/local half proof and process it.
193
type WaitingProof struct {
194
        *lnwire.AnnounceSignatures1
195
        isRemote bool
196
}
197

198
// NewWaitingProof constructs a new waiting prof instance.
199
func NewWaitingProof(isRemote bool,
200
        proof *lnwire.AnnounceSignatures1) *WaitingProof {
1✔
201

1✔
202
        return &WaitingProof{
1✔
203
                AnnounceSignatures1: proof,
1✔
204
                isRemote:            isRemote,
1✔
205
        }
1✔
206
}
1✔
207

208
// OppositeKey returns the key which uniquely identifies opposite waiting proof.
209
func (p *WaitingProof) OppositeKey() WaitingProofKey {
1✔
210
        var key [9]byte
1✔
211
        binary.BigEndian.PutUint64(key[:8], p.ShortChannelID.ToUint64())
1✔
212

1✔
213
        if !p.isRemote {
1✔
214
                key[8] = 1
×
215
        }
×
216
        return key
1✔
217
}
218

219
// Key returns the key which uniquely identifies waiting proof.
220
func (p *WaitingProof) Key() WaitingProofKey {
4✔
221
        var key [9]byte
4✔
222
        binary.BigEndian.PutUint64(key[:8], p.ShortChannelID.ToUint64())
4✔
223

4✔
224
        if p.isRemote {
8✔
225
                key[8] = 1
4✔
226
        }
4✔
227
        return key
4✔
228
}
229

230
// Encode writes the internal representation of waiting proof in byte stream.
231
func (p *WaitingProof) Encode(w io.Writer) error {
1✔
232
        if err := binary.Write(w, byteOrder, p.isRemote); err != nil {
1✔
233
                return err
×
234
        }
×
235

236
        // TODO(yy): remove the type assertion when we finished refactoring db
237
        // into using write buffer.
238
        buf, ok := w.(*bytes.Buffer)
1✔
239
        if !ok {
1✔
240
                return fmt.Errorf("expect io.Writer to be *bytes.Buffer")
×
241
        }
×
242

243
        if err := p.AnnounceSignatures1.Encode(buf, 0); err != nil {
1✔
244
                return err
×
245
        }
×
246

247
        return nil
1✔
248
}
249

250
// Decode reads the data from the byte stream and initializes the
251
// waiting proof object with it.
252
func (p *WaitingProof) Decode(r io.Reader) error {
1✔
253
        if err := binary.Read(r, byteOrder, &p.isRemote); err != nil {
1✔
254
                return err
×
255
        }
×
256

257
        msg := &lnwire.AnnounceSignatures1{}
1✔
258
        if err := msg.Decode(r, 0); err != nil {
1✔
259
                return err
×
260
        }
×
261

262
        p.AnnounceSignatures1 = msg
1✔
263

1✔
264
        return nil
1✔
265
}
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