]> Git Repo - VerusCoin.git/commitdiff
Merge pull request #5969
authorWladimir J. van der Laan <[email protected]>
Wed, 8 Apr 2015 07:40:44 +0000 (09:40 +0200)
committerWladimir J. van der Laan <[email protected]>
Wed, 8 Apr 2015 07:41:14 +0000 (09:41 +0200)
f14e687 Chainparams: Decouple CAlert from CChainParams (Jorge Timón)

src/Makefile.test.include
src/main.cpp
src/pow.cpp
src/qt/forms/sendcoinsdialog.ui
src/test/mempool_tests.cpp [new file with mode: 0644]
src/txmempool.cpp

index 8dd0a28454fa8f832946ca927015a3c9193f754c..52ff3f224fb7f9017c358a2a6cb84c00209eb714 100644 (file)
@@ -50,6 +50,7 @@ BITCOIN_TESTS =\
   test/hash_tests.cpp \
   test/key_tests.cpp \
   test/main_tests.cpp \
+  test/mempool_tests.cpp \
   test/miner_tests.cpp \
   test/mruset_tests.cpp \
   test/multisig_tests.cpp \
index bd424b18264b18b1db94b4b9123426f67c7661e0..8fb6766301e5384c0e8db60c4cad565ade99e8ab 100644 (file)
@@ -3248,6 +3248,7 @@ void static CheckBlockIndex()
     CBlockIndex* pindexFirstInvalid = NULL; // Oldest ancestor of pindex which is invalid.
     CBlockIndex* pindexFirstMissing = NULL; // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA.
     CBlockIndex* pindexFirstNotTreeValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not).
+    CBlockIndex* pindexFirstNotTransactionsValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not).
     CBlockIndex* pindexFirstNotChainValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not).
     CBlockIndex* pindexFirstNotScriptsValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not).
     while (pindex != NULL) {
@@ -3255,6 +3256,7 @@ void static CheckBlockIndex()
         if (pindexFirstInvalid == NULL && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
         if (pindexFirstMissing == NULL && !(pindex->nStatus & BLOCK_HAVE_DATA)) pindexFirstMissing = pindex;
         if (pindex->pprev != NULL && pindexFirstNotTreeValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TREE) pindexFirstNotTreeValid = pindex;
+        if (pindex->pprev != NULL && pindexFirstNotTransactionsValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TRANSACTIONS) pindexFirstNotTransactionsValid = pindex;
         if (pindex->pprev != NULL && pindexFirstNotChainValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_CHAIN) pindexFirstNotChainValid = pindex;
         if (pindex->pprev != NULL && pindexFirstNotScriptsValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS) pindexFirstNotScriptsValid = pindex;
 
@@ -3264,7 +3266,12 @@ void static CheckBlockIndex()
             assert(pindex->GetBlockHash() == Params().HashGenesisBlock()); // Genesis block's hash must match.
             assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block.
         }
+        // HAVE_DATA is equivalent to VALID_TRANSACTIONS and equivalent to nTx > 0 (we stored the number of transactions in the block)
+        assert(!(pindex->nStatus & BLOCK_HAVE_DATA) == (pindex->nTx == 0));
+        assert(((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindex->nTx > 0));
+        // All parents having data is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to nChainTx being set.
         assert((pindexFirstMissing != NULL) == (pindex->nChainTx == 0)); // nChainTx == 0 is used to signal that all parent block's transaction data is available.
+        assert((pindexFirstNotTransactionsValid != NULL) == (pindex->nChainTx == 0));
         assert(pindex->nHeight == nHeight); // nHeight must be consistent.
         assert(pindex->pprev == NULL || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's.
         assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks.
@@ -3320,6 +3327,7 @@ void static CheckBlockIndex()
             if (pindex == pindexFirstInvalid) pindexFirstInvalid = NULL;
             if (pindex == pindexFirstMissing) pindexFirstMissing = NULL;
             if (pindex == pindexFirstNotTreeValid) pindexFirstNotTreeValid = NULL;
+            if (pindex == pindexFirstNotTransactionsValid) pindexFirstNotTransactionsValid = NULL;
             if (pindex == pindexFirstNotChainValid) pindexFirstNotChainValid = NULL;
             if (pindex == pindexFirstNotScriptsValid) pindexFirstNotScriptsValid = NULL;
             // Find our parent.
index 3c5a8d9d9635968cd1127be3235809b791c34d97..cf7ac387f23d049e4a7436fadea6c374d6d4d57b 100644 (file)
@@ -42,9 +42,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
     }
 
     // Go back by what we want to be 14 days worth of blocks
-    const CBlockIndex* pindexFirst = pindexLast;
-    for (int i = 0; pindexFirst && i < params.DifficultyAdjustmentInterval()-1; i++)
-        pindexFirst = pindexFirst->pprev;
+    int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
+    assert(nHeightFirst >= 0);
+    const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
     assert(pindexFirst);
 
     return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
index b1ed7a27b5c8882be87077c33ae19383347ca76a..8911b41cbf31ac1f28a54df28ddba15ceede42e8 100644 (file)
              <string>collapse fee-settings</string>
             </property>
             <property name="text">
-             <string>Minimize</string>
+             <string>Hide</string>
             </property>
            </widget>
           </item>
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
new file mode 100644 (file)
index 0000000..0996e13
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright (c) 2011-2014 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "main.h"
+#include "txmempool.h"
+#include "util.h"
+
+#include "test/test_bitcoin.h"
+
+#include <boost/test/unit_test.hpp>
+#include <list>
+
+BOOST_FIXTURE_TEST_SUITE(mempool_tests, TestingSetup)
+
+BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
+{
+    // Test CTxMemPool::remove functionality
+
+    // Parent transaction with three children,
+    // and three grand-children:
+    CMutableTransaction txParent;
+    txParent.vin.resize(1);
+    txParent.vin[0].scriptSig = CScript() << OP_11;
+    txParent.vout.resize(3);
+    for (int i = 0; i < 3; i++)
+    {
+        txParent.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+        txParent.vout[i].nValue = 33000LL;
+    }
+    CMutableTransaction txChild[3];
+    for (int i = 0; i < 3; i++)
+    {
+        txChild[i].vin.resize(1);
+        txChild[i].vin[0].scriptSig = CScript() << OP_11;
+        txChild[i].vin[0].prevout.hash = txParent.GetHash();
+        txChild[i].vin[0].prevout.n = i;
+        txChild[i].vout.resize(1);
+        txChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+        txChild[i].vout[0].nValue = 11000LL;
+    }
+    CMutableTransaction txGrandChild[3];
+    for (int i = 0; i < 3; i++)
+    {
+        txGrandChild[i].vin.resize(1);
+        txGrandChild[i].vin[0].scriptSig = CScript() << OP_11;
+        txGrandChild[i].vin[0].prevout.hash = txChild[i].GetHash();
+        txGrandChild[i].vin[0].prevout.n = 0;
+        txGrandChild[i].vout.resize(1);
+        txGrandChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+        txGrandChild[i].vout[0].nValue = 11000LL;
+    }
+
+
+    CTxMemPool testPool(CFeeRate(0));
+    std::list<CTransaction> removed;
+
+    // Nothing in pool, remove should do nothing:
+    testPool.remove(txParent, removed, true);
+    BOOST_CHECK_EQUAL(removed.size(), 0);
+
+    // Just the parent:
+    testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1));
+    testPool.remove(txParent, removed, true);
+    BOOST_CHECK_EQUAL(removed.size(), 1);
+    removed.clear();
+    
+    // Parent, children, grandchildren:
+    testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1));
+    for (int i = 0; i < 3; i++)
+    {
+        testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1));
+        testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1));
+    }
+    // Remove Child[0], GrandChild[0] should be removed:
+    testPool.remove(txChild[0], removed, true);
+    BOOST_CHECK_EQUAL(removed.size(), 2);
+    removed.clear();
+    // ... make sure grandchild and child are gone:
+    testPool.remove(txGrandChild[0], removed, true);
+    BOOST_CHECK_EQUAL(removed.size(), 0);
+    testPool.remove(txChild[0], removed, true);
+    BOOST_CHECK_EQUAL(removed.size(), 0);
+    // Remove parent, all children/grandchildren should go:
+    testPool.remove(txParent, removed, true);
+    BOOST_CHECK_EQUAL(removed.size(), 5);
+    BOOST_CHECK_EQUAL(testPool.size(), 0);
+    removed.clear();
+
+    // Add children and grandchildren, but NOT the parent (simulate the parent being in a block)
+    for (int i = 0; i < 3; i++)
+    {
+        testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1));
+        testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1));
+    }
+    // Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be
+    // put into the mempool (maybe because it is non-standard):
+    testPool.remove(txParent, removed, true);
+    BOOST_CHECK_EQUAL(removed.size(), 6);
+    BOOST_CHECK_EQUAL(testPool.size(), 0);
+    removed.clear();
+}
+
+BOOST_AUTO_TEST_SUITE_END()
index 0d506603276f3a95b4676d2bbac0ce563e0d4eea..85ea3f77b5106439d4263420b7cfa39f5f84c8b4 100644 (file)
@@ -444,6 +444,18 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem
         LOCK(cs);
         std::deque<uint256> txToRemove;
         txToRemove.push_back(origTx.GetHash());
+        if (fRecursive && !mapTx.count(origTx.GetHash())) {
+            // If recursively removing but origTx isn't in the mempool
+            // be sure to remove any children that are in the pool. This can
+            // happen during chain re-orgs if origTx isn't re-accepted into
+            // the mempool for any reason.
+            for (unsigned int i = 0; i < origTx.vout.size(); i++) {
+                std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(origTx.GetHash(), i));
+                if (it == mapNextTx.end())
+                    continue;
+                txToRemove.push_back(it->second.ptx->GetHash());
+            }
+        }
         while (!txToRemove.empty())
         {
             uint256 hash = txToRemove.front();
This page took 0.044947 seconds and 4 git commands to generate.