Changeset View
Changeset View
Standalone View
Standalone View
src/test/mempool_tests.cpp
Show All 34 Lines | BOOST_AUTO_TEST_CASE(TestPackageAccounting) { | ||||
// Add some outpoints to the tracking vector | // Add some outpoints to the tracking vector | ||||
for (size_t i = 0; i < maxOutputs; i++) { | for (size_t i = 0; i < maxOutputs; i++) { | ||||
outpoints.emplace_back(COutPoint(parentOfAllId, i)); | outpoints.emplace_back(COutPoint(parentOfAllId, i)); | ||||
} | } | ||||
Amount totalFee = Amount::zero(); | Amount totalFee = Amount::zero(); | ||||
size_t totalSize = CTransaction(parentOfAll).GetTotalSize(); | size_t totalSize = CTransaction(parentOfAll).GetTotalSize(); | ||||
size_t totalBillableSize = CTransaction(parentOfAll).GetBillableSize(); | |||||
// Generate 100 transactions | // Generate 100 transactions | ||||
for (size_t totalTransactions = 0; totalTransactions < 100; | for (size_t totalTransactions = 0; totalTransactions < 100; | ||||
totalTransactions++) { | totalTransactions++) { | ||||
CMutableTransaction mtx; | CMutableTransaction mtx; | ||||
uint64_t minAncestors = std::numeric_limits<size_t>::max(); | uint64_t minAncestors = std::numeric_limits<size_t>::max(); | ||||
uint64_t maxAncestors = 0; | uint64_t maxAncestors = 0; | ||||
Amount minFees = MAX_MONEY; | Amount minFees = MAX_MONEY; | ||||
Amount maxFees = Amount::zero(); | Amount maxFees = Amount::zero(); | ||||
uint64_t minSize = std::numeric_limits<size_t>::max(); | uint64_t minSize = std::numeric_limits<size_t>::max(); | ||||
uint64_t maxSize = 0; | uint64_t maxSize = 0; | ||||
uint64_t minBillableSize = std::numeric_limits<size_t>::max(); | |||||
uint64_t maxBillableSize = 0; | |||||
// Consume random inputs, but make sure we don't consume more than | // Consume random inputs, but make sure we don't consume more than | ||||
// available | // available | ||||
for (size_t input = std::min(InsecureRandRange(maxOutputs) + 1, | for (size_t input = std::min(InsecureRandRange(maxOutputs) + 1, | ||||
uint64_t(outpoints.size())); | uint64_t(outpoints.size())); | ||||
input > 0; input--) { | input > 0; input--) { | ||||
std::swap(outpoints[InsecureRandRange(outpoints.size())], | std::swap(outpoints[InsecureRandRange(outpoints.size())], | ||||
outpoints.back()); | outpoints.back()); | ||||
mtx.vin.emplace_back(outpoints.back()); | mtx.vin.emplace_back(outpoints.back()); | ||||
outpoints.pop_back(); | outpoints.pop_back(); | ||||
// We don't know exactly how many ancestors this transaction has | // We don't know exactly how many ancestors this transaction has | ||||
// due to possible duplicates. Calculate a valid range based on | // due to possible duplicates. Calculate a valid range based on | ||||
// parents. | // parents. | ||||
CTxMemPoolEntry parent = | CTxMemPoolEntry parent = | ||||
*testPool.mapTx.find(mtx.vin.back().prevout.GetTxId()); | *testPool.mapTx.find(mtx.vin.back().prevout.GetTxId()); | ||||
minAncestors = | minAncestors = | ||||
std::min(minAncestors, parent.GetCountWithAncestors()); | std::min(minAncestors, parent.GetCountWithAncestors()); | ||||
maxAncestors += parent.GetCountWithAncestors(); | maxAncestors += parent.GetCountWithAncestors(); | ||||
minFees = std::min(minFees, parent.GetModFeesWithAncestors()); | minFees = std::min(minFees, parent.GetModFeesWithAncestors()); | ||||
maxFees += parent.GetModFeesWithAncestors(); | maxFees += parent.GetModFeesWithAncestors(); | ||||
minSize = std::min(minSize, parent.GetSizeWithAncestors()); | minSize = std::min(minSize, parent.GetSizeWithAncestors()); | ||||
maxSize += parent.GetSizeWithAncestors(); | maxSize += parent.GetSizeWithAncestors(); | ||||
minBillableSize = std::min(minBillableSize, | |||||
parent.GetBillableSizeWithAncestors()); | |||||
maxBillableSize += parent.GetBillableSizeWithAncestors(); | |||||
} | } | ||||
// Produce random number of outputs | // Produce random number of outputs | ||||
for (size_t output = InsecureRandRange(maxOutputs) + 1; output > 0; | for (size_t output = InsecureRandRange(maxOutputs) + 1; output > 0; | ||||
output--) { | output--) { | ||||
mtx.vout.emplace_back(10 * SATOSHI, CScript() << OP_TRUE); | mtx.vout.emplace_back(10 * SATOSHI, CScript() << OP_TRUE); | ||||
} | } | ||||
Show All 11 Lines | for (size_t totalTransactions = 0; totalTransactions < 100; | ||||
// Add this transaction to the totals. | // Add this transaction to the totals. | ||||
minAncestors += 1; | minAncestors += 1; | ||||
maxAncestors += 1; | maxAncestors += 1; | ||||
minFees += randFee; | minFees += randFee; | ||||
maxFees += randFee; | maxFees += randFee; | ||||
minSize += CTransaction(tx).GetTotalSize(); | minSize += CTransaction(tx).GetTotalSize(); | ||||
maxSize += CTransaction(tx).GetTotalSize(); | maxSize += CTransaction(tx).GetTotalSize(); | ||||
minBillableSize += CTransaction(tx).GetBillableSize(); | |||||
maxBillableSize += CTransaction(tx).GetBillableSize(); | |||||
// Calculate overall values | // Calculate overall values | ||||
totalFee += randFee; | totalFee += randFee; | ||||
totalSize += CTransaction(tx).GetTotalSize(); | totalSize += CTransaction(tx).GetTotalSize(); | ||||
totalBillableSize += CTransaction(tx).GetBillableSize(); | |||||
CTxMemPoolEntry parentEntry = *testPool.mapTx.find(parentOfAllId); | CTxMemPoolEntry parentEntry = *testPool.mapTx.find(parentOfAllId); | ||||
CTxMemPoolEntry latestEntry = *testPool.mapTx.find(curId); | CTxMemPoolEntry latestEntry = *testPool.mapTx.find(curId); | ||||
// Ensure values are within the expected ranges | // Ensure values are within the expected ranges | ||||
BOOST_CHECK(latestEntry.GetCountWithAncestors() >= minAncestors); | BOOST_CHECK(latestEntry.GetCountWithAncestors() >= minAncestors); | ||||
BOOST_CHECK(latestEntry.GetCountWithAncestors() <= maxAncestors); | BOOST_CHECK(latestEntry.GetCountWithAncestors() <= maxAncestors); | ||||
BOOST_CHECK(latestEntry.GetSizeWithAncestors() >= minSize); | BOOST_CHECK(latestEntry.GetSizeWithAncestors() >= minSize); | ||||
BOOST_CHECK(latestEntry.GetSizeWithAncestors() <= maxSize); | BOOST_CHECK(latestEntry.GetSizeWithAncestors() <= maxSize); | ||||
BOOST_CHECK(latestEntry.GetBillableSizeWithAncestors() >= | |||||
minBillableSize); | |||||
BOOST_CHECK(latestEntry.GetBillableSizeWithAncestors() <= | |||||
maxBillableSize); | |||||
BOOST_CHECK(latestEntry.GetModFeesWithAncestors() >= minFees); | BOOST_CHECK(latestEntry.GetModFeesWithAncestors() >= minFees); | ||||
BOOST_CHECK(latestEntry.GetModFeesWithAncestors() <= maxFees); | BOOST_CHECK(latestEntry.GetModFeesWithAncestors() <= maxFees); | ||||
BOOST_CHECK_EQUAL(parentEntry.GetCountWithDescendants(), | BOOST_CHECK_EQUAL(parentEntry.GetCountWithDescendants(), | ||||
testPool.mapTx.size()); | testPool.mapTx.size()); | ||||
BOOST_CHECK_EQUAL(parentEntry.GetSizeWithDescendants(), totalSize); | BOOST_CHECK_EQUAL(parentEntry.GetSizeWithDescendants(), totalSize); | ||||
BOOST_CHECK_EQUAL(parentEntry.GetBillableSizeWithDescendants(), | |||||
totalBillableSize); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetModFeesWithDescendants(), totalFee); | BOOST_CHECK_EQUAL(parentEntry.GetModFeesWithDescendants(), totalFee); | ||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(MempoolRemoveTest) { | BOOST_AUTO_TEST_CASE(MempoolRemoveTest) { | ||||
// Test CTxMemPool::remove functionality | // Test CTxMemPool::remove functionality | ||||
TestMemPoolEntryHelper entry; | TestMemPoolEntryHelper entry; | ||||
▲ Show 20 Lines • Show All 297 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 |