Changeset View
Changeset View
Standalone View
Standalone View
src/test/mempool_tests.cpp
Show All 12 Lines | |||||
#include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||
#include <algorithm> | #include <algorithm> | ||||
#include <vector> | #include <vector> | ||||
BOOST_FIXTURE_TEST_SUITE(mempool_tests, TestingSetup) | BOOST_FIXTURE_TEST_SUITE(mempool_tests, TestingSetup) | ||||
// this test should be removed after wellington is checkpointed | |||||
BOOST_AUTO_TEST_CASE(TestPreAndPostWellingtonAccounting) { | |||||
for (const bool wellington : {false, true}) { | |||||
CTxMemPool testPool; | |||||
// test pre-wellington versus post-wellington behavior | |||||
testPool.wellingtonLatched = wellington; | |||||
LOCK2(cs_main, testPool.cs); | |||||
TestMemPoolEntryHelper entry; | |||||
CMutableTransaction parentOfAll; | |||||
// Vector to track unspent outputs that are used to construct txs | |||||
std::vector<CTxIn> outpoints; | |||||
const size_t maxOutputs = 3; | |||||
// Construct a parent for the rest of the chain | |||||
parentOfAll.vin.resize(1); | |||||
parentOfAll.vin[0].scriptSig = CScript(); | |||||
// Give us a couple outpoints so we can spend them | |||||
for (size_t i = 0; i < maxOutputs; i++) { | |||||
parentOfAll.vout.emplace_back(10 * SATOSHI, CScript() << OP_TRUE); | |||||
} | |||||
TxId parentOfAllId = parentOfAll.GetId(); | |||||
testPool.addUnchecked(entry.SigChecks(0).FromTx(parentOfAll)); | |||||
// Add some outpoints to the tracking vector | |||||
for (size_t i = 0; i < maxOutputs; i++) { | |||||
outpoints.emplace_back(COutPoint(parentOfAllId, i)); | |||||
} | |||||
Amount totalFee = Amount::zero(); | |||||
size_t totalSize = CTransaction(parentOfAll).GetTotalSize(); | |||||
size_t totalVirtualSize = totalSize; | |||||
int64_t totalSigChecks = 0; | |||||
// Generate 100 transactions | |||||
for (size_t totalTransactions = 0; totalTransactions < 100; | |||||
totalTransactions++) { | |||||
CMutableTransaction tx; | |||||
uint64_t minAncestors = std::numeric_limits<size_t>::max(); | |||||
uint64_t maxAncestors = 0; | |||||
Amount minFees = MAX_MONEY; | |||||
Amount maxFees = Amount::zero(); | |||||
uint64_t minSize = std::numeric_limits<size_t>::max(); | |||||
uint64_t maxSize = 0; | |||||
uint64_t minVirtualSize = std::numeric_limits<size_t>::max(); | |||||
uint64_t maxVirtualSize = 0; | |||||
int64_t minSigChecks = std::numeric_limits<int64_t>::max(); | |||||
int64_t maxSigChecks = 0; | |||||
// Consume random inputs, but make sure we don't consume more than | |||||
// available | |||||
for (size_t input = std::min(InsecureRandRange(maxOutputs) + 1, | |||||
uint64_t(outpoints.size())); | |||||
input > 0; input--) { | |||||
std::swap(outpoints[InsecureRandRange(outpoints.size())], | |||||
outpoints.back()); | |||||
tx.vin.emplace_back(outpoints.back()); | |||||
outpoints.pop_back(); | |||||
// We don't know exactly how many ancestors this transaction has | |||||
// due to possible duplicates. Calculate a valid range based on | |||||
// parents. | |||||
const CTxMemPoolEntry &parent = | |||||
*testPool.mapTx.find(tx.vin.back().prevout.GetTxId()); | |||||
minAncestors = | |||||
std::min(minAncestors, parent.GetCountWithAncestors()); | |||||
maxAncestors += parent.GetCountWithAncestors(); | |||||
minFees = std::min(minFees, parent.GetModFeesWithAncestors()); | |||||
maxFees += parent.GetModFeesWithAncestors(); | |||||
minSize = std::min(minSize, parent.GetSizeWithAncestors()); | |||||
maxSize += parent.GetSizeWithAncestors(); | |||||
minVirtualSize = | |||||
std::min(minSize, parent.GetVirtualSizeWithAncestors()); | |||||
maxVirtualSize += parent.GetVirtualSizeWithAncestors(); | |||||
minSigChecks = | |||||
std::min(minSigChecks, parent.GetSigChecksWithAncestors()); | |||||
maxSigChecks += parent.GetSigChecksWithAncestors(); | |||||
} | |||||
// Produce random number of outputs | |||||
for (size_t output = InsecureRandRange(maxOutputs) + 1; output > 0; | |||||
output--) { | |||||
tx.vout.emplace_back(10 * SATOSHI, CScript() << OP_TRUE); | |||||
} | |||||
TxId curId = tx.GetId(); | |||||
// Record the outputs | |||||
for (size_t output = tx.vout.size(); output > 0; output--) { | |||||
outpoints.emplace_back(COutPoint(curId, output)); | |||||
} | |||||
const Amount randFee = int64_t(InsecureRandRange(300)) * SATOSHI; | |||||
const int randSigChecks = InsecureRandRange(5); | |||||
testPool.addUnchecked( | |||||
entry.Fee(randFee).SigChecks(randSigChecks).FromTx(tx)); | |||||
// Add this transaction to the totals. | |||||
minAncestors += 1; | |||||
maxAncestors += 1; | |||||
minFees += randFee; | |||||
maxFees += randFee; | |||||
minSize += CTransaction(tx).GetTotalSize(); | |||||
maxSize += CTransaction(tx).GetTotalSize(); | |||||
// virtualsize is a nonlinear function of its arguments, so we can't | |||||
// make as strong guarantees about its range; but assuming | |||||
// virtualsize is monotonically increasing in each argument, we can | |||||
// say the following: | |||||
minVirtualSize += 0; | |||||
maxVirtualSize += GetVirtualTransactionSize( | |||||
CTransaction(tx).GetTotalSize(), randSigChecks); | |||||
minSigChecks += randSigChecks; | |||||
maxSigChecks += randSigChecks; | |||||
// Calculate overall values | |||||
totalFee += randFee; | |||||
totalSize += CTransaction(tx).GetTotalSize(); | |||||
totalVirtualSize += GetVirtualTransactionSize( | |||||
CTransaction(tx).GetTotalSize(), randSigChecks); | |||||
totalSigChecks += randSigChecks; | |||||
const CTxMemPoolEntry &parentEntry = | |||||
*testPool.mapTx.find(parentOfAllId); | |||||
const CTxMemPoolEntry &latestEntry = *testPool.mapTx.find(curId); | |||||
// Based on size/sigChecks ranges we can compute more strict bounds | |||||
// for the virtual size ranges/totals, assuming virtualsize is | |||||
// monotonic in each argument. | |||||
uint64_t minVirtualSize_strict = | |||||
GetVirtualTransactionSize(minSize, minSigChecks); | |||||
uint64_t maxVirtualSize_strict = | |||||
GetVirtualTransactionSize(maxSize, maxSigChecks); | |||||
uint64_t totalVirtualSize_strict = | |||||
GetVirtualTransactionSize(totalSize, totalSigChecks); | |||||
if (!wellington) { | |||||
// these are as-good or better than the earlier estimations. | |||||
BOOST_CHECK(minVirtualSize_strict >= minVirtualSize); | |||||
BOOST_CHECK(maxVirtualSize_strict <= maxVirtualSize); | |||||
BOOST_CHECK(totalVirtualSize_strict <= totalVirtualSize); | |||||
// Ensure values are within the expected ranges | |||||
BOOST_CHECK(latestEntry.GetCountWithAncestors() >= | |||||
minAncestors); | |||||
BOOST_CHECK(latestEntry.GetCountWithAncestors() <= | |||||
maxAncestors); | |||||
BOOST_CHECK(latestEntry.GetSizeWithAncestors() >= minSize); | |||||
BOOST_CHECK(latestEntry.GetSizeWithAncestors() <= maxSize); | |||||
BOOST_CHECK(latestEntry.GetVirtualSizeWithAncestors() >= | |||||
minVirtualSize_strict); | |||||
BOOST_CHECK(latestEntry.GetVirtualSizeWithAncestors() <= | |||||
maxVirtualSize_strict); | |||||
BOOST_CHECK(latestEntry.GetSigChecksWithAncestors() >= | |||||
minSigChecks); | |||||
BOOST_CHECK(latestEntry.GetSigChecksWithAncestors() <= | |||||
maxSigChecks); | |||||
BOOST_CHECK(latestEntry.GetModFeesWithAncestors() >= minFees); | |||||
BOOST_CHECK(latestEntry.GetModFeesWithAncestors() <= maxFees); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetCountWithDescendants(), | |||||
testPool.mapTx.size()); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetSizeWithDescendants(), | |||||
totalSize); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetVirtualSizeWithDescendants(), | |||||
totalVirtualSize_strict); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetModFeesWithDescendants(), | |||||
totalFee); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetSigChecksWithDescendants(), | |||||
totalSigChecks); | |||||
} else { | |||||
// with wellington latched, we stop tracking these -- they stay | |||||
// at their defaults | |||||
BOOST_CHECK_EQUAL(latestEntry.GetCountWithAncestors(), 1); | |||||
BOOST_CHECK_EQUAL(latestEntry.GetSizeWithAncestors(), | |||||
latestEntry.GetTxSize()); | |||||
BOOST_CHECK_EQUAL(latestEntry.GetVirtualSizeWithAncestors(), | |||||
latestEntry.GetTxVirtualSize()); | |||||
BOOST_CHECK_EQUAL(latestEntry.GetSigChecksWithAncestors(), | |||||
latestEntry.GetSigChecks()); | |||||
BOOST_CHECK_EQUAL(latestEntry.GetModFeesWithAncestors(), | |||||
latestEntry.GetModifiedFee()); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetCountWithDescendants(), 1); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetSizeWithDescendants(), | |||||
parentEntry.GetTxSize()); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetVirtualSizeWithDescendants(), | |||||
parentEntry.GetTxVirtualSize()); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetModFeesWithDescendants(), | |||||
parentEntry.GetModifiedFee()); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetSigChecks(), 0); | |||||
BOOST_CHECK_EQUAL(parentEntry.GetSigChecksWithDescendants(), 0); | |||||
} | |||||
// Verify that wellington activation status didn't accidentally | |||||
// change during the test. | |||||
BOOST_CHECK_EQUAL(testPool.wellingtonLatched, wellington); | |||||
} | |||||
} | |||||
} | |||||
static constexpr auto REMOVAL_REASON_DUMMY = MemPoolRemovalReason::REPLACED; | static constexpr auto REMOVAL_REASON_DUMMY = MemPoolRemovalReason::REPLACED; | ||||
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; | ||||
▲ Show 20 Lines • Show All 466 Lines • ▼ Show 20 Lines | make_tx(std::vector<Amount> &&output_values, | ||||
} | } | ||||
for (size_t i = 0; i < output_values.size(); ++i) { | for (size_t i = 0; i < output_values.size(); ++i) { | ||||
tx.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | tx.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL; | ||||
tx.vout[i].nValue = output_values[i]; | tx.vout[i].nValue = output_values[i]; | ||||
} | } | ||||
return MakeTransactionRef(tx); | return MakeTransactionRef(tx); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(MempoolAncestryTests) { | |||||
size_t ancestors, descendants; | |||||
CTxMemPool pool; | |||||
LOCK2(cs_main, pool.cs); | |||||
TestMemPoolEntryHelper entry; | |||||
/* Base transaction */ | |||||
// | |||||
// [tx1] | |||||
// | |||||
CTransactionRef tx1 = make_tx(/* output_values */ {10 * COIN}); | |||||
pool.addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(tx1)); | |||||
// Ancestors / descendants should be 1 / 1 (itself / itself) | |||||
pool.GetTransactionAncestry(tx1->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 1ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 1ULL); | |||||
/* Child transaction */ | |||||
// | |||||
// [tx1].0 <- [tx2] | |||||
// | |||||
CTransactionRef tx2 = | |||||
make_tx(/* output_values */ {495 * CENT, 5 * COIN}, /* inputs */ {tx1}); | |||||
pool.addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(tx2)); | |||||
// Ancestors / descendants should be: | |||||
// transaction ancestors descendants | |||||
// ============ =========== =========== | |||||
// tx1 1 (tx1) 2 (tx1,2) | |||||
// tx2 2 (tx1,2) 2 (tx1,2) | |||||
pool.GetTransactionAncestry(tx1->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 1ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 2ULL); | |||||
pool.GetTransactionAncestry(tx2->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 2ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 2ULL); | |||||
/* Grand-child 1 */ | |||||
// | |||||
// [tx1].0 <- [tx2].0 <- [tx3] | |||||
// | |||||
CTransactionRef tx3 = make_tx(/* output_values */ {290 * CENT, 200 * CENT}, | |||||
/* inputs */ {tx2}); | |||||
pool.addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(tx3)); | |||||
// Ancestors / descendants should be: | |||||
// transaction ancestors descendants | |||||
// ============ =========== =========== | |||||
// tx1 1 (tx1) 3 (tx1,2,3) | |||||
// tx2 2 (tx1,2) 3 (tx1,2,3) | |||||
// tx3 3 (tx1,2,3) 3 (tx1,2,3) | |||||
pool.GetTransactionAncestry(tx1->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 1ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 3ULL); | |||||
pool.GetTransactionAncestry(tx2->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 2ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 3ULL); | |||||
pool.GetTransactionAncestry(tx3->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 3ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 3ULL); | |||||
/* Grand-child 2 */ | |||||
// | |||||
// [tx1].0 <- [tx2].0 <- [tx3] | |||||
// | | |||||
// \---1 <- [tx4] | |||||
// | |||||
CTransactionRef tx4 = make_tx(/* output_values */ {290 * CENT, 250 * CENT}, | |||||
/* inputs */ {tx2}, /* input_indices */ {1}); | |||||
pool.addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(tx4)); | |||||
// Ancestors / descendants should be: | |||||
// transaction ancestors descendants | |||||
// ============ =========== =========== | |||||
// tx1 1 (tx1) 4 (tx1,2,3,4) | |||||
// tx2 2 (tx1,2) 4 (tx1,2,3,4) | |||||
// tx3 3 (tx1,2,3) 4 (tx1,2,3,4) | |||||
// tx4 3 (tx1,2,4) 4 (tx1,2,3,4) | |||||
pool.GetTransactionAncestry(tx1->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 1ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 4ULL); | |||||
pool.GetTransactionAncestry(tx2->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 2ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 4ULL); | |||||
pool.GetTransactionAncestry(tx3->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 3ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 4ULL); | |||||
pool.GetTransactionAncestry(tx4->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 3ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 4ULL); | |||||
/* Make an alternate branch that is longer and connect it to tx3 */ | |||||
// | |||||
// [ty1].0 <- [ty2].0 <- [ty3].0 <- [ty4].0 <- [ty5].0 | |||||
// | | |||||
// [tx1].0 <- [tx2].0 <- [tx3].0 <- [ty6] --->--/ | |||||
// | | |||||
// \---1 <- [tx4] | |||||
// | |||||
CTransactionRef ty1, ty2, ty3, ty4, ty5; | |||||
CTransactionRef *ty[5] = {&ty1, &ty2, &ty3, &ty4, &ty5}; | |||||
Amount v = 5 * COIN; | |||||
for (uint64_t i = 0; i < 5; i++) { | |||||
CTransactionRef &tyi = *ty[i]; | |||||
tyi = make_tx(/* output_values */ {v}, | |||||
/* inputs */ i > 0 | |||||
? std::vector<CTransactionRef>{*ty[i - 1]} | |||||
: std::vector<CTransactionRef>{}); | |||||
v -= 50 * CENT; | |||||
pool.addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(tyi)); | |||||
pool.GetTransactionAncestry(tyi->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, i + 1); | |||||
BOOST_CHECK_EQUAL(descendants, i + 1); | |||||
} | |||||
CTransactionRef ty6 = | |||||
make_tx(/* output_values */ {5 * COIN}, /* inputs */ {tx3, ty5}); | |||||
pool.addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(ty6)); | |||||
// Ancestors / descendants should be: | |||||
// transaction ancestors descendants | |||||
// ============ =================== =========== | |||||
// tx1 1 (tx1) 5 (tx1,2,3,4, ty6) | |||||
// tx2 2 (tx1,2) 5 (tx1,2,3,4, ty6) | |||||
// tx3 3 (tx1,2,3) 5 (tx1,2,3,4, ty6) | |||||
// tx4 3 (tx1,2,4) 5 (tx1,2,3,4, ty6) | |||||
// ty1 1 (ty1) 6 (ty1,2,3,4,5,6) | |||||
// ty2 2 (ty1,2) 6 (ty1,2,3,4,5,6) | |||||
// ty3 3 (ty1,2,3) 6 (ty1,2,3,4,5,6) | |||||
// ty4 4 (y1234) 6 (ty1,2,3,4,5,6) | |||||
// ty5 5 (y12345) 6 (ty1,2,3,4,5,6) | |||||
// ty6 9 (tx123, ty123456) 6 (ty1,2,3,4,5,6) | |||||
pool.GetTransactionAncestry(tx1->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 1ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 5ULL); | |||||
pool.GetTransactionAncestry(tx2->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 2ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 5ULL); | |||||
pool.GetTransactionAncestry(tx3->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 3ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 5ULL); | |||||
pool.GetTransactionAncestry(tx4->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 3ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 5ULL); | |||||
pool.GetTransactionAncestry(ty1->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 1ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 6ULL); | |||||
pool.GetTransactionAncestry(ty2->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 2ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 6ULL); | |||||
pool.GetTransactionAncestry(ty3->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 3ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 6ULL); | |||||
pool.GetTransactionAncestry(ty4->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 4ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 6ULL); | |||||
pool.GetTransactionAncestry(ty5->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 5ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 6ULL); | |||||
pool.GetTransactionAncestry(ty6->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 9ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 6ULL); | |||||
/* Ancestors represented more than once ("diamond") */ | |||||
// | |||||
// [ta].0 <- [tb].0 -----<------- [td].0 | |||||
// | | | |||||
// \---1 <- [tc].0 --<--/ | |||||
// | |||||
CTransactionRef ta, tb, tc, td; | |||||
ta = make_tx(/* output_values */ {10 * COIN}); | |||||
tb = make_tx(/* output_values */ {5 * COIN, 3 * COIN}, /* inputs */ {ta}); | |||||
tc = make_tx(/* output_values */ {2 * COIN}, /* inputs */ {tb}, | |||||
/* input_indices */ {1}); | |||||
td = make_tx(/* output_values */ {6 * COIN}, /* inputs */ {tb, tc}, | |||||
/* input_indices */ {0, 0}); | |||||
pool.clear(); | |||||
pool.addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(ta)); | |||||
pool.addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(tb)); | |||||
pool.addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(tc)); | |||||
pool.addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(td)); | |||||
// Ancestors / descendants should be: | |||||
// transaction ancestors descendants | |||||
// ============ =================== =========== | |||||
// ta 1 (ta 4 (ta,tb,tc,td) | |||||
// tb 2 (ta,tb) 4 (ta,tb,tc,td) | |||||
// tc 3 (ta,tb,tc) 4 (ta,tb,tc,td) | |||||
// td 4 (ta,tb,tc,td) 4 (ta,tb,tc,td) | |||||
pool.GetTransactionAncestry(ta->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 1ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 4ULL); | |||||
pool.GetTransactionAncestry(tb->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 2ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 4ULL); | |||||
pool.GetTransactionAncestry(tc->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 3ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 4ULL); | |||||
pool.GetTransactionAncestry(td->GetId(), ancestors, descendants); | |||||
BOOST_CHECK_EQUAL(ancestors, 4ULL); | |||||
BOOST_CHECK_EQUAL(descendants, 4ULL); | |||||
} | |||||
BOOST_AUTO_TEST_CASE(GetModifiedFeeRateTest) { | BOOST_AUTO_TEST_CASE(GetModifiedFeeRateTest) { | ||||
CMutableTransaction tx = CMutableTransaction(); | CMutableTransaction tx = CMutableTransaction(); | ||||
tx.vin.resize(1); | tx.vin.resize(1); | ||||
// Make tx exactly 1000 bytes. | // Make tx exactly 1000 bytes. | ||||
const size_t dummyDataSize = | const size_t dummyDataSize = | ||||
1000 - | 1000 - | ||||
(GetSerializeSize(tx, PROTOCOL_VERSION) + 5 /* OP_PUSHDATA2 and ?? */); | (GetSerializeSize(tx, PROTOCOL_VERSION) + 5 /* OP_PUSHDATA2 and ?? */); | ||||
▲ Show 20 Lines • Show All 74 Lines • Show Last 20 Lines |