feat(merge): run per-address consolidation as a paced background job
"Keep in each address" posted one task that called z_mergetoaddress for every batch of every address back to back; each call is a whole-wallet scan under cs_main, and the daemon runs the ops one at a time anyway. It is now an App-owned services::ConsolidationRun: - one RPC at a time; the next merge only after the previous batch left the queue and a gap as long as the last call took (2-120 s); - pauses while the node syncs, the wallet is locked, a send of ours is in progress, or another wallet scan is running; - failures classified: nothing that may have queued is ever resent; a breaker stops after 3 dead addresses or 3 failed ops in a row; - each merge is charged to the scan budget; one re-read and one forced balance at the end; - it keeps running when the dialog closes: a status-bar chip, a run view with progress, the wait reason and a Stop button. The "Into one" merge can no longer be confirmed twice while its call is in flight. fake_dragonxd gains FAKE_SCAN_SECS, FAKE_MERGE_SERIAL and FAKE_MERGE_FAIL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+26
@@ -1427,6 +1427,8 @@ void App::update()
|
||||
// While the address scan that normally ends the send progress can't run (the background, a catch-up, the
|
||||
// connect gate, a retry hold), end it once the operations are done: it keeps the window rendering.
|
||||
if (send_progress_active_ && !addressScanCanRunNow()) maybeFinishTransactionSendProgress();
|
||||
// C210: the "Keep in each address" consolidation run, if one is going (paced; one RPC at a time).
|
||||
pumpConsolidation();
|
||||
|
||||
// After a bootstrap the preserved wallet.dat has stale spent-state and must be reconciled
|
||||
// against the freshly-imported chain, or the first send tries to spend already-spent notes and
|
||||
@@ -2979,6 +2981,30 @@ void App::renderStatusBar()
|
||||
ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), "%s%s", TR("sb_importing_keys"), dotStr);
|
||||
}
|
||||
|
||||
// C210: a consolidation run keeps going after its dialog closes. A static chip (no animation, no frames of
|
||||
// its own); clicking it reopens the run view.
|
||||
if (consolidation_.active()) {
|
||||
const services::RunProgress p = consolidation_.progress();
|
||||
const ImVec4 col(0.6f, 0.8f, 1.0f, 1.0f);
|
||||
ImGui::SameLine(0, sbSectionGap);
|
||||
ImGui::TextDisabled("|");
|
||||
ImGui::SameLine(0, sbSeparatorGap);
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushFont(ui::material::Type().iconSmall());
|
||||
ImGui::TextColored(col, ICON_MD_CALL_MERGE);
|
||||
ImGui::PopFont();
|
||||
ImGui::SameLine(0, sbIconTextGap);
|
||||
ImGui::TextColored(col, TR("merge_run_chip_fmt"), p.batchesSubmitted, std::max(1, p.batchesEstimated));
|
||||
ImGui::EndGroup();
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
if (!p.stopping) {
|
||||
if (const char* k = services::runWaitKey(p.wait)) ui::material::Tooltip("%s", TR(k));
|
||||
}
|
||||
}
|
||||
if (ImGui::IsItemClicked()) ui::ShieldDialog::showConsolidate(); // reopens the run view
|
||||
}
|
||||
|
||||
// Right side: version always at far right, connection status to its left.
|
||||
// Compute positions dynamically from actual text widths so they
|
||||
// never overlap and always stay within the window at any font scale.
|
||||
|
||||
Reference in New Issue
Block a user