fix(audit): batch 1 — latent unlock/path/rescan correctness bugs
Four correctness fixes surfaced by the codebase audit: 1. Lite address-book path bug: AddressBook::getDefaultPath() hardcoded "ObsidianDragon" while Settings::getDefaultPath() uses DRAGONX_APP_NAME, so the Lite build wrote addressbook.json into the full-node app's config dir instead of ObsidianDragonLite/. Now uses DRAGONX_APP_NAME on all platforms (no macOS path change — the getConfigDir consolidation, which would move the macOS dir, is deferred). 2. PIN-unlock lockout bypass: the PIN path duplicated unlockWallet's success/lockout logic and its RPC-error branch bumped the attempt counter but skipped the escalating-lockout math entirely — a PIN user hitting an RPC error escaped the lockout curve. Extracted App::applyUnlockSuccess() and App::applyUnlockFailure() and routed all unlock paths (passphrase, PIN vault-fail, PIN RPC-fail) through them, so the lockout curve now applies uniformly. (noVault stays a mode-switch, not a failed attempt.) 3. Witness/rescan reset drift: the ~11-line rescan+witness completion reset was copy-pasted at four sites (app.cpp x2, app_network.cpp x2); adding a witness field and missing a copy would leave stale progress. Folded into App::resetWitnessRescanProgress(). Left the distinct phase-transition reset in App::update() untouched (it sets witness_phase, not 0). 4. Truncation underflow: send_tab/receive_tab's size_t TruncateAddress copies computed (maxLen - 3) without guarding maxLen <= 3, which wraps and throws std::out_of_range on short inputs. Added the guard. Full-node + Lite build clean; ctest 1/1; source-hygiene clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "../util/logger.h"
|
||||
#include "../util/platform.h"
|
||||
#include "../config/version.h" // DRAGONX_APP_NAME (per-variant: ObsidianDragon / ObsidianDragonLite)
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <shlobj.h>
|
||||
@@ -29,10 +30,13 @@ AddressBook::~AddressBook() = default;
|
||||
|
||||
std::string AddressBook::getDefaultPath()
|
||||
{
|
||||
// Co-locate with settings.json in the per-variant config dir. Use DRAGONX_APP_NAME
|
||||
// (not a hardcoded "ObsidianDragon") so the Lite build writes to ObsidianDragonLite/
|
||||
// rather than polluting the full-node app's directory — matching Settings::getDefaultPath().
|
||||
#ifdef _WIN32
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, path))) {
|
||||
std::string dir = std::string(path) + "\\ObsidianDragon";
|
||||
std::string dir = std::string(path) + "\\" DRAGONX_APP_NAME;
|
||||
fs::create_directories(dir);
|
||||
return dir + "\\addressbook.json";
|
||||
}
|
||||
@@ -43,7 +47,7 @@ std::string AddressBook::getDefaultPath()
|
||||
struct passwd* pw = getpwuid(getuid());
|
||||
home = pw->pw_dir;
|
||||
}
|
||||
std::string dir = std::string(home) + "/Library/Application Support/ObsidianDragon";
|
||||
std::string dir = std::string(home) + "/Library/Application Support/" DRAGONX_APP_NAME;
|
||||
fs::create_directories(dir);
|
||||
return dir + "/addressbook.json";
|
||||
#else
|
||||
@@ -52,7 +56,7 @@ std::string AddressBook::getDefaultPath()
|
||||
struct passwd* pw = getpwuid(getuid());
|
||||
home = pw->pw_dir;
|
||||
}
|
||||
std::string dir = std::string(home) + "/.config/ObsidianDragon";
|
||||
std::string dir = std::string(home) + "/.config/" DRAGONX_APP_NAME;
|
||||
fs::create_directories(dir);
|
||||
return dir + "/addressbook.json";
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user