diff --git a/src/app.cpp b/src/app.cpp index dc1aefa..884208e 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -898,15 +898,19 @@ void App::update() rescan_confirmed_active_ = true; state_.sync.building_witnesses = true; - // Which sub-phase is this batch? A " remaining" token means the - // cache walk (phase 2); otherwise per-tx "Setting Initial" lines are the - // initial pass (phase 1). When both appear in one batch the walk wins — - // it always runs after the initial pass within a BuildWitnessCache call. - const int phase = (witnessRemaining >= 0) ? 2 - : (!witnessTxids.empty() ? 1 : state_.sync.witness_phase); + // Which sub-phase is this batch? A " remaining" token means the cache + // walk (phase 2); otherwise per-tx "Setting Initial" lines are the initial + // pass (phase 1). The two INTERLEAVE during a rescan (the daemon does both + // per block), so the phase is UPGRADE-ONLY: once the cache walk is seen it + // never drops back to the initial pass. Otherwise an interleaved initial + // line would flip the phase back and reset the bar every batch (thrash). + int phase = state_.sync.witness_phase; + if (witnessRemaining >= 0) phase = 2; + else if (!witnessTxids.empty() && phase < 2) phase = 1; - // Entering a new sub-phase → reset its progress + accumulators so the bar - // restarts from 0 instead of inheriting the previous phase's value. + // Entering a higher sub-phase → reset its progress + accumulators so the + // bar restarts from 0 (the two phases have different scales). Upgrade-only, + // so this happens at most twice (→1, →2), never repeatedly. if (phase != state_.sync.witness_phase) { state_.sync.witness_phase = phase; state_.sync.witness_progress = 0.0f;