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
5.8 KiB
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-levelCMakeLists.txt.SQLite::SQLite3linked intotriangles_common; the new sources added toCORE_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.
- Typed wrappers over the batch — DONE.
src/walletdb-batch.h(CWalletBatchTyped) providesRead/Write/Erase/Exists+ cursor over aWalletBatch, byte-identical toCDB's templates.CWalletDBderives from it instead ofCDB. - Re-base
CWalletDB. Hold astd::unique_ptr<WalletDatabase>+WalletBatchobtained fromMakeWalletDatabase("wallet.dat", err)instead of deriving fromCDB. RouteTxnBegin/Commit/Abortto the batch. - Cursors. Replace
GetAtCursor/GetTxnCursor/ReadAtCursor(BerkeleyDbc*,DB_NEXT) inwalletdb.cpp(LoadWallet,ReorderTransactions) withWalletBatch::GetNewCursor()+WalletCursor::Next(). - Berkeley-specific call sites.
BackupWallet()/AutoBackupWallet()→WalletDatabase::Backup().CDB::Rewrite()(used byCWallet::EncryptWallet) →WalletDatabase::Rewrite()(VACUUM). Unencrypted-key cleanup already happens via explicitErase.bitdb.Flush()/ env shutdown ininit.cpp→WalletDatabase::Flush()/Close()(no-op for SQLite).
- Berkeley behind the same seam (optional but recommended). Add a thin
BerkeleyDatabase/BerkeleyBatchadapter wrapping the existingCDBEnv/CDBso-walletdb=bdbroutes throughMakeWalletDatabasetoo, instead of the legacy path. Keeps one code path for one release, then delete BDB entirely. - Run the migration on startup. In
init.cpp, before the wallet is loaded and when the backend is SQLite, callMaybeMigrateBerkeleyWalletToSQLite(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:
- Build with
-DBUILD_TESTS=ON; confirm SQLite is found and linked. - Fresh wallet: start with no wallet → a SQLite
wallet.datis created;getnewaddress,getinfowork; restart preserves keys/balance. - Migration: copy a real Berkeley
wallet.datinto the datadir, start the node. Confirm:wallet.dat.bdb.bakis created,wallet.datis now SQLite (sqlite3 wallet.dat "PRAGMA integrity_check;"→ok), andlistaddressgroupings/getbalance/dumpwalletmatch a-walletdb=bdbrun against the.bdb.bakoriginal. - Key parity:
dumpwalletbefore (bdb) and after (sqlite); diff must be empty (same keys, labels, metadata, HD seed). - Encryption:
encryptwallet, restart,walletpassphrase, sign/spend. - Backup/restore:
backupwallet, restore into a fresh datadir, verify balance and spend. - Send/receive + staking over a few blocks; confirm new keys/txns persist across restart.
- Crash safety: kill -9 mid-write; restart;
integrity_checkok, no loss.
Follow-ups
- Add
test_wallet_sqliteunit tests (round-trip, migration parity, cursor). - Once SQLite is validated for a release, remove
-walletdb=bdb, deletedb.cpp/walletdb's Berkeley code, and drop theBerkeleyDBCMake dependency — completing the retirement.