aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wallet/feebumper.cpp2
-rw-r--r--src/wallet/test/wallet_tests.cpp6
-rw-r--r--src/wallet/wallet.cpp36
-rw-r--r--src/wallet/wallet.h4
4 files changed, 28 insertions, 20 deletions
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 43fdcee48d..3ae81456b6 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -21,7 +21,7 @@ namespace wallet {
//! 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)
{
- if (wallet.HasWalletSpend(wtx.GetHash())) {
+ if (wallet.HasWalletSpend(wtx.tx)) {
errors.push_back(Untranslated("Transaction has descendants in the wallet"));
return feebumper::Result::INVALID_PARAMETER;
}
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 81183aa738..ac87800293 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -843,16 +843,16 @@ BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
{
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);
- BOOST_CHECK(wallet->HasWalletSpend(prev_hash));
+ BOOST_CHECK(wallet->HasWalletSpend(prev_tx));
BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 1u);
std::vector<uint256> vHashIn{ block_hash }, vHashOut;
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);
}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 54a3221e2d..e244b604a9 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -569,11 +569,17 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
return result;
}
-bool CWallet::HasWalletSpend(const uint256& txid) const
+bool CWallet::HasWalletSpend(const CTransactionRef& tx) const
{
AssertLockHeld(cs_wallet);
- auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
- return (iter != mapTxSpends.end() && iter->first.hash == txid);
+ const uint256& txid = tx->GetHash();
+ 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()
@@ -1191,12 +1197,13 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
batch.WriteTx(wtx);
NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED);
// 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));
- while (iter != mapTxSpends.end() && iter->first.hash == now) {
- if (!done.count(iter->second)) {
- todo.insert(iter->second);
+ for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
+ 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)) {
+ todo.insert(iter->second);
+ }
}
- iter++;
}
// If a transaction changes 'conflicted' state, that changes the balance
// 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();
batch.WriteTx(wtx);
// 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));
- while (iter != mapTxSpends.end() && iter->first.hash == now) {
- if (!done.count(iter->second)) {
- todo.insert(iter->second);
- }
- iter++;
+ for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
+ 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)) {
+ todo.insert(iter->second);
+ }
+ }
}
// If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 15f5917040..5780749283 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -259,7 +259,7 @@ private:
* detect and report conflicts (double-spends or
* 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);
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);
@@ -708,7 +708,7 @@ public:
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
- 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)
void Flush();