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

lightningnetwork / lnd / 15778860361

20 Jun 2025 12:23PM UTC coverage: 68.208% (+0.07%) from 68.143%
15778860361

Pull #9752

github

web-flow
Merge 831fefef7 into 7857d2c6a
Pull Request #9752: routerrpc: reject payment to invoice that don't have payment secret or blinded paths

10 of 14 new or added lines in 2 files covered. (71.43%)

2644 existing lines in 29 files now uncovered.

134706 of 197494 relevant lines covered (68.21%)

22122.25 hits per line

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

3.55
/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
        // CfgLegacy specifies the config used to create a node that uses the
46
        // legacy channel format.
47
        CfgLegacy = []string{"--protocol.legacy.committweak"}
48

49
        // CfgStaticRemoteKey specifies the config used to create a node that
50
        // uses the static remote key feature.
51
        CfgStaticRemoteKey = []string{}
52

53
        // CfgAnchor specifies the config used to create a node that uses the
54
        // anchor output feature.
55
        CfgAnchor = []string{"--protocol.anchors"}
56

57
        // CfgLeased specifies the config used to create a node that uses the
58
        // leased channel feature.
59
        CfgLeased = []string{
60
                "--protocol.anchors",
61
                "--protocol.script-enforced-lease",
62
        }
63

64
        // CfgSimpleTaproot specifies the config used to create a node that
65
        // uses the simple taproot feature.
66
        CfgSimpleTaproot = []string{
67
                "--protocol.anchors",
68
                "--protocol.simple-taproot-chans",
69
        }
70

71
        // CfgRbfCoopClose specifies the config used to create a node that
72
        // supports the new RBF close protocol.
73
        CfgRbfClose = []string{
74
                "--protocol.rbf-coop-close",
75
        }
76

77
        // CfgZeroConf specifies the config used to create a node that uses the
78
        // zero-conf channel feature.
79
        CfgZeroConf = []string{
80
                "--protocol.anchors",
81
                "--protocol.option-scid-alias",
82
                "--protocol.zero-conf",
83
        }
84
)
85

86
type DatabaseBackend int
87

88
const (
89
        BackendBbolt DatabaseBackend = iota
90
        BackendEtcd
91
        BackendPostgres
92
        BackendSqlite
93
)
94

95
// Option is a function for updating a node's configuration.
96
type Option func(*BaseNodeConfig)
97

98
// BackendConfig is an interface that abstracts away the specific chain backend
99
// node implementation.
100
type BackendConfig interface {
101
        // GenArgs returns the arguments needed to be passed to LND at startup
102
        // for using this node as a chain backend.
103
        GenArgs() []string
104

105
        // ConnectMiner is called to establish a connection to the test miner.
106
        ConnectMiner() error
107

108
        // DisconnectMiner is called to disconnect the miner.
109
        DisconnectMiner() error
110

111
        // Name returns the name of the backend type.
112
        Name() string
113

114
        // Credentials returns the rpc username, password and host for the
115
        // backend.
116
        Credentials() (string, string, string, error)
117
}
118

119
// BaseNodeConfig is the base node configuration.
120
type BaseNodeConfig struct {
121
        Name string
122

123
        // LogFilenamePrefix is used to prefix node log files. Can be used to
124
        // store the current test case for simpler postmortem debugging.
125
        LogFilenamePrefix string
126

127
        NetParams         *chaincfg.Params
128
        BackendCfg        BackendConfig
129
        BaseDir           string
130
        ExtraArgs         []string
131
        OriginalExtraArgs []string
132

133
        DataDir        string
134
        LogDir         string
135
        TLSCertPath    string
136
        TLSKeyPath     string
137
        AdminMacPath   string
138
        ReadMacPath    string
139
        InvoiceMacPath string
140

141
        SkipUnlock bool
142
        Password   []byte
143

144
        P2PPort     int
145
        RPCPort     int
146
        RESTPort    int
147
        ProfilePort int
148

149
        FeeURL string
150

151
        DBBackend   DatabaseBackend
152
        PostgresDsn string
153
        NativeSQL   bool
154

155
        // NodeID is a unique ID used to identify the node.
156
        NodeID uint32
157

158
        // LndBinary is the full path to the lnd binary that was specifically
159
        // compiled with all required itest flags.
160
        LndBinary string
161

162
        // backupDBDir is the path where a database backup is stored, if any.
163
        backupDBDir string
164

165
        // postgresDBName is the name of the postgres database where lnd data
166
        // is stored in.
167
        postgresDBName string
168
}
169

170
func (cfg BaseNodeConfig) P2PAddr() string {
171
        return fmt.Sprintf(ListenerFormat, cfg.P2PPort)
172
}
UNCOV
173

×
174
func (cfg BaseNodeConfig) RPCAddr() string {
×
175
        return fmt.Sprintf(ListenerFormat, cfg.RPCPort)
×
176
}
UNCOV
177

×
178
func (cfg BaseNodeConfig) RESTAddr() string {
×
179
        return fmt.Sprintf(ListenerFormat, cfg.RESTPort)
×
180
}
UNCOV
181

×
UNCOV
182
// DBDir returns the holding directory path of the graph database.
×
183
func (cfg BaseNodeConfig) DBDir() string {
×
184
        return filepath.Join(cfg.DataDir, "graph", cfg.NetParams.Name)
185
}
UNCOV
186

×
187
func (cfg BaseNodeConfig) DBPath() string {
×
188
        return filepath.Join(cfg.DBDir(), "channel.db")
×
189
}
UNCOV
190

×
191
func (cfg BaseNodeConfig) ChanBackupPath() string {
×
192
        return filepath.Join(
×
193
                cfg.DataDir, "chain", lnd.BitcoinChainName,
194
                fmt.Sprintf(
×
195
                        "%v/%v", cfg.NetParams.Name,
×
196
                        chanbackup.DefaultBackupFileName,
×
197
                ),
×
198
        )
×
199
}
×
UNCOV
200

×
UNCOV
201
// GenerateListeningPorts generates the ports to listen on designated for the
×
UNCOV
202
// current lightning network test.
×
203
func (cfg *BaseNodeConfig) GenerateListeningPorts() {
204
        if cfg.P2PPort == 0 {
205
                cfg.P2PPort = port.NextAvailablePort()
206
        }
×
207
        if cfg.RPCPort == 0 {
×
208
                cfg.RPCPort = port.NextAvailablePort()
×
209
        }
×
210
        if cfg.RESTPort == 0 {
×
211
                cfg.RESTPort = port.NextAvailablePort()
×
212
        }
×
213
        if cfg.ProfilePort == 0 {
×
214
                cfg.ProfilePort = port.NextAvailablePort()
×
215
        }
×
UNCOV
216
}
×
UNCOV
217

×
UNCOV
218
// BaseConfig returns the base node configuration struct.
×
219
func (cfg *BaseNodeConfig) BaseConfig() *BaseNodeConfig {
220
        return cfg
221
}
UNCOV
222

×
UNCOV
223
// GenArgs generates a slice of command line arguments from the lightning node
×
UNCOV
224
// config struct.
×
225
func (cfg *BaseNodeConfig) GenArgs() []string {
226
        var args []string
227

228
        switch cfg.NetParams {
×
229
        case &chaincfg.TestNet3Params:
×
230
                args = append(args, "--bitcoin.testnet")
×
231
        case &chaincfg.TestNet4Params:
×
232
                args = append(args, "--bitcoin.testnet4")
×
233
        case &chaincfg.SimNetParams:
×
234
                args = append(args, "--bitcoin.simnet")
×
235
        case &chaincfg.RegressionNetParams:
×
236
                args = append(args, "--bitcoin.regtest")
×
UNCOV
237
        }
×
UNCOV
238

×
239
        backendArgs := cfg.BackendCfg.GenArgs()
×
240
        args = append(args, backendArgs...)
241

242
        nodeArgs := []string{
×
243
                "--nobootstrap",
×
244
                "--debuglevel=debug",
×
245
                "--bitcoin.defaultchanconfs=1",
×
246
                "--accept-keysend",
×
247
                "--keep-failed-payment-attempts",
×
248
                "--logging.no-commit-hash",
×
249
                fmt.Sprintf("--db.batch-commit-interval=%v", commitInterval),
×
250
                fmt.Sprintf("--bitcoin.defaultremotedelay=%v", DefaultCSV),
×
251
                fmt.Sprintf("--rpclisten=%v", cfg.RPCAddr()),
×
252
                fmt.Sprintf("--restlisten=%v", cfg.RESTAddr()),
×
253
                fmt.Sprintf("--restcors=https://%v", cfg.RESTAddr()),
×
254
                fmt.Sprintf("--listen=%v", cfg.P2PAddr()),
×
255
                fmt.Sprintf("--externalip=%v", cfg.P2PAddr()),
×
256
                fmt.Sprintf("--lnddir=%v", cfg.BaseDir),
×
257
                fmt.Sprintf("--adminmacaroonpath=%v", cfg.AdminMacPath),
×
258
                fmt.Sprintf("--readonlymacaroonpath=%v", cfg.ReadMacPath),
×
259
                fmt.Sprintf("--invoicemacaroonpath=%v", cfg.InvoiceMacPath),
×
260
                fmt.Sprintf("--trickledelay=%v", trickleDelay),
×
261

×
262
                // Use a small batch delay so we can broadcast the
×
263
                // announcements quickly in the tests.
×
264
                "--gossip.sub-batch-delay=5ms",
×
265

×
266
                // Use a small cache duration so the `DescribeGraph` can be
×
267
                // updated quicker.
×
268
                "--caches.rpc-graph-cache-duration=100ms",
×
269

×
270
                // Speed up the tests for bitcoind backend.
×
271
                "--bitcoind.blockpollinginterval=100ms",
×
272
                "--bitcoind.txpollinginterval=100ms",
×
273

×
274
                // Allow unsafe disconnect in itest.
×
275
                "--dev.unsafedisconnect",
×
276
        }
×
277

×
278
        args = append(args, nodeArgs...)
×
279

×
280
        if cfg.Password == nil {
×
281
                args = append(args, "--noseedbackup")
×
282
        }
×
UNCOV
283

×
284
        switch cfg.DBBackend {
×
285
        case BackendEtcd:
×
286
                args = append(args, "--db.backend=etcd")
287
                args = append(args, "--db.etcd.embedded")
×
288
                args = append(
×
289
                        args, fmt.Sprintf(
×
290
                                "--db.etcd.embedded_client_port=%v",
×
291
                                port.NextAvailablePort(),
×
292
                        ),
×
293
                )
×
294
                args = append(
×
295
                        args, fmt.Sprintf(
×
296
                                "--db.etcd.embedded_peer_port=%v",
×
297
                                port.NextAvailablePort(),
×
298
                        ),
×
299
                )
×
300
                args = append(
×
301
                        args, fmt.Sprintf(
×
302
                                "--db.etcd.embedded_log_file=%v",
×
303
                                path.Join(cfg.LogDir, "etcd.log"),
×
304
                        ),
×
305
                )
×
UNCOV
306

×
307
        case BackendPostgres:
×
308
                args = append(args, "--db.backend=postgres")
×
309
                args = append(args, "--db.postgres.dsn="+cfg.PostgresDsn)
310
                if cfg.NativeSQL {
×
311
                        args = append(args, "--db.use-native-sql")
×
312
                }
×
UNCOV
313

×
314
        case BackendSqlite:
×
315
                args = append(args, "--db.backend=sqlite")
×
316
                args = append(args, fmt.Sprintf("--db.sqlite.busytimeout=%v",
317
                        wait.SqliteBusyTimeout))
×
318
                if cfg.NativeSQL {
×
319
                        args = append(args, "--db.use-native-sql")
×
320
                }
×
UNCOV
321
        }
×
UNCOV
322

×
323
        if cfg.FeeURL != "" {
×
324
                args = append(args, "--fee.url="+cfg.FeeURL)
325
        }
UNCOV
326

×
UNCOV
327
        // Put extra args in the end so the args can be overwritten.
×
328
        if cfg.ExtraArgs != nil {
×
329
                args = append(args, cfg.ExtraArgs...)
330
        }
UNCOV
331

×
332
        return args
×
UNCOV
333
}
×
334

UNCOV
335
// ExtraArgsEtcd returns extra args for configuring LND to use an external etcd
×
336
// database (for remote channel DB and wallet DB).
337
func ExtraArgsEtcd(etcdCfg *etcd.Config, name string, cluster bool,
338
        leaderSessionTTL int) []string {
339

340
        extraArgs := []string{
341
                "--db.backend=etcd",
×
342
                fmt.Sprintf("--db.etcd.host=%v", etcdCfg.Host),
×
343
                fmt.Sprintf("--db.etcd.user=%v", etcdCfg.User),
×
344
                fmt.Sprintf("--db.etcd.pass=%v", etcdCfg.Pass),
×
345
                fmt.Sprintf("--db.etcd.namespace=%v", etcdCfg.Namespace),
×
346
        }
×
347

×
348
        if etcdCfg.InsecureSkipVerify {
×
349
                extraArgs = append(extraArgs, "--db.etcd.insecure_skip_verify")
×
350
        }
×
UNCOV
351

×
352
        if cluster {
×
353
                clusterArgs := []string{
×
354
                        "--cluster.enable-leader-election",
355
                        fmt.Sprintf("--cluster.id=%v", name),
×
356
                        fmt.Sprintf("--cluster.leader-session-ttl=%v",
×
357
                                leaderSessionTTL),
×
358
                }
×
359
                extraArgs = append(extraArgs, clusterArgs...)
×
360
                extraArgs = append(
×
361
                        extraArgs, "--healthcheck.leader.interval=10s",
×
362
                )
×
363
        }
×
UNCOV
364

×
365
        return extraArgs
×
UNCOV
366
}
×
367

UNCOV
368
// GetLogDir returns the passed --logdir flag or the default value if it wasn't
×
369
// set.
370
func GetLogDir() string {
371
        if logSubDir != nil && *logSubDir != "" {
372
                return *logSubDir
373
        }
×
UNCOV
374

×
375
        return "."
×
UNCOV
376
}
×
377

UNCOV
378
// CopyFile copies the file src to dest.
×
379
func CopyFile(dest, src string) error {
380
        s, err := os.Open(src)
381
        if err != nil {
382
                return err
×
383
        }
×
384
        defer s.Close()
×
385

×
386
        d, err := os.Create(dest)
×
387
        if err != nil {
×
388
                return err
×
389
        }
×
UNCOV
390

×
391
        if _, err := io.Copy(d, s); err != nil {
×
392
                d.Close()
×
393
                return err
394
        }
×
UNCOV
395

×
396
        return d.Close()
×
UNCOV
397
}
×
398

UNCOV
399
// GetBtcdBinary returns the full path to the binary of the custom built btcd
×
400
// executable or an empty string if none is set.
401
func GetBtcdBinary() string {
402
        if btcdExecutable != nil {
403
                return *btcdExecutable
404
        }
×
UNCOV
405

×
406
        return ""
×
UNCOV
407
}
×
408

UNCOV
409
func init() {
×
410
        // Before we start any node, we need to make sure that any btcd or
411
        // bitcoind node that is started through the RPC harness uses a unique
412
        // port as well to avoid any port collisions.
1✔
413
        rpctest.ListenAddressGenerator =
1✔
414
                port.GenerateSystemUniqueListenerAddresses
1✔
415
}
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