fix(sync): prioritize getblockchaininfo and pause chat scans while behind
The node kept falling behind the network near the tip because sync DETECTION was starved: getblockchaininfo was queued behind the O(mapWallet) wallet RPCs (z_gettotalbalance / z_listunspent), so longestchain went stale, the wallet decided it was "synced", and it resumed hammering cs_main — a feedback loop. - Issue getblockchaininfo FIRST each cycle and skip the balance/address/ tx refresh entirely while behind, so sync state (and kSyncProfile) updates before any heavy wallet scan runs. - Gate the two chat note scans (refreshChatNoteBudgetNode / fastScanChatMemos) on effectivelySyncing() and the active page, so chat memo scanning no longer competes with block connection during sync. - Windows debug.log tailer: reset the read offset when dragonxd truncates the log on startup (it was stranding at Block:0 with no witness/rescan progress). - Tests cover the getblockchaininfo-first ordering and behind-skip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1417,31 +1417,51 @@ void testNetworkRefreshRpcCollectors()
|
||||
});
|
||||
coreRpc.addResponse("getblockchaininfo", json{
|
||||
{"blocks", 150},
|
||||
{"headers", 155},
|
||||
{"headers", 150},
|
||||
{"bestblockhash", "core-best-150"},
|
||||
{"verificationprogress", 0.80},
|
||||
{"longestchain", 160},
|
||||
{"verificationprogress", 1.0},
|
||||
{"longestchain", 150}, // caught up → balance scan runs
|
||||
{"notarized", 145}
|
||||
});
|
||||
auto core = Refresh::collectCoreRefreshResult(coreRpc);
|
||||
// getblockchaininfo is issued FIRST — sync detection gates (and must not be delayed behind) the
|
||||
// O(mapWallet) balance scan. When caught up, the balance scan follows: display (minconf=0) +
|
||||
// spendable (minconf=1).
|
||||
EXPECT_TRUE(coreRpc.methodNames() == std::vector<std::string>({
|
||||
"z_gettotalbalance", "z_gettotalbalance", "getblockchaininfo" // display (minconf=0) + spendable (minconf=1)
|
||||
"getblockchaininfo", "z_gettotalbalance", "z_gettotalbalance"
|
||||
}));
|
||||
EXPECT_EQ(coreRpc.calls[0].params, json::array({0}));
|
||||
EXPECT_EQ(coreRpc.calls[1].params, json::array({1}));
|
||||
EXPECT_EQ(coreRpc.calls[1].params, json::array({0}));
|
||||
EXPECT_EQ(coreRpc.calls[2].params, json::array({1}));
|
||||
EXPECT_TRUE(core.balanceOk);
|
||||
EXPECT_TRUE(core.blockchainOk);
|
||||
EXPECT_NEAR(*core.totalBalance, 4.25, 0.00000001);
|
||||
EXPECT_EQ(*core.blocks, 150);
|
||||
EXPECT_EQ(*core.bestBlockHash, std::string("core-best-150"));
|
||||
EXPECT_EQ(*core.longestChain, 160);
|
||||
EXPECT_EQ(*core.longestChain, 150);
|
||||
|
||||
// When getblockchaininfo shows the node is behind (blocks < longestchain - 2), the balance scan is
|
||||
// skipped this cycle regardless of includeBalance — so sync-state (and hence kSyncProfile) updates
|
||||
// promptly instead of after the multi-second scan. Only getblockchaininfo is issued.
|
||||
MockRefreshRpc coreBehindRpc;
|
||||
coreBehindRpc.addResponse("z_gettotalbalance", json{{"total", "4.25000000"}});
|
||||
coreBehindRpc.addResponse("getblockchaininfo", json{
|
||||
{"blocks", 150}, {"headers", 160}, {"longestchain", 160}
|
||||
});
|
||||
auto coreBehind = Refresh::collectCoreRefreshResult(coreBehindRpc);
|
||||
EXPECT_TRUE(coreBehindRpc.methodNames() == std::vector<std::string>({"getblockchaininfo"}));
|
||||
EXPECT_FALSE(coreBehind.balanceOk);
|
||||
EXPECT_TRUE(coreBehind.blockchainOk);
|
||||
EXPECT_EQ(*coreBehind.blocks, 150);
|
||||
EXPECT_EQ(*coreBehind.longestChain, 160);
|
||||
|
||||
MockRefreshRpc coreFallbackRpc;
|
||||
coreFallbackRpc.addFailure("z_gettotalbalance", "wallet warming up");
|
||||
coreFallbackRpc.addResponse("getblockchaininfo", json{{"blocks", 8}, {"headers", 9}});
|
||||
auto partialCore = Refresh::collectCoreRefreshResult(coreFallbackRpc);
|
||||
// No longestchain in the response → not classified as "behind" → balance is still attempted (here it
|
||||
// fails). getblockchaininfo is still issued first.
|
||||
EXPECT_TRUE(coreFallbackRpc.methodNames() == std::vector<std::string>({
|
||||
"z_gettotalbalance", "z_gettotalbalance", "getblockchaininfo"
|
||||
"getblockchaininfo", "z_gettotalbalance", "z_gettotalbalance"
|
||||
}));
|
||||
EXPECT_FALSE(partialCore.balanceOk);
|
||||
EXPECT_TRUE(partialCore.blockchainOk);
|
||||
|
||||
Reference in New Issue
Block a user