Changeset View
Changeset View
Standalone View
Standalone View
src/test/mempool_tests.cpp
Show First 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | |||||
BOOST_AUTO_TEST_CASE(MempoolIndexingTest) { | BOOST_AUTO_TEST_CASE(MempoolIndexingTest) { | ||||
CTxMemPool pool(CFeeRate(0)); | CTxMemPool pool(CFeeRate(0)); | ||||
TestMemPoolEntryHelper entry; | TestMemPoolEntryHelper entry; | ||||
/* 3rd highest fee */ | /* 3rd highest fee */ | ||||
CMutableTransaction tx1 = CMutableTransaction(); | CMutableTransaction tx1 = CMutableTransaction(); | ||||
tx1.vout.resize(1); | tx1.vout.resize(1); | ||||
tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx1.vout[0].nValue = 10 * COIN; | tx1.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx1.GetId(), | pool.addUnchecked(tx1.GetId(), | ||||
entry.Fee(10000LL).Priority(10.0).FromTx(tx1)); | entry.Fee(10000LL).Priority(10.0).FromTx(tx1)); | ||||
/* highest fee */ | /* highest fee */ | ||||
CMutableTransaction tx2 = CMutableTransaction(); | CMutableTransaction tx2 = CMutableTransaction(); | ||||
tx2.vout.resize(1); | tx2.vout.resize(1); | ||||
tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx2.vout[0].nValue = 2 * COIN; | tx2.vout[0].nValue = 2 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx2.GetId(), | pool.addUnchecked(tx2.GetId(), | ||||
entry.Fee(20000LL).Priority(9.0).FromTx(tx2)); | entry.Fee(20000LL).Priority(9.0).FromTx(tx2)); | ||||
/* lowest fee */ | /* lowest fee */ | ||||
CMutableTransaction tx3 = CMutableTransaction(); | CMutableTransaction tx3 = CMutableTransaction(); | ||||
tx3.vout.resize(1); | tx3.vout.resize(1); | ||||
tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx3.vout[0].nValue = 5 * COIN; | tx3.vout[0].nValue = 5 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx3.GetId(), entry.Fee(0LL).Priority(100.0).FromTx(tx3)); | pool.addUnchecked(tx3.GetId(), entry.Fee(0LL).Priority(100.0).FromTx(tx3)); | ||||
/* 2nd highest fee */ | /* 2nd highest fee */ | ||||
CMutableTransaction tx4 = CMutableTransaction(); | CMutableTransaction tx4 = CMutableTransaction(); | ||||
tx4.vout.resize(1); | tx4.vout.resize(1); | ||||
tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx4.vout[0].nValue = 6 * COIN; | tx4.vout[0].nValue = 6 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx4.GetId(), | pool.addUnchecked(tx4.GetId(), | ||||
entry.Fee(15000LL).Priority(1.0).FromTx(tx4)); | entry.Fee(15000LL).Priority(1.0).FromTx(tx4)); | ||||
/* equal fee rate to tx1, but newer */ | /* equal fee rate to tx1, but newer */ | ||||
CMutableTransaction tx5 = CMutableTransaction(); | CMutableTransaction tx5 = CMutableTransaction(); | ||||
tx5.vout.resize(1); | tx5.vout.resize(1); | ||||
tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx5.vout[0].nValue = 11 * COIN; | tx5.vout[0].nValue = 11 * COIN.GetSatoshis(); | ||||
entry.nTime = 1; | entry.nTime = 1; | ||||
entry.dPriority = 10.0; | entry.dPriority = 10.0; | ||||
pool.addUnchecked(tx5.GetId(), entry.Fee(10000LL).FromTx(tx5)); | pool.addUnchecked(tx5.GetId(), entry.Fee(10000LL).FromTx(tx5)); | ||||
BOOST_CHECK_EQUAL(pool.size(), 5); | BOOST_CHECK_EQUAL(pool.size(), 5); | ||||
std::vector<std::string> sortedOrder; | std::vector<std::string> sortedOrder; | ||||
sortedOrder.resize(5); | sortedOrder.resize(5); | ||||
sortedOrder[0] = tx3.GetId().ToString(); // 0 | sortedOrder[0] = tx3.GetId().ToString(); // 0 | ||||
sortedOrder[1] = tx5.GetId().ToString(); // 10000 | sortedOrder[1] = tx5.GetId().ToString(); // 10000 | ||||
sortedOrder[2] = tx1.GetId().ToString(); // 10000 | sortedOrder[2] = tx1.GetId().ToString(); // 10000 | ||||
sortedOrder[3] = tx4.GetId().ToString(); // 15000 | sortedOrder[3] = tx4.GetId().ToString(); // 15000 | ||||
sortedOrder[4] = tx2.GetId().ToString(); // 20000 | sortedOrder[4] = tx2.GetId().ToString(); // 20000 | ||||
CheckSort<descendant_score>(pool, sortedOrder); | CheckSort<descendant_score>(pool, sortedOrder); | ||||
/* low fee but with high fee child */ | /* low fee but with high fee child */ | ||||
/* tx6 -> tx7 -> tx8, tx9 -> tx10 */ | /* tx6 -> tx7 -> tx8, tx9 -> tx10 */ | ||||
CMutableTransaction tx6 = CMutableTransaction(); | CMutableTransaction tx6 = CMutableTransaction(); | ||||
tx6.vout.resize(1); | tx6.vout.resize(1); | ||||
tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx6.vout[0].nValue = 20 * COIN; | tx6.vout[0].nValue = 20 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx6.GetId(), entry.Fee(0LL).FromTx(tx6)); | pool.addUnchecked(tx6.GetId(), entry.Fee(0LL).FromTx(tx6)); | ||||
BOOST_CHECK_EQUAL(pool.size(), 6); | BOOST_CHECK_EQUAL(pool.size(), 6); | ||||
// Check that at this point, tx6 is sorted low | // Check that at this point, tx6 is sorted low | ||||
sortedOrder.insert(sortedOrder.begin(), tx6.GetId().ToString()); | sortedOrder.insert(sortedOrder.begin(), tx6.GetId().ToString()); | ||||
CheckSort<descendant_score>(pool, sortedOrder); | CheckSort<descendant_score>(pool, sortedOrder); | ||||
CTxMemPool::setEntries setAncestors; | CTxMemPool::setEntries setAncestors; | ||||
setAncestors.insert(pool.mapTx.find(tx6.GetId())); | setAncestors.insert(pool.mapTx.find(tx6.GetId())); | ||||
CMutableTransaction tx7 = CMutableTransaction(); | CMutableTransaction tx7 = CMutableTransaction(); | ||||
tx7.vin.resize(1); | tx7.vin.resize(1); | ||||
tx7.vin[0].prevout = COutPoint(tx6.GetId(), 0); | tx7.vin[0].prevout = COutPoint(tx6.GetId(), 0); | ||||
tx7.vin[0].scriptSig = CScript() << OP_11; | tx7.vin[0].scriptSig = CScript() << OP_11; | ||||
tx7.vout.resize(2); | tx7.vout.resize(2); | ||||
tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx7.vout[0].nValue = 10 * COIN; | tx7.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
tx7.vout[1].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx7.vout[1].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx7.vout[1].nValue = 1 * COIN; | tx7.vout[1].nValue = 1 * COIN.GetSatoshis(); | ||||
CTxMemPool::setEntries setAncestorsCalculated; | CTxMemPool::setEntries setAncestorsCalculated; | ||||
std::string dummy; | std::string dummy; | ||||
BOOST_CHECK_EQUAL( | BOOST_CHECK_EQUAL( | ||||
pool.CalculateMemPoolAncestors(entry.Fee(2000000LL).FromTx(tx7), | pool.CalculateMemPoolAncestors(entry.Fee(2000000LL).FromTx(tx7), | ||||
setAncestorsCalculated, 100, 1000000, | setAncestorsCalculated, 100, 1000000, | ||||
1000, 1000000, dummy), | 1000, 1000000, dummy), | ||||
true); | true); | ||||
Show All 10 Lines | BOOST_AUTO_TEST_CASE(MempoolIndexingTest) { | ||||
/* low fee child of tx7 */ | /* low fee child of tx7 */ | ||||
CMutableTransaction tx8 = CMutableTransaction(); | CMutableTransaction tx8 = CMutableTransaction(); | ||||
tx8.vin.resize(1); | tx8.vin.resize(1); | ||||
tx8.vin[0].prevout = COutPoint(tx7.GetId(), 0); | tx8.vin[0].prevout = COutPoint(tx7.GetId(), 0); | ||||
tx8.vin[0].scriptSig = CScript() << OP_11; | tx8.vin[0].scriptSig = CScript() << OP_11; | ||||
tx8.vout.resize(1); | tx8.vout.resize(1); | ||||
tx8.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx8.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx8.vout[0].nValue = 10 * COIN; | tx8.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
setAncestors.insert(pool.mapTx.find(tx7.GetId())); | setAncestors.insert(pool.mapTx.find(tx7.GetId())); | ||||
pool.addUnchecked(tx8.GetId(), entry.Fee(0LL).Time(2).FromTx(tx8), | pool.addUnchecked(tx8.GetId(), entry.Fee(0LL).Time(2).FromTx(tx8), | ||||
setAncestors); | setAncestors); | ||||
// Now tx8 should be sorted low, but tx6/tx both high | // Now tx8 should be sorted low, but tx6/tx both high | ||||
sortedOrder.insert(sortedOrder.begin(), tx8.GetId().ToString()); | sortedOrder.insert(sortedOrder.begin(), tx8.GetId().ToString()); | ||||
CheckSort<descendant_score>(pool, sortedOrder); | CheckSort<descendant_score>(pool, sortedOrder); | ||||
/* low fee child of tx7 */ | /* low fee child of tx7 */ | ||||
CMutableTransaction tx9 = CMutableTransaction(); | CMutableTransaction tx9 = CMutableTransaction(); | ||||
tx9.vin.resize(1); | tx9.vin.resize(1); | ||||
tx9.vin[0].prevout = COutPoint(tx7.GetId(), 1); | tx9.vin[0].prevout = COutPoint(tx7.GetId(), 1); | ||||
tx9.vin[0].scriptSig = CScript() << OP_11; | tx9.vin[0].scriptSig = CScript() << OP_11; | ||||
tx9.vout.resize(1); | tx9.vout.resize(1); | ||||
tx9.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx9.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx9.vout[0].nValue = 1 * COIN; | tx9.vout[0].nValue = 1 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx9.GetId(), entry.Fee(0LL).Time(3).FromTx(tx9), | pool.addUnchecked(tx9.GetId(), entry.Fee(0LL).Time(3).FromTx(tx9), | ||||
setAncestors); | setAncestors); | ||||
// tx9 should be sorted low | // tx9 should be sorted low | ||||
BOOST_CHECK_EQUAL(pool.size(), 9); | BOOST_CHECK_EQUAL(pool.size(), 9); | ||||
sortedOrder.insert(sortedOrder.begin(), tx9.GetId().ToString()); | sortedOrder.insert(sortedOrder.begin(), tx9.GetId().ToString()); | ||||
CheckSort<descendant_score>(pool, sortedOrder); | CheckSort<descendant_score>(pool, sortedOrder); | ||||
std::vector<std::string> snapshotOrder = sortedOrder; | std::vector<std::string> snapshotOrder = sortedOrder; | ||||
setAncestors.insert(pool.mapTx.find(tx8.GetId())); | setAncestors.insert(pool.mapTx.find(tx8.GetId())); | ||||
setAncestors.insert(pool.mapTx.find(tx9.GetId())); | setAncestors.insert(pool.mapTx.find(tx9.GetId())); | ||||
/* tx10 depends on tx8 and tx9 and has a high fee*/ | /* tx10 depends on tx8 and tx9 and has a high fee*/ | ||||
CMutableTransaction tx10 = CMutableTransaction(); | CMutableTransaction tx10 = CMutableTransaction(); | ||||
tx10.vin.resize(2); | tx10.vin.resize(2); | ||||
tx10.vin[0].prevout = COutPoint(tx8.GetId(), 0); | tx10.vin[0].prevout = COutPoint(tx8.GetId(), 0); | ||||
tx10.vin[0].scriptSig = CScript() << OP_11; | tx10.vin[0].scriptSig = CScript() << OP_11; | ||||
tx10.vin[1].prevout = COutPoint(tx9.GetId(), 0); | tx10.vin[1].prevout = COutPoint(tx9.GetId(), 0); | ||||
tx10.vin[1].scriptSig = CScript() << OP_11; | tx10.vin[1].scriptSig = CScript() << OP_11; | ||||
tx10.vout.resize(1); | tx10.vout.resize(1); | ||||
tx10.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx10.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx10.vout[0].nValue = 10 * COIN; | tx10.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
setAncestorsCalculated.clear(); | setAncestorsCalculated.clear(); | ||||
BOOST_CHECK_EQUAL( | BOOST_CHECK_EQUAL( | ||||
pool.CalculateMemPoolAncestors(entry.Fee(200000LL).Time(4).FromTx(tx10), | pool.CalculateMemPoolAncestors(entry.Fee(200000LL).Time(4).FromTx(tx10), | ||||
setAncestorsCalculated, 100, 1000000, | setAncestorsCalculated, 100, 1000000, | ||||
1000, 1000000, dummy), | 1000, 1000000, dummy), | ||||
true); | true); | ||||
BOOST_CHECK(setAncestorsCalculated == setAncestors); | BOOST_CHECK(setAncestorsCalculated == setAncestors); | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) { | BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) { | ||||
CTxMemPool pool(CFeeRate(0)); | CTxMemPool pool(CFeeRate(0)); | ||||
TestMemPoolEntryHelper entry; | TestMemPoolEntryHelper entry; | ||||
/* 3rd highest fee */ | /* 3rd highest fee */ | ||||
CMutableTransaction tx1 = CMutableTransaction(); | CMutableTransaction tx1 = CMutableTransaction(); | ||||
tx1.vout.resize(1); | tx1.vout.resize(1); | ||||
tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx1.vout[0].nValue = 10 * COIN; | tx1.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx1.GetId(), | pool.addUnchecked(tx1.GetId(), | ||||
entry.Fee(10000LL).Priority(10.0).FromTx(tx1)); | entry.Fee(10000LL).Priority(10.0).FromTx(tx1)); | ||||
/* highest fee */ | /* highest fee */ | ||||
CMutableTransaction tx2 = CMutableTransaction(); | CMutableTransaction tx2 = CMutableTransaction(); | ||||
tx2.vout.resize(1); | tx2.vout.resize(1); | ||||
tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx2.vout[0].nValue = 2 * COIN; | tx2.vout[0].nValue = 2 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx2.GetId(), | pool.addUnchecked(tx2.GetId(), | ||||
entry.Fee(20000LL).Priority(9.0).FromTx(tx2)); | entry.Fee(20000LL).Priority(9.0).FromTx(tx2)); | ||||
uint64_t tx2Size = GetTransactionSize(tx2); | uint64_t tx2Size = GetTransactionSize(tx2); | ||||
/* lowest fee */ | /* lowest fee */ | ||||
CMutableTransaction tx3 = CMutableTransaction(); | CMutableTransaction tx3 = CMutableTransaction(); | ||||
tx3.vout.resize(1); | tx3.vout.resize(1); | ||||
tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx3.vout[0].nValue = 5 * COIN; | tx3.vout[0].nValue = 5 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx3.GetId(), entry.Fee(0LL).Priority(100.0).FromTx(tx3)); | pool.addUnchecked(tx3.GetId(), entry.Fee(0LL).Priority(100.0).FromTx(tx3)); | ||||
/* 2nd highest fee */ | /* 2nd highest fee */ | ||||
CMutableTransaction tx4 = CMutableTransaction(); | CMutableTransaction tx4 = CMutableTransaction(); | ||||
tx4.vout.resize(1); | tx4.vout.resize(1); | ||||
tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx4.vout[0].nValue = 6 * COIN; | tx4.vout[0].nValue = 6 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx4.GetId(), | pool.addUnchecked(tx4.GetId(), | ||||
entry.Fee(15000LL).Priority(1.0).FromTx(tx4)); | entry.Fee(15000LL).Priority(1.0).FromTx(tx4)); | ||||
/* equal fee rate to tx1, but newer */ | /* equal fee rate to tx1, but newer */ | ||||
CMutableTransaction tx5 = CMutableTransaction(); | CMutableTransaction tx5 = CMutableTransaction(); | ||||
tx5.vout.resize(1); | tx5.vout.resize(1); | ||||
tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx5.vout[0].nValue = 11 * COIN; | tx5.vout[0].nValue = 11 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx5.GetId(), entry.Fee(10000LL).FromTx(tx5)); | pool.addUnchecked(tx5.GetId(), entry.Fee(10000LL).FromTx(tx5)); | ||||
BOOST_CHECK_EQUAL(pool.size(), 5); | BOOST_CHECK_EQUAL(pool.size(), 5); | ||||
std::vector<std::string> sortedOrder; | std::vector<std::string> sortedOrder; | ||||
sortedOrder.resize(5); | sortedOrder.resize(5); | ||||
sortedOrder[0] = tx2.GetId().ToString(); // 20000 | sortedOrder[0] = tx2.GetId().ToString(); // 20000 | ||||
sortedOrder[1] = tx4.GetId().ToString(); // 15000 | sortedOrder[1] = tx4.GetId().ToString(); // 15000 | ||||
// tx1 and tx5 are both 10000 | // tx1 and tx5 are both 10000 | ||||
Show All 10 Lines | BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) { | ||||
CheckSort<ancestor_score>(pool, sortedOrder); | CheckSort<ancestor_score>(pool, sortedOrder); | ||||
/* low fee parent with high fee child */ | /* low fee parent with high fee child */ | ||||
/* tx6 (0) -> tx7 (high) */ | /* tx6 (0) -> tx7 (high) */ | ||||
CMutableTransaction tx6 = CMutableTransaction(); | CMutableTransaction tx6 = CMutableTransaction(); | ||||
tx6.vout.resize(1); | tx6.vout.resize(1); | ||||
tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx6.vout[0].nValue = 20 * COIN; | tx6.vout[0].nValue = 20 * COIN.GetSatoshis(); | ||||
uint64_t tx6Size = GetTransactionSize(tx6); | uint64_t tx6Size = GetTransactionSize(tx6); | ||||
pool.addUnchecked(tx6.GetId(), entry.Fee(0LL).FromTx(tx6)); | pool.addUnchecked(tx6.GetId(), entry.Fee(0LL).FromTx(tx6)); | ||||
BOOST_CHECK_EQUAL(pool.size(), 6); | BOOST_CHECK_EQUAL(pool.size(), 6); | ||||
// Ties are broken by hash | // Ties are broken by hash | ||||
if (tx3.GetId() < tx6.GetId()) { | if (tx3.GetId() < tx6.GetId()) { | ||||
sortedOrder.push_back(tx6.GetId().ToString()); | sortedOrder.push_back(tx6.GetId().ToString()); | ||||
} else { | } else { | ||||
sortedOrder.insert(sortedOrder.end() - 1, tx6.GetId().ToString()); | sortedOrder.insert(sortedOrder.end() - 1, tx6.GetId().ToString()); | ||||
} | } | ||||
CheckSort<ancestor_score>(pool, sortedOrder); | CheckSort<ancestor_score>(pool, sortedOrder); | ||||
CMutableTransaction tx7 = CMutableTransaction(); | CMutableTransaction tx7 = CMutableTransaction(); | ||||
tx7.vin.resize(1); | tx7.vin.resize(1); | ||||
tx7.vin[0].prevout = COutPoint(tx6.GetId(), 0); | tx7.vin[0].prevout = COutPoint(tx6.GetId(), 0); | ||||
tx7.vin[0].scriptSig = CScript() << OP_11; | tx7.vin[0].scriptSig = CScript() << OP_11; | ||||
tx7.vout.resize(1); | tx7.vout.resize(1); | ||||
tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx7.vout[0].nValue = 10 * COIN; | tx7.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
uint64_t tx7Size = GetTransactionSize(tx7); | uint64_t tx7Size = GetTransactionSize(tx7); | ||||
/* set the fee to just below tx2's feerate when including ancestor */ | /* set the fee to just below tx2's feerate when including ancestor */ | ||||
CAmount fee = (20000 / tx2Size) * (tx7Size + tx6Size) - 1; | CAmount fee = (20000 / tx2Size) * (tx7Size + tx6Size) - 1; | ||||
// CTxMemPoolEntry entry7(tx7, fee, 2, 10.0, 1, true); | // CTxMemPoolEntry entry7(tx7, fee, 2, 10.0, 1, true); | ||||
pool.addUnchecked(tx7.GetId(), entry.Fee(fee).FromTx(tx7)); | pool.addUnchecked(tx7.GetId(), entry.Fee(fee).FromTx(tx7)); | ||||
BOOST_CHECK_EQUAL(pool.size(), 7); | BOOST_CHECK_EQUAL(pool.size(), 7); | ||||
Show All 20 Lines | BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) { | ||||
TestMemPoolEntryHelper entry; | TestMemPoolEntryHelper entry; | ||||
entry.dPriority = 10.0; | entry.dPriority = 10.0; | ||||
CMutableTransaction tx1 = CMutableTransaction(); | CMutableTransaction tx1 = CMutableTransaction(); | ||||
tx1.vin.resize(1); | tx1.vin.resize(1); | ||||
tx1.vin[0].scriptSig = CScript() << OP_1; | tx1.vin[0].scriptSig = CScript() << OP_1; | ||||
tx1.vout.resize(1); | tx1.vout.resize(1); | ||||
tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; | tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; | ||||
tx1.vout[0].nValue = 10 * COIN; | tx1.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx1.GetId(), entry.Fee(10000LL).FromTx(tx1, &pool)); | pool.addUnchecked(tx1.GetId(), entry.Fee(10000LL).FromTx(tx1, &pool)); | ||||
CMutableTransaction tx2 = CMutableTransaction(); | CMutableTransaction tx2 = CMutableTransaction(); | ||||
tx2.vin.resize(1); | tx2.vin.resize(1); | ||||
tx2.vin[0].scriptSig = CScript() << OP_2; | tx2.vin[0].scriptSig = CScript() << OP_2; | ||||
tx2.vout.resize(1); | tx2.vout.resize(1); | ||||
tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL; | tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL; | ||||
tx2.vout[0].nValue = 10 * COIN; | tx2.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx2.GetId(), entry.Fee(5000LL).FromTx(tx2, &pool)); | pool.addUnchecked(tx2.GetId(), entry.Fee(5000LL).FromTx(tx2, &pool)); | ||||
// should do nothing | // should do nothing | ||||
pool.TrimToSize(pool.DynamicMemoryUsage()); | pool.TrimToSize(pool.DynamicMemoryUsage()); | ||||
BOOST_CHECK(pool.exists(tx1.GetId())); | BOOST_CHECK(pool.exists(tx1.GetId())); | ||||
BOOST_CHECK(pool.exists(tx2.GetId())); | BOOST_CHECK(pool.exists(tx2.GetId())); | ||||
// should remove the lower-feerate transaction | // should remove the lower-feerate transaction | ||||
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); | pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); | ||||
BOOST_CHECK(pool.exists(tx1.GetId())); | BOOST_CHECK(pool.exists(tx1.GetId())); | ||||
BOOST_CHECK(!pool.exists(tx2.GetId())); | BOOST_CHECK(!pool.exists(tx2.GetId())); | ||||
pool.addUnchecked(tx2.GetId(), entry.FromTx(tx2, &pool)); | pool.addUnchecked(tx2.GetId(), entry.FromTx(tx2, &pool)); | ||||
CMutableTransaction tx3 = CMutableTransaction(); | CMutableTransaction tx3 = CMutableTransaction(); | ||||
tx3.vin.resize(1); | tx3.vin.resize(1); | ||||
tx3.vin[0].prevout = COutPoint(tx2.GetId(), 0); | tx3.vin[0].prevout = COutPoint(tx2.GetId(), 0); | ||||
tx3.vin[0].scriptSig = CScript() << OP_2; | tx3.vin[0].scriptSig = CScript() << OP_2; | ||||
tx3.vout.resize(1); | tx3.vout.resize(1); | ||||
tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL; | tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL; | ||||
tx3.vout[0].nValue = 10 * COIN; | tx3.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx3.GetId(), entry.Fee(20000LL).FromTx(tx3, &pool)); | pool.addUnchecked(tx3.GetId(), entry.Fee(20000LL).FromTx(tx3, &pool)); | ||||
// tx3 should pay for tx2 (CPFP) | // tx3 should pay for tx2 (CPFP) | ||||
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); | pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); | ||||
BOOST_CHECK(!pool.exists(tx1.GetId())); | BOOST_CHECK(!pool.exists(tx1.GetId())); | ||||
BOOST_CHECK(pool.exists(tx2.GetId())); | BOOST_CHECK(pool.exists(tx2.GetId())); | ||||
BOOST_CHECK(pool.exists(tx3.GetId())); | BOOST_CHECK(pool.exists(tx3.GetId())); | ||||
// mempool is limited to tx1's size in memory usage, so nothing fits | // mempool is limited to tx1's size in memory usage, so nothing fits | ||||
pool.TrimToSize(GetTransactionSize(tx1)); | pool.TrimToSize(GetTransactionSize(tx1)); | ||||
BOOST_CHECK(!pool.exists(tx1.GetId())); | BOOST_CHECK(!pool.exists(tx1.GetId())); | ||||
BOOST_CHECK(!pool.exists(tx2.GetId())); | BOOST_CHECK(!pool.exists(tx2.GetId())); | ||||
BOOST_CHECK(!pool.exists(tx3.GetId())); | BOOST_CHECK(!pool.exists(tx3.GetId())); | ||||
CFeeRate maxFeeRateRemoved( | CFeeRate maxFeeRateRemoved(25000, GetTransactionSize(tx3) + | ||||
25000, GetTransactionSize(tx3) + GetTransactionSize(tx2)); | GetTransactionSize(tx2)); | ||||
BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), | BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), | ||||
maxFeeRateRemoved.GetFeePerK() + 1000); | maxFeeRateRemoved.GetFeePerK() + 1000); | ||||
CMutableTransaction tx4 = CMutableTransaction(); | CMutableTransaction tx4 = CMutableTransaction(); | ||||
tx4.vin.resize(2); | tx4.vin.resize(2); | ||||
tx4.vin[0].prevout.SetNull(); | tx4.vin[0].prevout.SetNull(); | ||||
tx4.vin[0].scriptSig = CScript() << OP_4; | tx4.vin[0].scriptSig = CScript() << OP_4; | ||||
tx4.vin[1].prevout.SetNull(); | tx4.vin[1].prevout.SetNull(); | ||||
tx4.vin[1].scriptSig = CScript() << OP_4; | tx4.vin[1].scriptSig = CScript() << OP_4; | ||||
tx4.vout.resize(2); | tx4.vout.resize(2); | ||||
tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL; | tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL; | ||||
tx4.vout[0].nValue = 10 * COIN; | tx4.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL; | tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL; | ||||
tx4.vout[1].nValue = 10 * COIN; | tx4.vout[1].nValue = 10 * COIN.GetSatoshis(); | ||||
CMutableTransaction tx5 = CMutableTransaction(); | CMutableTransaction tx5 = CMutableTransaction(); | ||||
tx5.vin.resize(2); | tx5.vin.resize(2); | ||||
tx5.vin[0].prevout = COutPoint(tx4.GetId(), 0); | tx5.vin[0].prevout = COutPoint(tx4.GetId(), 0); | ||||
tx5.vin[0].scriptSig = CScript() << OP_4; | tx5.vin[0].scriptSig = CScript() << OP_4; | ||||
tx5.vin[1].prevout.SetNull(); | tx5.vin[1].prevout.SetNull(); | ||||
tx5.vin[1].scriptSig = CScript() << OP_5; | tx5.vin[1].scriptSig = CScript() << OP_5; | ||||
tx5.vout.resize(2); | tx5.vout.resize(2); | ||||
tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL; | tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL; | ||||
tx5.vout[0].nValue = 10 * COIN; | tx5.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL; | tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL; | ||||
tx5.vout[1].nValue = 10 * COIN; | tx5.vout[1].nValue = 10 * COIN.GetSatoshis(); | ||||
CMutableTransaction tx6 = CMutableTransaction(); | CMutableTransaction tx6 = CMutableTransaction(); | ||||
tx6.vin.resize(2); | tx6.vin.resize(2); | ||||
tx6.vin[0].prevout = COutPoint(tx4.GetId(), 1); | tx6.vin[0].prevout = COutPoint(tx4.GetId(), 1); | ||||
tx6.vin[0].scriptSig = CScript() << OP_4; | tx6.vin[0].scriptSig = CScript() << OP_4; | ||||
tx6.vin[1].prevout.SetNull(); | tx6.vin[1].prevout.SetNull(); | ||||
tx6.vin[1].scriptSig = CScript() << OP_6; | tx6.vin[1].scriptSig = CScript() << OP_6; | ||||
tx6.vout.resize(2); | tx6.vout.resize(2); | ||||
tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL; | tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL; | ||||
tx6.vout[0].nValue = 10 * COIN; | tx6.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL; | tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL; | ||||
tx6.vout[1].nValue = 10 * COIN; | tx6.vout[1].nValue = 10 * COIN.GetSatoshis(); | ||||
CMutableTransaction tx7 = CMutableTransaction(); | CMutableTransaction tx7 = CMutableTransaction(); | ||||
tx7.vin.resize(2); | tx7.vin.resize(2); | ||||
tx7.vin[0].prevout = COutPoint(tx5.GetId(), 0); | tx7.vin[0].prevout = COutPoint(tx5.GetId(), 0); | ||||
tx7.vin[0].scriptSig = CScript() << OP_5; | tx7.vin[0].scriptSig = CScript() << OP_5; | ||||
tx7.vin[1].prevout = COutPoint(tx6.GetId(), 0); | tx7.vin[1].prevout = COutPoint(tx6.GetId(), 0); | ||||
tx7.vin[1].scriptSig = CScript() << OP_6; | tx7.vin[1].scriptSig = CScript() << OP_6; | ||||
tx7.vout.resize(2); | tx7.vout.resize(2); | ||||
tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL; | tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL; | ||||
tx7.vout[0].nValue = 10 * COIN; | tx7.vout[0].nValue = 10 * COIN.GetSatoshis(); | ||||
tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL; | tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL; | ||||
tx7.vout[1].nValue = 10 * COIN; | tx7.vout[1].nValue = 10 * COIN.GetSatoshis(); | ||||
pool.addUnchecked(tx4.GetId(), entry.Fee(7000LL).FromTx(tx4, &pool)); | pool.addUnchecked(tx4.GetId(), entry.Fee(7000LL).FromTx(tx4, &pool)); | ||||
pool.addUnchecked(tx5.GetId(), entry.Fee(1000LL).FromTx(tx5, &pool)); | pool.addUnchecked(tx5.GetId(), entry.Fee(1000LL).FromTx(tx5, &pool)); | ||||
pool.addUnchecked(tx6.GetId(), entry.Fee(1100LL).FromTx(tx6, &pool)); | pool.addUnchecked(tx6.GetId(), entry.Fee(1100LL).FromTx(tx6, &pool)); | ||||
pool.addUnchecked(tx7.GetId(), entry.Fee(9000LL).FromTx(tx7, &pool)); | pool.addUnchecked(tx7.GetId(), entry.Fee(9000LL).FromTx(tx7, &pool)); | ||||
// we only require this remove, at max, 2 txn, because its not clear what | // we only require this remove, at max, 2 txn, because its not clear what | ||||
// we're really optimizing for aside from that | // we're really optimizing for aside from that | ||||
▲ Show 20 Lines • Show All 62 Lines • Show Last 20 Lines |