Repository: dogecoin/dogecoin
File: src/wallet/scriptpubkeyman.cpp (C++)

Code before:
    }
    return true;
}

void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
{
    LOCK(cs_KeyStore);
    // extract addresses and check if they match with an unused keypool key
    for (const auto& keyid : GetAffectedKeys(script, *this)) {
        std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
        if (mi != m_pool_key_to_index.end()) {
            WalletLogPrintf("%s: Detected a used keypool key, mark all keypool keys up to this key as used\n", __func__);
            MarkReserveKeysAsUsed(mi->second);

            if (!TopUp()) {
                WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
            }
        }

        // Find the key's metadata and check if it's seed id (if it has one) is inactive, i.e. it is not the current m_hd_chain seed id.
        // If so, TopUp the inactive hd chain
        auto it = mapKeyMetadata.find(keyid);
        if (it != mapKeyMetadata.end()){
            CKeyMetadata meta = it->second;
            if (!meta.hd_seed_id.IsNull() && meta.hd_seed_id != m_hd_chain.seed_id) {
	    	bool internal = meta.key_origin.path[1] == (1 | 0x80000000);
                int64_t index = meta.key_origin.path[2] & ~BIP32_HARDENED_KEY_LIMIT;
                if (!TopUpInactiveHDChain(meta.hd_seed_id, index, internal)) {
                    WalletLogPrintf("%s: Adding inactive seed keys failed\n", __func__);
                }
            }
        }
    }
}

void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
{
    LOCK(cs_KeyStore);
    if (m_storage.IsLocked() || m_storage.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
        return;
    }

    std::unique_ptr<WalletBatch> batch = MakeUnique<WalletBatch>(m_storage.GetDatabase());
    for (auto& meta_pair : mapKeyMetadata) {
        CKeyMetadata& meta = meta_pair.second;
        if (!meta.hd_seed_id.IsNull() && !meta.has_key_origin && meta.hdKeypath != "s") { // If the hdKeypath is "s", that's the seed and it doesn't have a key origin
            CKey key;
            GetKey(meta.hd_seed_id, key);
            CExtKey masterKey;
            masterKey.SetSeed(key.begin(), key.size());
            // Add to map

Review comment (suggestion):
Not necessarily blocking, but note that this changes the behavior:

Before this change: anything other than the mainnet identifier was marked testnet.
After this change: anything other than the testnet identifier is marked as mainnet.

Personal preference: the former logic is more defensive.

Doesn't have to be fixed now, this anyway needs documentation so we can pick that up in a followup PR.

Code after:
    }
    return true;
}

void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
{
    LOCK(cs_KeyStore);
    // extract addresses and check if they match with an unused keypool key
    for (const auto& keyid : GetAffectedKeys(script, *this)) {
        std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
        if (mi != m_pool_key_to_index.end()) {
            WalletLogPrintf("%s: Detected a used keypool key, mark all keypool keys up to this key as used\n", __func__);
            MarkReserveKeysAsUsed(mi->second);

            if (!TopUp()) {
                WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
            }
        }

        // Find the key's metadata and check if it's seed id (if it has one) is inactive, i.e. it is not the current m_hd_chain seed id.
        // If so, TopUp the inactive hd chain
        auto it = mapKeyMetadata.find(keyid);
        if (it != mapKeyMetadata.end()){
            CKeyMetadata meta = it->second;
            if (!meta.hd_seed_id.IsNull() && meta.hd_seed_id != m_hd_chain.seed_id) {
                bool internal = ((meta.key_origin.path[1] == 0x80000003) || (meta.key_origin.path[1] == 0x80000000)) ? 0 : 1; 
                int64_t index = meta.key_origin.path[2] & ~BIP32_HARDENED_KEY_LIMIT;

                if (!TopUpInactiveHDChain(meta.hd_seed_id, index, internal)) {
                    WalletLogPrintf("%s: Adding inactive seed keys failed\n", __func__);
                }
            }
        }
    }
}

void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
{
    LOCK(cs_KeyStore);
    if (m_storage.IsLocked() || m_storage.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
        return;
    }

    std::unique_ptr<WalletBatch> batch = MakeUnique<WalletBatch>(m_storage.GetDatabase());
    for (auto& meta_pair : mapKeyMetadata) {
        CKeyMetadata& meta = meta_pair.second;
        if (!meta.hd_seed_id.IsNull() && !meta.has_key_origin && meta.hdKeypath != "s") { // If the hdKeypath is "s", that's the seed and it doesn't have a key origin
            CKey key;
            GetKey(meta.hd_seed_id, key);
            CExtKey masterKey;
            masterKey.SetSeed(key.begin(), key.size());