bfdb399772
Brings in uncommitted work from SAMI-PC E:\repos\triangles
cpp20-modernization branch:
- RocksDB default chain DB + auto-migrate from txleveldb
- SQLite default wallet + non-destructive migration from Berkeley
- Boost.Asio removed from RPC (rpc_httpsocket.h)
- Boost removed from all daemon + GUI code
- New: walletdb-base.h, walletdb-batch.h, walletdb-sqlite.{h,cpp},
walletdb-factory.{h,cpp}, walletmigrate.{h,cpp}
- New tests: chaindb_runtime_tests, chaindb_equivalence_tests,
snapshotnet_tests
- Docs: BOOST-REMOVAL.md, ROCKSDB-DEFAULT-MIGRATION.md,
WALLET-SQLITE-MIGRATION.md
Does not yet build — needs CWalletDB->CWalletBatchTyped rebase in
walletdb.cpp/wallet.cpp/db.cpp and merge with origin/master for
v6 source files (checkpointpublisher, tor/, snapshot/, utxosnapshot,
bootstrap.cpp).
Build flags: -DBUILD_QT=OFF -DUSE_I2P_EMBEDDED=OFF
99 lines
5.8 KiB
Markdown
99 lines
5.8 KiB
Markdown
# Wallet storage: Berkeley DB → SQLite
|
|
|
|
Goal: retire Berkeley DB as the wallet store and make **SQLite the default**
|
|
wallet backend, with a transparent, non-destructive migration of existing
|
|
`wallet.dat` files. This removes the single ugliest build dependency (BDB 5.3
|
|
with C++ bindings, hand-built on RHEL/MSYS2) and gives the wallet a modern,
|
|
maintainable, single-file store — the kind exchanges expect.
|
|
|
|
No consensus or wire behavior changes. The on-disk *record encoding* is
|
|
unchanged: keys and values are the exact `SER_DISK / CLIENT_VERSION` bytes
|
|
`CWalletDB` already produces, just stored as `(key BLOB, value BLOB)` rows in
|
|
SQLite instead of Berkeley B-tree entries. That byte-for-byte identity is what
|
|
makes migration a verbatim copy.
|
|
|
|
## Delivered in this pass
|
|
|
|
New, self-contained modules (do not disturb the working Berkeley path):
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `src/walletdb-base.h` | Backend-agnostic seam: `WalletDatabase`, `WalletBatch` (raw byte Read/Write/Erase/Has + cursor + txn), `WalletCursor`; `ResolveWalletDbKind()` / `MakeWalletDatabase()` declarations. |
|
|
| `src/walletdb-sqlite.h/.cpp` | `SQLiteDatabase` / `SQLiteBatch` — single `main(key BLOB PRIMARY KEY, value BLOB)` table, `synchronous=FULL`, prepared statements, transactions, cursor, online-backup, `integrity_check`. App-id/user-version stamping to reject foreign DBs. |
|
|
| `src/walletmigrate.h/.cpp` | `MaybeMigrateBerkeleyWalletToSQLite()` — detects a Berkeley `wallet.dat`, copies every record verbatim into a temp SQLite file, verifies the row count, backs up the original to `wallet.dat.bdb.bak`, then swaps SQLite into place. Idempotent and non-destructive. |
|
|
| `src/walletdb-factory.cpp` | `ResolveWalletDbKind()` (default **sqlite**, `-walletdb=bdb` fallback) and `MakeWalletDatabase()` (SQLite implemented). |
|
|
| `src/walletdb-batch.h` | `CWalletBatchTyped` — typed Read/Write/Erase/Exists + cursor over `WalletBatch`, byte-identical to the old `CDB` templates. The drop-in base for `CWalletDB`. |
|
|
|
|
Build wiring:
|
|
- `find_package(SQLite3 REQUIRED)` in the top-level `CMakeLists.txt`.
|
|
- `SQLite::SQLite3` linked into `triangles_common`; the new sources added to `CORE_SOURCES`.
|
|
|
|
## Remaining integration (compile-in-the-loop)
|
|
|
|
The new modules are complete but `CWalletDB` is not yet routed through the seam
|
|
— it still inherits Berkeley `CDB`. This is the mechanical-but-careful step that
|
|
needs a compiler in the loop. **It must be done and landed as one unit** (it
|
|
touches `walletdb.h`, `walletdb.cpp`, `wallet.cpp`, `db.cpp`, and `init.cpp`):
|
|
re-basing ~800 lines of funds-critical code is exactly the kind of change that
|
|
should be compiled and run against a real `wallet.dat` rather than committed
|
|
blind.
|
|
|
|
1. **Typed wrappers over the batch — DONE.** `src/walletdb-batch.h`
|
|
(`CWalletBatchTyped`) provides `Read/Write/Erase/Exists` + cursor over a
|
|
`WalletBatch`, byte-identical to `CDB`'s templates. `CWalletDB` derives from
|
|
it instead of `CDB`.
|
|
2. **Re-base `CWalletDB`.** Hold a `std::unique_ptr<WalletDatabase>` +
|
|
`WalletBatch` obtained from `MakeWalletDatabase("wallet.dat", err)` instead of
|
|
deriving from `CDB`. Route `TxnBegin/Commit/Abort` to the batch.
|
|
3. **Cursors.** Replace `GetAtCursor` / `GetTxnCursor` / `ReadAtCursor`
|
|
(Berkeley `Dbc*`, `DB_NEXT`) in `walletdb.cpp` (`LoadWallet`,
|
|
`ReorderTransactions`) with `WalletBatch::GetNewCursor()` + `WalletCursor::Next()`.
|
|
4. **Berkeley-specific call sites.**
|
|
- `BackupWallet()` / `AutoBackupWallet()` → `WalletDatabase::Backup()`.
|
|
- `CDB::Rewrite()` (used by `CWallet::EncryptWallet`) → `WalletDatabase::Rewrite()`
|
|
(VACUUM). Unencrypted-key cleanup already happens via explicit `Erase`.
|
|
- `bitdb.Flush()` / env shutdown in `init.cpp` → `WalletDatabase::Flush()/Close()`
|
|
(no-op for SQLite).
|
|
5. **Berkeley behind the same seam (optional but recommended).** Add a thin
|
|
`BerkeleyDatabase`/`BerkeleyBatch` adapter wrapping the existing `CDBEnv`/`CDB`
|
|
so `-walletdb=bdb` routes through `MakeWalletDatabase` too, instead of the
|
|
legacy path. Keeps one code path for one release, then delete BDB entirely.
|
|
6. **Run the migration on startup.** In `init.cpp`, before the wallet is loaded
|
|
and when the backend is SQLite, call
|
|
`MaybeMigrateBerkeleyWalletToSQLite(GetDataDir()/strWalletFileName, err)`.
|
|
|
|
## Gating
|
|
|
|
```
|
|
trianglesd # SQLite (default)
|
|
trianglesd -walletdb=bdb # Berkeley fallback (retained for one release)
|
|
```
|
|
|
|
## Validation checklist (must pass before release)
|
|
|
|
Cannot be verified without a build + a real wallet. Run on a node:
|
|
|
|
1. **Build** with `-DBUILD_TESTS=ON`; confirm SQLite is found and linked.
|
|
2. **Fresh wallet**: start with no wallet → a SQLite `wallet.dat` is created;
|
|
`getnewaddress`, `getinfo` work; restart preserves keys/balance.
|
|
3. **Migration**: copy a real Berkeley `wallet.dat` into the datadir, start the
|
|
node. Confirm: `wallet.dat.bdb.bak` is created, `wallet.dat` is now SQLite
|
|
(`sqlite3 wallet.dat "PRAGMA integrity_check;"` → `ok`), and
|
|
`listaddressgroupings` / `getbalance` / `dumpwallet` match a `-walletdb=bdb`
|
|
run against the `.bdb.bak` original.
|
|
4. **Key parity**: `dumpwallet` before (bdb) and after (sqlite); diff must be
|
|
empty (same keys, labels, metadata, HD seed).
|
|
5. **Encryption**: `encryptwallet`, restart, `walletpassphrase`, sign/spend.
|
|
6. **Backup/restore**: `backupwallet`, restore into a fresh datadir, verify
|
|
balance and spend.
|
|
7. **Send/receive + staking** over a few blocks; confirm new keys/txns persist
|
|
across restart.
|
|
8. **Crash safety**: kill -9 mid-write; restart; `integrity_check` ok, no loss.
|
|
|
|
## Follow-ups
|
|
|
|
- Add `test_wallet_sqlite` unit tests (round-trip, migration parity, cursor).
|
|
- Once SQLite is validated for a release, remove `-walletdb=bdb`, delete
|
|
`db.cpp`/`walletdb`'s Berkeley code, and drop the `BerkeleyDB` CMake
|
|
dependency — completing the retirement.
|