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

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 hits per line

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

0.0
/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.
UNCOV
42
func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) {
×
UNCOV
43
        path := filepath.Join(dbPath, dbName)
×
UNCOV
44

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

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

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

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

×
UNCOV
75
        return chanDB, nil
×
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.
UNCOV
82
func createChannelDB(dbPath string) error {
×
UNCOV
83
        if !fileExists(dbPath) {
×
84
                if err := os.MkdirAll(dbPath, 0700); err != nil {
×
85
                        return err
×
86
                }
×
87
        }
88

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

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

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

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

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

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

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

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

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

UNCOV
166
        return bdb.Close()
×
167
}
168

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

UNCOV
177
        return true
×
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.
UNCOV
186
func (d *DB) FetchClosedChannels(pendingOnly bool) ([]*ChannelCloseSummary, error) {
×
UNCOV
187
        var chanSummaries []*ChannelCloseSummary
×
UNCOV
188

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

UNCOV
195
                return closeBucket.ForEach(func(chanID []byte, summaryBytes []byte) error {
×
UNCOV
196
                        summaryReader := bytes.NewReader(summaryBytes)
×
UNCOV
197
                        chanSummary, err := deserializeCloseChannelSummary(summaryReader)
×
UNCOV
198
                        if err != nil {
×
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.
UNCOV
205
                        if !chanSummary.IsPending && pendingOnly {
×
206
                                return nil
×
207
                        }
×
208

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

UNCOV
218
        return chanSummaries, nil
×
219
}
220

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