feat(node): in-app "Rebuild wallet database" recovery for a BDB-inconsistent wallet
Automates the manual recovery that fixed a wallet.dat with stale Berkeley DB extent metadata (the "main" subdb metapage records a low last_pgno while its live data spans thousands of pages beyond it). A tolerant page-walk reads every record, but the daemon's BDB verify rejects the file and auto-salvages it — finding nothing and shrinking the wallet to empty on each restart (the salvage cascade that looks like fund loss). Plain "Restore original" can't fix it (hands the same broken file back → re-salvage); a rebuild must produce a fresh, consistent DB. Pieces (Approach A from the design workflow — out-of-process helper keeps AGPL Berkeley DB out of the GPLv3 GUI): - util/wallet_file_probe.h: extractWalletBtreeRecords() — sibling to parseWalletBtree that collects raw (key,value) bytes (same bounds-checked, subdb-aware walk). Records copied verbatim → encrypted key material passes through as opaque ciphertext (no passphrase). Overflow-page values (only large tx history) are skipped + counted; a rescan rebuilds history — funds unaffected. - tools/wallet_rebuild/main.cpp: dragonx-wallet-rebuild CLI — reads via the tolerant reader, writes the records into a fresh BDB "main" btree via libdb (DB_EXCL, never overwrites), prints a JSON summary. New BDB-guarded CMake target. - App::rebuildWalletDatabase(): picks the largest readable wallet/.bak as source, stops the daemon, runs the helper, VERIFIES the output (readable BDB with keys) before swapping, moves the current wallet aside (kept, timestamped), installs the rebuilt one, clears the stale BDB env, sets -rescan, restarts. Copy/rename only — never deletes. Result surfaced via the existing pumpWalletRestore channel. - Wired as the preferred action on the existing wallet-auto-recovery dialog (shown only when the helper is present). Full-node only; lite-safe. Verified end-to-end against the real broken wallet: helper reads 3,808 t-keys + 1 z-key + HD seed and the daemon LOADS the rebuilt output with no salvage. Adds extractWalletBtreeRecords coverage. Build clean, suite green (1/1). Remaining (follow-up): release packaging — build.sh bundling the helper built against the vendored per-platform static libdb (DRAGONX_BDB_ROOT), and a macOS Berkeley DB port (no in-tree artifact). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1075,6 +1075,26 @@ install(DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/res
|
||||
OPTIONAL
|
||||
)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# dragonx-wallet-rebuild — offline recovery helper for a BDB-inconsistent wallet.dat.
|
||||
# Bundled next to the daemon; the app spawns it out-of-process. It is the ONLY thing that links
|
||||
# Berkeley DB, so the AGPLv3 BDB never contaminates the GPLv3 GUI (same boundary as the daemon).
|
||||
# Release builds should point DRAGONX_BDB_ROOT at the vendored static libdb (external/dragonx/depends);
|
||||
# a dev build falls back to the system Berkeley DB. Skipped (with a note) if no BDB is found.
|
||||
# -----------------------------------------------------------------------------
|
||||
find_path(BDB_INCLUDE_DIR db.h HINTS ${DRAGONX_BDB_ROOT}/include /usr/include /usr/local/include)
|
||||
find_library(BDB_LIBRARY NAMES db-6.2 db-6.0 db-5.3 db libdb
|
||||
HINTS ${DRAGONX_BDB_ROOT}/lib /usr/lib /usr/local/lib /usr/lib/x86_64-linux-gnu)
|
||||
if(BDB_INCLUDE_DIR AND BDB_LIBRARY)
|
||||
add_executable(dragonx-wallet-rebuild tools/wallet_rebuild/main.cpp)
|
||||
target_include_directories(dragonx-wallet-rebuild PRIVATE ${CMAKE_SOURCE_DIR}/src ${BDB_INCLUDE_DIR})
|
||||
target_link_libraries(dragonx-wallet-rebuild PRIVATE ${BDB_LIBRARY})
|
||||
set_target_properties(dragonx-wallet-rebuild PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
message(STATUS "wallet-rebuild helper: ON (Berkeley DB ${BDB_LIBRARY})")
|
||||
else()
|
||||
message(STATUS "wallet-rebuild helper: OFF (no Berkeley DB found; set DRAGONX_BDB_ROOT for release builds)")
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Tests
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user