Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ jobs:
- name: Check RPC format
run: make rpc-check

- name: Check generated SQL code
run: make sqlc-check

- name: compile code
run: go install -v ./...

Expand Down
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ GOINSTALL := GO111MODULE=on go install -v

GOFILES = $(shell find . -type f -name '*.go' -not -name "*.pb.go")

SQL_DIR := wallet/internal/sql

RM := rm -f
CP := cp
MAKE := make
Expand Down Expand Up @@ -159,6 +161,21 @@ tidy-module:
tidy-module-check: tidy-module
if test -n "$$(git status --porcelain)"; then echo "modules not updated, please run `make tidy-module` again!"; git status; exit 1; fi

#? sqlc: Generate type-safe Go code for the SQL backends
sqlc: docker-tools
@$(call print, "Generating SQL models and queries.")
$(DOCKER_TOOLS) sqlc generate -f sqlc.yaml

#? sqlc-check: Verify generated SQL code is up to date
sqlc-check: sqlc
@$(call print, "Verifying generated SQL code.")
@if test -n "$$(git status --porcelain --untracked-files=all -- $(SQL_DIR))"; then \
echo "Generated SQL code is not up-to-date. Please run 'make sqlc' and commit the changes."; \
git status --short -- $(SQL_DIR); \
git diff -- $(SQL_DIR); \
exit 1; \
fi

.PHONY: all \
default \
build \
Expand All @@ -172,6 +189,8 @@ tidy-module-check: tidy-module
fmt-check \
tidy-module \
tidy-module-check \
sqlc \
sqlc-check \
rpc-format \
lint \
lint-config-check \
Expand Down
65 changes: 65 additions & 0 deletions docs/developer/sql_port_foundation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# SQL Port Foundation

## Scope

In this stage, we add the SQL build, connection, and migration foundation
without changing how `Wallet`, `waddrmgr`, or `wtxmgr` behave. The existing KV
path remains the reference implementation. SQLite and PostgreSQL are new
internal persistence targets behind the same wallet API.

The first schema slice contains block metadata only. Wallet, account, address,
transaction, UTXO, and lease tables land in later commits once their migration
contract has been checked against the current KV representation.

## `lnd/sqldb`

This stage uses the released `github.com/lightningnetwork/lnd/sqldb` module at
`v1.0.13` as the common SQL utility layer. In particular, the SQLite connection
defaults come directly from that module. Its transaction executor, retry
policy, backend-neutral error mapping, nullable-value helpers, and pagination
helpers are available to the later store adapter without copying those
utilities into btcwallet.

The schema and migration runners remain local to btcwallet. The concrete lnd
stores embed lnd's own schema and global migration ordering, while btcwallet
needs backend-specific triggers, functions, sequences, and table constraints.
The local wrappers also expose the down/target operations used by the rollback
gate. Sharing the utility layer without sharing the application schema keeps
the dependency boundary narrow.

We also evaluated the nested `github.com/lightningnetwork/lnd/sqldb/v2`
development module. It has useful connection work, but it has no released v2
tag and currently relies on a module-local `golang-migrate` replacement that
would not propagate to btcwallet. We therefore use the stable v1 module now
and leave a v2 upgrade as a normal dependency update once that line is
released.

## Compatibility Constraints

The wallet/address schema cannot be copied from `sql-wallet` unchanged. That
branch intentionally combines the storage port with a new encryption and
address-history model.

The port-first schema keeps the current dual-passphrase hierarchy. It must
represent the master public/private KDF parameters, all three encrypted crypto
keys, encrypted master HD public/private keys, and encrypted public/private
material at the scope, account, and address layers. Watch-only wallets retain
the current nullability rules, including the script fallback through the public
crypto key.

The port-first schema also persists the legacy sticky address-used bit. KV can
mark an address used without retaining enough transaction or UTXO history to
derive that fact later. Deriving used-ness from `EXISTS(utxos)` would therefore
change `LastUnusedAddress` and gap-limit behavior after migration.

These are storage compatibility requirements, not endorsements of the legacy
model forever. The single-passphrase/key-vault and history-derived address
designs can return as separate refactors after the SQL port has migration and
`lnd` end-to-end coverage.

## Verification

Every schema slice must regenerate cleanly with `make sqlc-check`. SQLite and
PostgreSQL migrations must both pass an empty-to-head, head-to-empty, and
empty-to-head round trip. No PR in this stage may change an exported wallet API
or require an `lnd` source adaptation.
107 changes: 91 additions & 16 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,48 +17,123 @@ require (
github.com/btcsuite/btcwallet/walletdb v1.6.0
github.com/btcsuite/btcwallet/wtxmgr v1.6.0
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792
github.com/davecgh/go-spew v1.1.1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0
github.com/golang-migrate/migrate/v4 v4.19.1
github.com/golang/protobuf v1.5.4
github.com/jackc/pgx/v5 v5.10.0
github.com/jessevdk/go-flags v1.6.1
github.com/jrick/logrotate v1.1.2
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf
github.com/lightninglabs/neutrino v0.18.0
github.com/lightninglabs/neutrino/cache v1.1.4
github.com/lightningnetwork/lnd/fn/v2 v2.0.8
github.com/lightningnetwork/lnd/sqldb v1.0.13
github.com/lightningnetwork/lnd/ticker v1.1.1
github.com/lightningnetwork/lnd/tlv v1.3.3-0.20260615022959-a067468f0f45
github.com/stretchr/testify v1.10.0
golang.org/x/crypto v0.41.0
golang.org/x/net v0.43.0
golang.org/x/sync v0.16.0
golang.org/x/term v0.34.0
google.golang.org/grpc v1.73.0
google.golang.org/protobuf v1.36.6
github.com/stretchr/testify v1.11.1
github.com/testcontainers/testcontainers-go v0.40.0
github.com/testcontainers/testcontainers-go/modules/postgres v0.40.0
golang.org/x/crypto v0.51.0
golang.org/x/net v0.53.0
golang.org/x/sync v0.20.0
golang.org/x/term v0.43.0
google.golang.org/grpc v1.80.0
google.golang.org/protobuf v1.36.11
modernc.org/sqlite v1.53.0
)

require (
dario.cat/mergo v1.0.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/aead/siphash v1.0.1 // indirect
github.com/btcsuite/btcd/v2transport v1.0.1 // indirect
github.com/btcsuite/btclog/v2 v2.0.1-0.20250602222548-9967d19bb084 // indirect
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/continuity v0.3.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/creack/pty v1.1.24 // indirect
github.com/decred/dcrd/crypto/blake256 v1.1.0 // indirect
github.com/decred/dcrd/lru v1.1.3 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/cli v28.1.1+incompatible // indirect
github.com/docker/docker v28.5.1+incompatible // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.10.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.14.3 // indirect
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.3 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/kcalvinalvin/anet v0.0.0-20251112173137-d8ddc1f6dbee // indirect
github.com/kkdai/bstream v1.0.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/klauspost/compress v1.18.5 // indirect
github.com/lightningnetwork/lnd/clock v1.0.1 // indirect
github.com/lightningnetwork/lnd/queue v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.10 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/go-archive v0.2.0 // indirect
github.com/moby/patternmatcher v0.6.1 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/runc v1.1.14 // indirect
github.com/ory/dockertest/v3 v3.10.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/shirou/gopsutil/v4 v4.26.5 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/stretchr/objx v0.5.3 // indirect
github.com/tklauser/go-sysconf v0.3.16 // indirect
github.com/tklauser/numcpus v0.11.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.etcd.io/bbolt v1.3.11 // indirect
go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.41.0 // indirect
go.opentelemetry.io/otel/metric v1.41.0 // indirect
go.opentelemetry.io/otel/trace v1.41.0 // indirect
golang.org/x/exp v0.0.0-20250811191247-51f88131bc50 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/text v0.28.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
golang.org/x/sys v0.45.0 // indirect
golang.org/x/text v0.37.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.73.4 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
)

// If you change this please run `make lint` to see where else it needs to be
Expand Down
Loading
Loading