mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-04 02:02:42 +02:00
Rework miner_tests to not require large cluster limit
This commit is contained in:
@@ -56,7 +56,12 @@ struct MinerTestingSetup : public TestingSetup {
|
||||
// instead.
|
||||
m_node.mempool.reset();
|
||||
bilingual_str error;
|
||||
m_node.mempool = std::make_unique<CTxMemPool>(MemPoolOptionsForTest(m_node), error);
|
||||
auto opts = MemPoolOptionsForTest(m_node);
|
||||
// The "block size > limit" test creates a cluster of 1192590 vbytes,
|
||||
// so set the cluster vbytes limit big enough so that the txgraph
|
||||
// doesn't become oversized.
|
||||
opts.limits.cluster_size_vbytes = 1'200'000;
|
||||
m_node.mempool = std::make_unique<CTxMemPool>(opts, error);
|
||||
Assert(error.empty());
|
||||
return *m_node.mempool;
|
||||
}
|
||||
@@ -253,6 +258,48 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
|
||||
BOOST_CHECK(block.vtx[8]->GetHash() == hashLowFeeTx2);
|
||||
}
|
||||
|
||||
std::vector<CTransactionRef> CreateBigSigOpsCluster(const CTransactionRef& first_tx)
|
||||
{
|
||||
std::vector<CTransactionRef> ret;
|
||||
|
||||
CMutableTransaction tx;
|
||||
// block sigops > limit: 1000 CHECKMULTISIG + 1
|
||||
tx.vin.resize(1);
|
||||
// NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG
|
||||
tx.vin[0].scriptSig = CScript() << OP_0 << OP_0 << OP_CHECKSIG << OP_1;
|
||||
tx.vin[0].prevout.hash = first_tx->GetHash();
|
||||
tx.vin[0].prevout.n = 0;
|
||||
tx.vout.resize(50);
|
||||
for (auto &out : tx.vout) {
|
||||
out.nValue = first_tx->vout[0].nValue / 50;
|
||||
out.scriptPubKey = CScript() << OP_1;
|
||||
}
|
||||
|
||||
tx.vout[0].nValue -= CENT;
|
||||
CTransactionRef parent_tx = MakeTransactionRef(tx);
|
||||
ret.push_back(parent_tx);
|
||||
assert(GetLegacySigOpCount(*parent_tx) == 1);
|
||||
|
||||
// Tx1 has 1 sigops, 1 input, 50 outputs.
|
||||
// Tx2-51 has 400 sigops: 1 input, 20 CHECKMULTISIG outputs
|
||||
// Total: 1000 CHECKMULTISIG + 1
|
||||
for (unsigned int i = 0; i < 50; ++i) {
|
||||
auto tx2 = tx;
|
||||
tx2.vin.resize(1);
|
||||
tx2.vin[0].prevout.hash = parent_tx->GetHash();
|
||||
tx2.vin[0].prevout.n = i;
|
||||
tx2.vin[0].scriptSig = CScript() << OP_1;
|
||||
tx2.vout.resize(20);
|
||||
tx2.vout[0].nValue = parent_tx->vout[i].nValue - CENT;
|
||||
for (auto &out : tx2.vout) {
|
||||
out.nValue = 0;
|
||||
out.scriptPubKey = CScript() << OP_0 << OP_0 << OP_0 << OP_NOP << OP_CHECKMULTISIG << OP_1;
|
||||
}
|
||||
ret.push_back(MakeTransactionRef(tx2));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst, int baseheight)
|
||||
{
|
||||
Txid hash;
|
||||
@@ -281,23 +328,18 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
BOOST_REQUIRE(block_template);
|
||||
CBlock block{block_template->getBlock()};
|
||||
|
||||
// block sigops > limit: 1000 CHECKMULTISIG + 1
|
||||
tx.vin.resize(1);
|
||||
// NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG
|
||||
tx.vin[0].scriptSig = CScript() << OP_0 << OP_0 << OP_0 << OP_NOP << OP_CHECKMULTISIG << OP_1;
|
||||
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
||||
tx.vin[0].prevout.n = 0;
|
||||
tx.vout.resize(1);
|
||||
tx.vout[0].nValue = BLOCKSUBSIDY;
|
||||
for (unsigned int i = 0; i < 1001; ++i) {
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
hash = tx.GetHash();
|
||||
bool spendsCoinbase = i == 0; // only first tx spends coinbase
|
||||
// If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
|
||||
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
|
||||
tx.vin[0].prevout.hash = hash;
|
||||
}
|
||||
auto txs = CreateBigSigOpsCluster(txFirst[0]);
|
||||
|
||||
int64_t legacy_sigops = 0;
|
||||
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));
|
||||
legacy_sigops += GetLegacySigOpCount(*t);
|
||||
BOOST_CHECK(tx_mempool.GetIter(t->GetHash()).has_value());
|
||||
}
|
||||
assert(tx_mempool.mapTx.size() == 51);
|
||||
assert(legacy_sigops == 20001);
|
||||
BOOST_CHECK_EXCEPTION(mining->createNewBlock(options), std::runtime_error, HasReason("bad-blk-sigops"));
|
||||
}
|
||||
|
||||
@@ -305,16 +347,25 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
CTxMemPool& tx_mempool{MakeMempool()};
|
||||
LOCK(tx_mempool.cs);
|
||||
|
||||
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
||||
tx.vout[0].nValue = BLOCKSUBSIDY;
|
||||
for (unsigned int i = 0; i < 1001; ++i) {
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
hash = tx.GetHash();
|
||||
bool spendsCoinbase = i == 0; // only first tx spends coinbase
|
||||
// If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
|
||||
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
|
||||
tx.vin[0].prevout.hash = hash;
|
||||
// Check that the mempool is empty.
|
||||
assert(tx_mempool.mapTx.empty());
|
||||
|
||||
// Just to make sure we can still make simple blocks
|
||||
auto block_template{mining->createNewBlock(options)};
|
||||
BOOST_REQUIRE(block_template);
|
||||
CBlock block{block_template->getBlock()};
|
||||
|
||||
auto txs = CreateBigSigOpsCluster(txFirst[0]);
|
||||
|
||||
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));
|
||||
legacy_sigops += GetLegacySigOpCount(*t);
|
||||
BOOST_CHECK(tx_mempool.GetIter(t->GetHash()).has_value());
|
||||
}
|
||||
assert(tx_mempool.mapTx.size() == 51);
|
||||
assert(legacy_sigops == 20001);
|
||||
|
||||
BOOST_REQUIRE(mining->createNewBlock(options));
|
||||
}
|
||||
|
||||
@@ -323,20 +374,26 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||
LOCK(tx_mempool.cs);
|
||||
|
||||
// block size > limit
|
||||
tx.vin[0].scriptSig = CScript();
|
||||
// 18 * (520char + DROP) + OP_1 = 9433 bytes
|
||||
tx.vin.resize(1);
|
||||
tx.vout.resize(1);
|
||||
tx.vout[0].nValue = BLOCKSUBSIDY;
|
||||
// 36 * (520char + DROP) + OP_1 = 18757 bytes
|
||||
std::vector<unsigned char> vchData(520);
|
||||
for (unsigned int i = 0; i < 18; ++i) {
|
||||
tx.vin[0].scriptSig << vchData << OP_DROP;
|
||||
tx.vout[0].scriptPubKey << vchData << OP_DROP;
|
||||
}
|
||||
tx.vin[0].scriptSig << OP_1;
|
||||
tx.vout[0].scriptPubKey << OP_1;
|
||||
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
||||
tx.vin[0].prevout.n = 0;
|
||||
tx.vout[0].nValue = BLOCKSUBSIDY;
|
||||
for (unsigned int i = 0; i < 128; ++i) {
|
||||
for (unsigned int i = 0; i < 63; ++i) {
|
||||
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));
|
||||
BOOST_CHECK(tx_mempool.GetIter(hash).has_value());
|
||||
tx.vin[0].prevout.hash = hash;
|
||||
}
|
||||
BOOST_REQUIRE(mining->createNewBlock(options));
|
||||
|
||||
Reference in New Issue
Block a user