Skip to content

Conversation

@DashCoreAutoGuix
Copy link
Owner

@DashCoreAutoGuix DashCoreAutoGuix commented Sep 30, 2025

Summary

Backports Bitcoin Core PR bitcoin#27405 to Dash Core.

This PR improves time measurement in several areas by switching from SystemClock (which can be affected by system time changes) to SteadyClock (monotonic clock) for duration measurements.

Changes:

  • Network: Use steady clock in InterruptibleRecv for socket timeout handling
  • GUI: Use steady clock to throttle GUI notifications during sync
  • Wallet: Use steady clock to calculate derive iterations timing for password encryption
  • Tests: Use steady clock for index sync timeouts in blockfilter and txindex tests

Dash-Specific Adaptations:

  • Adapted Qt client model to use Dash's header parameter instead of Bitcoin's synctype
  • Preserved Dash's m_scanning_with_passphrase field in wallet scanning logic
  • All changes maintain compatibility with Dash-specific features

Original Bitcoin PR:

bitcoin#27405

Bitcoin commit: e460c0a

Test Plan

  • Cherry-picked and resolved conflicts
  • Build successful
  • All modified files use appropriate steady clock types
  • Wallet encryption timing logic preserved
  • GUI throttling logic preserved

Backporting Notes

All timing-related code properly uses steady clock for duration measurements. The changes are type-safe improvements that prevent issues with system clock adjustments.

Summary by CodeRabbit

  • Bug Fixes

    • More reliable SOCKS5 proxy timeouts and network reads.
    • More accurate wallet scan duration reported by getwalletinfo.
    • More consistent timing during wallet encryption and passphrase changes.
  • Refactor

    • Switched to monotonic timing for timeouts and durations to improve robustness against system clock changes.
  • Tests

    • Updated sync-wait logic to use explicit timeout loops for more predictable test behavior.

…o measure durations

fa83fb3 wallet: Use steady clock to calculate number of derive iterations (MarcoFalke)
fa2c099 wallet: Use steady clock to measure scanning duration (MarcoFalke)
fa97621 qt: Use steady clock to throttle GUI notifications (MarcoFalke)
fa1d804 test: Use steady clock in index tests (MarcoFalke)
fa454dc net: Use steady clock in InterruptibleRecv (MarcoFalke)

Pull request description:

  `GetTimeMillis` has multiple issues:

  * It doesn't denote the underlying clock type
  * It isn't type-safe
  * It is used incorrectly in places that should use a steady clock

  Fix all issues here.

ACKs for top commit:
  willcl-ark:
    ACK fa83fb3
  martinus:
    Code review ACK bitcoin@fa83fb3, also ran all tests. All usages of the steady_clock are just for duration measurements, so the change to a different epoch is ok.

Tree-SHA512: 5ec4fede8c7f97e2e08863c011856e8304f16ba30a68fdeb42f96a50a04961092cbe46ccf9ea6ac99ff5203c09f9e0924eb483eb38d7df0759addc85116c8a9f
@coderabbitai
Copy link

coderabbitai bot commented Sep 30, 2025

Walkthrough

This change migrates various timeouts and timing logic to std::chrono and steady clock across networking, GUI, wallet, and tests. It updates SOCKS5 receive timeout types, throttling mechanics, wallet scanning state/duration APIs, derives iteration timing, RPC duration reporting, and replaces index sync helpers with explicit polling loops.

Changes

Cohort / File(s) Summary
Networking timeouts and recv
src/netbase.cpp
Convert g_socks5_recv_timeout and InterruptibleRecv timeout parameter from int (ms) to std::chrono::milliseconds. Switch internal timing to steady-clock durations and time_points. Control flow for receive and interruptions unchanged.
GUI model throttling (steady clock)
src/qt/clientmodel.cpp
Replace integer epoch-based throttling with SteadyClock::time_point tracking for header/block tip updates. Use SteadyClock::now() comparisons against MODEL_UPDATE_DELAY. Rename trackers to g_last_*_notification.
Test index sync wait loops
src/test/blockfilter_index_tests.cpp, src/test/txindex_tests.cpp
Replace IndexWaitSynced(...) with explicit polling of BlockUntilSyncedToCurrentChain() with a 10s timeout and 100ms sleeps. Adds steady-clock start and timeout checks.
Fuzz SOCKS5 timeout type alignment
src/test/fuzz/socks5.cpp
Update extern to std::chrono::milliseconds g_socks5_recv_timeout. Redefine default_socks5_recv_timeout via decltype(g_socks5_recv_timeout). Use 1ms when fake latency enabled. Remove old extern int declaration.
Wallet timing and scanning APIs
src/wallet/wallet.cpp, src/wallet/wallet.h, src/wallet/rpc/wallet.cpp
Switch derive-iteration timing to steady clock with 100ms target window; update calculations accordingly. Introduce passphrase-aware scanning state, replace scan start int with SteadyClock::time_point, expose IsScanningWithPassphrase(), and return SteadyClock::duration from ScanningDuration(). RPC uses Ticks<std::chrono::seconds>(ScanningDuration()) for duration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly summarizes the primary change—using a steady clock instead of a system clock for measuring durations—and provides relevant context by referencing the upstream PR being merged, making it concise and specific enough for maintainers to understand the main purpose at a glance.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch backport-0.25-batch-415-pr-27405

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/qt/clientmodel.cpp (1)

271-279: Use .count() for QTimer interval calls with MODEL_UPDATE_DELAY

  • QTimer::setInterval and QTimer::start expect an integer millisecond count, but MODEL_UPDATE_DELAY is a std::chrono::milliseconds. Update as follows:
    • src/qt/clientmodel.cpp (line 56):
      timer->setInterval(MODEL_UPDATE_DELAY.count());
    • src/qt/peertablemodel.cpp (line 24):
      timer->setInterval(MODEL_UPDATE_DELAY.count());
    • src/qt/walletmodel.cpp (line 80):
      timer->start(MODEL_UPDATE_DELAY.count());
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 54e2588 and 11d65a7.

📒 Files selected for processing (8)
  • src/netbase.cpp (4 hunks)
  • src/qt/clientmodel.cpp (2 hunks)
  • src/test/blockfilter_index_tests.cpp (1 hunks)
  • src/test/fuzz/socks5.cpp (2 hunks)
  • src/test/txindex_tests.cpp (1 hunks)
  • src/wallet/rpc/wallet.cpp (1 hunks)
  • src/wallet/wallet.cpp (2 hunks)
  • src/wallet/wallet.h (3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

C++20 codebase should be placed under src/

Files:

  • src/test/blockfilter_index_tests.cpp
  • src/qt/clientmodel.cpp
  • src/wallet/rpc/wallet.cpp
  • src/wallet/wallet.h
  • src/test/txindex_tests.cpp
  • src/netbase.cpp
  • src/wallet/wallet.cpp
  • src/test/fuzz/socks5.cpp
src/{test,wallet/test,qt/test}/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests should be placed in src/test/, src/wallet/test/, or src/qt/test/ and use Boost::Test or Qt 5 for GUI tests

Files:

  • src/test/blockfilter_index_tests.cpp
  • src/test/txindex_tests.cpp
  • src/test/fuzz/socks5.cpp
**

⚙️ CodeRabbit configuration file

**: # CodeRabbit AI Review Instructions for Dash Backports

Your Role

You are reviewing Bitcoin Core backports to Dash Core. Your ONLY job is to validate that the Dash commit faithfully represents the original Bitcoin commit with minimal, necessary adaptations.

Critical Validation Rules

1. File Operations Must Match (AUTO-REJECT if violated)

  • If Bitcoin modifies an existing file → Dash MUST modify (not create new)
  • If Bitcoin creates a new file → Dash creates
  • If Bitcoin deletes a file → Dash deletes
  • Common failure: Bitcoin modifies keys.txt, Dash creates new file with 58 keys

2. Size Ratio Check (80-150% of Bitcoin)

  • Count functional lines changed (exclude comments/whitespace)
  • Dash changes should be 80-150% of Bitcoin's size
  • Red flag: 2-line Bitcoin fix becoming 150+ lines in Dash

3. No Scope Creep

  • Reject if you see: "TODO:", "FIXME:", "while we're here", "also fix"
  • No unrelated refactoring or style changes
  • Only Bitcoin's intended changes + minimal Dash adaptations

4. Bitcoin-Specific Code Detection

  • Auto-reject witness/segwit code: msg_wtxidrelay, MSG_WTX, witness imports
  • Auto-reject RBF (replace-by-fee) functionality
  • Note: PSBT is supported in Dash (don't flag)

5. Mandatory Adaptations Only

  • bitcoindash in strings/paths
  • BitcoinDash in user-facing text
  • Port numbers: 8332→9998 (RPC), 8333→9999 (P2P)
  • Hardcoded test values specific to Dash
  • No other changes unless absolutely required

6. Completeness Check

  • All files changed in Bitcoin must be present
  • Extra files need clear justification (Dash-specific compatibility)
  • Missing files = incomplete backport

Review Process

  1. First: Check file operations match exactly
  2. Second: Calculate size ratio
  3. Third: Scan for scope creep patterns
  4. Fourth: Detect Bitcoin-specific code
  5. Fifth: Verify all changes are minimal adaptations

Output Format

VALIDATION: [PASS/FAIL]

File Operatio...

Files:

  • src/test/blockfilter_index_tests.cpp
  • src/qt/clientmodel.cpp
  • src/wallet/rpc/wallet.cpp
  • src/wallet/wallet.h
  • src/test/txindex_tests.cpp
  • src/netbase.cpp
  • src/wallet/wallet.cpp
  • src/test/fuzz/socks5.cpp
🧠 Learnings (1)
📓 Common learnings
Learnt from: DashCoreAutoGuix
PR: DashCoreAutoGuix/dash#0
File: :0-0
Timestamp: 2025-07-31T01:14:55.631Z
Learning: DashCoreAutoGuix successfully completed a complex Bitcoin Core backport (PR #29412) for block mutation detection by implementing the IsBlockMutated function, adding net processing integration, creating comprehensive unit tests, and properly adapting all Bitcoin-specific witness code for Dash compatibility. The backport maintains full security functionality while respecting Dash's non-witness transaction architecture.
Learnt from: DashCoreAutoGuix
PR: DashCoreAutoGuix/dash#0
File: :0-0
Timestamp: 2025-07-28T22:03:12.364Z
Learning: During multiple verification attempts of Bitcoin Core commit 06d469c26b backport to Dash PR #566, DashCoreAutoGuix consistently identified scope creep in interface_usdt_utxocache.py where additional pruning test functionality was added beyond the original Bitcoin commit. The user provided comprehensive fixes including both scope creep removal and missing mempool test file additions, but couldn't push due to authentication restrictions. The scope creep fix was identified as the priority to resolve CI failures.
Learnt from: DashCoreAutoGuix
PR: DashCoreAutoGuix/dash#0
File: :0-0
Timestamp: 2025-07-28T20:34:29.061Z
Learning: During Dash backport verification of Bitcoin Core commit 06d469c26b, scope creep was detected when additional pruning test functionality was added to interface_usdt_utxocache.py beyond what was in the original Bitcoin commit. The fix involved removing the extra test block while maintaining the core compiler flag fixes for USDT compilation errors.
🧬 Code graph analysis (3)
src/qt/clientmodel.cpp (1)
src/util/time.h (1)
  • now (21-55)
src/wallet/wallet.h (1)
src/util/time.h (1)
  • now (21-55)
src/wallet/wallet.cpp (1)
src/util/time.h (1)
  • now (21-55)
🔇 Additional comments (12)
src/test/txindex_tests.cpp (1)

34-39: LGTM! Steady clock migration correctly implemented.

The replacement of IndexWaitSynced(txindex) with an explicit polling loop using SteadyClock::now() for timeout tracking is correct and aligns with the PR objective to migrate from system clock to steady clock for duration measurements.

src/test/blockfilter_index_tests.cpp (1)

145-150: LGTM! Consistent steady clock implementation.

The migration to SteadyClock::now() for timeout tracking in the polling loop is correct and consistent with the identical change in txindex_tests.cpp. Both files now use steady clock instead of system clock for synchronization timing.

src/qt/clientmodel.cpp (1)

34-35: Steady clock globals LGTM

Static SteadyClock::time_point vars are an appropriate replacement for ms-since-epoch ints; scope and defaults look fine.

src/wallet/wallet.h (1)

580-582: Accessors align with steady-clock migration

Returning a chrono duration and computing it against an atomic start time-point is fine once the include is added.

Optional: consider documenting the unit expectation for callers (RPC uses seconds).

src/wallet/rpc/wallet.cpp (1)

264-266: Steady duration formatting LGTM

Using Ticks<std::chrono::seconds>(pwallet->ScanningDuration()) correctly reports elapsed seconds with the new steady-clock duration.

src/test/fuzz/socks5.cpp (1)

37-38: Remove unnecessary chrono change suggestion
socks5.cpp already includes test/util/setup_common.h, which pulls in using namespace std::chrono_literals; from util/time.h, so the 1ms literal is valid—no change needed.

Likely an incorrect or invalid review comment.

src/netbase.cpp (6)

38-39: LGTM - Type migration to std::chrono::milliseconds

The global timeout variable has been correctly migrated from an integer (representing milliseconds) to std::chrono::milliseconds with a chrono literal 20s. This aligns with the PR objective of using steady clock for duration measurements.


303-303: LGTM - Documentation updated for type-safe parameter

Comment appropriately simplified by removing "in milliseconds" since the parameter type std::chrono::milliseconds is now self-documenting.


313-313: LGTM - Function signature updated for type-safe timeout

The InterruptibleRecv function signature correctly updated to accept std::chrono::milliseconds instead of int, providing type safety for timeout handling.


315-316: LGTM - Critical migration to steady clock for reliable timeouts

This is the core change implementing the PR objective. The timing logic now uses Now<SteadyMilliseconds>() (steady clock) instead of system clock, ensuring that socket timeouts are not affected by system time adjustments. This is particularly important for long-running operations like Tor proxy negotiations.


340-340: LGTM - Consistent steady clock usage in loop

The curTime update correctly uses Now<SteadyMilliseconds>() to maintain consistency with the steady clock approach throughout the timeout loop.


38-340: BACKPORT VALIDATION: PASS

File Operations: ✓ MATCH - Bitcoin modifies existing file, Dash modifies existing file

Size Ratio: Appropriate - 5 functional lines changed, all directly related to clock type migration

Scope Creep: ✓ NONE - All changes strictly related to migrating from system clock (int milliseconds) to steady clock (std::chrono::milliseconds)

Bitcoin-Specific Code: ✓ NONE - No witness, segwit, RBF, or other Bitcoin-specific features

Completeness: ✓ COMPLETE for this file - All timeout-related code in InterruptibleRecv and g_socks5_recv_timeout properly migrated

Changes Summary:

  1. Global timeout variable migrated to type-safe chrono duration
  2. Function signature updated for type safety
  3. Timing calculations switched from epoch-based to steady-time points
  4. Documentation updated appropriately

This is a faithful, minimal backport of Bitcoin Core PR bitcoin#27405 for the netbase.cpp component. The changes ensure socket timeouts are immune to system clock adjustments, which is critical for reliable network operations especially with slow proxies like Tor.

Comment on lines +16 to 20
extern std::chrono::milliseconds g_socks5_recv_timeout;

namespace {
int default_socks5_recv_timeout;
decltype(g_socks5_recv_timeout) default_socks5_recv_timeout;
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add required header for chrono types

This TU now uses std::chrono::milliseconds; explicitly include to avoid relying on transitive includes:

+#include <chrono>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
extern std::chrono::milliseconds g_socks5_recv_timeout;
namespace {
int default_socks5_recv_timeout;
decltype(g_socks5_recv_timeout) default_socks5_recv_timeout;
};
#include <chrono>
extern std::chrono::milliseconds g_socks5_recv_timeout;
namespace {
decltype(g_socks5_recv_timeout) default_socks5_recv_timeout;
};
🤖 Prompt for AI Agents
In src/test/fuzz/socks5.cpp around lines 16 to 20, the translation unit uses
std::chrono::milliseconds but does not include the <chrono> header; add an
explicit #include <chrono> at the top of the file (or before any use of
std::chrono types) so the code does not rely on transitive includes and builds
correctly across compilers.

Comment on lines +497 to 505
constexpr MillisecondsDouble target{100};
auto start{SteadyClock::now()};
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()) - nStartTime))));
pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));

nStartTime = TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now());
start = SteadyClock::now();
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()) - nStartTime)))) / 2;
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Use a standard chrono type; avoid undefined MillisecondsDouble

MillisecondsDouble may not exist in Dash’s util/time.h. Prefer std::chrono types:

-                constexpr MillisecondsDouble target{100};
+                constexpr std::chrono::milliseconds target{100};
                 auto start{SteadyClock::now()};
 ...
-                pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
+                pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (target / (SteadyClock::now() - start)));
 ...
-                start = SteadyClock::now();
+                start = SteadyClock::now();
 ...
-                pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
+                pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (target / (SteadyClock::now() - start)))) / 2;

This keeps the intended ratio (100 ms per measurement window) while eliminating a likely missing alias.

Quick check for alias presence:


🏁 Script executed:

#!/bin/bash
rg -n 'MillisecondsDouble' src/util src/wallet

Length of output: 155


🏁 Script executed:

#!/bin/bash
set -e
# Locate util/time.h
file=$(fd --full-path time.h src/util)
echo "Inspecting $file"
# Check for Double aliases
rg -n 'using .*Double' "$file"
rg -n 'typedef .*Double' "$file"

Length of output: 194


Replace undefined MillisecondsDouble with std::chrono::duration<double, std::milli>

MillisecondsDouble isn’t defined in src/util/time.h. Replace both occurrences with a double-precision duration and wrap the ratio in parentheses for correct precision:

--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ lines 497,704
-    constexpr MillisecondsDouble target{100};
+    constexpr std::chrono::duration<double, std::milli> target{100.0};

@@ lines 500,707
-    pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
+    pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(
+        pMasterKey.second.nDeriveIterations * (target / (SteadyClock::now() - start))
+    );

@@ lines 504,711
-    pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
+    pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(
+        (pMasterKey.second.nDeriveIterations +
+         pMasterKey.second.nDeriveIterations * (target / (SteadyClock::now() - start)))
+        / 2
+    );

This eliminates the undefined alias while preserving fractional-millisecond precision.

🤖 Prompt for AI Agents
In src/wallet/wallet.cpp around lines 497 to 505, the code uses an undefined
MillisecondsDouble type; replace both occurrences with
std::chrono::duration<double, std::milli> to preserve fractional-millisecond
precision, and wrap the division used to scale nDeriveIterations in parentheses
so the ratio is computed in double precision (e.g. static_cast<unsigned
int>(pMasterKey.second.nDeriveIterations * (target / (SteadyClock::now() -
start)))); update both lines that compute nDeriveIterations accordingly.

Comment on lines 703 to 713
CCrypter crypter;
int64_t nStartTime = TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now());
constexpr MillisecondsDouble target{100};
auto start{SteadyClock::now()};
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = static_cast<unsigned int>(2500000 / ((double)(TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()) - nStartTime)));
kMasterKey.nDeriveIterations = static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));

nStartTime = TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now());
start = SteadyClock::now();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()) - nStartTime)))) / 2;
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;

if (kMasterKey.nDeriveIterations < 25000)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Same MillisecondsDouble issue here

Mirror the change as above:

-    constexpr MillisecondsDouble target{100};
+    constexpr std::chrono::milliseconds target{100};
     auto start{SteadyClock::now()};
 ...
-    kMasterKey.nDeriveIterations = static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
+    kMasterKey.nDeriveIterations = static_cast<unsigned int>(25000 * (target / (SteadyClock::now() - start)));
 ...
-    start = SteadyClock::now();
+    start = SteadyClock::now();
 ...
-    kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
+    kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * (target / (SteadyClock::now() - start)))) / 2;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
CCrypter crypter;
int64_t nStartTime = TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now());
constexpr MillisecondsDouble target{100};
auto start{SteadyClock::now()};
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = static_cast<unsigned int>(2500000 / ((double)(TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()) - nStartTime)));
kMasterKey.nDeriveIterations = static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
nStartTime = TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now());
start = SteadyClock::now();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()) - nStartTime)))) / 2;
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
if (kMasterKey.nDeriveIterations < 25000)
CCrypter crypter;
constexpr std::chrono::milliseconds target{100};
auto start{SteadyClock::now()};
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = static_cast<unsigned int>(25000 * (target / (SteadyClock::now() - start)));
start = SteadyClock::now();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations
+ static_cast<unsigned int>(kMasterKey.nDeriveIterations * (target / (SteadyClock::now() - start))))
/ 2;
if (kMasterKey.nDeriveIterations < 25000)
🤖 Prompt for AI Agents
In src/wallet/wallet.cpp around lines 703 to 713, the timing math uses
SteadyClock durations implicitly against MillisecondsDouble which causes the
same MillisecondsDouble-type issue noted earlier; change both places so you
first compute the elapsed time as a MillisecondsDouble from (SteadyClock::now()
- start) and use that explicit MillisecondsDouble value in the nDeriveIterations
calculations (i.e., divide target by the elapsed MillisecondsDouble), and guard
the divisor against zero before assigning to kMasterKey.nDeriveIterations.

Comment on lines +270 to 272
std::atomic<bool> m_scanning_with_passphrase{false};
std::atomic<SteadyClock::time_point> m_scanning_start{SteadyClock::time_point{}};
std::atomic<double> m_scanning_progress{0};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing include for SteadyClock types used in header

SteadyClock::time_point requires <util/time.h> (your alias) in this header to avoid ODR/order-dependent builds.

Add at the top near other util includes:

+#include <util/time.h>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
std::atomic<bool> m_scanning_with_passphrase{false};
std::atomic<SteadyClock::time_point> m_scanning_start{SteadyClock::time_point{}};
std::atomic<double> m_scanning_progress{0};
#include <util/time.h>
🤖 Prompt for AI Agents
In src/wallet/wallet.h around lines 270 to 272, the header uses
SteadyClock::time_point in an atomic member but does not include the util/time.h
alias that defines SteadyClock; add #include "util/time.h" near the other util
includes at the top of the file so SteadyClock::time_point is defined in this
translation unit and avoids ODR/order-dependent build issues.

Comment on lines +1090 to 1092
m_wallet.m_scanning_with_passphrase.exchange(with_passphrase);
m_wallet.m_scanning_start = SteadyClock::now();
m_wallet.m_scanning_progress = 0;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Compile error: undefined identifier ‘with_passphrase’

WalletRescanReserver::reserve() references with_passphrase which is not in scope and the method takes no parameter. Minimal fix (keep prior behavior) is to drop the assignment:

-        m_wallet.m_scanning_with_passphrase.exchange(with_passphrase);
+        m_wallet.m_scanning_with_passphrase = false; // or plumb a parameter from the call sites if needed

Alternatively, extend reserve(bool with_passphrase) and update all call sites, but that exceeds backport scope.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
m_wallet.m_scanning_with_passphrase.exchange(with_passphrase);
m_wallet.m_scanning_start = SteadyClock::now();
m_wallet.m_scanning_progress = 0;
m_wallet.m_scanning_with_passphrase = false; // or plumb a parameter from the call sites if needed
m_wallet.m_scanning_start = SteadyClock::now();
m_wallet.m_scanning_progress = 0;
🤖 Prompt for AI Agents
In src/wallet/wallet.h around lines 1090-1092, the reserve() method references
an undefined identifier with_passphrase; remove the call that assigns
m_wallet.m_scanning_with_passphrase.exchange(with_passphrase) so the method
compiles and preserves prior behavior, leaving the m_wallet.m_scanning_start and
m_wallet.m_scanning_progress assignments intact; do not add new parameters or
change call sites.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants