Changeset View
Changeset View
Standalone View
Standalone View
src/test/mempool_tests.cpp
// Copyright (c) 2011-2016 The Bitcoin Core developers | // Copyright (c) 2011-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include "policy/policy.h" | #include "policy/policy.h" | ||||
#include "txmempool.h" | #include "txmempool.h" | ||||
#include "util.h" | #include "util.h" | ||||
#include "test/test_bitcoin.h" | #include "test/test_bitcoin.h" | ||||
#include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||
#include <list> | #include <list> | ||||
#include <vector> | #include <vector> | ||||
BOOST_FIXTURE_TEST_SUITE(mempool_tests, TestingSetup) | BOOST_FIXTURE_TEST_SUITE(mempool_tests, TestingSetup) | ||||
BOOST_AUTO_TEST_CASE(TestPackageAccounting) { | |||||
CTxMemPool testPool; | |||||
TestMemPoolEntryHelper entry; | |||||
CMutableTransaction tx; | |||||
tx.vin.resize(1); | |||||
tx.vin[0].scriptSig = CScript(); | |||||
tx.vout.resize(1); | |||||
tx.vout[0].scriptPubKey = CScript() << OP_TRUE; | |||||
tx.vout[0].nValue = 10 * SATOSHI; | |||||
testPool.addUnchecked(tx.GetId(), entry.FromTx(tx)); | |||||
TxId parentOfAll = tx.GetId(); | |||||
Amount totalFee = Amount::zero(); | |||||
size_t totalSize = CTransaction(tx).GetTotalSize(); | |||||
std::vector<TxId> txIds; | |||||
for (int64_t i = 0; i < 100; i++) { | |||||
// Recycle the transaction | |||||
TxId parentId = tx.GetId(); | |||||
txIds.push_back(parentId); | |||||
tx.vin[0].prevout = COutPoint(tx.GetId(), 0); | |||||
testPool.addUnchecked(tx.GetId(), entry.Fee(i * SATOSHI).FromTx(tx)); | |||||
totalFee += i * SATOSHI; | |||||
totalSize += CTransaction(tx).GetTotalSize(); | |||||
CTxMemPoolEntry parentEntry = *testPool.mapTx.find(parentOfAll); | |||||
CTxMemPoolEntry latestEntry = *testPool.mapTx.find(tx.GetId()); | |||||
BOOST_CHECK_EQUAL(latestEntry.GetCountWithAncestors(), i + 2); | |||||
BOOST_CHECK_EQUAL(latestEntry.GetSizeWithAncestors(), totalSize); | |||||
BOOST_CHECK_EQUAL(latestEntry.GetModFeesWithAncestors(), totalFee); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetCountWithDescendants(), | |||||
latestEntry.GetCountWithAncestors()); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetSizeWithDescendants(), | |||||
latestEntry.GetSizeWithAncestors()); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetModFeesWithDescendants(), | |||||
latestEntry.GetModFeesWithAncestors()); | |||||
} | |||||
} | |||||
BOOST_AUTO_TEST_CASE(MempoolRemoveTest) { | BOOST_AUTO_TEST_CASE(MempoolRemoveTest) { | ||||
// Test CTxMemPool::remove functionality | // Test CTxMemPool::remove functionality | ||||
TestMemPoolEntryHelper entry; | TestMemPoolEntryHelper entry; | ||||
// Parent transaction with three children, and three grand-children: | // Parent transaction with three children, and three grand-children: | ||||
CMutableTransaction txParent; | CMutableTransaction txParent; | ||||
txParent.vin.resize(1); | txParent.vin.resize(1); | ||||
txParent.vin[0].scriptSig = CScript() << OP_11; | txParent.vin[0].scriptSig = CScript() << OP_11; | ||||
▲ Show 20 Lines • Show All 293 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(MempoolIndexingTest) { | ||||
* tx9 = 200k (2 txs) | * tx9 = 200k (2 txs) | ||||
* tx8 = 200k (2 txs) | * tx8 = 200k (2 txs) | ||||
* tx10 = 200k (1 tx) | * tx10 = 200k (1 tx) | ||||
* tx6 = 2.2M (5 txs) | * tx6 = 2.2M (5 txs) | ||||
* tx7 = 2.2M (4 txs) | * tx7 = 2.2M (4 txs) | ||||
*/ | */ | ||||
// take out tx9, tx8 from the beginning | // take out tx9, tx8 from the beginning | ||||
sortedOrder.erase(sortedOrder.begin(), sortedOrder.begin() + 2); | sortedOrder.erase(sortedOrder.begin(), sortedOrder.begin() + 2); | ||||
sortedOrder.insert(sortedOrder.begin() + 5, tx9.GetId().ToString()); | sortedOrder.insert(sortedOrder.begin() + 7, tx9.GetId().ToString()); | ||||
sortedOrder.insert(sortedOrder.begin() + 6, tx8.GetId().ToString()); | sortedOrder.insert(sortedOrder.begin() + 8, tx8.GetId().ToString()); | ||||
// tx10 is just before tx6 | // tx10 is before tx7 | ||||
sortedOrder.insert(sortedOrder.begin() + 7, tx10.GetId().ToString()); | sortedOrder.insert(sortedOrder.begin() + 9, tx10.GetId().ToString()); | ||||
CheckSort<descendant_score>(pool, sortedOrder, "MempoolIndexingTest6"); | CheckSort<descendant_score>(pool, sortedOrder, "MempoolIndexingTest6"); | ||||
// there should be 10 transactions in the mempool | // there should be 10 transactions in the mempool | ||||
BOOST_CHECK_EQUAL(pool.size(), 10UL); | BOOST_CHECK_EQUAL(pool.size(), 10UL); | ||||
// Now try removing tx10 and verify the sort order returns to normal | // Now try removing tx10 and verify the sort order returns to normal | ||||
pool.removeRecursive(pool.mapTx.find(tx10.GetId())->GetTx()); | pool.removeRecursive(pool.mapTx.find(tx10.GetId())->GetTx()); | ||||
CheckSort<descendant_score>(pool, snapshotOrder, "MempoolIndexingTest7"); | CheckSort<descendant_score>(pool, snapshotOrder, "MempoolIndexingTest7"); | ||||
▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) { | ||||
uint64_t tx7Size = CTransaction(tx7).GetTotalSize(); | uint64_t tx7Size = CTransaction(tx7).GetTotalSize(); | ||||
/* set the fee to just below tx2's feerate when including ancestor */ | /* set the fee to just below tx2's feerate when including ancestor */ | ||||
Amount fee = int64_t((20000 / tx2Size) * (tx7Size + tx6Size) - 1) * SATOSHI; | Amount fee = int64_t((20000 / tx2Size) * (tx7Size + tx6Size) - 1) * SATOSHI; | ||||
// CTxMemPoolEntry entry7(tx7, fee, 2, 10.0, 1, true); | // CTxMemPoolEntry entry7(tx7, fee, 2, 10.0, 1, true); | ||||
pool.addUnchecked(tx7.GetId(), entry.Fee(Amount(fee)).FromTx(tx7)); | pool.addUnchecked(tx7.GetId(), entry.Fee(Amount(fee)).FromTx(tx7)); | ||||
BOOST_CHECK_EQUAL(pool.size(), 7UL); | BOOST_CHECK_EQUAL(pool.size(), 7UL); | ||||
sortedOrder.insert(sortedOrder.begin() + 1, tx7.GetId().ToString()); | sortedOrder.insert(sortedOrder.begin(), tx7.GetId().ToString()); | ||||
CheckSort<ancestor_score>(pool, sortedOrder, | CheckSort<ancestor_score>(pool, sortedOrder, | ||||
"MempoolAncestorIndexingTest3"); | "MempoolAncestorIndexingTest3"); | ||||
/* after tx6 is mined, tx7 should move up in the sort */ | /* after tx6 is mined, tx7 should move up in the sort */ | ||||
std::vector<CTransactionRef> vtx; | std::vector<CTransactionRef> vtx; | ||||
vtx.push_back(MakeTransactionRef(tx6)); | vtx.push_back(MakeTransactionRef(tx6)); | ||||
pool.removeForBlock(vtx, 1); | pool.removeForBlock(vtx, 1); | ||||
sortedOrder.erase(sortedOrder.begin() + 1); | sortedOrder.erase(sortedOrder.begin()); | ||||
// Ties are broken by hash | // Ties are broken by hash | ||||
if (tx3.GetId() < tx6.GetId()) { | if (tx3.GetId() < tx6.GetId()) { | ||||
sortedOrder.pop_back(); | sortedOrder.pop_back(); | ||||
} else { | } else { | ||||
sortedOrder.erase(sortedOrder.end() - 2); | sortedOrder.erase(sortedOrder.end() - 2); | ||||
} | } | ||||
sortedOrder.insert(sortedOrder.begin(), tx7.GetId().ToString()); | sortedOrder.insert(sortedOrder.begin(), tx7.GetId().ToString()); | ||||
CheckSort<ancestor_score>(pool, sortedOrder, | CheckSort<ancestor_score>(pool, sortedOrder, | ||||
▲ Show 20 Lines • Show All 179 Lines • Show Last 20 Lines |