0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-03 09:56:38 -05:00

Change mapTxSpends to be a std::unordered_multimap

This commit is contained in:
Andrew Chow 2019-09-17 18:56:50 -04:00
parent 1f798fe85b
commit 97532867cf
4 changed files with 28 additions and 20 deletions

View file

@ -21,7 +21,7 @@ namespace wallet {
//! mined, or conflicts with a mined transaction. Return a feebumper::Result. //! mined, or conflicts with a mined transaction. Return a feebumper::Result.
static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWalletTx& wtx, std::vector<bilingual_str>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWalletTx& wtx, std::vector<bilingual_str>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{ {
if (wallet.HasWalletSpend(wtx.GetHash())) { if (wallet.HasWalletSpend(wtx.tx)) {
errors.push_back(Untranslated("Transaction has descendants in the wallet")); errors.push_back(Untranslated("Transaction has descendants in the wallet"));
return feebumper::Result::INVALID_PARAMETER; return feebumper::Result::INVALID_PARAMETER;
} }

View file

@ -843,16 +843,16 @@ BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
{ {
auto block_hash = block_tx.GetHash(); auto block_hash = block_tx.GetHash();
auto prev_hash = m_coinbase_txns[0]->GetHash(); auto prev_tx = m_coinbase_txns[0];
LOCK(wallet->cs_wallet); LOCK(wallet->cs_wallet);
BOOST_CHECK(wallet->HasWalletSpend(prev_hash)); BOOST_CHECK(wallet->HasWalletSpend(prev_tx));
BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 1u); BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 1u);
std::vector<uint256> vHashIn{ block_hash }, vHashOut; std::vector<uint256> vHashIn{ block_hash }, vHashOut;
BOOST_CHECK_EQUAL(wallet->ZapSelectTx(vHashIn, vHashOut), DBErrors::LOAD_OK); BOOST_CHECK_EQUAL(wallet->ZapSelectTx(vHashIn, vHashOut), DBErrors::LOAD_OK);
BOOST_CHECK(!wallet->HasWalletSpend(prev_hash)); BOOST_CHECK(!wallet->HasWalletSpend(prev_tx));
BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 0u); BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 0u);
} }

View file

@ -569,11 +569,17 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
return result; return result;
} }
bool CWallet::HasWalletSpend(const uint256& txid) const bool CWallet::HasWalletSpend(const CTransactionRef& tx) const
{ {
AssertLockHeld(cs_wallet); AssertLockHeld(cs_wallet);
auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0)); const uint256& txid = tx->GetHash();
return (iter != mapTxSpends.end() && iter->first.hash == txid); for (unsigned int i = 0; i < tx->vout.size(); ++i) {
auto iter = mapTxSpends.find(COutPoint(txid, i));
if (iter != mapTxSpends.end()) {
return true;
}
}
return false;
} }
void CWallet::Flush() void CWallet::Flush()
@ -1191,12 +1197,13 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
batch.WriteTx(wtx); batch.WriteTx(wtx);
NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED); NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED);
// Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0)); for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
while (iter != mapTxSpends.end() && iter->first.hash == now) { std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(now, i));
for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
if (!done.count(iter->second)) { if (!done.count(iter->second)) {
todo.insert(iter->second); todo.insert(iter->second);
} }
iter++; }
} }
// If a transaction changes 'conflicted' state, that changes the balance // If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed // available of the outputs it spends. So force those to be recomputed
@ -1242,12 +1249,13 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
wtx.MarkDirty(); wtx.MarkDirty();
batch.WriteTx(wtx); batch.WriteTx(wtx);
// Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0)); for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
while (iter != mapTxSpends.end() && iter->first.hash == now) { std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(now, i));
for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
if (!done.count(iter->second)) { if (!done.count(iter->second)) {
todo.insert(iter->second); todo.insert(iter->second);
} }
iter++; }
} }
// If a transaction changes 'conflicted' state, that changes the balance // If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed // available of the outputs it spends. So force those to be recomputed

View file

@ -259,7 +259,7 @@ private:
* detect and report conflicts (double-spends or * detect and report conflicts (double-spends or
* mutated transactions where the mutant gets mined). * mutated transactions where the mutant gets mined).
*/ */
typedef std::multimap<COutPoint, uint256> TxSpends; typedef std::unordered_multimap<COutPoint, uint256, SaltedOutpointHasher> TxSpends;
TxSpends mapTxSpends GUARDED_BY(cs_wallet); TxSpends mapTxSpends GUARDED_BY(cs_wallet);
void AddToSpends(const COutPoint& outpoint, const uint256& wtxid, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); void AddToSpends(const COutPoint& outpoint, const uint256& wtxid, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void AddToSpends(const CWalletTx& wtx, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); void AddToSpends(const CWalletTx& wtx, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@ -708,7 +708,7 @@ public:
std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Check if a given transaction has any of its outputs spent by another transaction in the wallet //! Check if a given transaction has any of its outputs spent by another transaction in the wallet
bool HasWalletSpend(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool HasWalletSpend(const CTransactionRef& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Flush wallet (bitdb flush) //! Flush wallet (bitdb flush)
void Flush(); void Flush();