From 235507ae48718ee8ce5289b2791b4b449090dabc Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 13 Apr 2012 16:03:09 -0400 Subject: [PATCH 1/4] New class CTxMemPool, encapsulating TX memory pool data members --- src/main.cpp | 59 ++++++++++++++++++++++++++-------------------------- src/main.h | 8 +++++++ 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f2932804e..9e2fbe99e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,10 +23,8 @@ set setpwalletRegistered; CCriticalSection cs_main; -static map mapTransactions; -CCriticalSection cs_mapTransactions; +static CTxMemPool mempool; unsigned int nTransactionsUpdated = 0; -map mapNextTx; map mapBlockIndex; uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); @@ -474,8 +472,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi // Do we already have it? uint256 hash = GetHash(); { - LOCK(cs_mapTransactions); - if (mapTransactions.count(hash)) + LOCK(mempool.cs); + if (mempool.mapTx.count(hash)) return false; } if (fCheckInputs) @@ -487,7 +485,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi for (int i = 0; i < vin.size(); i++) { COutPoint outpoint = vin[i].prevout; - if (mapNextTx.count(outpoint)) + if (mempool.mapNextTx.count(outpoint)) { // Disable replacement feature for now return false; @@ -495,7 +493,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi // Allow replacing with a newer version of the same transaction if (i != 0) return false; - ptxOld = mapNextTx[outpoint].ptx; + ptxOld = mempool.mapNextTx[outpoint].ptx; if (ptxOld->IsFinal()) return false; if (!IsNewerThan(*ptxOld)) @@ -503,7 +501,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi for (int i = 0; i < vin.size(); i++) { COutPoint outpoint = vin[i].prevout; - if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld) + if (!mempool.mapNextTx.count(outpoint) || mempool.mapNextTx[outpoint].ptx != ptxOld) return false; } break; @@ -574,7 +572,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi // Store transaction in memory { - LOCK(cs_mapTransactions); + LOCK(mempool.cs); if (ptxOld) { printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str()); @@ -596,15 +594,15 @@ uint64 nPooledTx = 0; bool CTransaction::AddToMemoryPoolUnchecked() { - printf("AcceptToMemoryPoolUnchecked(): size %lu\n", mapTransactions.size()); + printf("AcceptToMemoryPoolUnchecked(): size %lu\n", mempool.mapTx.size()); // Add to memory pool without checking anything. Don't call this directly, // call AcceptToMemoryPool to properly check the transaction first. { - LOCK(cs_mapTransactions); + LOCK(mempool.cs); uint256 hash = GetHash(); - mapTransactions[hash] = *this; + mempool.mapTx[hash] = *this; for (int i = 0; i < vin.size(); i++) - mapNextTx[vin[i].prevout] = CInPoint(&mapTransactions[hash], i); + mempool.mapNextTx[vin[i].prevout] = CInPoint(&mempool.mapTx[hash], i); nTransactionsUpdated++; ++nPooledTx; } @@ -616,13 +614,13 @@ bool CTransaction::RemoveFromMemoryPool() { // Remove transaction from memory pool { - LOCK(cs_mapTransactions); + LOCK(mempool.cs); uint256 hash = GetHash(); - if (mapTransactions.count(hash)) + if (mempool.mapTx.count(hash)) { BOOST_FOREACH(const CTxIn& txin, vin) - mapNextTx.erase(txin.prevout); - mapTransactions.erase(hash); + mempool.mapNextTx.erase(txin.prevout); + mempool.mapTx.erase(hash); nTransactionsUpdated++; --nPooledTx; } @@ -695,14 +693,14 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs) { { - LOCK(cs_mapTransactions); + LOCK(mempool.cs); // Add previous supporting transactions first BOOST_FOREACH(CMerkleTx& tx, vtxPrev) { if (!tx.IsCoinBase()) { uint256 hash = tx.GetHash(); - if (!mapTransactions.count(hash) && !txdb.ContainsTx(hash)) + if (!mempool.mapTx.count(hash) && !txdb.ContainsTx(hash)) tx.AcceptToMemoryPool(txdb, fCheckInputs); } } @@ -1017,10 +1015,10 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map& mapTes { // Get prev tx from single transactions in memory { - LOCK(cs_mapTransactions); - if (!mapTransactions.count(prevout.hash)) - return error("FetchInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str()); - txPrev = mapTransactions[prevout.hash]; + LOCK(mempool.cs); + if (!mempool.mapTx.count(prevout.hash)) + return error("FetchInputs() : %s mempool.mapTx prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str()); + txPrev = mempool.mapTx[prevout.hash]; } if (!fFound) txindex.vSpent.resize(txPrev.vout.size()); @@ -1183,15 +1181,15 @@ bool CTransaction::ClientConnectInputs() // Take over previous transactions' spent pointers { - LOCK(cs_mapTransactions); + LOCK(mempool.cs); int64 nValueIn = 0; for (int i = 0; i < vin.size(); i++) { // Get prev tx from single transactions in memory COutPoint prevout = vin[i].prevout; - if (!mapTransactions.count(prevout.hash)) + if (!mempool.mapTx.count(prevout.hash)) return false; - CTransaction& txPrev = mapTransactions[prevout.hash]; + CTransaction& txPrev = mempool.mapTx[prevout.hash]; if (prevout.n >= txPrev.vout.size()) return false; @@ -1200,7 +1198,8 @@ bool CTransaction::ClientConnectInputs() if (!VerifySignature(txPrev, *this, i, true, 0)) return error("ConnectInputs() : VerifySignature failed"); - ///// this is redundant with the mapNextTx stuff, not sure which I want to get rid of + ///// this is redundant with the mempool.mapNextTx stuff, + ///// not sure which I want to get rid of ///// this has to go away now that posNext is gone // // Check for conflicts // if (!txPrev.vout[prevout.n].posNext.IsNull()) @@ -2135,7 +2134,7 @@ bool static AlreadyHave(CTxDB& txdb, const CInv& inv) { switch (inv.type) { - case MSG_TX: return mapTransactions.count(inv.hash) || mapOrphanTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash); + case MSG_TX: return mempool.mapTx.count(inv.hash) || mapOrphanTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash); case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash); } // Don't know what it is, just say we already got one @@ -3093,14 +3092,14 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) // Collect memory pool transactions into the block int64 nFees = 0; { - LOCK2(cs_main, cs_mapTransactions); + LOCK2(cs_main, mempool.cs); CTxDB txdb("r"); // Priority order to process transactions list vOrphan; // list memory doesn't move map > mapDependers; multimap mapPriority; - for (map::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi) + for (map::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi) { CTransaction& tx = (*mi).second; if (tx.IsCoinBase() || !tx.IsFinal()) diff --git a/src/main.h b/src/main.h index a89c0935f..ef4ee137b 100644 --- a/src/main.h +++ b/src/main.h @@ -1608,4 +1608,12 @@ public: bool ProcessAlert(); }; +class CTxMemPool +{ +public: + mutable CCriticalSection cs; + std::map mapTx; + std::map mapNextTx; +}; + #endif From 8e45ed66dde5d5eb5fde0fc1eba64b26bd48bfb0 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 13 Apr 2012 16:28:07 -0400 Subject: [PATCH 2/4] CTxMemPool: encapsulate AddToMemoryPoolUnchecked(), RemoveFromMemoryPool(), and nPooledTx --- src/bitcoinrpc.cpp | 2 +- src/main.cpp | 42 +++++++++++++++++++----------------------- src/main.h | 15 +++++++++++---- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 63c51ada8..b8ef5275f 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -363,7 +363,7 @@ Value getmininginfo(const Array& params, bool fHelp) obj.push_back(Pair("generate", GetBoolArg("-gen"))); obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); obj.push_back(Pair("hashespersec", gethashespersec(params, false))); - obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx)); + obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); obj.push_back(Pair("testnet", fTestNet)); return obj; } diff --git a/src/main.cpp b/src/main.cpp index 9e2fbe99e..ba20af055 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,7 +23,7 @@ set setpwalletRegistered; CCriticalSection cs_main; -static CTxMemPool mempool; +CTxMemPool mempool; unsigned int nTransactionsUpdated = 0; map mapBlockIndex; @@ -576,9 +576,9 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi if (ptxOld) { printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str()); - ptxOld->RemoveFromMemoryPool(); + mempool.remove(*ptxOld); } - AddToMemoryPoolUnchecked(); + mempool.addUnchecked(*this); } ///// are we sure this is ok when loading transactions or restoring block txes @@ -590,39 +590,35 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi return true; } -uint64 nPooledTx = 0; - -bool CTransaction::AddToMemoryPoolUnchecked() +bool CTxMemPool::addUnchecked(CTransaction &tx) { - printf("AcceptToMemoryPoolUnchecked(): size %lu\n", mempool.mapTx.size()); + printf("AcceptToMemoryPoolUnchecked(): size %lu\n", mapTx.size()); // Add to memory pool without checking anything. Don't call this directly, // call AcceptToMemoryPool to properly check the transaction first. { - LOCK(mempool.cs); - uint256 hash = GetHash(); - mempool.mapTx[hash] = *this; - for (int i = 0; i < vin.size(); i++) - mempool.mapNextTx[vin[i].prevout] = CInPoint(&mempool.mapTx[hash], i); + LOCK(cs); + uint256 hash = tx.GetHash(); + mapTx[hash] = tx; + for (int i = 0; i < tx.vin.size(); i++) + mapNextTx[tx.vin[i].prevout] = CInPoint(&mapTx[hash], i); nTransactionsUpdated++; - ++nPooledTx; } return true; } -bool CTransaction::RemoveFromMemoryPool() +bool CTxMemPool::remove(CTransaction &tx) { // Remove transaction from memory pool { - LOCK(mempool.cs); - uint256 hash = GetHash(); - if (mempool.mapTx.count(hash)) + LOCK(cs); + uint256 hash = tx.GetHash(); + if (mapTx.count(hash)) { - BOOST_FOREACH(const CTxIn& txin, vin) - mempool.mapNextTx.erase(txin.prevout); - mempool.mapTx.erase(hash); + BOOST_FOREACH(const CTxIn& txin, tx.vin) + mapNextTx.erase(txin.prevout); + mapTx.erase(hash); nTransactionsUpdated++; - --nPooledTx; } } return true; @@ -1435,7 +1431,7 @@ bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) // Delete redundant memory transactions that are in the connected branch BOOST_FOREACH(CTransaction& tx, vDelete) - tx.RemoveFromMemoryPool(); + mempool.remove(tx); printf("REORGANIZE: done\n"); @@ -1471,7 +1467,7 @@ bool CBlock::SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew) // Delete redundant memory transactions BOOST_FOREACH(CTransaction& tx, vtx) - tx.RemoveFromMemoryPool(); + mempool.remove(tx); return true; } diff --git a/src/main.h b/src/main.h index ef4ee137b..bf24944ce 100644 --- a/src/main.h +++ b/src/main.h @@ -67,7 +67,6 @@ extern CBigNum bnBestChainWork; extern CBigNum bnBestInvalidWork; extern uint256 hashBestChain; extern CBlockIndex* pindexBest; -extern uint64 nPooledTx; extern unsigned int nTransactionsUpdated; extern uint64 nLastBlockTx; extern uint64 nLastBlockSize; @@ -689,9 +688,6 @@ public: protected: const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const; - bool AddToMemoryPoolUnchecked(); -public: - bool RemoveFromMemoryPool(); }; @@ -1614,6 +1610,17 @@ public: mutable CCriticalSection cs; std::map mapTx; std::map mapNextTx; + + bool addUnchecked(CTransaction &tx); + bool remove(CTransaction &tx); + + unsigned long size() + { + LOCK(cs); + return mapTx.size(); + } }; +extern CTxMemPool mempool; + #endif From d01903e7511c143f8844bd83da884e7c9d25241e Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 13 Apr 2012 17:34:22 -0400 Subject: [PATCH 3/4] CTxMemPool: encapsulate AcceptToMemoryPool --- src/main.cpp | 86 ++++++++++++++++++++++++++++------------------------ src/main.h | 2 ++ 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ba20af055..facf355ec 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -449,31 +449,32 @@ bool CTransaction::CheckTransaction() const return true; } -bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs) +bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs, + bool* pfMissingInputs) { if (pfMissingInputs) *pfMissingInputs = false; - if (!CheckTransaction()) - return error("AcceptToMemoryPool() : CheckTransaction failed"); + if (!tx.CheckTransaction()) + return error("CTxMemPool::accept() : CheckTransaction failed"); // Coinbase is only valid in a block, not as a loose transaction - if (IsCoinBase()) - return DoS(100, error("AcceptToMemoryPool() : coinbase as individual tx")); + if (tx.IsCoinBase()) + return tx.DoS(100, error("CTxMemPool::accept() : coinbase as individual tx")); // To help v0.1.5 clients who would see it as a negative number - if ((int64)nLockTime > std::numeric_limits::max()) - return error("AcceptToMemoryPool() : not accepting nLockTime beyond 2038 yet"); + if ((int64)tx.nLockTime > std::numeric_limits::max()) + return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet"); // Rather not work on nonstandard transactions (unless -testnet) - if (!fTestNet && !IsStandard()) - return error("AcceptToMemoryPool() : nonstandard transaction type"); + if (!fTestNet && !tx.IsStandard()) + return error("CTxMemPool::accept() : nonstandard transaction type"); // Do we already have it? - uint256 hash = GetHash(); + uint256 hash = tx.GetHash(); { - LOCK(mempool.cs); - if (mempool.mapTx.count(hash)) + LOCK(cs); + if (mapTx.count(hash)) return false; } if (fCheckInputs) @@ -482,10 +483,10 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi // Check for conflicts with in-memory transactions CTransaction* ptxOld = NULL; - for (int i = 0; i < vin.size(); i++) + for (int i = 0; i < tx.vin.size(); i++) { - COutPoint outpoint = vin[i].prevout; - if (mempool.mapNextTx.count(outpoint)) + COutPoint outpoint = tx.vin[i].prevout; + if (mapNextTx.count(outpoint)) { // Disable replacement feature for now return false; @@ -493,15 +494,15 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi // Allow replacing with a newer version of the same transaction if (i != 0) return false; - ptxOld = mempool.mapNextTx[outpoint].ptx; + ptxOld = mapNextTx[outpoint].ptx; if (ptxOld->IsFinal()) return false; - if (!IsNewerThan(*ptxOld)) + if (!tx.IsNewerThan(*ptxOld)) return false; - for (int i = 0; i < vin.size(); i++) + for (int i = 0; i < tx.vin.size(); i++) { - COutPoint outpoint = vin[i].prevout; - if (!mempool.mapNextTx.count(outpoint) || mempool.mapNextTx[outpoint].ptx != ptxOld) + COutPoint outpoint = tx.vin[i].prevout; + if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld) return false; } break; @@ -513,29 +514,29 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi MapPrevTx mapInputs; map mapUnused; bool fInvalid = false; - if (!FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid)) + if (!tx.FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid)) { if (fInvalid) - return error("AcceptToMemoryPool() : FetchInputs found invalid tx %s", hash.ToString().substr(0,10).c_str()); + return error("CTxMemPool::accept() : FetchInputs found invalid tx %s", hash.ToString().substr(0,10).c_str()); if (pfMissingInputs) *pfMissingInputs = true; - return error("AcceptToMemoryPool() : FetchInputs failed %s", hash.ToString().substr(0,10).c_str()); + return error("CTxMemPool::accept() : FetchInputs failed %s", hash.ToString().substr(0,10).c_str()); } // Check for non-standard pay-to-script-hash in inputs - if (!AreInputsStandard(mapInputs) && !fTestNet) - return error("AcceptToMemoryPool() : nonstandard transaction input"); + if (!tx.AreInputsStandard(mapInputs) && !fTestNet) + return error("CTxMemPool::accept() : nonstandard transaction input"); // Note: if you modify this code to accept non-standard transactions, then // you should add code here to check that the transaction does a // reasonable number of ECDSA signature verifications. - int64 nFees = GetValueIn(mapInputs)-GetValueOut(); - unsigned int nSize = ::GetSerializeSize(*this, SER_NETWORK); + int64 nFees = tx.GetValueIn(mapInputs)-tx.GetValueOut(); + unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK); // Don't accept it if it can't get into a block - if (nFees < GetMinFee(1000, true, GMF_RELAY)) - return error("AcceptToMemoryPool() : not enough fees"); + if (nFees < tx.GetMinFee(1000, true, GMF_RELAY)) + return error("CTxMemPool::accept() : not enough fees"); // Continuously rate-limit free transactions // This mitigates 'penny-flooding' -- sending thousands of free transactions just to @@ -554,8 +555,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi nLastTime = nNow; // -limitfreerelay unit is thousand-bytes-per-minute // At default rate it would take over a month to fill 1GB - if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(*this)) - return error("AcceptToMemoryPool() : free transaction rejected by rate limiter"); + if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(tx)) + return error("CTxMemPool::accept() : free transaction rejected by rate limiter"); if (fDebug) printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize); dFreeCount += nSize; @@ -564,21 +565,21 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. - if (!ConnectInputs(mapInputs, mapUnused, CDiskTxPos(1,1,1), pindexBest, false, false)) + if (!tx.ConnectInputs(mapInputs, mapUnused, CDiskTxPos(1,1,1), pindexBest, false, false)) { - return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str()); + return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str()); } } // Store transaction in memory { - LOCK(mempool.cs); + LOCK(cs); if (ptxOld) { - printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str()); - mempool.remove(*ptxOld); + printf("CTxMemPool::accept() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str()); + remove(*ptxOld); } - mempool.addUnchecked(*this); + addUnchecked(tx); } ///// are we sure this is ok when loading transactions or restoring block txes @@ -586,15 +587,20 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi if (ptxOld) EraseFromWallets(ptxOld->GetHash()); - printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,10).c_str()); + printf("CTxMemPool::accept() : accepted %s\n", hash.ToString().substr(0,10).c_str()); return true; } +bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs) +{ + return mempool.accept(txdb, *this, fCheckInputs, pfMissingInputs); +} + bool CTxMemPool::addUnchecked(CTransaction &tx) { - printf("AcceptToMemoryPoolUnchecked(): size %lu\n", mapTx.size()); + printf("addUnchecked(): size %lu\n", mapTx.size()); // Add to memory pool without checking anything. Don't call this directly, - // call AcceptToMemoryPool to properly check the transaction first. + // call CTxMemPool::accept to properly check the transaction first. { LOCK(cs); uint256 hash = tx.GetHash(); diff --git a/src/main.h b/src/main.h index bf24944ce..29bd358c5 100644 --- a/src/main.h +++ b/src/main.h @@ -1611,6 +1611,8 @@ public: std::map mapTx; std::map mapNextTx; + bool accept(CTxDB& txdb, CTransaction &tx, + bool fCheckInputs, bool* pfMissingInputs); bool addUnchecked(CTransaction &tx); bool remove(CTransaction &tx); From ca4c4c53a8b1417563c72da0aea626f111a7f25d Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 13 Apr 2012 18:20:44 -0400 Subject: [PATCH 4/4] CTxMemPool: add helper methods, to reduce global mempool.mapTx accesses --- src/main.cpp | 24 ++++++++++++++++-------- src/main.h | 10 ++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index facf355ec..1c040bdee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -702,7 +702,7 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs) if (!tx.IsCoinBase()) { uint256 hash = tx.GetHash(); - if (!mempool.mapTx.count(hash) && !txdb.ContainsTx(hash)) + if (!mempool.exists(hash) && !txdb.ContainsTx(hash)) tx.AcceptToMemoryPool(txdb, fCheckInputs); } } @@ -1018,9 +1018,9 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map& mapTes // Get prev tx from single transactions in memory { LOCK(mempool.cs); - if (!mempool.mapTx.count(prevout.hash)) - return error("FetchInputs() : %s mempool.mapTx prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str()); - txPrev = mempool.mapTx[prevout.hash]; + if (!mempool.exists(prevout.hash)) + return error("FetchInputs() : %s mempool Tx prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str()); + txPrev = mempool.lookup(prevout.hash); } if (!fFound) txindex.vSpent.resize(txPrev.vout.size()); @@ -1189,9 +1189,9 @@ bool CTransaction::ClientConnectInputs() { // Get prev tx from single transactions in memory COutPoint prevout = vin[i].prevout; - if (!mempool.mapTx.count(prevout.hash)) + if (!mempool.exists(prevout.hash)) return false; - CTransaction& txPrev = mempool.mapTx[prevout.hash]; + CTransaction& txPrev = mempool.lookup(prevout.hash); if (prevout.n >= txPrev.vout.size()) return false; @@ -2136,8 +2136,16 @@ bool static AlreadyHave(CTxDB& txdb, const CInv& inv) { switch (inv.type) { - case MSG_TX: return mempool.mapTx.count(inv.hash) || mapOrphanTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash); - case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash); + case MSG_TX: + { + LOCK(mempool.cs); + return mempool.exists(inv.hash) || + mapOrphanTransactions.count(inv.hash) || + txdb.ContainsTx(inv.hash); + } + + case MSG_BLOCK: + return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash); } // Don't know what it is, just say we already got one return true; diff --git a/src/main.h b/src/main.h index 29bd358c5..30bf1dd69 100644 --- a/src/main.h +++ b/src/main.h @@ -1621,6 +1621,16 @@ public: LOCK(cs); return mapTx.size(); } + + bool exists(uint256 hash) + { + return (mapTx.count(hash) != 0); + } + + CTransaction& lookup(uint256 hash) + { + return mapTx[hash]; + } }; extern CTxMemPool mempool;