mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-09 06:09:48 +02:00
Merge bitcoin/bitcoin#33591: Cluster mempool followups
b8d279a81cdoc: add comment to explain correctness of GatherClusters() (Suhas Daftuar)aba7500a30Fix parameter name in getmempoolcluster rpc (Suhas Daftuar)6c1325a091Rename weight -> clusterweight in RPC output, and add doc explaining mempool terminology (Suhas Daftuar)bc2eb931daRequire mempool lock to be held when invoking TRUC checks (Suhas Daftuar)957ae23241Improve comments for getTransactionAncestry to reference cluster counts instead of descendants (Suhas Daftuar)d97d6199ceFix comment to reference cluster limits, not chain limits (Suhas Daftuar)a1b341ef98Sanity check feerate diagram in CTxMemPool::check() (Suhas Daftuar)23d6f457c4rpc: improve getmempoolcluster output (Suhas Daftuar)d2dcd37aacAvoid using mapTx.modify() to update modified fees (Suhas Daftuar)d84ffc24d2doc: add release notes snippet for cluster mempool (Suhas Daftuar)b0417ba944doc: Add design notes for cluster mempool and explain new mempool limits (Suhas Daftuar)2d88966e43miner: replace "package" with "chunk" (Suhas Daftuar)6f3e8eb300Add a GetFeePerVSize() accessor to CFeeRate, and use it in the BlockAssembler (Suhas Daftuar)b5f245f6f2Remove unused DEFAULT_ANCESTOR_SIZE_LIMIT_KVB and DEFAULT_DESCENDANT_SIZE_LIMIT_KVB (Suhas Daftuar)1dac54d506Use cluster size limit instead of ancestor size limit in txpackage unit test (Suhas Daftuar)04f65488caUse cluster size limit instead of ancestor/descendant size limits when sanity checking TRUC policy limits (Suhas Daftuar)634291a7dcUse cluster limits instead of ancestor/descendant limits when sanity checking package policy limits (Suhas Daftuar)fc18ef1f3fRemove ancestor and descendant vsize limits from MemPoolLimits (Suhas Daftuar)ed8e819121Warn user if using -limitancestorsize/-limitdescendantsize that the options have no effect (Suhas Daftuar)80d8df2d47Invoke removeUnchecked() directly in removeForBlock() (Suhas Daftuar)9292570f4cRewrite GetChildren without sets (Suhas Daftuar)3e39ea8c30Rewrite removeForReorg to avoid using sets (Suhas Daftuar)a3c31dfd71scripted-diff: rename AddToMempool -> TryAddToMempool (Suhas Daftuar)a5a7905d83Simplify removeRecursive (Suhas Daftuar)01d8520038Remove unused argument to RemoveStaged (Suhas Daftuar)bc64013e6fRemove unused variable (cacheMap) in mempool (Suhas Daftuar) Pull request description: As suggested in the main cluster mempool PR (https://github.com/bitcoin/bitcoin/pull/28676#pullrequestreview-3177119367), I've pulled out some of the non-essential optimizations and cleanups into this separate PR. Will continue to add more commits here to address non-blocking suggestions/improvements as they come up. ACKs for top commit: instagibbs: ACKb8d279a81csipa: ACKb8d279a81cTree-SHA512: 1a05e99eaf8db2e274a1801307fed5d82f8f917e75ccb9ab0e1b0eb2f9672b13c79d691d78ea7cd96900d0e7d5031a3dd582ebcccc9b1d66eb7455b1d3642235
This commit is contained in:
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
|
||||
CBlock block(BuildBlockTestCase(rand_ctx));
|
||||
|
||||
LOCK2(cs_main, pool.cs);
|
||||
AddToMempool(pool, entry.FromTx(block.vtx[2]));
|
||||
TryAddToMempool(pool, entry.FromTx(block.vtx[2]));
|
||||
BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
|
||||
|
||||
// Do a simple ShortTxIDs RT
|
||||
@@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
|
||||
CBlock block(BuildBlockTestCase(rand_ctx));
|
||||
|
||||
LOCK2(cs_main, pool.cs);
|
||||
AddToMempool(pool, entry.FromTx(block.vtx[2]));
|
||||
TryAddToMempool(pool, entry.FromTx(block.vtx[2]));
|
||||
BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
|
||||
|
||||
Txid txhash;
|
||||
@@ -222,7 +222,7 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
|
||||
CBlock block(BuildBlockTestCase(rand_ctx));
|
||||
|
||||
LOCK2(cs_main, pool.cs);
|
||||
AddToMempool(pool, entry.FromTx(block.vtx[1]));
|
||||
TryAddToMempool(pool, entry.FromTx(block.vtx[1]));
|
||||
BOOST_CHECK_EQUAL(pool.get(block.vtx[1]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
|
||||
|
||||
Txid txhash;
|
||||
@@ -322,7 +322,7 @@ BOOST_AUTO_TEST_CASE(ReceiveWithExtraTransactions) {
|
||||
extra_txn.resize(10);
|
||||
|
||||
LOCK2(cs_main, pool.cs);
|
||||
AddToMempool(pool, entry.FromTx(block.vtx[2]));
|
||||
TryAddToMempool(pool, entry.FromTx(block.vtx[2]));
|
||||
BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
|
||||
// Ensure the non_block_tx is actually not in the block
|
||||
for (const auto &block_tx : block.vtx) {
|
||||
|
||||
@@ -67,7 +67,7 @@ FUZZ_TARGET(mini_miner, .init = initialize_miner)
|
||||
TestMemPoolEntryHelper entry;
|
||||
const CAmount fee{ConsumeMoney(fuzzed_data_provider, /*max=*/MAX_MONEY/100000)};
|
||||
assert(MoneyRange(fee));
|
||||
AddToMempool(pool, entry.Fee(fee).FromTx(tx));
|
||||
TryAddToMempool(pool, entry.Fee(fee).FromTx(tx));
|
||||
|
||||
// All outputs are available to spend
|
||||
for (uint32_t n{0}; n < num_outputs; ++n) {
|
||||
|
||||
@@ -122,9 +122,7 @@ std::unique_ptr<CTxMemPool> MakeMempool(FuzzedDataProvider& fuzzed_data_provider
|
||||
|
||||
// ...override specific options for this specific fuzz suite
|
||||
mempool_opts.limits.ancestor_count = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 50);
|
||||
mempool_opts.limits.ancestor_size_vbytes = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 202) * 1'000;
|
||||
mempool_opts.limits.descendant_count = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 50);
|
||||
mempool_opts.limits.descendant_size_vbytes = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 202) * 1'000;
|
||||
mempool_opts.max_size_bytes = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 200) * 1'000'000;
|
||||
mempool_opts.expiry = std::chrono::hours{fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 999)};
|
||||
// Only interested in 2 cases: sigop cost 0 or when single legacy sigop cost is >> 1KvB
|
||||
|
||||
@@ -81,7 +81,7 @@ FUZZ_TARGET(partially_downloaded_block, .init = initialize_pdb)
|
||||
|
||||
if (add_to_mempool && !pool.exists(tx->GetHash())) {
|
||||
LOCK2(cs_main, pool.cs);
|
||||
AddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, *tx));
|
||||
TryAddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, *tx));
|
||||
available.insert(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,14 +75,14 @@ FUZZ_TARGET(rbf, .init = initialize_rbf)
|
||||
}
|
||||
LOCK2(cs_main, pool.cs);
|
||||
if (!pool.GetIter(another_tx.GetHash())) {
|
||||
AddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, another_tx));
|
||||
TryAddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, another_tx));
|
||||
}
|
||||
}
|
||||
const CTransaction tx{*mtx};
|
||||
if (fuzzed_data_provider.ConsumeBool()) {
|
||||
LOCK2(cs_main, pool.cs);
|
||||
if (!pool.GetIter(tx.GetHash())) {
|
||||
AddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, tx));
|
||||
TryAddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, tx));
|
||||
}
|
||||
}
|
||||
{
|
||||
@@ -143,7 +143,7 @@ FUZZ_TARGET(package_rbf, .init = initialize_package_rbf)
|
||||
break;
|
||||
}
|
||||
assert(!pool.GetIter(parent_entry.GetTx().GetHash()));
|
||||
AddToMempool(pool, parent_entry);
|
||||
TryAddToMempool(pool, parent_entry);
|
||||
|
||||
// It's possible that adding this to the mempool failed due to cluster
|
||||
// size limits; if so bail out.
|
||||
@@ -162,7 +162,7 @@ FUZZ_TARGET(package_rbf, .init = initialize_package_rbf)
|
||||
break;
|
||||
}
|
||||
if (!pool.GetIter(child_entry.GetTx().GetHash())) {
|
||||
AddToMempool(pool, child_entry);
|
||||
TryAddToMempool(pool, child_entry);
|
||||
// Adding this transaction to the mempool may fail due to cluster
|
||||
// size limits; if so bail out.
|
||||
if(!pool.GetIter(child_entry.GetTx().GetHash())) {
|
||||
|
||||
@@ -72,17 +72,17 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
|
||||
BOOST_CHECK_EQUAL(testPool.size(), poolSize);
|
||||
|
||||
// Just the parent:
|
||||
AddToMempool(testPool, entry.FromTx(txParent));
|
||||
TryAddToMempool(testPool, entry.FromTx(txParent));
|
||||
poolSize = testPool.size();
|
||||
testPool.removeRecursive(CTransaction(txParent), REMOVAL_REASON_DUMMY);
|
||||
BOOST_CHECK_EQUAL(testPool.size(), poolSize - 1);
|
||||
|
||||
// Parent, children, grandchildren:
|
||||
AddToMempool(testPool, entry.FromTx(txParent));
|
||||
TryAddToMempool(testPool, entry.FromTx(txParent));
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
AddToMempool(testPool, entry.FromTx(txChild[i]));
|
||||
AddToMempool(testPool, entry.FromTx(txGrandChild[i]));
|
||||
TryAddToMempool(testPool, entry.FromTx(txChild[i]));
|
||||
TryAddToMempool(testPool, entry.FromTx(txGrandChild[i]));
|
||||
}
|
||||
// Remove Child[0], GrandChild[0] should be removed:
|
||||
poolSize = testPool.size();
|
||||
@@ -104,8 +104,8 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
|
||||
// Add children and grandchildren, but NOT the parent (simulate the parent being in a block)
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
AddToMempool(testPool, entry.FromTx(txChild[i]));
|
||||
AddToMempool(testPool, entry.FromTx(txGrandChild[i]));
|
||||
TryAddToMempool(testPool, entry.FromTx(txChild[i]));
|
||||
TryAddToMempool(testPool, entry.FromTx(txGrandChild[i]));
|
||||
}
|
||||
// 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):
|
||||
@@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||
tx1.vout.resize(1);
|
||||
tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
|
||||
tx1.vout[0].nValue = 10 * COIN;
|
||||
AddToMempool(pool, entry.Fee(1000LL).FromTx(tx1));
|
||||
TryAddToMempool(pool, entry.Fee(1000LL).FromTx(tx1));
|
||||
|
||||
CMutableTransaction tx2 = CMutableTransaction();
|
||||
tx2.vin.resize(1);
|
||||
@@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||
tx2.vout.resize(1);
|
||||
tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
|
||||
tx2.vout[0].nValue = 10 * COIN;
|
||||
AddToMempool(pool, entry.Fee(500LL).FromTx(tx2));
|
||||
TryAddToMempool(pool, entry.Fee(500LL).FromTx(tx2));
|
||||
|
||||
pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing
|
||||
BOOST_CHECK(pool.exists(tx1.GetHash()));
|
||||
@@ -145,7 +145,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||
BOOST_CHECK(pool.exists(tx1.GetHash()));
|
||||
BOOST_CHECK(!pool.exists(tx2.GetHash()));
|
||||
|
||||
AddToMempool(pool, entry.FromTx(tx2));
|
||||
TryAddToMempool(pool, entry.FromTx(tx2));
|
||||
CMutableTransaction tx3 = CMutableTransaction();
|
||||
tx3.vin.resize(1);
|
||||
tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0);
|
||||
@@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||
tx3.vout.resize(1);
|
||||
tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
|
||||
tx3.vout[0].nValue = 10 * COIN;
|
||||
AddToMempool(pool, entry.Fee(2000LL).FromTx(tx3));
|
||||
TryAddToMempool(pool, entry.Fee(2000LL).FromTx(tx3));
|
||||
|
||||
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP)
|
||||
BOOST_CHECK(!pool.exists(tx1.GetHash()));
|
||||
@@ -216,11 +216,11 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||
tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
|
||||
tx7.vout[1].nValue = 10 * COIN;
|
||||
|
||||
AddToMempool(pool, entry.Fee(700LL).FromTx(tx4));
|
||||
TryAddToMempool(pool, entry.Fee(700LL).FromTx(tx4));
|
||||
auto usage_with_tx4_only = pool.DynamicMemoryUsage();
|
||||
AddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
|
||||
AddToMempool(pool, entry.Fee(110LL).FromTx(tx6));
|
||||
AddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
|
||||
TryAddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
|
||||
TryAddToMempool(pool, entry.Fee(110LL).FromTx(tx6));
|
||||
TryAddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
|
||||
|
||||
// From the topology above, tx7 must be sorted last, so it should
|
||||
// definitely evicted first if we must trim. tx4 should definitely remain
|
||||
@@ -234,10 +234,10 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||
// tx7, but this behavior need not be guaranteed.
|
||||
|
||||
if (!pool.exists(tx5.GetHash()))
|
||||
AddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
|
||||
TryAddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
|
||||
if (!pool.exists(tx6.GetHash()))
|
||||
AddToMempool(pool, entry.Fee(110LL).FromTx(tx6));
|
||||
AddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
|
||||
TryAddToMempool(pool, entry.Fee(110LL).FromTx(tx6));
|
||||
TryAddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
|
||||
|
||||
// If we trim sufficiently, everything but tx4 should be removed.
|
||||
pool.TrimToSize(usage_with_tx4_only + 1);
|
||||
@@ -246,9 +246,9 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||
BOOST_CHECK(!pool.exists(tx6.GetHash()));
|
||||
BOOST_CHECK(!pool.exists(tx7.GetHash()));
|
||||
|
||||
AddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
|
||||
AddToMempool(pool, entry.Fee(110LL).FromTx(tx6));
|
||||
AddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
|
||||
TryAddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
|
||||
TryAddToMempool(pool, entry.Fee(110LL).FromTx(tx6));
|
||||
TryAddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
|
||||
|
||||
std::vector<CTransactionRef> vtx;
|
||||
SetMockTime(42);
|
||||
@@ -307,7 +307,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
||||
// [tx1]
|
||||
//
|
||||
CTransactionRef tx1 = make_tx(/*output_values=*/{10 * COIN});
|
||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx1));
|
||||
TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tx1));
|
||||
|
||||
// Ancestors / clustersize should be 1 / 1 (itself / itself)
|
||||
pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize);
|
||||
@@ -319,7 +319,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
||||
// [tx1].0 <- [tx2]
|
||||
//
|
||||
CTransactionRef tx2 = make_tx(/*output_values=*/{495 * CENT, 5 * COIN}, /*inputs=*/{tx1});
|
||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx2));
|
||||
TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tx2));
|
||||
|
||||
// Ancestors / clustersize should be:
|
||||
// transaction ancestors clustersize
|
||||
@@ -338,7 +338,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
||||
// [tx1].0 <- [tx2].0 <- [tx3]
|
||||
//
|
||||
CTransactionRef tx3 = make_tx(/*output_values=*/{290 * CENT, 200 * CENT}, /*inputs=*/{tx2});
|
||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx3));
|
||||
TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tx3));
|
||||
|
||||
// Ancestors / clustersize should be:
|
||||
// transaction ancestors clustersize
|
||||
@@ -363,7 +363,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
||||
// \---1 <- [tx4]
|
||||
//
|
||||
CTransactionRef tx4 = make_tx(/*output_values=*/{290 * CENT, 250 * CENT}, /*inputs=*/{tx2}, /*input_indices=*/{1});
|
||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx4));
|
||||
TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tx4));
|
||||
|
||||
// Ancestors / clustersize should be:
|
||||
// transaction ancestors clustersize
|
||||
@@ -400,13 +400,13 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
||||
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;
|
||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tyi));
|
||||
TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tyi));
|
||||
pool.GetTransactionAncestry(tyi->GetHash(), ancestors, clustersize);
|
||||
BOOST_CHECK_EQUAL(ancestors, i+1);
|
||||
BOOST_CHECK_EQUAL(clustersize, i+1);
|
||||
}
|
||||
CTransactionRef ty6 = make_tx(/*output_values=*/{5 * COIN}, /*inputs=*/{tx3, ty5});
|
||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(ty6));
|
||||
TryAddToMempool(pool, entry.Fee(10000LL).FromTx(ty6));
|
||||
|
||||
// Ancestors / clustersize should be:
|
||||
// transaction ancestors clustersize
|
||||
@@ -472,10 +472,10 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTestsDiamond)
|
||||
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});
|
||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(ta));
|
||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tb));
|
||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tc));
|
||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(td));
|
||||
TryAddToMempool(pool, entry.Fee(10000LL).FromTx(ta));
|
||||
TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tb));
|
||||
TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tc));
|
||||
TryAddToMempool(pool, entry.Fee(10000LL).FromTx(td));
|
||||
|
||||
// Ancestors / descendants should be:
|
||||
// transaction ancestors descendants
|
||||
|
||||
@@ -149,21 +149,21 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
|
||||
// This tx has a low fee: 1000 satoshis
|
||||
Txid hashParentTx = tx.GetHash(); // save this txid for later use
|
||||
const auto parent_tx{entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx)};
|
||||
AddToMempool(tx_mempool, parent_tx);
|
||||
TryAddToMempool(tx_mempool, parent_tx);
|
||||
|
||||
// This tx has a medium fee: 10000 satoshis
|
||||
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
|
||||
tx.vout[0].nValue = 5000000000LL - 10000;
|
||||
Txid hashMediumFeeTx = tx.GetHash();
|
||||
const auto medium_fee_tx{entry.Fee(10000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx)};
|
||||
AddToMempool(tx_mempool, medium_fee_tx);
|
||||
TryAddToMempool(tx_mempool, medium_fee_tx);
|
||||
|
||||
// This tx has a high fee, but depends on the first transaction
|
||||
tx.vin[0].prevout.hash = hashParentTx;
|
||||
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee
|
||||
Txid hashHighFeeTx = tx.GetHash();
|
||||
const auto high_fee_tx{entry.Fee(50000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx)};
|
||||
AddToMempool(tx_mempool, high_fee_tx);
|
||||
TryAddToMempool(tx_mempool, high_fee_tx);
|
||||
|
||||
block_template = mining->createNewBlock(options);
|
||||
BOOST_REQUIRE(block_template);
|
||||
@@ -192,7 +192,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
|
||||
tx.vin[0].prevout.hash = hashHighFeeTx;
|
||||
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee
|
||||
Txid hashFreeTx = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(0).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(0).FromTx(tx));
|
||||
uint64_t freeTxSize{::GetSerializeSize(TX_WITH_WITNESS(tx))};
|
||||
|
||||
// Calculate a fee on child transaction that will put the package just
|
||||
@@ -202,7 +202,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
|
||||
tx.vin[0].prevout.hash = hashFreeTx;
|
||||
tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
|
||||
Txid hashLowFeeTx = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(feeToUse).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(feeToUse).FromTx(tx));
|
||||
|
||||
// waitNext() should return nullptr because there is no better template
|
||||
should_be_nullptr = block_template->waitNext({.timeout = MillisecondsDouble{0}, .fee_threshold = 1});
|
||||
@@ -221,7 +221,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
|
||||
tx_mempool.removeRecursive(CTransaction(tx), MemPoolRemovalReason::REPLACED);
|
||||
tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
|
||||
hashLowFeeTx = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(feeToUse + 2).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(feeToUse + 2).FromTx(tx));
|
||||
|
||||
// waitNext() should return if fees for the new template are at least 1 sat up
|
||||
block_template = block_template->waitNext({.fee_threshold = 1});
|
||||
@@ -243,7 +243,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
|
||||
// hashFreeTx2 + hashLowFeeTx2.
|
||||
BulkTransaction(tx, 4000);
|
||||
Txid hashFreeTx2 = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
|
||||
|
||||
// This tx can't be mined by itself
|
||||
tx.vin[0].prevout.hash = hashFreeTx2;
|
||||
@@ -251,7 +251,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
|
||||
feeToUse = blockMinFeeRate.GetFee(freeTxSize);
|
||||
tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
|
||||
Txid hashLowFeeTx2 = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
|
||||
block_template = mining->createNewBlock(options);
|
||||
BOOST_REQUIRE(block_template);
|
||||
block = block_template->getBlock();
|
||||
@@ -266,7 +266,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
|
||||
// as well.
|
||||
tx.vin[0].prevout.n = 1;
|
||||
tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
|
||||
AddToMempool(tx_mempool, entry.Fee(10000).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(10000).FromTx(tx));
|
||||
block_template = mining->createNewBlock(options);
|
||||
BOOST_REQUIRE(block_template);
|
||||
block = block_template->getBlock();
|
||||
@@ -350,7 +350,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
for (auto& t : txs) {
|
||||
// If we don't set the number of sigops in the CTxMemPoolEntry,
|
||||
// template creation fails during sanity checks.
|
||||
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(t));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(t));
|
||||
legacy_sigops += GetLegacySigOpCount(*t);
|
||||
BOOST_CHECK(tx_mempool.GetIter(t->GetHash()).has_value());
|
||||
}
|
||||
@@ -375,7 +375,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
|
||||
int64_t legacy_sigops = 0;
|
||||
for (auto& t : txs) {
|
||||
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).SigOpsCost(GetLegacySigOpCount(*t)*WITNESS_SCALE_FACTOR).FromTx(t));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).SigOpsCost(GetLegacySigOpCount(*t)*WITNESS_SCALE_FACTOR).FromTx(t));
|
||||
legacy_sigops += GetLegacySigOpCount(*t);
|
||||
BOOST_CHECK(tx_mempool.GetIter(t->GetHash()).has_value());
|
||||
}
|
||||
@@ -408,7 +408,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
hash = tx.GetHash();
|
||||
bool spendsCoinbase = i == 0; // only first tx spends coinbase
|
||||
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
|
||||
BOOST_CHECK(tx_mempool.GetIter(hash).has_value());
|
||||
tx.vin[0].prevout.hash = hash;
|
||||
}
|
||||
@@ -421,7 +421,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
|
||||
// orphan in tx_mempool, template creation fails
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).FromTx(tx));
|
||||
BOOST_CHECK_EXCEPTION(mining->createNewBlock(options), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
|
||||
}
|
||||
|
||||
@@ -434,7 +434,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
|
||||
tx.vout[0].nValue = BLOCKSUBSIDY - HIGHFEE;
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
tx.vin[0].prevout.hash = hash;
|
||||
tx.vin.resize(2);
|
||||
tx.vin[1].scriptSig = CScript() << OP_1;
|
||||
@@ -442,7 +442,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
tx.vin[1].prevout.n = 0;
|
||||
tx.vout[0].nValue = tx.vout[0].nValue + BLOCKSUBSIDY - HIGHERFEE; // First txn output + fresh coinbase - new txn fee
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(HIGHERFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(HIGHERFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
BOOST_REQUIRE(mining->createNewBlock(options));
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
tx.vout[0].nValue = 0;
|
||||
hash = tx.GetHash();
|
||||
// give it a fee so it'll get mined
|
||||
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
|
||||
// Should throw bad-cb-multiple
|
||||
BOOST_CHECK_EXCEPTION(mining->createNewBlock(options), std::runtime_error, HasReason("bad-cb-multiple"));
|
||||
}
|
||||
@@ -472,10 +472,10 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
tx.vout[0].nValue = BLOCKSUBSIDY - HIGHFEE;
|
||||
tx.vout[0].scriptPubKey = CScript() << OP_1;
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
tx.vout[0].scriptPubKey = CScript() << OP_2;
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
BOOST_CHECK_EXCEPTION(mining->createNewBlock(options), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
|
||||
}
|
||||
|
||||
@@ -518,12 +518,12 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
CScript script = CScript() << OP_0;
|
||||
tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script));
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
tx.vin[0].prevout.hash = hash;
|
||||
tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
|
||||
BOOST_CHECK_EXCEPTION(mining->createNewBlock(options), std::runtime_error, HasReason("block-script-verify-flag-failed"));
|
||||
|
||||
// Delete the dummy blocks again.
|
||||
@@ -559,7 +559,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
tx.vout[0].scriptPubKey = CScript() << OP_1;
|
||||
tx.nLockTime = 0;
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
|
||||
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks fail
|
||||
|
||||
@@ -573,7 +573,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1-m_node.chainman->ActiveChain()[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block
|
||||
prevheights[0] = baseheight + 2;
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Time(Now<NodeSeconds>()).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Time(Now<NodeSeconds>()).FromTx(tx));
|
||||
BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
|
||||
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks fail
|
||||
|
||||
@@ -596,7 +596,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
prevheights[0] = baseheight + 3;
|
||||
tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Time(Now<NodeSeconds>()).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Time(Now<NodeSeconds>()).FromTx(tx));
|
||||
BOOST_CHECK(!CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime fails
|
||||
BOOST_CHECK(TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks pass
|
||||
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
|
||||
@@ -611,7 +611,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
prevheights.resize(1);
|
||||
prevheights[0] = baseheight + 4;
|
||||
hash = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Time(Now<NodeSeconds>()).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Time(Now<NodeSeconds>()).FromTx(tx));
|
||||
BOOST_CHECK(!CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime fails
|
||||
BOOST_CHECK(TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks pass
|
||||
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
|
||||
@@ -675,7 +675,7 @@ void MinerTestingSetup::TestPrioritisedMining(const CScript& scriptPubKey, const
|
||||
tx.vout.resize(1);
|
||||
tx.vout[0].nValue = 5000000000LL; // 0 fee
|
||||
Txid hashFreePrioritisedTx = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(0).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(0).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
tx_mempool.PrioritiseTransaction(hashFreePrioritisedTx, 5 * COIN);
|
||||
|
||||
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
|
||||
@@ -683,20 +683,20 @@ void MinerTestingSetup::TestPrioritisedMining(const CScript& scriptPubKey, const
|
||||
tx.vout[0].nValue = 5000000000LL - 1000;
|
||||
// This tx has a low fee: 1000 satoshis
|
||||
Txid hashParentTx = tx.GetHash(); // save this txid for later use
|
||||
AddToMempool(tx_mempool, entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
|
||||
// This tx has a medium fee: 10000 satoshis
|
||||
tx.vin[0].prevout.hash = txFirst[2]->GetHash();
|
||||
tx.vout[0].nValue = 5000000000LL - 10000;
|
||||
Txid hashMediumFeeTx = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(10000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(10000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
|
||||
tx_mempool.PrioritiseTransaction(hashMediumFeeTx, -5 * COIN);
|
||||
|
||||
// This tx also has a low fee, but is prioritised
|
||||
tx.vin[0].prevout.hash = hashParentTx;
|
||||
tx.vout[0].nValue = 5000000000LL - 1000 - 1000; // 1000 satoshi fee
|
||||
Txid hashPrioritsedChild = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
|
||||
tx_mempool.PrioritiseTransaction(hashPrioritsedChild, 2 * COIN);
|
||||
|
||||
// Test that transaction selection properly updates ancestor fee calculations as prioritised
|
||||
@@ -708,19 +708,19 @@ void MinerTestingSetup::TestPrioritisedMining(const CScript& scriptPubKey, const
|
||||
tx.vin[0].prevout.hash = txFirst[3]->GetHash();
|
||||
tx.vout[0].nValue = 5000000000LL; // 0 fee
|
||||
Txid hashFreeParent = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
|
||||
tx_mempool.PrioritiseTransaction(hashFreeParent, 10 * COIN);
|
||||
|
||||
tx.vin[0].prevout.hash = hashFreeParent;
|
||||
tx.vout[0].nValue = 5000000000LL; // 0 fee
|
||||
Txid hashFreeChild = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
|
||||
tx_mempool.PrioritiseTransaction(hashFreeChild, 1 * COIN);
|
||||
|
||||
tx.vin[0].prevout.hash = hashFreeChild;
|
||||
tx.vout[0].nValue = 5000000000LL; // 0 fee
|
||||
Txid hashFreeGrandchild = tx.GetHash();
|
||||
AddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
|
||||
TryAddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
|
||||
|
||||
auto block_template = mining->createNewBlock(options);
|
||||
BOOST_REQUIRE(block_template);
|
||||
|
||||
@@ -84,7 +84,7 @@ BOOST_FIXTURE_TEST_CASE(miniminer_negative, TestChain100Setup)
|
||||
const CAmount negative_modified_fees{positive_base_fee + negative_fee_delta};
|
||||
BOOST_CHECK(negative_modified_fees < 0);
|
||||
const auto tx_mod_negative = make_tx({COutPoint{m_coinbase_txns[4]->GetHash(), 0}}, /*num_outputs=*/1);
|
||||
AddToMempool(pool, entry.Fee(positive_base_fee).FromTx(tx_mod_negative));
|
||||
TryAddToMempool(pool, entry.Fee(positive_base_fee).FromTx(tx_mod_negative));
|
||||
pool.PrioritiseTransaction(tx_mod_negative->GetHash(), negative_fee_delta);
|
||||
const COutPoint only_outpoint{tx_mod_negative->GetHash(), 0};
|
||||
|
||||
@@ -114,21 +114,21 @@ BOOST_FIXTURE_TEST_CASE(miniminer_1p1c, TestChain100Setup)
|
||||
|
||||
// Create a parent tx0 and child tx1 with normal fees:
|
||||
const auto tx0 = make_tx({COutPoint{m_coinbase_txns[0]->GetHash(), 0}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(med_fee).FromTx(tx0));
|
||||
TryAddToMempool(pool, entry.Fee(med_fee).FromTx(tx0));
|
||||
const auto tx1 = make_tx({COutPoint{tx0->GetHash(), 0}}, /*num_outputs=*/1);
|
||||
AddToMempool(pool, entry.Fee(med_fee).FromTx(tx1));
|
||||
TryAddToMempool(pool, entry.Fee(med_fee).FromTx(tx1));
|
||||
|
||||
// Create a low-feerate parent tx2 and high-feerate child tx3 (cpfp)
|
||||
const auto tx2 = make_tx({COutPoint{m_coinbase_txns[1]->GetHash(), 0}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(tx2));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(tx2));
|
||||
const auto tx3 = make_tx({COutPoint{tx2->GetHash(), 0}}, /*num_outputs=*/1);
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(tx3));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(tx3));
|
||||
|
||||
// Create a parent tx4 and child tx5 where both have low fees
|
||||
const auto tx4 = make_tx({COutPoint{m_coinbase_txns[2]->GetHash(), 0}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(tx4));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(tx4));
|
||||
const auto tx5 = make_tx({COutPoint{tx4->GetHash(), 0}}, /*num_outputs=*/1);
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(tx5));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(tx5));
|
||||
const CAmount tx5_delta{CENT/100};
|
||||
// Make tx5's modified fee much higher than its base fee. This should cause it to pass
|
||||
// the fee-related checks despite being low-feerate.
|
||||
@@ -137,9 +137,9 @@ BOOST_FIXTURE_TEST_CASE(miniminer_1p1c, TestChain100Setup)
|
||||
|
||||
// Create a high-feerate parent tx6, low-feerate child tx7
|
||||
const auto tx6 = make_tx({COutPoint{m_coinbase_txns[3]->GetHash(), 0}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(tx6));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(tx6));
|
||||
const auto tx7 = make_tx({COutPoint{tx6->GetHash(), 0}}, /*num_outputs=*/1);
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(tx7));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(tx7));
|
||||
|
||||
std::vector<COutPoint> all_unspent_outpoints({
|
||||
COutPoint{tx0->GetHash(), 1},
|
||||
@@ -405,23 +405,23 @@ BOOST_FIXTURE_TEST_CASE(miniminer_overlap, TestChain100Setup)
|
||||
|
||||
// Create 3 parents of different feerates, and 1 child spending outputs from all 3 parents.
|
||||
const auto tx0 = make_tx({COutPoint{m_coinbase_txns[0]->GetHash(), 0}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(tx0));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(tx0));
|
||||
const auto tx1 = make_tx({COutPoint{m_coinbase_txns[1]->GetHash(), 0}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(med_fee).FromTx(tx1));
|
||||
TryAddToMempool(pool, entry.Fee(med_fee).FromTx(tx1));
|
||||
const auto tx2 = make_tx({COutPoint{m_coinbase_txns[2]->GetHash(), 0}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(tx2));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(tx2));
|
||||
const auto tx3 = make_tx({COutPoint{tx0->GetHash(), 0}, COutPoint{tx1->GetHash(), 0}, COutPoint{tx2->GetHash(), 0}}, /*num_outputs=*/3);
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(tx3));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(tx3));
|
||||
|
||||
// Create 1 grandparent and 1 parent, then 2 children.
|
||||
const auto tx4 = make_tx({COutPoint{m_coinbase_txns[3]->GetHash(), 0}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(tx4));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(tx4));
|
||||
const auto tx5 = make_tx({COutPoint{tx4->GetHash(), 0}}, /*num_outputs=*/3);
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(tx5));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(tx5));
|
||||
const auto tx6 = make_tx({COutPoint{tx5->GetHash(), 0}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(med_fee).FromTx(tx6));
|
||||
TryAddToMempool(pool, entry.Fee(med_fee).FromTx(tx6));
|
||||
const auto tx7 = make_tx({COutPoint{tx5->GetHash(), 1}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(tx7));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(tx7));
|
||||
|
||||
std::vector<CTransactionRef> all_transactions{tx0, tx1, tx2, tx3, tx4, tx5, tx6, tx7};
|
||||
std::vector<int64_t> tx_vsizes;
|
||||
@@ -608,7 +608,7 @@ BOOST_FIXTURE_TEST_CASE(calculate_cluster, TestChain100Setup)
|
||||
lasttx = m_coinbase_txns[cluster_count];
|
||||
for (auto i{0}; i < 50; ++i) {
|
||||
const auto tx = make_tx({COutPoint{lasttx->GetHash(), 0}}, /*num_outputs=*/1);
|
||||
AddToMempool(pool, entry.Fee(CENT).FromTx(tx));
|
||||
TryAddToMempool(pool, entry.Fee(CENT).FromTx(tx));
|
||||
chain_txids.push_back(tx->GetHash());
|
||||
lasttx = tx;
|
||||
}
|
||||
@@ -622,7 +622,7 @@ BOOST_FIXTURE_TEST_CASE(calculate_cluster, TestChain100Setup)
|
||||
|
||||
// GatherClusters stops at 500 transactions.
|
||||
const auto tx_501 = make_tx({COutPoint{lasttx->GetHash(), 0}}, /*num_outputs=*/1);
|
||||
AddToMempool(pool, entry.Fee(CENT).FromTx(tx_501));
|
||||
TryAddToMempool(pool, entry.Fee(CENT).FromTx(tx_501));
|
||||
const auto cluster_501 = pool.GatherClusters(last_txs);
|
||||
BOOST_CHECK_EQUAL(cluster_501.size(), 0);
|
||||
|
||||
@@ -635,12 +635,12 @@ BOOST_FIXTURE_TEST_CASE(calculate_cluster, TestChain100Setup)
|
||||
std::vector<Txid> zigzag_txids;
|
||||
for (auto p{0}; p < 32; ++p) {
|
||||
const auto txp = make_tx({COutPoint{Txid::FromUint256(GetRandHash()), 0}}, /*num_outputs=*/2);
|
||||
AddToMempool(pool, entry.Fee(CENT).FromTx(txp));
|
||||
TryAddToMempool(pool, entry.Fee(CENT).FromTx(txp));
|
||||
zigzag_txids.push_back(txp->GetHash());
|
||||
}
|
||||
for (auto c{0}; c < 31; ++c) {
|
||||
const auto txc = make_tx({COutPoint{zigzag_txids[c], 1}, COutPoint{zigzag_txids[c+1], 0}}, /*num_outputs=*/1);
|
||||
AddToMempool(pool, entry.Fee(CENT).FromTx(txc));
|
||||
TryAddToMempool(pool, entry.Fee(CENT).FromTx(txc));
|
||||
zigzag_txids.push_back(txc->GetHash());
|
||||
}
|
||||
const auto vec_iters_zigzag = pool.GetIterVec(zigzag_txids);
|
||||
|
||||
@@ -63,9 +63,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
|
||||
tx.vin[0].prevout.n = 10000*blocknum+100*j+k; // make transaction unique
|
||||
{
|
||||
LOCK2(cs_main, mpool.cs);
|
||||
AddToMempool(mpool, entry.Fee(feeV[j]).Time(Now<NodeSeconds>()).Height(blocknum).FromTx(tx));
|
||||
TryAddToMempool(mpool, entry.Fee(feeV[j]).Time(Now<NodeSeconds>()).Height(blocknum).FromTx(tx));
|
||||
// Since TransactionAddedToMempool callbacks are generated in ATMP,
|
||||
// not AddToMempool, we cheat and create one manually here
|
||||
// not TryAddToMempool, we cheat and create one manually here
|
||||
const int64_t virtual_size = GetVirtualTransactionSize(*MakeTransactionRef(tx));
|
||||
const NewMempoolTransactionInfo tx_info{NewMempoolTransactionInfo(MakeTransactionRef(tx),
|
||||
feeV[j],
|
||||
@@ -163,9 +163,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
|
||||
tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
|
||||
{
|
||||
LOCK2(cs_main, mpool.cs);
|
||||
AddToMempool(mpool, entry.Fee(feeV[j]).Time(Now<NodeSeconds>()).Height(blocknum).FromTx(tx));
|
||||
TryAddToMempool(mpool, entry.Fee(feeV[j]).Time(Now<NodeSeconds>()).Height(blocknum).FromTx(tx));
|
||||
// Since TransactionAddedToMempool callbacks are generated in ATMP,
|
||||
// not AddToMempool, we cheat and create one manually here
|
||||
// not TryAddToMempool, we cheat and create one manually here
|
||||
const int64_t virtual_size = GetVirtualTransactionSize(*MakeTransactionRef(tx));
|
||||
const NewMempoolTransactionInfo tx_info{NewMempoolTransactionInfo(MakeTransactionRef(tx),
|
||||
feeV[j],
|
||||
@@ -226,9 +226,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
|
||||
tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
|
||||
{
|
||||
LOCK2(cs_main, mpool.cs);
|
||||
AddToMempool(mpool, entry.Fee(feeV[j]).Time(Now<NodeSeconds>()).Height(blocknum).FromTx(tx));
|
||||
TryAddToMempool(mpool, entry.Fee(feeV[j]).Time(Now<NodeSeconds>()).Height(blocknum).FromTx(tx));
|
||||
// Since TransactionAddedToMempool callbacks are generated in ATMP,
|
||||
// not AddToMempool, we cheat and create one manually here
|
||||
// not TryAddToMempool, we cheat and create one manually here
|
||||
const int64_t virtual_size = GetVirtualTransactionSize(*MakeTransactionRef(tx));
|
||||
const NewMempoolTransactionInfo tx_info{NewMempoolTransactionInfo(MakeTransactionRef(tx),
|
||||
feeV[j],
|
||||
|
||||
@@ -47,7 +47,7 @@ static CTransactionRef add_descendants(const CTransactionRef& tx, int32_t num_de
|
||||
auto tx_to_spend = tx;
|
||||
for (int32_t i{0}; i < num_descendants; ++i) {
|
||||
auto next_tx = make_tx(/*inputs=*/{tx_to_spend}, /*output_values=*/{(50 - i) * CENT});
|
||||
AddToMempool(pool, entry.FromTx(next_tx));
|
||||
TryAddToMempool(pool, entry.FromTx(next_tx));
|
||||
BOOST_CHECK(pool.GetIter(next_tx->GetHash()).has_value());
|
||||
tx_to_spend = next_tx;
|
||||
}
|
||||
@@ -67,40 +67,40 @@ BOOST_FIXTURE_TEST_CASE(rbf_helper_functions, TestChain100Setup)
|
||||
|
||||
// Create a parent tx1 and child tx2 with normal fees:
|
||||
const auto tx1 = make_tx(/*inputs=*/ {m_coinbase_txns[0]}, /*output_values=*/ {10 * COIN});
|
||||
AddToMempool(pool, entry.Fee(normal_fee).FromTx(tx1));
|
||||
TryAddToMempool(pool, entry.Fee(normal_fee).FromTx(tx1));
|
||||
const auto tx2 = make_tx(/*inputs=*/ {tx1}, /*output_values=*/ {995 * CENT});
|
||||
AddToMempool(pool, entry.Fee(normal_fee).FromTx(tx2));
|
||||
TryAddToMempool(pool, entry.Fee(normal_fee).FromTx(tx2));
|
||||
|
||||
// Create a low-feerate parent tx3 and high-feerate child tx4 (cpfp)
|
||||
const auto tx3 = make_tx(/*inputs=*/ {m_coinbase_txns[1]}, /*output_values=*/ {1099 * CENT});
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(tx3));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(tx3));
|
||||
const auto tx4 = make_tx(/*inputs=*/ {tx3}, /*output_values=*/ {999 * CENT});
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(tx4));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(tx4));
|
||||
|
||||
// Create a parent tx5 and child tx6 where both have very low fees
|
||||
const auto tx5 = make_tx(/*inputs=*/ {m_coinbase_txns[2]}, /*output_values=*/ {1099 * CENT});
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(tx5));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(tx5));
|
||||
const auto tx6 = make_tx(/*inputs=*/ {tx5}, /*output_values=*/ {1098 * CENT});
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(tx6));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(tx6));
|
||||
// Make tx6's modified fee much higher than its base fee. This should cause it to pass
|
||||
// the fee-related checks despite being low-feerate.
|
||||
pool.PrioritiseTransaction(tx6->GetHash(), 1 * COIN);
|
||||
|
||||
// Two independent high-feerate transactions, tx7 and tx8
|
||||
const auto tx7 = make_tx(/*inputs=*/ {m_coinbase_txns[3]}, /*output_values=*/ {999 * CENT});
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(tx7));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(tx7));
|
||||
const auto tx8 = make_tx(/*inputs=*/ {m_coinbase_txns[4]}, /*output_values=*/ {999 * CENT});
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(tx8));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(tx8));
|
||||
|
||||
// Will make these two parents of single child
|
||||
const auto tx11 = make_tx(/*inputs=*/ {m_coinbase_txns[7]}, /*output_values=*/ {995 * CENT});
|
||||
AddToMempool(pool, entry.Fee(normal_fee).FromTx(tx11));
|
||||
TryAddToMempool(pool, entry.Fee(normal_fee).FromTx(tx11));
|
||||
const auto tx12 = make_tx(/*inputs=*/ {m_coinbase_txns[8]}, /*output_values=*/ {995 * CENT});
|
||||
AddToMempool(pool, entry.Fee(normal_fee).FromTx(tx12));
|
||||
TryAddToMempool(pool, entry.Fee(normal_fee).FromTx(tx12));
|
||||
|
||||
// Will make two children of this single parent
|
||||
const auto tx13 = make_tx(/*inputs=*/ {m_coinbase_txns[9]}, /*output_values=*/ {995 * CENT, 995 * CENT});
|
||||
AddToMempool(pool, entry.Fee(normal_fee).FromTx(tx13));
|
||||
TryAddToMempool(pool, entry.Fee(normal_fee).FromTx(tx13));
|
||||
|
||||
const auto entry1_normal = pool.GetIter(tx1->GetHash()).value();
|
||||
const auto entry2_normal = pool.GetIter(tx2->GetHash()).value();
|
||||
@@ -179,8 +179,8 @@ BOOST_FIXTURE_TEST_CASE(rbf_conflicts_calculator, TestChain100Setup)
|
||||
|
||||
const auto parent_tx_1 = make_tx(/*inputs=*/ {m_coinbase_txns[0]}, /*output_values=*/ output_values);
|
||||
const auto parent_tx_2 = make_tx(/*inputs=*/ {m_coinbase_txns[1]}, /*output_values=*/ output_values);
|
||||
AddToMempool(pool, entry.Fee(normal_fee).FromTx(parent_tx_1));
|
||||
AddToMempool(pool, entry.Fee(normal_fee).FromTx(parent_tx_2));
|
||||
TryAddToMempool(pool, entry.Fee(normal_fee).FromTx(parent_tx_1));
|
||||
TryAddToMempool(pool, entry.Fee(normal_fee).FromTx(parent_tx_2));
|
||||
|
||||
std::vector<CTransactionRef> direct_children;
|
||||
|
||||
@@ -190,7 +190,7 @@ BOOST_FIXTURE_TEST_CASE(rbf_conflicts_calculator, TestChain100Setup)
|
||||
auto pretx = make_tx(/*inputs=*/ {parent_tx}, /*output_values=*/ {995 * CENT});
|
||||
CMutableTransaction tx(*pretx);
|
||||
tx.vin[0].prevout.n = i;
|
||||
AddToMempool(pool, entry.Fee(normal_fee).FromTx(tx));
|
||||
TryAddToMempool(pool, entry.Fee(normal_fee).FromTx(tx));
|
||||
BOOST_CHECK(pool.GetIter(tx.GetHash()).has_value());
|
||||
direct_children.push_back(MakeTransactionRef(tx));
|
||||
}
|
||||
@@ -257,9 +257,9 @@ BOOST_FIXTURE_TEST_CASE(improves_feerate, TestChain100Setup)
|
||||
|
||||
// low feerate parent with normal feerate child
|
||||
const auto tx1 = make_tx(/*inputs=*/ {m_coinbase_txns[0], m_coinbase_txns[1]}, /*output_values=*/ {10 * COIN});
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(tx1));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(tx1));
|
||||
const auto tx2 = make_tx(/*inputs=*/ {tx1}, /*output_values=*/ {995 * CENT});
|
||||
AddToMempool(pool, entry.Fee(normal_fee).FromTx(tx2));
|
||||
TryAddToMempool(pool, entry.Fee(normal_fee).FromTx(tx2));
|
||||
|
||||
const auto entry1 = pool.GetIter(tx1->GetHash()).value();
|
||||
const auto tx1_fee = entry1->GetModifiedFee();
|
||||
@@ -323,7 +323,7 @@ BOOST_FIXTURE_TEST_CASE(improves_feerate, TestChain100Setup)
|
||||
|
||||
// Adding a grandchild makes the cluster size 3, which is also calculable
|
||||
const auto tx5 = make_tx(/*inputs=*/ {tx2}, /*output_values=*/ {995 * CENT});
|
||||
AddToMempool(pool, entry.Fee(normal_fee).FromTx(tx5));
|
||||
TryAddToMempool(pool, entry.Fee(normal_fee).FromTx(tx5));
|
||||
const auto entry5 = pool.GetIter(tx5->GetHash()).value();
|
||||
|
||||
changeset = pool.GetChangeSet();
|
||||
@@ -348,7 +348,7 @@ BOOST_FIXTURE_TEST_CASE(calc_feerate_diagram_rbf, TestChain100Setup)
|
||||
// low -> high -> medium fee transactions that would result in two chunks together since they
|
||||
// are all same size
|
||||
const auto low_tx = make_tx(/*inputs=*/ {m_coinbase_txns[0]}, /*output_values=*/ {10 * COIN});
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(low_tx));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(low_tx));
|
||||
|
||||
const auto entry_low = pool.GetIter(low_tx->GetHash()).value();
|
||||
const auto low_size = entry_low->GetAdjustedWeight();
|
||||
@@ -384,7 +384,7 @@ BOOST_FIXTURE_TEST_CASE(calc_feerate_diagram_rbf, TestChain100Setup)
|
||||
|
||||
// Add a second transaction to the cluster that will make a single chunk, to be evicted in the RBF
|
||||
const auto high_tx = make_tx(/*inputs=*/ {low_tx}, /*output_values=*/ {995 * CENT});
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(high_tx));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(high_tx));
|
||||
const auto entry_high = pool.GetIter(high_tx->GetHash()).value();
|
||||
const auto high_size = entry_high->GetAdjustedWeight();
|
||||
|
||||
@@ -416,12 +416,12 @@ BOOST_FIXTURE_TEST_CASE(calc_feerate_diagram_rbf, TestChain100Setup)
|
||||
|
||||
// Make a size 2 cluster that is itself two chunks; evict both txns
|
||||
const auto high_tx_2 = make_tx(/*inputs=*/ {m_coinbase_txns[1]}, /*output_values=*/ {10 * COIN});
|
||||
AddToMempool(pool, entry.Fee(high_fee).FromTx(high_tx_2));
|
||||
TryAddToMempool(pool, entry.Fee(high_fee).FromTx(high_tx_2));
|
||||
const auto entry_high_2 = pool.GetIter(high_tx_2->GetHash()).value();
|
||||
const auto high_size_2 = entry_high_2->GetAdjustedWeight();
|
||||
|
||||
const auto low_tx_2 = make_tx(/*inputs=*/ {high_tx_2}, /*output_values=*/ {9 * COIN});
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(low_tx_2));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(low_tx_2));
|
||||
const auto entry_low_2 = pool.GetIter(low_tx_2->GetHash()).value();
|
||||
const auto low_size_2 = entry_low_2->GetAdjustedWeight();
|
||||
|
||||
@@ -440,15 +440,15 @@ BOOST_FIXTURE_TEST_CASE(calc_feerate_diagram_rbf, TestChain100Setup)
|
||||
|
||||
// You can have more than two direct conflicts
|
||||
const auto conflict_1 = make_tx(/*inputs=*/ {m_coinbase_txns[2]}, /*output_values=*/ {10 * COIN});
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(conflict_1));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(conflict_1));
|
||||
const auto conflict_1_entry = pool.GetIter(conflict_1->GetHash()).value();
|
||||
|
||||
const auto conflict_2 = make_tx(/*inputs=*/ {m_coinbase_txns[3]}, /*output_values=*/ {10 * COIN});
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(conflict_2));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(conflict_2));
|
||||
const auto conflict_2_entry = pool.GetIter(conflict_2->GetHash()).value();
|
||||
|
||||
const auto conflict_3 = make_tx(/*inputs=*/ {m_coinbase_txns[4]}, /*output_values=*/ {10 * COIN});
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(conflict_3));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(conflict_3));
|
||||
const auto conflict_3_entry = pool.GetIter(conflict_3->GetHash()).value();
|
||||
|
||||
{
|
||||
@@ -465,7 +465,7 @@ BOOST_FIXTURE_TEST_CASE(calc_feerate_diagram_rbf, TestChain100Setup)
|
||||
|
||||
// Add a child transaction to conflict_1 and make it cluster size 2, two chunks due to same feerate
|
||||
const auto conflict_1_child = make_tx(/*inputs=*/{conflict_1}, /*output_values=*/ {995 * CENT});
|
||||
AddToMempool(pool, entry.Fee(low_fee).FromTx(conflict_1_child));
|
||||
TryAddToMempool(pool, entry.Fee(low_fee).FromTx(conflict_1_child));
|
||||
const auto conflict_1_child_entry = pool.GetIter(conflict_1_child->GetHash()).value();
|
||||
|
||||
{
|
||||
|
||||
@@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE(package_validation_tests)
|
||||
}
|
||||
// A single, giant transaction submitted through ProcessNewPackage fails on single tx policy.
|
||||
CTransactionRef giant_ptx = create_placeholder_tx(999, 999);
|
||||
BOOST_CHECK(GetVirtualTransactionSize(*giant_ptx) > DEFAULT_ANCESTOR_SIZE_LIMIT_KVB * 1000);
|
||||
BOOST_CHECK(GetVirtualTransactionSize(*giant_ptx) > DEFAULT_CLUSTER_SIZE_LIMIT_KVB * 1000);
|
||||
Package package_single_giant{giant_ptx};
|
||||
auto result_single_large = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_single_giant, /*test_accept=*/true, /*client_maxfeerate=*/{});
|
||||
if (auto err_single_large{CheckPackageMempoolAcceptResult(package_single_giant, result_single_large, /*expect_valid=*/false, nullptr)}) {
|
||||
|
||||
@@ -225,7 +225,7 @@ BOOST_FIXTURE_TEST_CASE(ephemeral_tests, RegTestingSetup)
|
||||
BOOST_CHECK_EQUAL(child_wtxid, Wtxid());
|
||||
|
||||
// Add first grandparent to mempool and fetch entry
|
||||
AddToMempool(pool, entry.FromTx(grandparent_tx_1));
|
||||
TryAddToMempool(pool, entry.FromTx(grandparent_tx_1));
|
||||
|
||||
// Ignores ancestors that aren't direct parents
|
||||
BOOST_CHECK(CheckEphemeralSpends({child_no_dust}, dustrelay, pool, child_state, child_wtxid));
|
||||
@@ -248,7 +248,7 @@ BOOST_FIXTURE_TEST_CASE(ephemeral_tests, RegTestingSetup)
|
||||
BOOST_CHECK_EQUAL(child_wtxid, Wtxid());
|
||||
|
||||
// Add second grandparent to mempool
|
||||
AddToMempool(pool, entry.FromTx(grandparent_tx_2));
|
||||
TryAddToMempool(pool, entry.FromTx(grandparent_tx_2));
|
||||
|
||||
// Only spends single dust out of two direct parents
|
||||
BOOST_CHECK(!CheckEphemeralSpends({dust_non_spend_both_parents}, dustrelay, pool, child_state, child_wtxid));
|
||||
@@ -263,7 +263,7 @@ BOOST_FIXTURE_TEST_CASE(ephemeral_tests, RegTestingSetup)
|
||||
BOOST_CHECK_EQUAL(child_wtxid, Wtxid());
|
||||
|
||||
// Now add dusty parent to mempool
|
||||
AddToMempool(pool, entry.FromTx(parent_with_dust));
|
||||
TryAddToMempool(pool, entry.FromTx(parent_with_dust));
|
||||
|
||||
// Passes dust checks even with non-parent ancestors
|
||||
BOOST_CHECK(CheckEphemeralSpends({child_no_dust}, dustrelay, pool, child_state, child_wtxid));
|
||||
@@ -281,9 +281,9 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
std::vector<CTxMemPoolEntry::CTxMemPoolEntryRef> empty_parents;
|
||||
|
||||
auto mempool_tx_v3 = make_tx(random_outpoints(1), /*version=*/3);
|
||||
AddToMempool(pool, entry.FromTx(mempool_tx_v3));
|
||||
TryAddToMempool(pool, entry.FromTx(mempool_tx_v3));
|
||||
auto mempool_tx_v2 = make_tx(random_outpoints(1), /*version=*/2);
|
||||
AddToMempool(pool, entry.FromTx(mempool_tx_v2));
|
||||
TryAddToMempool(pool, entry.FromTx(mempool_tx_v2));
|
||||
|
||||
// Cannot spend from an unconfirmed TRUC transaction unless this tx is also TRUC.
|
||||
{
|
||||
@@ -389,7 +389,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
package_multi_parents.emplace_back(mempool_tx_v3);
|
||||
for (size_t i{0}; i < 2; ++i) {
|
||||
auto mempool_tx = make_tx(random_outpoints(i + 1), /*version=*/3);
|
||||
AddToMempool(pool, entry.FromTx(mempool_tx));
|
||||
TryAddToMempool(pool, entry.FromTx(mempool_tx));
|
||||
mempool_outpoints.emplace_back(mempool_tx->GetHash(), 0);
|
||||
package_multi_parents.emplace_back(mempool_tx);
|
||||
}
|
||||
@@ -414,7 +414,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
auto last_outpoint{random_outpoints(1)[0]};
|
||||
for (size_t i{0}; i < 2; ++i) {
|
||||
auto mempool_tx = make_tx({last_outpoint}, /*version=*/3);
|
||||
AddToMempool(pool, entry.FromTx(mempool_tx));
|
||||
TryAddToMempool(pool, entry.FromTx(mempool_tx));
|
||||
last_outpoint = COutPoint{mempool_tx->GetHash(), 0};
|
||||
package_multi_gen.emplace_back(mempool_tx);
|
||||
if (i == 1) middle_tx = mempool_tx;
|
||||
@@ -501,7 +501,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
BOOST_CHECK(GetTransactionWeight(*tx_mempool_v3_child) <= TRUC_CHILD_MAX_VSIZE * WITNESS_SCALE_FACTOR);
|
||||
auto parents{pool.GetParents(entry.FromTx(tx_mempool_v3_child))};
|
||||
BOOST_CHECK(SingleTRUCChecks(pool, tx_mempool_v3_child, parents, empty_conflicts_set, GetVirtualTransactionSize(*tx_mempool_v3_child)) == std::nullopt);
|
||||
AddToMempool(pool, entry.FromTx(tx_mempool_v3_child));
|
||||
TryAddToMempool(pool, entry.FromTx(tx_mempool_v3_child));
|
||||
|
||||
Package package_v3_1p1c{mempool_tx_v3, tx_mempool_v3_child};
|
||||
BOOST_CHECK(PackageTRUCChecks(pool, tx_mempool_v3_child, GetVirtualTransactionSize(*tx_mempool_v3_child), package_v3_1p1c, empty_parents) == std::nullopt);
|
||||
@@ -528,7 +528,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
expected_error_str);
|
||||
|
||||
// Configuration where parent already has 2 other children in mempool (no sibling eviction allowed). This may happen as the result of a reorg.
|
||||
AddToMempool(pool, entry.FromTx(tx_v3_child2));
|
||||
TryAddToMempool(pool, entry.FromTx(tx_v3_child2));
|
||||
auto tx_v3_child3 = make_tx({COutPoint{mempool_tx_v3->GetHash(), 24}}, /*version=*/3);
|
||||
auto entry_mempool_parent = pool.GetIter(mempool_tx_v3->GetHash()).value();
|
||||
BOOST_CHECK_EQUAL(pool.GetDescendantCount(entry_mempool_parent), 3);
|
||||
@@ -547,9 +547,9 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
auto tx_mempool_nibling = make_tx({COutPoint{tx_mempool_sibling->GetHash(), 0}}, /*version=*/3);
|
||||
auto tx_to_submit = make_tx({COutPoint{tx_mempool_grandparent->GetHash(), 1}}, /*version=*/3);
|
||||
|
||||
AddToMempool(pool, entry.FromTx(tx_mempool_grandparent));
|
||||
AddToMempool(pool, entry.FromTx(tx_mempool_sibling));
|
||||
AddToMempool(pool, entry.FromTx(tx_mempool_nibling));
|
||||
TryAddToMempool(pool, entry.FromTx(tx_mempool_grandparent));
|
||||
TryAddToMempool(pool, entry.FromTx(tx_mempool_sibling));
|
||||
TryAddToMempool(pool, entry.FromTx(tx_mempool_nibling));
|
||||
|
||||
auto parents_3gen{pool.GetParents(entry.FromTx(tx_to_submit))};
|
||||
const auto expected_error_str{strprintf("tx %s (wtxid=%s) would exceed descendant count limit",
|
||||
|
||||
@@ -212,7 +212,7 @@ void CheckMempoolTRUCInvariants(const CTxMemPool& tx_pool)
|
||||
}
|
||||
}
|
||||
|
||||
void AddToMempool(CTxMemPool& tx_pool, const CTxMemPoolEntry& entry)
|
||||
void TryAddToMempool(CTxMemPool& tx_pool, const CTxMemPoolEntry& entry)
|
||||
{
|
||||
LOCK2(cs_main, tx_pool.cs);
|
||||
auto changeset = tx_pool.GetChangeSet();
|
||||
|
||||
@@ -65,7 +65,7 @@ void CheckMempoolTRUCInvariants(const CTxMemPool& tx_pool);
|
||||
|
||||
/** One-line wrapper for creating a mempool changeset with a single transaction
|
||||
* and applying it if the policy limits are respected. */
|
||||
void AddToMempool(CTxMemPool& tx_pool, const CTxMemPoolEntry& entry);
|
||||
void TryAddToMempool(CTxMemPool& tx_pool, const CTxMemPoolEntry& entry);
|
||||
|
||||
/** Mock the mempool minimum feerate by adding a transaction and calling TrimToSize(0),
|
||||
* simulating the mempool "reaching capacity" and evicting by descendant feerate. Note that
|
||||
|
||||
Reference in New Issue
Block a user