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:
parent
1f798fe85b
commit
97532867cf
4 changed files with 28 additions and 20 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
if (!done.count(iter->second)) {
|
for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
|
||||||
todo.insert(iter->second);
|
if (!done.count(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));
|
||||||
if (!done.count(iter->second)) {
|
for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
|
||||||
todo.insert(iter->second);
|
if (!done.count(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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Add table
Reference in a new issue