diff options
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r-- | src/wallet/wallet.cpp | 95 |
1 files changed, 54 insertions, 41 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d16baf60e4..e6227048d2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -94,6 +94,16 @@ static void UpdateWalletSetting(interfaces::Chain& chain, } } +/** + * Refresh mempool status so the wallet is in an internally consistent state and + * immediately knows the transaction's status: Whether it can be considered + * trusted and is eligible to be abandoned ... + */ +static void RefreshMempoolStatus(CWalletTx& tx, interfaces::Chain& chain) +{ + tx.fInMempool = chain.isInMempool(tx.GetHash()); +} + bool AddWallet(const std::shared_ptr<CWallet>& wallet) { LOCK(cs_wallets); @@ -803,10 +813,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash) wtx.mapValue["replaced_by_txid"] = newHash.ToString(); // Refresh mempool status without waiting for transactionRemovedFromMempool - // notification so the wallet is in an internally consistent state and - // immediately knows the old transaction should not be considered trusted - // and is eligible to be abandoned - wtx.fInMempool = chain().isInMempool(originalHash); + RefreshMempoolStatus(wtx, chain()); WalletBatch batch(GetDatabase()); @@ -1206,7 +1213,7 @@ void CWallet::transactionAddedToMempool(const CTransactionRef& tx, uint64_t memp auto it = mapWallet.find(tx->GetHash()); if (it != mapWallet.end()) { - it->second.fInMempool = true; + RefreshMempoolStatus(it->second, chain()); } } @@ -1214,7 +1221,7 @@ void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRe LOCK(cs_wallet); auto it = mapWallet.find(tx->GetHash()); if (it != mapWallet.end()) { - it->second.fInMempool = false; + RefreshMempoolStatus(it->second, chain()); } // Handle transactions that were removed from the mempool because they // conflict with transactions in a newly connected block. @@ -2298,44 +2305,48 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const { AssertLockHeld(cs_wallet); mapKeyBirth.clear(); - LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan(); - assert(spk_man != nullptr); - LOCK(spk_man->cs_KeyStore); - - // get birth times for keys with metadata - for (const auto& entry : spk_man->mapKeyMetadata) { - if (entry.second.nCreateTime) { - mapKeyBirth[entry.first] = entry.second.nCreateTime; - } - } - // map in which we'll infer heights of other keys std::map<CKeyID, const CWalletTx::Confirmation*> mapKeyFirstBlock; CWalletTx::Confirmation max_confirm; max_confirm.block_height = GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0; // the tip can be reorganized; use a 144-block safety margin CHECK_NONFATAL(chain().findAncestorByHeight(GetLastBlockHash(), max_confirm.block_height, FoundBlock().hash(max_confirm.hashBlock))); - for (const CKeyID &keyid : spk_man->GetKeys()) { - if (mapKeyBirth.count(keyid) == 0) - mapKeyFirstBlock[keyid] = &max_confirm; - } - // if there are no such keys, we're done - if (mapKeyFirstBlock.empty()) - return; + { + LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan(); + assert(spk_man != nullptr); + LOCK(spk_man->cs_KeyStore); + + // get birth times for keys with metadata + for (const auto& entry : spk_man->mapKeyMetadata) { + if (entry.second.nCreateTime) { + mapKeyBirth[entry.first] = entry.second.nCreateTime; + } + } - // find first block that affects those keys, if there are any left - for (const auto& entry : mapWallet) { - // iterate over all wallet transactions... - const CWalletTx &wtx = entry.second; - if (wtx.m_confirm.status == CWalletTx::CONFIRMED) { - // ... which are already in a block - for (const CTxOut &txout : wtx.tx->vout) { - // iterate over all their outputs - for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *spk_man)) { - // ... and all their affected keys - auto rit = mapKeyFirstBlock.find(keyid); - if (rit != mapKeyFirstBlock.end() && wtx.m_confirm.block_height < rit->second->block_height) { - rit->second = &wtx.m_confirm; + // Prepare to infer birth heights for keys without metadata + for (const CKeyID &keyid : spk_man->GetKeys()) { + if (mapKeyBirth.count(keyid) == 0) + mapKeyFirstBlock[keyid] = &max_confirm; + } + + // if there are no such keys, we're done + if (mapKeyFirstBlock.empty()) + return; + + // find first block that affects those keys, if there are any left + for (const auto& entry : mapWallet) { + // iterate over all wallet transactions... + const CWalletTx &wtx = entry.second; + if (wtx.m_confirm.status == CWalletTx::CONFIRMED) { + // ... which are already in a block + for (const CTxOut &txout : wtx.tx->vout) { + // iterate over all their outputs + for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *spk_man)) { + // ... and all their affected keys + auto rit = mapKeyFirstBlock.find(keyid); + if (rit != mapKeyFirstBlock.end() && wtx.m_confirm.block_height < rit->second->block_height) { + rit->second = &wtx.m_confirm; + } } } } @@ -2582,19 +2593,21 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain* chain, const std::st } if (!gArgs.GetArg("-addresstype", "").empty()) { - if (!ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) { + std::optional<OutputType> parsed = ParseOutputType(gArgs.GetArg("-addresstype", "")); + if (!parsed) { error = strprintf(_("Unknown address type '%s'"), gArgs.GetArg("-addresstype", "")); return nullptr; } + walletInstance->m_default_address_type = parsed.value(); } if (!gArgs.GetArg("-changetype", "").empty()) { - OutputType out_type; - if (!ParseOutputType(gArgs.GetArg("-changetype", ""), out_type)) { + std::optional<OutputType> parsed = ParseOutputType(gArgs.GetArg("-changetype", "")); + if (!parsed) { error = strprintf(_("Unknown change type '%s'"), gArgs.GetArg("-changetype", "")); return nullptr; } - walletInstance->m_default_change_type = out_type; + walletInstance->m_default_change_type = parsed.value(); } if (gArgs.IsArgSet("-mintxfee")) { |