CTxMemPool: encapsulate AcceptToMemoryPool
[novacoin.git] / src / main.cpp
index 9e2fbe9..facf355 100644 (file)
@@ -23,7 +23,7 @@ set<CWallet*> setpwalletRegistered;
 
 CCriticalSection cs_main;
 
-static CTxMemPool mempool;
+CTxMemPool mempool;
 unsigned int nTransactionsUpdated = 0;
 
 map<uint256, CBlockIndex*> mapBlockIndex;
@@ -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<int>::max())
-        return error("AcceptToMemoryPool() : not accepting nLockTime beyond 2038 yet");
+    if ((int64)tx.nLockTime > std::numeric_limits<int>::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<uint256, CTxIndex> 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());
-            ptxOld->RemoveFromMemoryPool();
+            printf("CTxMemPool::accept() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
+            remove(*ptxOld);
         }
-        AddToMemoryPoolUnchecked();
+        addUnchecked(tx);
     }
 
     ///// are we sure this is ok when loading transactions or restoring block txes
@@ -586,43 +587,44 @@ 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;
 }
 
-uint64 nPooledTx = 0;
+bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)
+{
+    return mempool.accept(txdb, *this, fCheckInputs, pfMissingInputs);
+}
 
-bool CTransaction::AddToMemoryPoolUnchecked()
+bool CTxMemPool::addUnchecked(CTransaction &tx)
 {
-    printf("AcceptToMemoryPoolUnchecked(): size %lu\n",  mempool.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(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 +1437,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 +1473,7 @@ bool CBlock::SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew)
 
     // Delete redundant memory transactions
     BOOST_FOREACH(CTransaction& tx, vtx)
-        tx.RemoveFromMemoryPool();
+        mempool.remove(tx);
 
     return true;
 }