[grade=A] fix(chain): disable destructive automatic rebuild (urn:ump:yukhymo2kpp227nesu56snay6mfuctqgglvox476weezc2geij7a)
This commit is contained in:
+15
-95
@@ -178,95 +178,19 @@ void ExitTimeout(void* parg)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait up to maxWaitSec for at least minPeers peers to have reported their
|
// Automatic recovery is intentionally non-destructive. Older builds deleted the
|
||||||
// chain height via the version handshake. Returns the median peer height, or
|
// chain DB and blk0001.dat when a node lagged its peers, which could turn a
|
||||||
// -1 if we couldn't get enough peers (timeout, no peers, all nStartingHeight=-1).
|
// transient peer-height report into permanent local data loss. A privacy coin
|
||||||
int WaitForPeerHeights(int minPeers, int maxWaitSec)
|
// must never rewrite historical chain data automatically; recovery remains an
|
||||||
|
// explicit operator action after wallet and chain-state backups.
|
||||||
|
// Legacy hook retained only to surface that -autorerebuild no longer mutates
|
||||||
|
// chain state.
|
||||||
|
static void LogAutoRebuildDisabled(int thresholdBlocks)
|
||||||
{
|
{
|
||||||
const int pollIntervalMs = 500;
|
if (thresholdBlocks > 0) {
|
||||||
const int64_t deadline = GetTimeMillis() + (int64_t)maxWaitSec * 1000;
|
printf("AutoRebuild: -autorerebuild=%d ignored; automatic chain deletion is disabled.\n",
|
||||||
|
thresholdBlocks);
|
||||||
while (GetTimeMillis() < deadline && !fRequestShutdown) {
|
|
||||||
std::vector<int> heights;
|
|
||||||
{
|
|
||||||
LOCK(cs_vNodes);
|
|
||||||
for (CNode* pnode : vNodes) {
|
|
||||||
if (pnode && pnode->nStartingHeight > 0)
|
|
||||||
heights.push_back(pnode->nStartingHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((int)heights.size() >= minPeers) {
|
|
||||||
std::sort(heights.begin(), heights.end());
|
|
||||||
int median = heights[heights.size() / 2];
|
|
||||||
printf("AutoRebuild: got %zu peer heights; median=%d\n", heights.size(), median);
|
|
||||||
return median;
|
|
||||||
}
|
|
||||||
MilliSleep(pollIntervalMs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> heights;
|
|
||||||
{
|
|
||||||
LOCK(cs_vNodes);
|
|
||||||
for (CNode* pnode : vNodes) {
|
|
||||||
if (pnode && pnode->nStartingHeight > 0)
|
|
||||||
heights.push_back(pnode->nStartingHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (heights.empty()) {
|
|
||||||
printf("AutoRebuild: no peers reported heights after %ds\n", maxWaitSec);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
std::sort(heights.begin(), heights.end());
|
|
||||||
int median = heights[heights.size() / 2];
|
|
||||||
printf("AutoRebuild: timed out with %zu peers; median=%d\n", heights.size(), median);
|
|
||||||
return median;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If -autorerebuild is set and our local chain is more than that many blocks
|
|
||||||
// behind the median peer height, wipe the chain DB (preserving wallet.dat +
|
|
||||||
// onion + smsg state) and request shutdown. On restart, the daemon sees no
|
|
||||||
// chain DB and the snapshot path takes over.
|
|
||||||
void MaybeAutoRebuild(int thresholdBlocks)
|
|
||||||
{
|
|
||||||
if (thresholdBlocks <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (nBestHeight < 0) {
|
|
||||||
printf("AutoRebuild: local nBestHeight unset — skipping\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("AutoRebuild: enabled (threshold=%d blocks). Local chain tip: %d\n",
|
|
||||||
thresholdBlocks, nBestHeight);
|
|
||||||
int medianPeer = WaitForPeerHeights(/*minPeers=*/3, /*maxWaitSec=*/60);
|
|
||||||
if (medianPeer <= 0) {
|
|
||||||
printf("AutoRebuild: could not get peer heights — skipping rebuild\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int lag = medianPeer - nBestHeight;
|
|
||||||
printf("AutoRebuild: peer median=%d, local=%d, lag=%d\n",
|
|
||||||
medianPeer, nBestHeight, lag);
|
|
||||||
|
|
||||||
if (lag < thresholdBlocks) {
|
|
||||||
printf("AutoRebuild: lag %d < threshold %d — no rebuild needed\n",
|
|
||||||
lag, thresholdBlocks);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n*** AutoRebuild: chain is %d blocks behind — wiping chain DB ***\n", lag);
|
|
||||||
printf("*** Preserving wallet.dat, smsgDB, onion state. ***\n");
|
|
||||||
printf("*** Daemon will shutdown; restart to load signed UTXO snapshot. ***\n\n");
|
|
||||||
|
|
||||||
WipeChainDataDir();
|
|
||||||
|
|
||||||
fs::path blkPath = GetDataDir() / "blk0001.dat";
|
|
||||||
if (fs::exists(blkPath)) {
|
|
||||||
fs::remove(blkPath);
|
|
||||||
printf("AutoRebuild: removed stale %s\n", blkPath.string().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
StartShutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartShutdown()
|
void StartShutdown()
|
||||||
@@ -655,7 +579,7 @@ std::string HelpMessage()
|
|||||||
" -onionseed " + _("Find peers using .onion seeds (default: 1 unless -connect)") + "\n" +
|
" -onionseed " + _("Find peers using .onion seeds (default: 1 unless -connect)") + "\n" +
|
||||||
" -seedurl=<host> " + _("HTTP seed list host (default: seeds.cryptographic-triangles.org)") + "\n" +
|
" -seedurl=<host> " + _("HTTP seed list host (default: seeds.cryptographic-triangles.org)") + "\n" +
|
||||||
" -noseedurl " + _("Disable HTTP seed list fetch on startup") + "\n" +
|
" -noseedurl " + _("Disable HTTP seed list fetch on startup") + "\n" +
|
||||||
" -autorerebuild=<n> " + _("If our chain is more than <n> blocks behind peers, wipe chain DB and shutdown for clean restart (default: 0=disabled)") + "\n" +
|
" -autorerebuild=<n> " + _("Deprecated compatibility option; automatic chain deletion is disabled") + "\n" +
|
||||||
" -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" +
|
" -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" +
|
||||||
" -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
|
" -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
|
||||||
" -par=<n> " + _("Set the number of script verification threads (default: auto, 0 = auto, 1 = single-threaded)") + "\n" +
|
" -par=<n> " + _("Set the number of script verification threads (default: auto, 0 = auto, 1 = single-threaded)") + "\n" +
|
||||||
@@ -1581,13 +1505,9 @@ bool AppInit2()
|
|||||||
uiInterface.InitMessage(_("UTXO rebuild complete"));
|
uiInterface.InitMessage(_("UTXO rebuild complete"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// AutoRebuild: if -autorerebuild is set and we are behind peers, wipe chain DB
|
// Keep the legacy option parse for compatibility, but automatic recovery is
|
||||||
// and shutdown for clean restart.
|
// diagnostic-only and never removes chain data.
|
||||||
MaybeAutoRebuild(GetArg("-autorerebuild", 0));
|
LogAutoRebuildDisabled(GetArg("-autorerebuild", 0));
|
||||||
if (fRequestShutdown) {
|
|
||||||
printf("AutoRebuild: shutdown requested before chain load complete\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block index loaded. With fast-import removed, the only supported sync path
|
// Block index loaded. With fast-import removed, the only supported sync path
|
||||||
// is the UTXO snapshot (auto-downloaded from bootstrap or placed manually in datadir).
|
// is the UTXO snapshot (auto-downloaded from bootstrap or placed manually in datadir).
|
||||||
|
|||||||
+5
-5
@@ -118,12 +118,12 @@ void ThreadForkDetector(void*)
|
|||||||
printf("*** Possible fork or sync stall. Check peers: 'getpeerinfo' and chain: 'getblockhash %d' ***\n",
|
printf("*** Possible fork or sync stall. Check peers: 'getpeerinfo' and chain: 'getblockhash %d' ***\n",
|
||||||
nOurHeight);
|
nOurHeight);
|
||||||
|
|
||||||
// If severe lag persists, suggest auto-rebuild
|
// Severe lag is diagnostic only. Recovery must be explicitly
|
||||||
if (lag >= threshold * 3 && GetBoolArg("-autorerebuild", 0) > 0)
|
// initiated by an operator after backups; never request an
|
||||||
|
// automatic shutdown that could lead to chain-state deletion.
|
||||||
|
if (lag >= threshold * 3 && GetBoolArg("-autorerebuild", false))
|
||||||
{
|
{
|
||||||
printf("*** FORK DETECTOR: lag %d >= %d, triggering AutoRebuild ***\n",
|
printf("*** FORK DETECTOR: automatic rebuild is disabled; operator review required ***\n");
|
||||||
lag, threshold * 3);
|
|
||||||
StartShutdown();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user