Repository: lightningnetwork/lnd
Pull request #9713 (2025-04-14 14:56:22)

scripts: use LND status to determine when a node is ready for RPC calls
## Context

The backwards compatibility test sometimes fails due to the `[lncli] rpc error: code = Unknown desc = server is still in the process of starting` error when we try to connect nodes right after checking if they have started. This is cause the `has started` check currently only checks if the GetInfo call is available - but it can be available before LND has actually fully started.  

## This PR:

use The `StateServer` (via `lncli status`) when waiting for a node to be ready as this is a more reliable/accurate signal that the node is ready for other RPC calls. 

coderabbitai[bot]: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Auto reviews are limited to specific labels.
> 
> <details>
> <summary>:label: Labels to auto review (1)</summary>
> 
> * llm-review
> 
> </details>
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=lightningnetwork/lnd&utm_content=9713):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
bhandras: Note that we also have the state service which has similar functionality that we already suggest using for readiness probes:
https://github.com/lightningnetwork/lnd/blob/master/lnrpc/stateservice.proto (docs: https://github.com/lightningnetwork/lnd/blob/6d648ad90ab70e45449fa98594305a4aa2865f62/docs/leader_election.md?plain=1#L82).
ellemouton: ah! cool, thanks @bhandras ! I'll update to make use of that instead 
bhandras: > ah! cool, thanks @bhandras ! I'll update to make use of that instead

Actually, there's an even simpler way to check which doesn't require installing `curl` and `jq` to the container image:

```
lncli state | grep -q SERVER_ACTIVE
```

Patch:
diff --git a/channeldb/migration_01_to_11/db.go b/channeldb/migration_01_to_11/db.go
index 4045d52bd..65cc8d221 100644
--- a/channeldb/migration_01_to_11/db.go
+++ b/channeldb/migration_01_to_11/db.go
@@ -57,7 +57,7 @@ func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) {
 	// freelist grows to be very large.
 	bdb, err := kvdb.Open(
 		kvdb.BoltBackendName, path,
-		opts.NoFreelistSync, opts.DBTimeout, false,
+		opts.NoFreelistSync, opts.DBTimeout,
 	)
 	if err != nil {
 		return nil, err
@@ -89,7 +89,6 @@ func createChannelDB(dbPath string) error {
 	path := filepath.Join(dbPath, dbName)
 	bdb, err := kvdb.Create(
 		kvdb.BoltBackendName, path, false, kvdb.DefaultDBTimeout,
-		false,
 	)
 	if err != nil {
 		return err
diff --git a/config_builder.go b/config_builder.go
index 2214250e7..d4106a0ab 100644
--- a/config_builder.go
+++ b/config_builder.go
@@ -1430,74 +1430,6 @@ func importWatchOnlyAccounts(wallet *wallet.Wallet,
 	return nil
 }
 
-// handleNeutrinoPostgresDBMigration handles the migration of the neutrino db
-// to postgres. Initially we kept the neutrino db in the bolt db when running
-// with kvdb postgres backend. Now now move it to postgres as well. However we
-// need to make a distinction whether the user migrated the neutrino db to
-// postgres via lndinit or not. Currently if the db is not migrated we start
-// with a fresh db in postgres.
-//
-// TODO(ziggie): Also migrate the db to postgres in case it is still not
-// migrated ?
-func handleNeutrinoPostgresDBMigration(dbName, dbPath string,
-	cfg *Config) error {
-
-	if !lnrpc.FileExists(dbName) {
-		return nil
-	}
-
-	// Open bolt db to check if it is tombstoned. If it is we assume that
-	// the neutrino db was successfully migrated to postgres. We open it
-	// in read-only mode to avoid long db open times.
-	boltDB, err := kvdb.Open(
-		kvdb.BoltBackendName, dbName, true,
-		cfg.DB.Bolt.DBTimeout, true,
-	)
-	if err != nil {
-		return fmt.Errorf("failed to open bolt db: %w", err)
-	}
-	defer boltDB.Close()
-
-	isTombstoned := false
-	err = boltDB.View(func(tx kvdb.RTx) error {
-		_, err = channeldb.CheckMarkerPresent(
-			tx, channeldb.TombstoneKey,
-		)
-
-		return err
-	}, func() {})
-	if err == nil {
-		isTombstoned = true
-	}
-
-	if isTombstoned {
-		ltndLog.Infof("Neutrino Bolt DB is tombstoned, assuming " +
-			"database was successfully migrated to postgres")
-
-		return nil
-	}
-
-	// If the db is not tombstoned, we remove the files and start fresh with
-	// postgres. This is the case when a user was running lnd with the
-	// postgres backend from the beginning without migrating from bolt.
-	ltndLog.Infof("Neutrino Bolt DB found but NOT tombstoned, removing " +
-		"it and starting fresh with postgres")
-
-	filesToRemove := []string{
-		filepath.Join(dbPath, "block_headers.bin"),
-		filepath.Join(dbPath, "reg_filter_headers.bin"),
-		dbName,
-	}
-
-	for _, file := range filesToRemove {
-		if err := os.Remove(file); err != nil {
-			ltndLog.Warnf("Could not remove %s: %v", file, err)
-		}
-	}
-
-	return nil
-}
-
 // initNeutrinoBackend inits a new instance of the neutrino light client
 // backend given a target chain directory to store the chain state.
 func initNeutrinoBackend(ctx context.Context, cfg *Config, chainDir string,
@@ -1539,29 +1471,10 @@ func initNeutrinoBackend(ctx context.Context, cfg *Config, chainDir string,
 			lncfg.SqliteNeutrinoDBName, lncfg.NSNeutrinoDB,
 		)
 
-	case cfg.DB.Backend == kvdb.PostgresBackendName:
-		dbName := filepath.Join(dbPath, lncfg.NeutrinoDBName)
-
-		// This code needs to be in place because we did not start
-		// the postgres backend for neutrino at the beginning. Now we
-		// are also moving it into the postgres backend so we can phase
-		// out the bolt backend.
-		err = handleNeutrinoPostgresDBMigration(dbName, dbPath, cfg)
-		if err != nil {
-			return nil, nil, err
-		}
-
-		postgresConfig := lncfg.GetPostgresConfigKVDB(cfg.DB.Postgres)
-		db, err = kvdb.Open(
-			kvdb.PostgresBackendName, ctx, postgresConfig,
-			lncfg.NSNeutrinoDB,
-		)
-
 	default:
-		dbName := filepath.Join(dbPath, lncfg.NeutrinoDBName)
+		dbName := filepath.Join(dbPath, "neutrino.db")
 		db, err = walletdb.Create(
-			kvdb.BoltBackendName, dbName, !cfg.SyncFreelist,
-			cfg.DB.Bolt.DBTimeout, false,
+			"bdb", dbName, !cfg.SyncFreelist, cfg.DB.Bolt.DBTimeout,
 		)
 	}
 	if err != nil {
diff --git a/docs/release-notes/release-notes-0.19.0.md b/docs/release-notes/release-notes-0.19.0.md
index 5f02bbbd8..31d1800cf 100644
--- a/docs/release-notes/release-notes-0.19.0.md
+++ b/docs/release-notes/release-notes-0.19.0.md
@@ -111,9 +111,6 @@ keysend payment validation is stricter.
   process of the node won't be interrupted if a non-fatal error is returned from
   the subsystems.
 
-* [Fixed](https://github.com/lightningnetwork/lnd/pull/9703) a possible panic
-  when reloading legacy inflight payments which don't have the MPP feature.
-
 # New Features
 
 * Add support for [archiving channel backup](https://github.com/lightningnetwork/lnd/pull/9232)
@@ -150,6 +147,8 @@ close transaction.
   initial historical sync may be blocked due to a race condition in handling the
   syncer's internal state.
 
+
+
 * [The max fee rate](https://github.com/lightningnetwork/lnd/pull/9491) is now
   respected when a coop close is initiated. Before the max fee rate would only
   be effective for the remote party in the negotiation.
@@ -464,9 +463,6 @@ the on going rate we'll permit.
 * [Establish a base DB version even if it is not yet
   tracked](https://github.com/lightningnetwork/lnd/pull/9647).
 
-* [When running with neutrino as a backend with the kv-db backend `postgres`
-selected use postgres for the neutrino.db store](https://github.com/lightningnetwork/lnd/pull/9674).
-
 ## Code Health
 
 * A code refactor that [moves all the graph related DB code out of the 
diff --git a/go.mod b/go.mod
index cb032f756..58959279b 100644
--- a/go.mod
+++ b/go.mod
@@ -11,11 +11,11 @@ require (
 	github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0
 	github.com/btcsuite/btclog v0.0.0-20241003133417-09c4e92e319c
 	github.com/btcsuite/btclog/v2 v2.0.1-0.20250110154127-3ae4bf1cb318
-	github.com/btcsuite/btcwallet v0.16.13-0.20250409141346-8e790bfb5832
+	github.com/btcsuite/btcwallet v0.16.12
 	github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5
 	github.com/btcsuite/btcwallet/wallet/txrules v1.2.2
-	github.com/btcsuite/btcwallet/walletdb v1.5.1
-	github.com/btcsuite/btcwallet/wtxmgr v1.5.5
+	github.com/btcsuite/btcwallet/walletdb v1.4.4
+	github.com/btcsuite/btcwallet/wtxmgr v1.5.4
 	github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
 	github.com/davecgh/go-spew v1.1.1
 	github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0
@@ -40,7 +40,7 @@ require (
 	github.com/lightningnetwork/lnd/clock v1.1.1
 	github.com/lightningnetwork/lnd/fn/v2 v2.0.8
 	github.com/lightningnetwork/lnd/healthcheck v1.2.6
-	github.com/lightningnetwork/lnd/kvdb v1.4.15
+	github.com/lightningnetwork/lnd/kvdb v1.4.14
 	github.com/lightningnetwork/lnd/queue v1.1.1
 	github.com/lightningnetwork/lnd/sqldb v1.0.9
 	github.com/lightningnetwork/lnd/ticker v1.1.1
diff --git a/go.sum b/go.sum
index 5bbd5a544..445f10f1b 100644
--- a/go.sum
+++ b/go.sum
@@ -62,18 +62,18 @@ github.com/btcsuite/btclog v0.0.0-20241003133417-09c4e92e319c/go.mod h1:w7xnGOhw
 github.com/btcsuite/btclog/v2 v2.0.1-0.20250110154127-3ae4bf1cb318 h1:oCjIcinPt7XQ644MP/22JcjYEC84qRc3bRBH0d7Hhd4=
 github.com/btcsuite/btclog/v2 v2.0.1-0.20250110154127-3ae4bf1cb318/go.mod h1:XItGUfVOxotJL8kkuk2Hj3EVow5KCugXl3wWfQ6K0AE=
 github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
-github.com/btcsuite/btcwallet v0.16.13-0.20250409141346-8e790bfb5832 h1:Nd5r1YDNN47hn2UVyOcIJjNRvA90bpUrSVp8wnPMa18=
-github.com/btcsuite/btcwallet v0.16.13-0.20250409141346-8e790bfb5832/go.mod h1:Lpr6jNoTiWlgaXqFP+ar2YWSiD6Fl8xlh99WPvuErS4=
+github.com/btcsuite/btcwallet v0.16.12 h1:9SREKY892i1xTGlGLcu6x7O+WSQFn6+uQrSuskAOqh0=
+github.com/btcsuite/btcwallet v0.16.12/go.mod h1:jBn+ThFrx/QqW0nXiGvXtJytju4aVoW7C0hY4s/+9vo=
 github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5 h1:Rr0njWI3r341nhSPesKQ2JF+ugDSzdPoeckS75SeDZk=
 github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5/go.mod h1:+tXJ3Ym0nlQc/iHSwW1qzjmPs3ev+UVWMbGgfV1OZqU=
 github.com/btcsuite/btcwallet/wallet/txrules v1.2.2 h1:YEO+Lx1ZJJAtdRrjuhXjWrYsmAk26wLTlNzxt2q0lhk=
 github.com/btcsuite/btcwallet/wallet/txrules v1.2.2/go.mod h1:4v+grppsDpVn91SJv+mZT7B8hEV4nSmpREM4I8Uohws=
 github.com/btcsuite/btcwallet/wallet/txsizes v1.2.5 h1:93o5Xz9dYepBP4RMFUc9RGIFXwqP2volSWRkYJFrNtI=
 github.com/btcsuite/btcwallet/wallet/txsizes v1.2.5/go.mod h1:lQ+e9HxZ85QP7r3kdxItkiMSloSLg1PEGis5o5CXUQw=
-github.com/btcsuite/btcwallet/walletdb v1.5.1 h1:HgMhDNCrtEFPC+8q0ei5DQ5U9Tl4RCspA22DEKXlopI=
-github.com/btcsuite/btcwallet/walletdb v1.5.1/go.mod h1:jk/hvpLFINF0C1kfTn0bfx2GbnFT+Nvnj6eblZALfjs=
-github.com/btcsuite/btcwallet/wtxmgr v1.5.5 h1:VA/rHzAjiNuySPcKgdX3uAywbVczZlG5OZeSU7jYoZo=
-github.com/btcsuite/btcwallet/wtxmgr v1.5.5/go.mod h1:lzVbDkk/jRao2ib5kge46aLZW1yFc8RFNycdYpnsmZA=
+github.com/btcsuite/btcwallet/walletdb v1.4.4 h1:BDel6iT/ltYSIYKs0YbjwnEDi7xR3yzABIsQxN2F1L8=
+github.com/btcsuite/btcwallet/walletdb v1.4.4/go.mod h1:jk/hvpLFINF0C1kfTn0bfx2GbnFT+Nvnj6eblZALfjs=
+github.com/btcsuite/btcwallet/wtxmgr v1.5.4 h1:hJjHy1h/dJwSfD9uDsCwcH21D1iOrus6OrI5gR9E/O0=
+github.com/btcsuite/btcwallet/wtxmgr v1.5.4/go.mod h1:lAv0b1Vj9Ig5U8QFm0yiJ9WqPl8yGO/6l7JxdHY1PKE=
 github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
 github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
 github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc=
@@ -371,8 +371,8 @@ github.com/lightningnetwork/lnd/fn/v2 v2.0.8 h1:r2SLz7gZYQPVc3IZhU82M66guz3Zk2oY
 github.com/lightningnetwork/lnd/fn/v2 v2.0.8/go.mod h1:TOzwrhjB/Azw1V7aa8t21ufcQmdsQOQMDtxVOQWNl8s=
 github.com/lightningnetwork/lnd/healthcheck v1.2.6 h1:1sWhqr93GdkWy4+6U7JxBfcyZIE78MhIHTJZfPx7qqI=
 github.com/lightningnetwork/lnd/healthcheck v1.2.6/go.mod h1:Mu02um4CWY/zdTOvFje7WJgJcHyX2zq/FG3MhOAiGaQ=
-github.com/lightningnetwork/lnd/kvdb v1.4.15 h1:3eN6uGcubvGB5itPp1D0D4uEEkIMYht3w0LDnqLzAWI=
-github.com/lightningnetwork/lnd/kvdb v1.4.15/go.mod h1:HW+bvwkxNaopkz3oIgBV6NEnV4jCEZCACFUcNg4xSjM=
+github.com/lightningnetwork/lnd/kvdb v1.4.14 h1:VALUyoBCFKQm/3GAIdTIoUGplWBfZbo5uCr7BTY9QZY=
+github.com/lightningnetwork/lnd/kvdb v1.4.14/go.mod h1:1y0Z81CGQu4SMpcnAie/oK4tzgEqFQqFdj6k3fz2s8s=
 github.com/lightningnetwork/lnd/queue v1.1.1 h1:99ovBlpM9B0FRCGYJo6RSFDlt8/vOkQQZznVb18iNMI=
 github.com/lightningnetwork/lnd/queue v1.1.1/go.mod h1:7A6nC1Qrm32FHuhx/mi1cieAiBZo5O6l8IBIoQxvkz4=
 github.com/lightningnetwork/lnd/sqldb v1.0.9 h1:7OHi+Hui823mB/U9NzCdlZTAGSVdDCbjp33+6d/Q+G0=
diff --git a/invoices/sql_migration.go b/invoices/sql_migration.go
index 2ee41fd41..0d590320d 100644
--- a/invoices/sql_migration.go
+++ b/invoices/sql_migration.go
@@ -17,7 +17,6 @@ import (
 	"github.com/lightningnetwork/lnd/sqldb"
 	"github.com/lightningnetwork/lnd/sqldb/sqlc"
 	"github.com/pmezard/go-difflib/difflib"
-	"golang.org/x/time/rate"
 )
 
 var (
@@ -434,17 +433,11 @@ func MigrateInvoicesToSQL(ctx context.Context, db kvdb.Backend,
 	}
 	log.Debugf("Created SQL invoice hash index in %v", time.Since(t0))
 
-	s := rate.Sometimes{
-		Interval: 30 * time.Second,
-	}
-
-	t0 = time.Now()
-	chunk := 0
 	total := 0
-
 	// Now we can start migrating the invoices. We'll do this in
 	// batches to reduce memory usage.
 	for {
+		t0 = time.Now()
 		query := InvoiceQuery{
 			IndexOffset:    offset,
 			NumMaxInvoices: uint64(batchSize),
@@ -452,11 +445,13 @@ func MigrateInvoicesToSQL(ctx context.Context, db kvdb.Backend,
 
 		queryResult, err := kvStore.QueryInvoices(ctx, query)
 		if err != nil && !errors.Is(err, ErrNoInvoicesCreated) {
-			return fmt.Errorf("unable to query invoices: %w", err)
+			return fmt.Errorf("unable to query invoices: "+
+				"%w", err)
 		}
 
 		if len(queryResult.Invoices) == 0 {
-			log.Infof("All invoices migrated. Total: %d", total)
+			log.Infof("All invoices migrated")
+
 			break
 		}
 
@@ -466,19 +461,9 @@ func MigrateInvoicesToSQL(ctx context.Context, db kvdb.Backend,
 		}
 
 		offset = queryResult.LastIndexOffset
-		resultCnt := len(queryResult.Invoices)
-		total += resultCnt
-		chunk += resultCnt
-
-		s.Do(func() {
-			elapsed := time.Since(t0).Seconds()
-			ratePerSec := float64(chunk) / elapsed
-			log.Debugf("Migrated %d invoices (%.2f invoices/sec)",
-				total, ratePerSec)
-
-			t0 = time.Now()
-			chunk = 0
-		})
+		total += len(queryResult.Invoices)
+		log.Debugf("Migrated %d KV invoices to SQL in %v\n", total,
+			time.Since(t0))
 	}
 
 	// Clean up the hash index as it's no longer needed.
diff --git a/kvdb/backend.go b/kvdb/backend.go
index 269d5d821..e42c02233 100644
--- a/kvdb/backend.go
+++ b/kvdb/backend.go
@@ -73,10 +73,6 @@ type BoltBackendConfig struct {
 	// DBTimeout specifies the timeout value to use when opening the wallet
 	// database.
 	DBTimeout time.Duration
-
-	// ReadOnly specifies if the database should be opened in read-only
-	// mode.
-	ReadOnly bool
 }
 
 // GetBoltBackend opens (or creates if doesn't exits) a bbolt backed database
@@ -94,7 +90,7 @@ func GetBoltBackend(cfg *BoltBackendConfig) (Backend, error) {
 
 		return Create(
 			BoltBackendName, dbFilePath,
-			cfg.NoFreelistSync, cfg.DBTimeout, cfg.ReadOnly,
+			cfg.NoFreelistSync, cfg.DBTimeout,
 		)
 	}
 
@@ -108,7 +104,7 @@ func GetBoltBackend(cfg *BoltBackendConfig) (Backend, error) {
 
 	return Open(
 		BoltBackendName, dbFilePath,
-		cfg.NoFreelistSync, cfg.DBTimeout, cfg.ReadOnly,
+		cfg.NoFreelistSync, cfg.DBTimeout,
 	)
 }
 
@@ -298,7 +294,6 @@ func GetTestBackend(path, name string) (Backend, func(), error) {
 			DBFileName:     name,
 			NoFreelistSync: true,
 			DBTimeout:      DefaultDBTimeout,
-			ReadOnly:       false,
 		})
 		if err != nil {
 			return nil, nil, err
diff --git a/kvdb/backend_js.go b/kvdb/backend_js.go
index 23dc0b2ea..f1774408d 100644
--- a/kvdb/backend_js.go
+++ b/kvdb/backend_js.go
@@ -35,10 +35,6 @@ type BoltBackendConfig struct {
 	// DBTimeout specifies the timeout value to use when opening the wallet
 	// database.
 	DBTimeout time.Duration
-
-	// ReadOnly specifies if the database should be opened in read-only
-	// mode.
-	ReadOnly bool
 }
 
 // GetBoltBackend opens (or creates if doesn't exits) a bbolt backed database
diff --git a/kvdb/bolt_fixture.go b/kvdb/bolt_fixture.go
index fc3ca1a17..0ac54b55f 100644
--- a/kvdb/bolt_fixture.go
+++ b/kvdb/bolt_fixture.go
@@ -28,7 +28,6 @@ func (b *boltFixture) NewBackend() walletdb.DB {
 		DBFileName:     "test.db",
 		NoFreelistSync: true,
 		DBTimeout:      DefaultDBTimeout,
-		ReadOnly:       false,
 	})
 	require.NoError(b.t, err)
 
diff --git a/kvdb/go.mod b/kvdb/go.mod
index b18fe0870..646c1691e 100644
--- a/kvdb/go.mod
+++ b/kvdb/go.mod
@@ -2,7 +2,7 @@ module github.com/lightningnetwork/lnd/kvdb
 
 require (
 	github.com/btcsuite/btclog/v2 v2.0.0-20241017175713-3428138b75c7
-	github.com/btcsuite/btcwallet/walletdb v1.5.1
+	github.com/btcsuite/btcwallet/walletdb v1.4.4
 	github.com/davecgh/go-spew v1.1.1
 	github.com/fergusstrange/embedded-postgres v1.25.0
 	github.com/google/btree v1.0.1
diff --git a/kvdb/go.sum b/kvdb/go.sum
index 5dce9ab8a..ba8f6edaf 100644
--- a/kvdb/go.sum
+++ b/kvdb/go.sum
@@ -42,8 +42,8 @@ github.com/btcsuite/btclog v0.0.0-20241003133417-09c4e92e319c/go.mod h1:w7xnGOhw
 github.com/btcsuite/btclog/v2 v2.0.0-20241017175713-3428138b75c7 h1:3Ct3zN3VCEKVm5nceWBBEKczc+jvTfVyOEG71ob2Yuc=
 github.com/btcsuite/btclog/v2 v2.0.0-20241017175713-3428138b75c7/go.mod h1:XItGUfVOxotJL8kkuk2Hj3EVow5KCugXl3wWfQ6K0AE=
 github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
-github.com/btcsuite/btcwallet/walletdb v1.5.1 h1:HgMhDNCrtEFPC+8q0ei5DQ5U9Tl4RCspA22DEKXlopI=
-github.com/btcsuite/btcwallet/walletdb v1.5.1/go.mod h1:jk/hvpLFINF0C1kfTn0bfx2GbnFT+Nvnj6eblZALfjs=
+github.com/btcsuite/btcwallet/walletdb v1.4.4 h1:BDel6iT/ltYSIYKs0YbjwnEDi7xR3yzABIsQxN2F1L8=
+github.com/btcsuite/btcwallet/walletdb v1.4.4/go.mod h1:jk/hvpLFINF0C1kfTn0bfx2GbnFT+Nvnj6eblZALfjs=
 github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
 github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
 github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
diff --git a/kvdb/interface.go b/kvdb/interface.go
index 5fd1ecd16..892483024 100644
--- a/kvdb/interface.go
+++ b/kvdb/interface.go
@@ -157,8 +157,4 @@ var (
 	// ErrDatabaseNotOpen is returned when a database instance is accessed
 	// before it is opened or after it is closed.
 	ErrDatabaseNotOpen = walletdb.ErrDbNotOpen
-
-	// ErrDbDoesNotExist is returned when a database instance is opened
-	// but it does not exist.
-	ErrDbDoesNotExist = walletdb.ErrDbDoesNotExist
 )
diff --git a/lncfg/db.go b/lncfg/db.go
index 553fa5733..d6400eac5 100644
--- a/lncfg/db.go
+++ b/lncfg/db.go
@@ -25,7 +25,6 @@ const (
 	TowerClientDBName = "wtclient.db"
 	TowerServerDBName = "watchtower.db"
 	WalletDBName      = "wallet.db"
-	NeutrinoDBName    = "neutrino.db"
 
 	SqliteChannelDBName  = "channel.sqlite"
 	SqliteChainDBName    = "chain.sqlite"
diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go
index a64c8c87e..9a7414079 100644
--- a/routing/payment_lifecycle.go
+++ b/routing/payment_lifecycle.go
@@ -14,7 +14,6 @@ import (
 	"github.com/lightningnetwork/lnd/graph/db/models"
 	"github.com/lightningnetwork/lnd/htlcswitch"
 	"github.com/lightningnetwork/lnd/lntypes"
-	"github.com/lightningnetwork/lnd/lnutils"
 	"github.com/lightningnetwork/lnd/lnwire"
 	"github.com/lightningnetwork/lnd/routing/route"
 	"github.com/lightningnetwork/lnd/routing/shards"
@@ -501,8 +500,7 @@ func (p *paymentLifecycle) collectResultAsync(attempt *channeldb.HTLCAttempt) {
 func (p *paymentLifecycle) collectResult(
 	attempt *channeldb.HTLCAttempt) (*htlcswitch.PaymentResult, error) {
 
-	log.Tracef("Collecting result for attempt %v",
-		lnutils.SpewLogClosure(attempt))
+	log.Tracef("Collecting result for attempt %v", spew.Sdump(attempt))
 
 	result := &htlcswitch.PaymentResult{}
 
@@ -1062,38 +1060,6 @@ func marshallError(sendError error, time time.Time) *channeldb.HTLCFailInfo {
 	return response
 }
 
-// patchLegacyPaymentHash will make a copy of the passed attempt and sets its
-// Hash field to be the payment hash if it's nil.
-//
-// NOTE: For legacy payments, which were created before the AMP feature was
-// enabled, the `Hash` field in their HTLC attempts is nil. In that case, we use
-// the payment hash as the `attempt.Hash` as they are identical.
-func (p *paymentLifecycle) patchLegacyPaymentHash(
-	a channeldb.HTLCAttempt) channeldb.HTLCAttempt {
-
-	// Exit early if this is not a legacy attempt.
-	if a.Hash != nil {
-		return a
-	}
-
-	// Log a warning if the user is still using legacy payments, which has
-	// weaker support.
-	log.Warnf("Found legacy htlc attempt %v in payment %v", a.AttemptID,
-		p.identifier)
-
-	// Set the attempt's hash to be the payment hash, which is the payment's
-	// `PaymentHash`` in the `PaymentCreationInfo`. For legacy payments
-	// before AMP feature, the `Hash` field was not set so we use the
-	// payment hash instead.
-	//
-	// NOTE: During the router's startup, we have a similar logic in
-	// `resumePayments`, in which we will use the payment hash instead if
-	// the attempt's hash is nil.
-	a.Hash = &p.identifier
-
-	return a
-}
-
 // reloadInflightAttempts is called when the payment lifecycle is resumed after
 // a restart. It reloads all inflight attempts from the control tower and
 // collects the results of the attempts that have been sent before.
@@ -1109,10 +1075,6 @@ func (p *paymentLifecycle) reloadInflightAttempts() (DBMPPayment, error) {
 		log.Infof("Resuming HTLC attempt %v for payment %v",
 			a.AttemptID, p.identifier)
 
-		// Potentially attach the payment hash to the `Hash` field if
-		// it's a legacy payment.
-		a = p.patchLegacyPaymentHash(a)
-
 		p.resultCollector(&a)
 	}
 


Test patch:
diff --git a/aliasmgr/aliasmgr_test.go b/aliasmgr/aliasmgr_test.go
index b288ade0d..1844a82ef 100644
--- a/aliasmgr/aliasmgr_test.go
+++ b/aliasmgr/aliasmgr_test.go
@@ -19,7 +19,6 @@ func TestAliasStorePeerAlias(t *testing.T) {
 	dbPath := filepath.Join(t.TempDir(), "testdb")
 	db, err := kvdb.Create(
 		kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout,
-		false,
 	)
 	require.NoError(t, err)
 	defer db.Close()
@@ -53,7 +52,6 @@ func TestAliasStoreRequest(t *testing.T) {
 	dbPath := filepath.Join(t.TempDir(), "testdb")
 	db, err := kvdb.Create(
 		kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout,
-		false,
 	)
 	require.NoError(t, err)
 	defer db.Close()
@@ -86,7 +84,6 @@ func TestAliasLifecycle(t *testing.T) {
 	dbPath := filepath.Join(t.TempDir(), "testdb")
 	db, err := kvdb.Create(
 		kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout,
-		false,
 	)
 	require.NoError(t, err)
 	defer db.Close()
diff --git a/batch/batch_test.go b/batch/batch_test.go
index 7a73b8f4b..fef2c5597 100644
--- a/batch/batch_test.go
+++ b/batch/batch_test.go
@@ -17,7 +17,7 @@ func TestRetry(t *testing.T) {
 
 	dbName := filepath.Join(dbDir, "weks.db")
 	db, err := walletdb.Create(
-		"bdb", dbName, true, kvdb.DefaultDBTimeout, false,
+		"bdb", dbName, true, kvdb.DefaultDBTimeout,
 	)
 	if err != nil {
 		t.Fatalf("unable to create walletdb: %v", err)
diff --git a/channeldb/forwarding_package_test.go b/channeldb/forwarding_package_test.go
index b11764bee..c113d13d5 100644
--- a/channeldb/forwarding_package_test.go
+++ b/channeldb/forwarding_package_test.go
@@ -859,7 +859,7 @@ func makeFwdPkgDB(t *testing.T, path string) kvdb.Backend { // nolint:unparam
 	}
 
 	bdb, err := kvdb.Create(
-		kvdb.BoltBackendName, path, true, kvdb.DefaultDBTimeout, false,
+		kvdb.BoltBackendName, path, true, kvdb.DefaultDBTimeout,
 	)
 	require.NoError(t, err, "unable to open boltdb")
 
diff --git a/channeldb/migtest/migtest.go b/channeldb/migtest/migtest.go
index 66024c317..a3884a0d6 100644
--- a/channeldb/migtest/migtest.go
+++ b/channeldb/migtest/migtest.go
@@ -25,7 +25,6 @@ func MakeDB(t testing.TB) (kvdb.Backend, error) {
 
 	db, err := kvdb.Open(
 		kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout,
-		false,
 	)
 	if err != nil {
 		return nil, err
diff --git a/contractcourt/briefcase_test.go b/contractcourt/briefcase_test.go
index 3dfc155e4..aa2e711ef 100644
--- a/contractcourt/briefcase_test.go
+++ b/contractcourt/briefcase_test.go
@@ -149,7 +149,7 @@ var (
 func makeTestDB(t *testing.T) (kvdb.Backend, error) {
 	db, err := kvdb.Create(
 		kvdb.BoltBackendName, t.TempDir()+"/test.db", true,
-		kvdb.DefaultDBTimeout, false,
+		kvdb.DefaultDBTimeout,
 	)
 	if err != nil {
 		return nil, err
diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go
index 67a9a42e8..827e10b5c 100644
--- a/contractcourt/channel_arbitrator_test.go
+++ b/contractcourt/channel_arbitrator_test.go
@@ -475,7 +475,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog,
 		dbPath := filepath.Join(t.TempDir(), "testdb")
 		db, err := kvdb.Create(
 			kvdb.BoltBackendName, dbPath, true,
-			kvdb.DefaultDBTimeout, false,
+			kvdb.DefaultDBTimeout,
 		)
 		if err != nil {
 			return nil, err
diff --git a/htlcswitch/resolution_store_test.go b/htlcswitch/resolution_store_test.go
index 7562b6897..122c699a1 100644
--- a/htlcswitch/resolution_store_test.go
+++ b/htlcswitch/resolution_store_test.go
@@ -41,7 +41,6 @@ func TestInsertAndDelete(t *testing.T) {
 	dbPath := filepath.Join(t.TempDir(), "testdb")
 	db, err := kvdb.Create(
 		kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout,
-		false,
 	)
 	require.NoError(t, err)
 	t.Cleanup(func() {
diff --git a/lntest/unittest/backend.go b/lntest/unittest/backend.go
index 0c93fdb15..2bca3f96e 100644
--- a/lntest/unittest/backend.go
+++ b/lntest/unittest/backend.go
@@ -324,8 +324,7 @@ func NewNeutrinoBackend(t *testing.T, netParams *chaincfg.Params,
 
 	dbName := filepath.Join(spvDir, "neutrino.db")
 	spvDatabase, err := walletdb.Create(
-		kvdb.BoltBackendName, dbName, true, kvdb.DefaultDBTimeout,
-		false,
+		"bdb", dbName, true, kvdb.DefaultDBTimeout,
 	)
 	if err != nil {
 		t.Fatalf("unable to create walletdb: %v", err)
diff --git a/lnwallet/test/test_interface.go b/lnwallet/test/test_interface.go
index 8dce4892d..52ad1dded 100644
--- a/lnwallet/test/test_interface.go
+++ b/lnwallet/test/test_interface.go
@@ -3294,9 +3294,8 @@ func runTests(t *testing.T, walletDriver *lnwallet.WalletDriver,
 			// Start Alice - open a database, start a neutrino
 			// instance, and initialize a btcwallet driver for it.
 			aliceDB, err := walletdb.Create(
-				kvdb.BoltBackendName,
-				filepath.Join(tempTestDirAlice, "neutrino.db"),
-				true, kvdb.DefaultDBTimeout, false,
+				"bdb", tempTestDirAlice+"/neutrino.db", true,
+				kvdb.DefaultDBTimeout,
 			)
 			if err != nil {
 				t.Fatalf("unable to create DB: %v", err)
@@ -3324,9 +3323,8 @@ func runTests(t *testing.T, walletDriver *lnwallet.WalletDriver,
 			// Start Bob - open a database, start a neutrino
 			// instance, and initialize a btcwallet driver for it.
 			bobDB, err := walletdb.Create(
-				kvdb.BoltBackendName,
-				filepath.Join(tempTestDirBob, "neutrino.db"),
-				true, kvdb.DefaultDBTimeout, false,
+				"bdb", tempTestDirBob+"/neutrino.db", true,
+				kvdb.DefaultDBTimeout,
 			)
 			if err != nil {
 				t.Fatalf("unable to create DB: %v", err)
diff --git a/macaroons/service_test.go b/macaroons/service_test.go
index b7694ab3e..aad8af8db 100644
--- a/macaroons/service_test.go
+++ b/macaroons/service_test.go
@@ -35,7 +35,7 @@ var (
 func setupTestRootKeyStorage(t *testing.T) kvdb.Backend {
 	db, err := kvdb.Create(
 		kvdb.BoltBackendName, path.Join(t.TempDir(), "macaroons.db"), true,
-		kvdb.DefaultDBTimeout, false,
+		kvdb.DefaultDBTimeout,
 	)
 	require.NoError(t, err, "Error opening store DB")
 	t.Cleanup(func() {
diff --git a/macaroons/store_test.go b/macaroons/store_test.go
index 37dce7110..ace1e764a 100644
--- a/macaroons/store_test.go
+++ b/macaroons/store_test.go
@@ -37,7 +37,7 @@ func newTestStore(t *testing.T) (string, *macaroons.RootKeyStorage) {
 func openTestStore(t *testing.T, tempDir string) *macaroons.RootKeyStorage {
 	db, err := kvdb.Create(
 		kvdb.BoltBackendName, path.Join(tempDir, "weks.db"), true,
-		kvdb.DefaultDBTimeout, false,
+		kvdb.DefaultDBTimeout,
 	)
 	require.NoError(t, err)
 
diff --git a/routing/chainview/interface_test.go b/routing/chainview/interface_test.go
index ecd8bd597..b8726a875 100644
--- a/routing/chainview/interface_test.go
+++ b/routing/chainview/interface_test.go
@@ -757,8 +757,7 @@ var interfaceImpls = []struct {
 
 			dbName := filepath.Join(spvDir, "neutrino.db")
 			spvDatabase, err := walletdb.Create(
-				kvdb.BoltBackendName, dbName, true,
-				kvdb.DefaultDBTimeout, false,
+				"bdb", dbName, true, kvdb.DefaultDBTimeout,
 			)
 			if err != nil {
 				return nil, err
diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go
index e89df8aee..7270b6f6d 100644
--- a/routing/integrated_routing_context_test.go
+++ b/routing/integrated_routing_context_test.go
@@ -152,7 +152,6 @@ func (c *integratedRoutingContext) testPayment(maxParts uint32,
 
 	db, err := kvdb.Open(
 		kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout,
-		false,
 	)
 	if err != nil {
 		c.t.Fatal(err)
diff --git a/routing/missioncontrol_store_test.go b/routing/missioncontrol_store_test.go
index b83a526e9..f1788a96a 100644
--- a/routing/missioncontrol_store_test.go
+++ b/routing/missioncontrol_store_test.go
@@ -54,7 +54,6 @@ func newMCStoreTestHarness(t testing.TB, maxRecords int,
 
 	db, err := kvdb.Create(
 		kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout,
-		false,
 	)
 	require.NoError(t, err)
 	t.Cleanup(func() {
diff --git a/routing/missioncontrol_test.go b/routing/missioncontrol_test.go
index aa13a064a..dad033ac4 100644
--- a/routing/missioncontrol_test.go
+++ b/routing/missioncontrol_test.go
@@ -72,7 +72,6 @@ func createMcTestContext(t *testing.T) *mcTestContext {
 
 	ctx.db, err = kvdb.Open(
 		kvdb.BoltBackendName, ctx.dbPath, true, kvdb.DefaultDBTimeout,
-		false,
 	)
 	if err != nil {
 		t.Fatal(err)
diff --git a/routing/payment_lifecycle_test.go b/routing/payment_lifecycle_test.go
index 9df02ec32..b04b04d4b 100644
--- a/routing/payment_lifecycle_test.go
+++ b/routing/payment_lifecycle_test.go
@@ -1809,61 +1809,3 @@ func TestHandleAttemptResultSuccess(t *testing.T) {
 	require.NoError(t, err, "expected no error")
 	require.Equal(t, attempt, attemptResult.attempt)
 }
-
-// TestReloadInflightAttemptsLegacy checks that when handling a legacy HTLC
-// attempt, `collectResult` behaves as expected.
-func TestReloadInflightAttemptsLegacy(t *testing.T) {
-	t.Parallel()
-
-	// Create a test paymentLifecycle with the initial two calls mocked.
-	p, m := newTestPaymentLifecycle(t)
-
-	// Mount the resultCollector to check the full call path.
-	p.resultCollector = p.collectResultAsync
-
-	// Create testing params.
-	paymentAmt := 10_000
-	preimage := lntypes.Preimage{1}
-	attempt := makeSettledAttempt(t, paymentAmt, preimage)
-
-	// Make the attempt.Hash to be nil to mock a legacy payment.
-	attempt.Hash = nil
-
-	// Create a mock result returned from the switch.
-	result := &htlcswitch.PaymentResult{
-		Preimage: preimage,
-	}
-
-	// 1. calls `FetchPayment` and return the payment.
-	m.control.On("FetchPayment", p.identifier).Return(m.payment, nil).Once()
-
-	// 2. calls `InFlightHTLCs` and return the attempt.
-	attempts := []channeldb.HTLCAttempt{*attempt}
-	m.payment.On("InFlightHTLCs").Return(attempts).Once()
-
-	// 3. Mock the htlcswitch to return a the result chan.
-	resultChan := make(chan *htlcswitch.PaymentResult, 1)
-	m.payer.On("GetAttemptResult",
-		attempt.AttemptID, p.identifier, mock.Anything,
-	).Return(resultChan, nil).Once().Run(func(args mock.Arguments) {
-		// Send the preimage to the result chan.
-		resultChan <- result
-	})
-
-	// Now call the method under test.
-	payment, err := p.reloadInflightAttempts()
-	require.NoError(t, err)
-	require.Equal(t, m.payment, payment)
-
-	var r *switchResult
-
-	// Assert the result is returned within testTimeout.
-	waitErr := wait.NoError(func() error {
-		r = <-p.resultCollected
-		return nil
-	}, testTimeout)
-	require.NoError(t, waitErr, "timeout waiting for result")
-
-	// Assert the result is received as expected.
-	require.Equal(t, result, r.result)
-}
diff --git a/scripts/bw-compatibility-test/network.sh b/scripts/bw-compatibility-test/network.sh
index 16749e460..98eca675b 100644
--- a/scripts/bw-compatibility-test/network.sh
+++ b/scripts/bw-compatibility-test/network.sh
@@ -60,7 +60,7 @@ wait_for_node() {
 
   echo -n "⌛ Waiting for $node to start (timeout: ${TIMEOUT}s)"
 
-  while ! $node getinfo 2>/dev/null | grep -q identity_pubkey; do
+  while ! $node state 2>/dev/null | grep -q SERVER_ACTIVE; do
       echo -n "."
       sleep 0.5
 
@@ -96,10 +96,10 @@ do_for() {
 
 # setup_network sets up the basic A <> B <> C <> D network.
 function setup_network() {
-  wait_for_nodes alice bob charlie dave
-
   setup_bitcoin
 
+  wait_for_nodes alice bob charlie dave
+
   do_for fund_node alice bob charlie dave
   mine 6
 
diff --git a/walletunlocker/service_test.go b/walletunlocker/service_test.go
index 62dfc28d7..13ddb61e5 100644
--- a/walletunlocker/service_test.go
+++ b/walletunlocker/service_test.go
@@ -114,7 +114,7 @@ func openOrCreateTestMacStore(tempDir string, pw *[]byte,
 	}
 	db, err := kvdb.Create(
 		kvdb.BoltBackendName, path.Join(netDir, "macaroons.db"),
-		true, kvdb.DefaultDBTimeout, false,
+		true, kvdb.DefaultDBTimeout,
 	)
 	if err != nil {
 		return nil, err