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:
@@ -72,7 +72,9 @@ static bool s_generating_address = false;
|
||||
// Helpers
|
||||
// ============================================================================
|
||||
static std::string TruncateAddress(const std::string& addr, size_t maxLen = 40) {
|
||||
if (addr.length() <= maxLen) return addr;
|
||||
// Guard maxLen <= 3 before the unsigned (maxLen - 3): otherwise it wraps and the
|
||||
// trailing substr(length - halfLen) throws std::out_of_range on short inputs.
|
||||
if (maxLen <= 3 || addr.length() <= maxLen) return addr;
|
||||
size_t halfLen = (maxLen - 3) / 2;
|
||||
return addr.substr(0, halfLen) + "..." + addr.substr(addr.length() - halfLen);
|
||||
}
|
||||
|
||||
@@ -148,7 +148,9 @@ static double GetAvailableBalance(App* app) {
|
||||
}
|
||||
|
||||
static std::string TruncateAddress(const std::string& addr, size_t maxLen = 40) {
|
||||
if (addr.length() <= maxLen) return addr;
|
||||
// Guard maxLen <= 3 before the unsigned (maxLen - 3): otherwise it wraps and the
|
||||
// trailing substr(length - halfLen) throws std::out_of_range on short inputs.
|
||||
if (maxLen <= 3 || addr.length() <= maxLen) return addr;
|
||||
size_t halfLen = (maxLen - 3) / 2;
|
||||
return addr.substr(0, halfLen) + "..." + addr.substr(addr.length() - halfLen);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user