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

Code before:
    }
    if (!WriteBlockToDisk(block, blockPos)) {
        m_opts.notifications.fatalError(_("Failed to write block."));
        return FlatFilePos();
    }
    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++;

Review comment (suggestion):
Jjust noting here that if the user specifies `-blocksxor=01234567` and a file-based key already exists in the datadir, the key from the file is silently used.

This is the correct behaviour IMO, but wonder if we should log that the user-set option has been overridden?

As @maflcko pointed out to me previously, even if a user mistakenly thought they were using a custom xor key set as a CL option and removed the key file, they could still restore it. So I don't see any dangers with this current behaviour.

Code after:
        return FlatFilePos();
    }
    if (!WriteBlockToDisk(block, blockPos)) {
        m_opts.notifications.fatalError(_("Failed to write block."));
        return FlatFilePos();
    }
    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},