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

lightningnetwork / lnd / 15951470896

29 Jun 2025 04:23AM UTC coverage: 67.594% (-0.01%) from 67.606%
15951470896

Pull #9751

github

web-flow
Merge 599d9b051 into 6290edf14
Pull Request #9751: multi: update Go to 1.23.10 and update some packages

135088 of 199851 relevant lines covered (67.59%)

21909.44 hits per line

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

62.5
/channeldb/migration_01_to_11/db.go
1
package migration_01_to_11
2

3
import (
4
        "bytes"
5
        "encoding/binary"
6
        "fmt"
7
        "os"
8
        "path/filepath"
9
        "time"
10

11
        "github.com/lightningnetwork/lnd/kvdb"
12
)
13

14
const (
15
        dbName           = "channel.db"
16
        dbFilePermission = 0600
17
)
18

19
// migration is a function which takes a prior outdated version of the database
20
// instances and mutates the key/bucket structure to arrive at a more
21
// up-to-date version of the database.
22
type migration func(tx kvdb.RwTx) error
23

24
var (
25
        // Big endian is the preferred byte order, due to cursor scans over
26
        // integer keys iterating in order.
27
        byteOrder = binary.BigEndian
28
)
29

30
// DB is the primary datastore for the lnd daemon. The database stores
31
// information related to nodes, routing data, open/closed channels, fee
32
// schedules, and reputation data.
33
type DB struct {
34
        kvdb.Backend
35
        dbPath string
36
        graph  *ChannelGraph
37
        now    func() time.Time
38
}
39

40
// Open opens an existing channeldb. Any necessary schemas migrations due to
41
// updates will take place as necessary.
42
func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) {
9✔
43
        path := filepath.Join(dbPath, dbName)
9✔
44

9✔
45
        if !fileExists(path) {
18✔
46
                if err := createChannelDB(dbPath); err != nil {
9✔
47
                        return nil, err
×
48
                }
×
49
        }
50

51
        opts := DefaultOptions()
9✔
52
        for _, modifier := range modifiers {
9✔
53
                modifier(&opts)
×
54
        }
×
55

56
        // Specify bbolt freelist options to reduce heap pressure in case the
57
        // freelist grows to be very large.
58
        bdb, err := kvdb.Open(
9✔
59
                kvdb.BoltBackendName, path,
9✔
60
                opts.NoFreelistSync, opts.DBTimeout, false,
9✔
61
        )
9✔
62
        if err != nil {
9✔
63
                return nil, err
×
64
        }
×
65

66
        chanDB := &DB{
9✔
67
                Backend: bdb,
9✔
68
                dbPath:  dbPath,
9✔
69
                now:     time.Now,
9✔
70
        }
9✔
71
        chanDB.graph = newChannelGraph(
9✔
72
                chanDB, opts.RejectCacheSize, opts.ChannelCacheSize,
9✔
73
        )
9✔
74

9✔
75
        return chanDB, nil
9✔
76
}
77

78
// createChannelDB creates and initializes a fresh version of channeldb. In
79
// the case that the target path has not yet been created or doesn't yet exist,
80
// then the path is created. Additionally, all required top-level buckets used
81
// within the database are created.
82
func createChannelDB(dbPath string) error {
9✔
83
        if !fileExists(dbPath) {
9✔
84
                if err := os.MkdirAll(dbPath, 0700); err != nil {
×
85
                        return err
×
86
                }
×
87
        }
88

89
        path := filepath.Join(dbPath, dbName)
9✔
90
        bdb, err := kvdb.Create(
9✔
91
                kvdb.BoltBackendName, path, false, kvdb.DefaultDBTimeout,
9✔
92
                false,
9✔
93
        )
9✔
94
        if err != nil {
9✔
95
                return err
×
96
        }
×
97

98
        err = kvdb.Update(bdb, func(tx kvdb.RwTx) error {
18✔
99
                if _, err := tx.CreateTopLevelBucket(openChannelBucket); err != nil {
9✔
100
                        return err
×
101
                }
×
102
                if _, err := tx.CreateTopLevelBucket(closedChannelBucket); err != nil {
9✔
103
                        return err
×
104
                }
×
105

106
                if _, err := tx.CreateTopLevelBucket(invoiceBucket); err != nil {
9✔
107
                        return err
×
108
                }
×
109

110
                if _, err := tx.CreateTopLevelBucket(paymentBucket); err != nil {
9✔
111
                        return err
×
112
                }
×
113

114
                nodes, err := tx.CreateTopLevelBucket(nodeBucket)
9✔
115
                if err != nil {
9✔
116
                        return err
×
117
                }
×
118
                _, err = nodes.CreateBucket(aliasIndexBucket)
9✔
119
                if err != nil {
9✔
120
                        return err
×
121
                }
×
122
                _, err = nodes.CreateBucket(nodeUpdateIndexBucket)
9✔
123
                if err != nil {
9✔
124
                        return err
×
125
                }
×
126

127
                edges, err := tx.CreateTopLevelBucket(edgeBucket)
9✔
128
                if err != nil {
9✔
129
                        return err
×
130
                }
×
131
                if _, err := edges.CreateBucket(edgeIndexBucket); err != nil {
9✔
132
                        return err
×
133
                }
×
134
                if _, err := edges.CreateBucket(edgeUpdateIndexBucket); err != nil {
9✔
135
                        return err
×
136
                }
×
137
                if _, err := edges.CreateBucket(channelPointBucket); err != nil {
9✔
138
                        return err
×
139
                }
×
140
                if _, err := edges.CreateBucket(zombieBucket); err != nil {
9✔
141
                        return err
×
142
                }
×
143

144
                graphMeta, err := tx.CreateTopLevelBucket(graphMetaBucket)
9✔
145
                if err != nil {
9✔
146
                        return err
×
147
                }
×
148
                _, err = graphMeta.CreateBucket(pruneLogBucket)
9✔
149
                if err != nil {
9✔
150
                        return err
×
151
                }
×
152

153
                if _, err := tx.CreateTopLevelBucket(metaBucket); err != nil {
9✔
154
                        return err
×
155
                }
×
156

157
                meta := &Meta{
9✔
158
                        DbVersionNumber: 0,
9✔
159
                }
9✔
160
                return putMeta(meta, tx)
9✔
161
        }, func() {})
9✔
162
        if err != nil {
9✔
163
                return fmt.Errorf("unable to create new channeldb")
×
164
        }
×
165

166
        return bdb.Close()
9✔
167
}
168

169
// fileExists returns true if the file exists, and false otherwise.
170
func fileExists(path string) bool {
18✔
171
        if _, err := os.Stat(path); err != nil {
27✔
172
                if os.IsNotExist(err) {
18✔
173
                        return false
9✔
174
                }
9✔
175
        }
176

177
        return true
9✔
178
}
179

180
// FetchClosedChannels attempts to fetch all closed channels from the database.
181
// The pendingOnly bool toggles if channels that aren't yet fully closed should
182
// be returned in the response or not. When a channel was cooperatively closed,
183
// it becomes fully closed after a single confirmation.  When a channel was
184
// forcibly closed, it will become fully closed after _all_ the pending funds
185
// (if any) have been swept.
186
func (d *DB) FetchClosedChannels(pendingOnly bool) ([]*ChannelCloseSummary, error) {
3✔
187
        var chanSummaries []*ChannelCloseSummary
3✔
188

3✔
189
        if err := kvdb.View(d, func(tx kvdb.RTx) error {
6✔
190
                closeBucket := tx.ReadBucket(closedChannelBucket)
3✔
191
                if closeBucket == nil {
3✔
192
                        return ErrNoClosedChannels
×
193
                }
×
194

195
                return closeBucket.ForEach(func(chanID []byte, summaryBytes []byte) error {
6✔
196
                        summaryReader := bytes.NewReader(summaryBytes)
3✔
197
                        chanSummary, err := deserializeCloseChannelSummary(summaryReader)
3✔
198
                        if err != nil {
3✔
199
                                return err
×
200
                        }
×
201

202
                        // If the query specified to only include pending
203
                        // channels, then we'll skip any channels which aren't
204
                        // currently pending.
205
                        if !chanSummary.IsPending && pendingOnly {
3✔
206
                                return nil
×
207
                        }
×
208

209
                        chanSummaries = append(chanSummaries, chanSummary)
3✔
210
                        return nil
3✔
211
                })
212
        }, func() {
3✔
213
                chanSummaries = nil
3✔
214
        }); err != nil {
3✔
215
                return nil, err
×
216
        }
×
217

218
        return chanSummaries, nil
3✔
219
}
220

221
// ChannelGraph returns a new instance of the directed channel graph.
222
func (d *DB) ChannelGraph() *ChannelGraph {
10✔
223
        return d.graph
10✔
224
}
10✔
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