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

Code before:
    uint256 base_blockhash = metadata.m_base_blockhash;

    CBlockIndex* snapshot_start_block = WITH_LOCK(::cs_main, return m_blockman.LookupBlockIndex(base_blockhash));

    if (!snapshot_start_block) {
        // Needed for ComputeUTXOStats to determine the
        // height and to avoid a crash when base_blockhash.IsNull()
        LogPrintf("[snapshot] Did not find snapshot start blockheader %s\n",
                  base_blockhash.ToString());
        return false;
    }

    int base_height = snapshot_start_block->nHeight;
    const auto& maybe_au_data = GetParams().AssumeutxoForHeight(base_height);

    if (!maybe_au_data) {
        LogPrintf("[snapshot] assumeutxo height in snapshot metadata not recognized "
                  "(%d) - refusing to load snapshot\n", base_height);
        return false;
    }

    const AssumeutxoData& au_data = *maybe_au_data;

    // This work comparison is a duplicate check with the one performed later in
    // ActivateSnapshot(), but is done so that we avoid doing the long work of staging
    // a snapshot that isn't actually usable.
    if (WITH_LOCK(::cs_main, return !CBlockIndexWorkComparator()(ActiveTip(), snapshot_start_block))) {
        LogPrintf("[snapshot] activation failed - work does not exceed active chainstate\n");
        return false;
    }

    const uint64_t coins_count = metadata.m_coins_count;
    uint64_t coins_left = metadata.m_coins_count;

    LogPrintf("[snapshot] loading %d coins from snapshot %s\n", coins_left, base_blockhash.ToString());
    int64_t coins_processed{0};

    while (coins_left > 0) {
        try {
            Txid txid;
            coins_file >> txid;
            size_t coins_per_txid{0};
            coins_per_txid = ReadCompactSize(coins_file);

            if (coins_per_txid > coins_left) {
                LogPrintf("[snapshot] mismatch in coins count in snapshot metadata and actual snapshot data\n");
                return false;
            }

            for (size_t i = 0; i < coins_per_txid; i++) {
                COutPoint outpoint;

Review comment (bug):
In commit "rpc: Return precise loadtxoutset error messages" (fa91404c68b4d503e6568f49aaf74a5746887185)

The error message seems inconsistent with other ones because it is prefixed with "Activation failed -". Maybe drop that prefix or also include it in the other messages?

Code after:
    uint256 base_blockhash = metadata.m_base_blockhash;

    CBlockIndex* snapshot_start_block = WITH_LOCK(::cs_main, return m_blockman.LookupBlockIndex(base_blockhash));

    if (!snapshot_start_block) {
        // Needed for ComputeUTXOStats to determine the
        // height and to avoid a crash when base_blockhash.IsNull()
        return util::Error{strprintf(Untranslated("Did not find snapshot start blockheader %s"),
                  base_blockhash.ToString())};
    }

    int base_height = snapshot_start_block->nHeight;
    const auto& maybe_au_data = GetParams().AssumeutxoForHeight(base_height);

    if (!maybe_au_data) {
        return util::Error{strprintf(Untranslated("Assumeutxo height in snapshot metadata not recognized "
                  "(%d) - refusing to load snapshot"), base_height)};
    }

    const AssumeutxoData& au_data = *maybe_au_data;

    // This work comparison is a duplicate check with the one performed later in
    // ActivateSnapshot(), but is done so that we avoid doing the long work of staging
    // a snapshot that isn't actually usable.
    if (WITH_LOCK(::cs_main, return !CBlockIndexWorkComparator()(ActiveTip(), snapshot_start_block))) {
        return util::Error{Untranslated("Work does not exceed active chainstate")};
    }

    const uint64_t coins_count = metadata.m_coins_count;
    uint64_t coins_left = metadata.m_coins_count;

    LogPrintf("[snapshot] loading %d coins from snapshot %s\n", coins_left, base_blockhash.ToString());
    int64_t coins_processed{0};

    while (coins_left > 0) {
        try {
            Txid txid;
            coins_file >> txid;
            size_t coins_per_txid{0};
            coins_per_txid = ReadCompactSize(coins_file);

            if (coins_per_txid > coins_left) {
                return util::Error{Untranslated("Mismatch in coins count in snapshot metadata and actual snapshot data")};
            }

            for (size_t i = 0; i < coins_per_txid; i++) {
                COutPoint outpoint;
                Coin coin;
                outpoint.n = static_cast<uint32_t>(ReadCompactSize(coins_file));
                outpoint.hash = txid;
                coins_file >> coin;