From a38bfd2f97c36baf956e34a9a89ea018690b0025 Mon Sep 17 00:00:00 2001 From: hermes Date: Fri, 19 Jun 2026 19:40:40 -0700 Subject: [PATCH] fix: auto-download UTXO snapshot when chain DB missing (3 root causes) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three bugs prevented the wallet from automatically downloading the UTXO snapshot when starting with stale blk0001.dat but no chain database: 1. NeedsBootstrap() only checked for blk0001.dat existence, not the chain DB. If blk0001.dat was present (leftover from old version) but txleveldb/chainstate was missing, it reported "no bootstrap needed" and the snapshot download never triggered. Fix: check for txleveldb/ or blocks/chainstate/ instead. 2. Bootstrap HTTP download was skipped when snapshotMode was true (the default). The code deferred to P2P snapshot fetch (Step 11.6), but that runs AFTER Step 7 which errored out on the FastImport gate. Fix: always attempt HTTP bootstrap when NeedsBootstrap is true, regardless of snapshotMode. The UTXO snapshot HTTP download IS the fast path — no reason to defer to P2P when HTTP is available. 3. FastImport gate (Step 7) was a hard InitError that killed the daemon before it ever reached the snapshot fetch path. blk0001.dat present + no chain index + FastImport disabled = immediate crash. Fix: instead of erroring, remove the stale blk0001.dat and continue. The daemon syncs from the snapshot that was already loaded in Step 6b, or from P2P if that somehow failed. --- src/bootstrap.cpp | 9 ++++++++- src/init.cpp | 23 ++++++++++------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/bootstrap.cpp b/src/bootstrap.cpp index 7ba2669..11a3a8b 100644 --- a/src/bootstrap.cpp +++ b/src/bootstrap.cpp @@ -50,7 +50,14 @@ namespace Bootstrap { bool NeedsBootstrap(const fs::path& dataDir) { - return !fs::exists(dataDir / "blk0001.dat"); + // Need bootstrap if there's no chain database (the UTXO set / block index). + // blk0001.dat alone is NOT sufficient — it's raw block data that requires + // FastImport to build an index, and FastImport is disabled by default. + // Check for both LevelDB (txleveldb/) and RocksDB (chainstate/) backends. + bool hasChainDb = fs::exists(dataDir / "txleveldb") + || fs::exists(dataDir / "blocks" / "chainstate") + || fs::exists(dataDir / "chainstate"); + return !hasChainDb; } // Direct TCP connection bypassing Tor SOCKS proxy. diff --git a/src/init.cpp b/src/init.cpp index cd98760..8faad44 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1030,14 +1030,11 @@ bool AppInit2() fs::path dataPath = GetDataDir(); bool needsBootstrap = Bootstrap::NeedsBootstrap(dataPath); - if (needsBootstrap && !noBootstrap && !snapshotMode) { - printf("Bootstrap: no blockchain data found — downloading automatically.\n"); + if (needsBootstrap && !noBootstrap) { + printf("Bootstrap: no blockchain data found — downloading UTXO snapshot automatically.\n"); printf("Bootstrap: (use -nobootstrap to skip)\n"); - uiInterface.InitMessage(_("Downloading blockchain data...")); + uiInterface.InitMessage(_("Downloading UTXO snapshot...")); wantsBootstrap = true; - } else if (needsBootstrap && snapshotMode && !wantsBootstrap) { - printf("Bootstrap: no blockchain data found — will fetch UTXO snapshot via P2P after network start.\n"); - printf("Bootstrap: (use -bootstrap for legacy clearnet HTTP bootstrap, or -snapshot=0 to disable P2P fetcher)\n"); } if (wantsBootstrap) @@ -1229,20 +1226,20 @@ bool AppInit2() { if (!GetBoolArg("-allowfastimport", false)) { - return InitError(_( - "Block index empty and blk0001.dat is present, but FastImport is disabled " - "(default). The snapshot path is the only supported sync start.\n\n" - "To recover:\n" - " 1. Place a signed utxo-snapshot.bin in the data directory and restart, OR\n" - " 2. Delete blk0001.dat (the snapshot path will sync from network), OR\n" - " 3. Pass -allowfastimport=1 to permit FastImport (operator opt-in only).")); + printf("FastImport: blk0001.dat present but -allowfastimport not set — " + "ignoring block file, will sync from network via UTXO snapshot.\n"); + // Remove the stale blk0001.dat so it doesn't trigger again + std::filesystem::remove(GetDataDir() / "blk0001.dat"); } + else + { printf("FastImport: WARNING -allowfastimport is set; rebuilding from local blk0001.dat.\n"); uiInterface.InitMessage(_("Importing bootstrap blocks...")); printf("Block index empty but blk0001.dat exists - running fast import...\n"); int64_t nFastImportStart = GetTimeMillis(); FastImportBlockFile(); StartupPerfLog("bootstrap_fast_import", GetTimeMillis() - nFastImportStart, strprintf("bestheight=%d", nBestHeight)); + } } // as LoadBlockIndex can take several minutes, it's possible the user