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

lightningnetwork / lnd / 10203737448

01 Aug 2024 06:26PM UTC coverage: 58.674% (+0.05%) from 58.627%
10203737448

push

github

web-flow
Merge pull request #8938 from bhandras/etcd-leader-election-fixups

multi: check leader status with our health checker to correctly shut down LND if network partitions

28 of 73 new or added lines in 6 files covered. (38.36%)

117 existing lines in 18 files now uncovered.

125392 of 213710 relevant lines covered (58.67%)

28078.2 hits per line

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

3.59
/lntest/node/config.go
1
package node
2

3
import (
4
        "flag"
5
        "fmt"
6
        "io"
7
        "os"
8
        "path"
9
        "path/filepath"
10

11
        "github.com/btcsuite/btcd/chaincfg"
12
        "github.com/btcsuite/btcd/integration/rpctest"
13
        "github.com/lightningnetwork/lnd"
14
        "github.com/lightningnetwork/lnd/chanbackup"
15
        "github.com/lightningnetwork/lnd/kvdb/etcd"
16
        "github.com/lightningnetwork/lnd/lntest/port"
17
        "github.com/lightningnetwork/lnd/lntest/wait"
18
)
19

20
const (
21
        // ListenerFormat is the format string that is used to generate local
22
        // listener addresses.
23
        ListenerFormat = "127.0.0.1:%d"
24

25
        // DefaultCSV is the CSV delay (remotedelay) we will start our test
26
        // nodes with.
27
        DefaultCSV = 4
28
)
29

30
var (
31
        // logOutput is a flag that can be set to append the output from the
32
        // seed nodes to log files.
33
        logOutput = flag.Bool("logoutput", false,
34
                "log output from node n to file output-n.log")
35

36
        // logSubDir is the default directory where the logs are written to if
37
        // logOutput is true.
38
        logSubDir = flag.String("logdir", ".", "default dir to write logs to")
39

40
        // btcdExecutable is the full path to the btcd binary.
41
        btcdExecutable = flag.String(
42
                "btcdexec", "", "full path to btcd binary",
43
        )
44
)
45

46
type DatabaseBackend int
47

48
const (
49
        BackendBbolt DatabaseBackend = iota
50
        BackendEtcd
51
        BackendPostgres
52
        BackendSqlite
53
)
54

55
// Option is a function for updating a node's configuration.
56
type Option func(*BaseNodeConfig)
57

58
// BackendConfig is an interface that abstracts away the specific chain backend
59
// node implementation.
60
type BackendConfig interface {
61
        // GenArgs returns the arguments needed to be passed to LND at startup
62
        // for using this node as a chain backend.
63
        GenArgs() []string
64

65
        // ConnectMiner is called to establish a connection to the test miner.
66
        ConnectMiner() error
67

68
        // DisconnectMiner is called to disconnect the miner.
69
        DisconnectMiner() error
70

71
        // Name returns the name of the backend type.
72
        Name() string
73

74
        // Credentials returns the rpc username, password and host for the
75
        // backend.
76
        Credentials() (string, string, string, error)
77
}
78

79
// BaseNodeConfig is the base node configuration.
80
type BaseNodeConfig struct {
81
        Name string
82

83
        // LogFilenamePrefix is used to prefix node log files. Can be used to
84
        // store the current test case for simpler postmortem debugging.
85
        LogFilenamePrefix string
86

87
        NetParams         *chaincfg.Params
88
        BackendCfg        BackendConfig
89
        BaseDir           string
90
        ExtraArgs         []string
91
        OriginalExtraArgs []string
92

93
        DataDir        string
94
        LogDir         string
95
        TLSCertPath    string
96
        TLSKeyPath     string
97
        AdminMacPath   string
98
        ReadMacPath    string
99
        InvoiceMacPath string
100

101
        SkipUnlock bool
102
        Password   []byte
103

104
        P2PPort     int
105
        RPCPort     int
106
        RESTPort    int
107
        ProfilePort int
108

109
        FeeURL string
110

111
        DBBackend   DatabaseBackend
112
        PostgresDsn string
113
        NativeSQL   bool
114

115
        // NodeID is a unique ID used to identify the node.
116
        NodeID uint32
117

118
        // LndBinary is the full path to the lnd binary that was specifically
119
        // compiled with all required itest flags.
120
        LndBinary string
121

122
        // backupDBDir is the path where a database backup is stored, if any.
123
        backupDBDir string
124

125
        // postgresDBName is the name of the postgres database where lnd data
126
        // is stored in.
127
        postgresDBName string
128
}
129

130
func (cfg BaseNodeConfig) P2PAddr() string {
×
131
        return fmt.Sprintf(ListenerFormat, cfg.P2PPort)
×
132
}
×
133

134
func (cfg BaseNodeConfig) RPCAddr() string {
×
135
        return fmt.Sprintf(ListenerFormat, cfg.RPCPort)
×
136
}
×
137

138
func (cfg BaseNodeConfig) RESTAddr() string {
×
139
        return fmt.Sprintf(ListenerFormat, cfg.RESTPort)
×
140
}
×
141

142
// DBDir returns the holding directory path of the graph database.
143
func (cfg BaseNodeConfig) DBDir() string {
×
144
        return filepath.Join(cfg.DataDir, "graph", cfg.NetParams.Name)
×
145
}
×
146

147
func (cfg BaseNodeConfig) DBPath() string {
×
148
        return filepath.Join(cfg.DBDir(), "channel.db")
×
149
}
×
150

151
func (cfg BaseNodeConfig) ChanBackupPath() string {
×
152
        return filepath.Join(
×
153
                cfg.DataDir, "chain", lnd.BitcoinChainName,
×
154
                fmt.Sprintf(
×
155
                        "%v/%v", cfg.NetParams.Name,
×
156
                        chanbackup.DefaultBackupFileName,
×
157
                ),
×
158
        )
×
159
}
×
160

161
// GenerateListeningPorts generates the ports to listen on designated for the
162
// current lightning network test.
163
func (cfg *BaseNodeConfig) GenerateListeningPorts() {
×
164
        if cfg.P2PPort == 0 {
×
165
                cfg.P2PPort = port.NextAvailablePort()
×
166
        }
×
167
        if cfg.RPCPort == 0 {
×
168
                cfg.RPCPort = port.NextAvailablePort()
×
169
        }
×
170
        if cfg.RESTPort == 0 {
×
171
                cfg.RESTPort = port.NextAvailablePort()
×
172
        }
×
173
        if cfg.ProfilePort == 0 {
×
174
                cfg.ProfilePort = port.NextAvailablePort()
×
175
        }
×
176
}
177

178
// BaseConfig returns the base node configuration struct.
179
func (cfg *BaseNodeConfig) BaseConfig() *BaseNodeConfig {
×
180
        return cfg
×
181
}
×
182

183
// GenArgs generates a slice of command line arguments from the lightning node
184
// config struct.
185
func (cfg *BaseNodeConfig) GenArgs() []string {
×
186
        var args []string
×
187

×
188
        switch cfg.NetParams {
×
189
        case &chaincfg.TestNet3Params:
×
190
                args = append(args, "--bitcoin.testnet")
×
191
        case &chaincfg.SimNetParams:
×
192
                args = append(args, "--bitcoin.simnet")
×
193
        case &chaincfg.RegressionNetParams:
×
194
                args = append(args, "--bitcoin.regtest")
×
195
        }
196

197
        backendArgs := cfg.BackendCfg.GenArgs()
×
198
        args = append(args, backendArgs...)
×
199

×
200
        nodeArgs := []string{
×
201
                "--nobootstrap",
×
202
                "--debuglevel=debug",
×
203
                "--bitcoin.defaultchanconfs=1",
×
204
                "--accept-keysend",
×
205
                "--keep-failed-payment-attempts",
×
206
                fmt.Sprintf("--db.batch-commit-interval=%v", commitInterval),
×
207
                fmt.Sprintf("--bitcoin.defaultremotedelay=%v", DefaultCSV),
×
208
                fmt.Sprintf("--rpclisten=%v", cfg.RPCAddr()),
×
209
                fmt.Sprintf("--restlisten=%v", cfg.RESTAddr()),
×
210
                fmt.Sprintf("--restcors=https://%v", cfg.RESTAddr()),
×
211
                fmt.Sprintf("--listen=%v", cfg.P2PAddr()),
×
212
                fmt.Sprintf("--externalip=%v", cfg.P2PAddr()),
×
213
                fmt.Sprintf("--lnddir=%v", cfg.BaseDir),
×
214
                fmt.Sprintf("--adminmacaroonpath=%v", cfg.AdminMacPath),
×
215
                fmt.Sprintf("--readonlymacaroonpath=%v", cfg.ReadMacPath),
×
216
                fmt.Sprintf("--invoicemacaroonpath=%v", cfg.InvoiceMacPath),
×
217
                fmt.Sprintf("--trickledelay=%v", trickleDelay),
×
218
                fmt.Sprintf("--profile=%d", cfg.ProfilePort),
×
219

×
220
                // Use a small batch delay so we can broadcast the
×
221
                // announcements quickly in the tests.
×
222
                "--gossip.sub-batch-delay=5ms",
×
223

×
224
                // Use a small cache duration so the `DescribeGraph` can be
×
225
                // updated quicker.
×
226
                "--caches.rpc-graph-cache-duration=100ms",
×
227

×
228
                // Speed up the tests for bitcoind backend.
×
229
                "--bitcoind.blockpollinginterval=100ms",
×
230
                "--bitcoind.txpollinginterval=100ms",
×
231

×
232
                // Allow unsafe disconnect in itest.
×
233
                "--dev.unsafedisconnect",
×
234
        }
×
235

×
236
        args = append(args, nodeArgs...)
×
237

×
238
        if cfg.Password == nil {
×
239
                args = append(args, "--noseedbackup")
×
240
        }
×
241

242
        switch cfg.DBBackend {
×
243
        case BackendEtcd:
×
244
                args = append(args, "--db.backend=etcd")
×
245
                args = append(args, "--db.etcd.embedded")
×
246
                args = append(
×
247
                        args, fmt.Sprintf(
×
248
                                "--db.etcd.embedded_client_port=%v",
×
249
                                port.NextAvailablePort(),
×
250
                        ),
×
251
                )
×
252
                args = append(
×
253
                        args, fmt.Sprintf(
×
254
                                "--db.etcd.embedded_peer_port=%v",
×
255
                                port.NextAvailablePort(),
×
256
                        ),
×
257
                )
×
258
                args = append(
×
259
                        args, fmt.Sprintf(
×
260
                                "--db.etcd.embedded_log_file=%v",
×
261
                                path.Join(cfg.LogDir, "etcd.log"),
×
262
                        ),
×
263
                )
×
264

265
        case BackendPostgres:
×
266
                args = append(args, "--db.backend=postgres")
×
267
                args = append(args, "--db.postgres.dsn="+cfg.PostgresDsn)
×
268
                if cfg.NativeSQL {
×
269
                        args = append(args, "--db.use-native-sql")
×
270
                }
×
271

272
        case BackendSqlite:
×
273
                args = append(args, "--db.backend=sqlite")
×
274
                args = append(args, fmt.Sprintf("--db.sqlite.busytimeout=%v",
×
275
                        wait.SqliteBusyTimeout))
×
276
                if cfg.NativeSQL {
×
277
                        args = append(args, "--db.use-native-sql")
×
278
                }
×
279
        }
280

281
        if cfg.FeeURL != "" {
×
282
                args = append(args, "--fee.url="+cfg.FeeURL)
×
283
        }
×
284

285
        // Put extra args in the end so the args can be overwritten.
286
        if cfg.ExtraArgs != nil {
×
287
                args = append(args, cfg.ExtraArgs...)
×
288
        }
×
289

290
        return args
×
291
}
292

293
// ExtraArgsEtcd returns extra args for configuring LND to use an external etcd
294
// database (for remote channel DB and wallet DB).
295
func ExtraArgsEtcd(etcdCfg *etcd.Config, name string, cluster bool,
296
        leaderSessionTTL int) []string {
×
297

×
298
        extraArgs := []string{
×
299
                "--db.backend=etcd",
×
300
                fmt.Sprintf("--db.etcd.host=%v", etcdCfg.Host),
×
301
                fmt.Sprintf("--db.etcd.user=%v", etcdCfg.User),
×
302
                fmt.Sprintf("--db.etcd.pass=%v", etcdCfg.Pass),
×
303
                fmt.Sprintf("--db.etcd.namespace=%v", etcdCfg.Namespace),
×
304
        }
×
305

×
306
        if etcdCfg.InsecureSkipVerify {
×
307
                extraArgs = append(extraArgs, "--db.etcd.insecure_skip_verify")
×
308
        }
×
309

310
        if cluster {
×
311
                clusterArgs := []string{
×
312
                        "--cluster.enable-leader-election",
×
313
                        fmt.Sprintf("--cluster.id=%v", name),
×
314
                        fmt.Sprintf("--cluster.leader-session-ttl=%v",
×
315
                                leaderSessionTTL),
×
316
                }
×
317
                extraArgs = append(extraArgs, clusterArgs...)
×
NEW
318
                extraArgs = append(
×
NEW
319
                        extraArgs, "--healthcheck.leader.interval=10s",
×
NEW
320
                )
×
UNCOV
321
        }
×
322

323
        return extraArgs
×
324
}
325

326
// GetLogDir returns the passed --logdir flag or the default value if it wasn't
327
// set.
328
func GetLogDir() string {
×
329
        if logSubDir != nil && *logSubDir != "" {
×
330
                return *logSubDir
×
331
        }
×
332

333
        return "."
×
334
}
335

336
// CopyFile copies the file src to dest.
337
func CopyFile(dest, src string) error {
×
338
        s, err := os.Open(src)
×
339
        if err != nil {
×
340
                return err
×
341
        }
×
342
        defer s.Close()
×
343

×
344
        d, err := os.Create(dest)
×
345
        if err != nil {
×
346
                return err
×
347
        }
×
348

349
        if _, err := io.Copy(d, s); err != nil {
×
350
                d.Close()
×
351
                return err
×
352
        }
×
353

354
        return d.Close()
×
355
}
356

357
// GetBtcdBinary returns the full path to the binary of the custom built btcd
358
// executable or an empty string if none is set.
359
func GetBtcdBinary() string {
×
360
        if btcdExecutable != nil {
×
361
                return *btcdExecutable
×
362
        }
×
363

364
        return ""
×
365
}
366

367
func init() {
1✔
368
        // Before we start any node, we need to make sure that any btcd or
1✔
369
        // bitcoind node that is started through the RPC harness uses a unique
1✔
370
        // port as well to avoid any port collisions.
1✔
371
        rpctest.ListenAddressGenerator =
1✔
372
                port.GenerateSystemUniqueListenerAddresses
1✔
373
}
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