wallet/sql: implement waddrmgr store with sqlc - #1296
Draft
Roasbeef wants to merge 3 commits into
Draft
Conversation
The SQL port needs a persistence boundary that does not expose a walletdb bucket on every operation. At the same time, the Bolt path should continue to use the existing row codecs and manager helpers. In this commit, we add durable manager, sync, scope, account, and address state types together with read and write store interfaces. A thin KV adapter binds the bucket once and delegates to the existing implementation. The adapter preserves address hashes, used state, birthday block timestamps, and bulk sync restore semantics. A focused KV test covers the adapter against a real manager database. Extracted-from: 650062f Extracted-from: 2839c1e
The manager boundary now covers the complete durable waddrmgr state, but the SQL backends still need to implement it without introducing a second hand-written query layer or changing wallet control flow. In this commit, we add named sqlc queries for manager metadata, sync state, key scopes, accounts, and addresses. SQLite and PostgreSQL adapters normalize their generated integer and nullable types behind one store contract. The SQL store preserves the callback transaction model, legacy address identifiers, birthday block timestamps, private-key deletion behavior, and waddrmgr not-found errors. The two dialect query trees remain explicit. All runtime SQL in this path is generated by sqlc. Extracted-from: 168d1df470f95a04000181b43035cebb271b5cee Extracted-from: 99e40ab Extracted-from: 7e20ac1
The address-manager port needs one behavioral vector that runs unchanged against both SQL dialects. Separate happy-path tests would not catch differences in null handling, integer widths, or legacy error translation. In this commit, we extend the manager-store conformance suite across the complete durable waddrmgr surface. The vector covers manager and sync metadata, exact birthday block stamps, scopes, both account encodings, address variants, used state, updates, private-key deletion, and legacy not-found errors. The same test runs against SQLite and PostgreSQL. Extracted-from: e0622ab Extracted-from: f371c683950093a5306b57a9070d876ec32d956e
Roasbeef
force-pushed
the
sql-port-stage2-waddrmgr
branch
from
July 15, 2026 00:56
3ca9326 to
3cf0329
Compare
Roasbeef
changed the base branch from
sql-port-stage2-store-contract
to
sql-port-stage2-wtxmgr
July 15, 2026 00:56
This was referenced Jul 20, 2026
[DRAFT] wallet: Stage 3 SQL runtime — Gate 2 recovery vertical on the #1296 salvage foundation
#1297
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
In this PR, we complete the
waddrmgrside of the SQL store boundary introduced in #1293. This is the address-manager follow-up stacked on #1295, so the combined branch exercises both complete manager surfaces behind one transaction boundary.The goal here is deliberately narrow: carry the existing durable
waddrmgrstate across the backend boundary without exposing walletdb buckets to SQL callers. We don't route the wallet runtime through the new store or add migration logic in this PR.Design
The new
waddrmgrinterfaces cover manager metadata, sync state, key scopes, accounts, addresses, and private-key deletion. The KV adapter binds its bucket once, then delegates to the existingwaddrmgrhelpers and row codecs. This keeps the Bolt path on the implementation we already use today.For SQL, both SQLite and PostgreSQL use named sqlc queries and generated query types. There is no hand-written runtime SQL or DBTX escape hatch in the manager store. The dialect-specific query trees remain separate for now, with integer widths and nullable values normalized in the backend adapters.
The store preserves the details that matter for a port-first cut:
waddrmgrnot-found error codes.Relationship to the Existing waddrmgr
The new
waddrmgr/store.gois the persistence contract and durable state model. The newwaddrmgr/store_kv.gois the thin KV adapter overdb.go. Neither file replacesmanager.goor adds a second address manager.manager.goremains the behavioral layer. It owns key management, locking, scopes, accounts, address derivation, and the other wallet operations already exposed bywaddrmgr.db.goremains the existing KV persistence implementation. It owns the bucket layout, legacy rows, serialization, and low-level read/write helpers.For the KV backend,
store_kv.gobinds the walletdb bucket once and presents the bucket-free interface. Its methods assemble the new durable state types or translate them back into the existing rows, then call the helpers indb.go. As an example,SyncStatecalls the existing start-block, synced-to, birthday, and birthday-block readers.PutAddressconverts anAddressStateinto the existing address row and calls the existingputAddresshelper.The SQL backend implements the same interface in
wallet/internal/db/sqlstore, using generated sqlc queries instead of the KV adapter. The intended routing is therefore:Keeping
store_kv.goin thewaddrmgrpackage is intentional: the adapter can reuse the existing unexported helpers, row types, and codecs without exporting KV internals or creating a second implementation. Productionmanager.gostill calls walletdb anddb.godirectly today. Moving those call sites behind the interface is a later integration slice. This PR only creates the complete durable boundary and proves that the old KV representation and the two SQL backends can satisfy it.The commits retain extraction trailers for the source work so the original contribution remains visible.
Testing
make sqlcgo test -count=1 ./waddrmgr ./wallet/internal/db/...go test -tags=test_db_postgres -count=1 ./wallet/internal/db/itest -vgo vet ./waddrmgr ./wallet/internal/db/...A full
go test -count=1 ./...attempt passed the changed packages and stopped inchain/TestBitcoindEventswhen the locally spawned bitcoind RPC endpoints refused connections.