Repository: bitcoin/bitcoin
File: src/node/blockstorage.cpp (C++)

Code before:
    return blockPos;
}

class ImportingNow
{
    std::atomic<bool>& m_importing;

public:
    ImportingNow(std::atomic<bool>& importing) : m_importing{importing}
    {
        assert(m_importing == false);
        m_importing = true;
    }
    ~ImportingNow()
    {
        assert(m_importing == true);
        m_importing = false;
    }
};

void ImportBlocks(ChainstateManager& chainman, std::vector<fs::path> vImportFiles)
{
    ImportingNow imp{chainman.m_blockman.m_importing};

    // -reindex
    if (!chainman.m_blockman.m_blockfiles_indexed) {
        int nFile = 0;
        // Map of disk positions for blocks with unknown parent (only used for reindex);
        // parent hash -> child disk position, multiple children can have the same parent.
        std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent;
        while (true) {
            FlatFilePos pos(nFile, 0);
            if (!fs::exists(chainman.m_blockman.GetBlockPosFilename(pos))) {
                break; // No block files left to reindex
            }
            AutoFile file{chainman.m_blockman.OpenBlockFile(pos, true)};
            if (file.IsNull()) {
                break; // This error is logged in OpenBlockFile
            }
            LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
            chainman.LoadExternalBlockFile(file, &pos, &blocks_with_unknown_parent);
            if (chainman.m_interrupt) {
                LogPrintf("Interrupt requested. Exit %s\n", __func__);
                return;
            }
            nFile++;
        }
        WITH_LOCK(::cs_main, chainman.m_blockman.m_block_tree_db->WriteReindexing(false));
        chainman.m_blockman.m_blockfiles_indexed = true;
        LogPrintf("Reindexing finished\n");
        // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):

Review comment (suggestion):
Nit: I found this a bit hard to follow and a bit unfortunate that a new random key would be generated every time whether it were used or not. How about:
```diff
@@ -1166,4 +1165,0 @@ static auto InitBlocksdirXorKey(const BlockManager::Options& opts)
-    // Initialize random fresh key, ...
-    FastRandomContext{}.fillrand(xor_key);
-    // ... but allow legacy or user-disabled key.
-    if (!fs::is_empty(opts.blocks_dir) || opts.xor_key == false) std::fill(xor_key.begin(), xor_key.end(), std::byte{});
@@ -1171 +1167,8 @@ static auto InitBlocksdirXorKey(const BlockManager::Options& opts)
-    if (fs::exists(xor_key_path)) {
+    bool key_exists = fs::exists(xor_key_path);
+
+    if (!key_exists && opts.xor_key && fs::is_empty(opts.blocks_dir)) {
+        // Initialize random fresh key, ...
+        FastRandomContext{}.fillrand(xor_key);
+    }
+
+    if (key_exists) {
```

Code after:
    }
    return blockPos;
}

static auto InitBlocksdirXorKey(const BlockManager::Options& opts)
{
    // Bytes are serialized without length indicator, so this is also the exact
    // size of the XOR-key file.
    std::array<std::byte, 8> xor_key{};

    if (opts.use_xor && fs::is_empty(opts.blocks_dir)) {
        // Only use random fresh key when the boolean option is set and on the
        // very first start of the program.
        FastRandomContext{}.fillrand(xor_key);
    }

    const fs::path xor_key_path{opts.blocks_dir / "xor.dat"};
    if (fs::exists(xor_key_path)) {
        // A pre-existing xor key file has priority.
        AutoFile xor_key_file{fsbridge::fopen(xor_key_path, "rb")};
        xor_key_file >> xor_key;
    } else {
        // Create initial or missing xor key file
        AutoFile xor_key_file{fsbridge::fopen(xor_key_path,
#ifdef __MINGW64__
            "wb" // Temporary workaround for https://github.com/bitcoin/bitcoin/issues/30210
#else
            "wbx"
#endif
        )};
        xor_key_file << xor_key;
    }
    // If the user disabled the key, it must be zero.
    if (!opts.use_xor && xor_key != decltype(xor_key){}) {
        throw std::runtime_error{
            strprintf("The blocksdir XOR-key can not be disabled when a random key was already stored! "
                      "Stored key: '%s', stored path: '%s'.",
                      HexStr(xor_key), fs::PathToString(xor_key_path)),
        };
    }
    LogInfo("Using obfuscation key for blocksdir *.dat files (%s): '%s'\n", fs::PathToString(opts.blocks_dir), HexStr(xor_key));
    return std::vector<std::byte>{xor_key.begin(), xor_key.end()};
}

BlockManager::BlockManager(const util::SignalInterrupt& interrupt, Options opts)
    : m_prune_mode{opts.prune_target > 0},
      m_xor_key{InitBlocksdirXorKey(opts)},
      m_opts{std::move(opts)},
      m_block_file_seq{FlatFileSeq{m_opts.blocks_dir, "blk", m_opts.fast_prune ? 0x4000 /* 16kB */ : BLOCKFILE_CHUNK_SIZE}},
      m_undo_file_seq{FlatFileSeq{m_opts.blocks_dir, "rev", UNDOFILE_CHUNK_SIZE}},
      m_interrupt{interrupt} {}