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

lightningnetwork / lnd / 15736109134

18 Jun 2025 02:46PM UTC coverage: 58.197% (-10.1%) from 68.248%
15736109134

Pull #9752

github

web-flow
Merge d2634a68c into 31c74f20f
Pull Request #9752: routerrpc: reject payment to invoice that don't have payment secret or blinded paths

6 of 13 new or added lines in 2 files covered. (46.15%)

28331 existing lines in 455 files now uncovered.

97860 of 168153 relevant lines covered (58.2%)

1.81 hits per line

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

0.0
/watchtower/wtdb/migration1/client_db.go
1
package migration1
2

3
import (
4
        "bytes"
5
        "errors"
6
        "fmt"
7

8
        "github.com/lightningnetwork/lnd/kvdb"
9
)
10

11
var (
12
        // cSessionBkt is a top-level bucket storing:
13
        //   session-id => cSessionBody -> encoded ClientSessionBody
14
        //              => cSessionCommits => seqnum -> encoded CommittedUpdate
15
        //              => cSessionAcks => seqnum -> encoded BackupID
16
        cSessionBkt = []byte("client-session-bucket")
17

18
        // cSessionBody is a sub-bucket of cSessionBkt storing only the body of
19
        // the ClientSession.
20
        cSessionBody = []byte("client-session-body")
21

22
        // cTowerIDToSessionIDIndexBkt is a top-level bucket storing:
23
        //         tower-id -> session-id -> 1
24
        cTowerIDToSessionIDIndexBkt = []byte(
25
                "client-tower-to-session-index-bucket",
26
        )
27

28
        // ErrUninitializedDB signals that top-level buckets for the database
29
        // have not been initialized.
30
        ErrUninitializedDB = errors.New("db not initialized")
31

32
        // ErrClientSessionNotFound signals that the requested client session
33
        // was not found in the database.
34
        ErrClientSessionNotFound = errors.New("client session not found")
35

36
        // ErrCorruptClientSession signals that the client session's on-disk
37
        // structure deviates from what is expected.
38
        ErrCorruptClientSession = errors.New("client session corrupted")
39
)
40

41
// MigrateTowerToSessionIndex constructs a new towerID-to-sessionID for the
42
// watchtower client DB.
UNCOV
43
func MigrateTowerToSessionIndex(tx kvdb.RwTx) error {
×
UNCOV
44
        log.Infof("Migrating the tower client db to add a " +
×
UNCOV
45
                "towerID-to-sessionID index")
×
UNCOV
46

×
UNCOV
47
        // First, we collect all the entries we want to add to the index.
×
UNCOV
48
        entries, err := getIndexEntries(tx)
×
UNCOV
49
        if err != nil {
×
UNCOV
50
                return err
×
UNCOV
51
        }
×
52

53
        // Then we create a new top-level bucket for the index.
UNCOV
54
        indexBkt, err := tx.CreateTopLevelBucket(cTowerIDToSessionIDIndexBkt)
×
UNCOV
55
        if err != nil {
×
56
                return err
×
57
        }
×
58

59
        // Finally, we add all the collected entries to the index.
UNCOV
60
        for towerID, sessions := range entries {
×
UNCOV
61
                // Create a sub-bucket using the tower ID.
×
UNCOV
62
                towerBkt, err := indexBkt.CreateBucketIfNotExists(
×
UNCOV
63
                        towerID.Bytes(),
×
UNCOV
64
                )
×
UNCOV
65
                if err != nil {
×
66
                        return err
×
67
                }
×
68

UNCOV
69
                for sessionID := range sessions {
×
UNCOV
70
                        err := addIndex(towerBkt, sessionID)
×
UNCOV
71
                        if err != nil {
×
72
                                return err
×
73
                        }
×
74
                }
75
        }
76

UNCOV
77
        return nil
×
78
}
79

80
// addIndex adds a new towerID-sessionID pair to the given bucket. The
81
// session ID is used as a key within the bucket and a value of []byte{1} is
82
// used for each session ID key.
UNCOV
83
func addIndex(towerBkt kvdb.RwBucket, sessionID SessionID) error {
×
UNCOV
84
        session := towerBkt.Get(sessionID[:])
×
UNCOV
85
        if session != nil {
×
86
                return fmt.Errorf("session %x duplicated", sessionID)
×
87
        }
×
88

UNCOV
89
        return towerBkt.Put(sessionID[:], []byte{1})
×
90
}
91

92
// getIndexEntries collects all the towerID-sessionID entries that need to be
93
// added to the new index.
UNCOV
94
func getIndexEntries(tx kvdb.RwTx) (map[TowerID]map[SessionID]bool, error) {
×
UNCOV
95
        sessions := tx.ReadBucket(cSessionBkt)
×
UNCOV
96
        if sessions == nil {
×
97
                return nil, ErrUninitializedDB
×
98
        }
×
99

UNCOV
100
        index := make(map[TowerID]map[SessionID]bool)
×
UNCOV
101
        err := sessions.ForEach(func(k, _ []byte) error {
×
UNCOV
102
                session, err := getClientSession(sessions, k)
×
UNCOV
103
                if err != nil {
×
UNCOV
104
                        return err
×
UNCOV
105
                }
×
106

UNCOV
107
                if index[session.TowerID] == nil {
×
UNCOV
108
                        index[session.TowerID] = make(map[SessionID]bool)
×
UNCOV
109
                }
×
110

UNCOV
111
                index[session.TowerID][session.ID] = true
×
UNCOV
112
                return nil
×
113
        })
UNCOV
114
        if err != nil {
×
UNCOV
115
                return nil, err
×
UNCOV
116
        }
×
117

UNCOV
118
        return index, nil
×
119
}
120

121
// getClientSession fetches the session with the given ID from the db.
122
func getClientSession(sessions kvdb.RBucket, idBytes []byte) (*ClientSession,
UNCOV
123
        error) {
×
UNCOV
124

×
UNCOV
125
        sessionBkt := sessions.NestedReadBucket(idBytes)
×
UNCOV
126
        if sessionBkt == nil {
×
127
                return nil, ErrClientSessionNotFound
×
128
        }
×
129

130
        // Should never have a sessionBkt without also having its body.
UNCOV
131
        sessionBody := sessionBkt.Get(cSessionBody)
×
UNCOV
132
        if sessionBody == nil {
×
UNCOV
133
                return nil, ErrCorruptClientSession
×
UNCOV
134
        }
×
135

UNCOV
136
        var session ClientSession
×
UNCOV
137
        copy(session.ID[:], idBytes)
×
UNCOV
138

×
UNCOV
139
        err := session.Decode(bytes.NewReader(sessionBody))
×
UNCOV
140
        if err != nil {
×
141
                return nil, err
×
142
        }
×
143

UNCOV
144
        return &session, nil
×
145
}
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