• 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

88.5
/watchtower/wtmock/tower_db.go
1
package wtmock
2

3
import (
4
        "sync"
5

6
        "github.com/lightningnetwork/lnd/chainntnfs"
7
        "github.com/lightningnetwork/lnd/watchtower/blob"
8
        "github.com/lightningnetwork/lnd/watchtower/wtdb"
9
)
10

11
// TowerDB is a mock, in-memory implementation of a watchtower.DB.
12
type TowerDB struct {
13
        mu        sync.Mutex
14
        lastEpoch *chainntnfs.BlockEpoch
15
        sessions  map[wtdb.SessionID]*wtdb.SessionInfo
16
        blobs     map[blob.BreachHint]map[wtdb.SessionID]*wtdb.SessionStateUpdate
17
}
18

19
// NewTowerDB initializes a fresh mock TowerDB.
20
func NewTowerDB() *TowerDB {
49✔
21
        return &TowerDB{
49✔
22
                sessions: make(map[wtdb.SessionID]*wtdb.SessionInfo),
49✔
23
                blobs:    make(map[blob.BreachHint]map[wtdb.SessionID]*wtdb.SessionStateUpdate),
49✔
24
        }
49✔
25
}
49✔
26

27
// InsertStateUpdate stores an update sent by the client after validating that
28
// the update is well-formed in the context of other updates sent for the same
29
// session. This include verifying that the sequence number is incremented
30
// properly and the last applied values echoed by the client are sane.
31
func (db *TowerDB) InsertStateUpdate(update *wtdb.SessionStateUpdate) (uint16, error) {
715✔
32
        db.mu.Lock()
715✔
33
        defer db.mu.Unlock()
715✔
34

715✔
35
        info, ok := db.sessions[update.ID]
715✔
36
        if !ok {
715✔
37
                return 0, wtdb.ErrSessionNotFound
×
38
        }
×
39

40
        commitType, err := info.Policy.BlobType.CommitmentType(nil)
715✔
41
        if err != nil {
715✔
42
                return 0, err
×
43
        }
×
44

45
        kit, err := commitType.EmptyJusticeKit()
715✔
46
        if err != nil {
715✔
47
                return 0, err
×
48
        }
×
49

50
        // Assert that the blob is the correct size for the session's blob type.
51
        if len(update.EncryptedBlob) != blob.Size(kit) {
715✔
52
                return 0, wtdb.ErrInvalidBlobSize
×
53
        }
×
54

55
        err = info.AcceptUpdateSequence(update.SeqNum, update.LastApplied)
715✔
56
        if err != nil {
721✔
57
                return info.LastApplied, err
6✔
58
        }
6✔
59

60
        sessionsToUpdates, ok := db.blobs[update.Hint]
709✔
61
        if !ok {
1,186✔
62
                sessionsToUpdates = make(map[wtdb.SessionID]*wtdb.SessionStateUpdate)
477✔
63
                db.blobs[update.Hint] = sessionsToUpdates
477✔
64
        }
477✔
65
        sessionsToUpdates[update.ID] = update
709✔
66

709✔
67
        return info.LastApplied, nil
709✔
68
}
69

70
// GetSessionInfo retrieves the session for the passed session id. An error is
71
// returned if the session could not be found.
72
func (db *TowerDB) GetSessionInfo(id *wtdb.SessionID) (*wtdb.SessionInfo, error) {
140✔
73
        db.mu.Lock()
140✔
74
        defer db.mu.Unlock()
140✔
75

140✔
76
        if info, ok := db.sessions[*id]; ok {
183✔
77
                return info, nil
43✔
78
        }
43✔
79

80
        return nil, wtdb.ErrSessionNotFound
97✔
81
}
82

83
// InsertSessionInfo records a negotiated session in the tower database. An
84
// error is returned if the session already exists.
85
func (db *TowerDB) InsertSessionInfo(info *wtdb.SessionInfo) error {
125✔
86
        db.mu.Lock()
125✔
87
        defer db.mu.Unlock()
125✔
88

125✔
89
        dbInfo, ok := db.sessions[info.ID]
125✔
90
        if ok && dbInfo.LastApplied > 0 {
125✔
91
                return wtdb.ErrSessionAlreadyExists
×
92
        }
×
93

94
        // Perform a quick sanity check on the session policy before accepting.
95
        if err := info.Policy.Validate(); err != nil {
125✔
96
                return err
×
97
        }
×
98

99
        db.sessions[info.ID] = info
125✔
100

125✔
101
        return nil
125✔
102
}
103

104
// DeleteSession removes all data associated with a particular session id from
105
// the tower's database.
106
func (db *TowerDB) DeleteSession(target wtdb.SessionID) error {
6✔
107
        db.mu.Lock()
6✔
108
        defer db.mu.Unlock()
6✔
109

6✔
110
        // Fail if the session doesn't exit.
6✔
111
        if _, ok := db.sessions[target]; !ok {
7✔
112
                return wtdb.ErrSessionNotFound
1✔
113
        }
1✔
114

115
        // Remove the target session.
116
        delete(db.sessions, target)
5✔
117

5✔
118
        // Remove the state updates for any blobs stored under the target
5✔
119
        // session identifier.
5✔
120
        for hint, sessionUpdates := range db.blobs {
47✔
121
                delete(sessionUpdates, target)
42✔
122

42✔
123
                // If this was the last state update, we can also remove the
42✔
124
                // hint that would map to an empty set.
42✔
125
                if len(sessionUpdates) == 0 {
62✔
126
                        delete(db.blobs, hint)
20✔
127
                }
20✔
128
        }
129

130
        return nil
5✔
131
}
132

133
// QueryMatches searches against all known state updates for any that match the
134
// passed breachHints. More than one Match will be returned for a given hint if
135
// they exist in the database.
136
func (db *TowerDB) QueryMatches(
137
        breachHints []blob.BreachHint) ([]wtdb.Match, error) {
121✔
138

121✔
139
        db.mu.Lock()
121✔
140
        defer db.mu.Unlock()
121✔
141

121✔
142
        var matches []wtdb.Match
121✔
143
        for _, hint := range breachHints {
613✔
144
                sessionsToUpdates, ok := db.blobs[hint]
492✔
145
                if !ok {
494✔
146
                        continue
2✔
147
                }
148

149
                for id, update := range sessionsToUpdates {
981✔
150
                        info, ok := db.sessions[id]
491✔
151
                        if !ok {
491✔
152
                                panic("session not found")
×
153
                        }
154

155
                        match := wtdb.Match{
491✔
156
                                ID:            id,
491✔
157
                                SeqNum:        update.SeqNum,
491✔
158
                                Hint:          hint,
491✔
159
                                EncryptedBlob: update.EncryptedBlob,
491✔
160
                                SessionInfo:   info,
491✔
161
                        }
491✔
162
                        matches = append(matches, match)
491✔
163
                }
164
        }
165

166
        return matches, nil
121✔
167
}
168

169
// SetLookoutTip stores the provided epoch as the latest lookout tip epoch in
170
// the tower database.
171
func (db *TowerDB) SetLookoutTip(epoch *chainntnfs.BlockEpoch) error {
2✔
172
        db.lastEpoch = epoch
2✔
173
        return nil
2✔
174
}
2✔
175

176
// GetLookoutTip retrieves the current lookout tip block epoch from the tower
177
// database.
178
func (db *TowerDB) GetLookoutTip() (*chainntnfs.BlockEpoch, error) {
1✔
179
        db.mu.Lock()
1✔
180
        defer db.mu.Unlock()
1✔
181

1✔
182
        return db.lastEpoch, nil
1✔
183
}
1✔
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