Line data Source code
1 : // Copyright (c) 2011-2021 The Bitcoin Core developers
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #include <chainparams.h>
6 : #include <consensus/consensus.h>
7 : #include <consensus/merkle.h>
8 : #include <consensus/tx_verify.h>
9 : #include <consensus/validation.h>
10 : #include <node/miner.h>
11 : #include <policy/policy.h>
12 : #include <pow.h>
13 : #include <script/standard.h>
14 : #include <test/util/random.h>
15 : #include <test/util/txmempool.h>
16 : #include <uint256.h>
17 : #include <util/strencodings.h>
18 : #include <util/system.h>
19 : #include <util/time.h>
20 : #include <validation.h>
21 : #include <versionbits.h>
22 :
23 : #include <evo/evodb.h>
24 : #include <chainlock/handler.h>
25 : #include <governance/governance.h>
26 : #include <instantsend/instantsend.h>
27 : #include <llmq/blockprocessor.h>
28 : #include <llmq/context.h>
29 :
30 : #include <test/util/setup_common.h>
31 :
32 : #include <memory>
33 :
34 : #include <boost/test/unit_test.hpp>
35 :
36 : using node::BlockAssembler;
37 : using node::CBlockTemplate;
38 :
39 : namespace miner_tests {
40 1 : struct MinerTestingSetup : public TestingSetup {
41 : void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs);
42 : void TestBasicMining(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst, int baseheight) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs);
43 : void TestPrioritisedMining(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs);
44 8 : bool TestSequenceLocks(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs)
45 : {
46 8 : CCoinsViewMemPool view_mempool(&m_node.chainman->ActiveChainstate().CoinsTip(), *m_node.mempool);
47 8 : CBlockIndex* tip{m_node.chainman->ActiveChain().Tip()};
48 8 : const std::optional<LockPoints> lock_points{CalculateLockPointsAtTip(tip, view_mempool, tx)};
49 8 : return lock_points.has_value() && CheckSequenceLocksAtTip(tip, *lock_points);
50 8 : }
51 : BlockAssembler AssemblerForTest(const CChainParams& params);
52 : };
53 :
54 : static constexpr int WAIT_FOR_ISLOCK_TIMEOUT{601};
55 : } // namespace miner_tests
56 :
57 146 : BOOST_FIXTURE_TEST_SUITE(miner_tests, MinerTestingSetup)
58 :
59 146 : static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
60 :
61 18 : BlockAssembler MinerTestingSetup::AssemblerForTest(const CChainParams& params)
62 : {
63 18 : BlockAssembler::Options options;
64 :
65 18 : options.nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
66 18 : options.blockMinFeeRate = blockMinFeeRate;
67 18 : return BlockAssembler(m_node.chainman->ActiveChainstate(), m_node, m_node.mempool.get(), params, options);
68 : }
69 :
70 : constexpr static struct {
71 : unsigned char extranonce;
72 : unsigned int nonce;
73 : } BLOCKINFO[]{{0, 1123860}, {0, 1148713}, {0, 2157897}, {0, 6137383}, {0, 1440467}, {0, 1248137},
74 : {0, 974559}, {0, 3450180}, {0, 2050647}, {0, 1174391}, {0, 3336468}, {0, 464427},
75 : {0, 470596}, {0, 182567}, {0, 2534464}, {0, 1926037}, {0, 3526872}, {0, 2481471},
76 : {0, 1294544}, {0, 367787}, {0, 3164800}, {0, 917651}, {0, 654264}, {0, 3621441},
77 : {0, 4300293}, {0, 3692002}, {0, 3171815}, {0, 2334617}, {0, 2655536}, {0, 4862462},
78 : {0, 3306418}, {0, 720711}, {0, 3443522}, {0, 1435662}, {0, 833747}, {0, 2754854},
79 : {0, 1788881}, {0, 1006158}, {0, 3889636}, {0, 1065940}, {0, 2637337}, {0, 1540467},
80 : {0, 809898}, {0, 414399}, {0, 5978379}, {0, 2301882}, {0, 3224887}, {0, 2557012},
81 : {0, 8076465}, {0, 73633}, {0, 1285282}, {0, 3114919}, {0, 1762402}, {0, 3343293},
82 : {0, 3822496}, {0, 2957067}, {0, 1943866}, {0, 5933446}, {0, 886955}, {0, 975375},
83 : {0, 1626364}, {0, 4337875}, {0, 522971}, {0, 979749}, {0, 2343272}, {0, 2530995},
84 : {0, 1060534}, {0, 2522523}, {0, 1315215}, {0, 1730093}, {0, 2547908}, {0, 2889564},
85 : {0, 5456339}, {0, 3881378}, {0, 4533810}, {0, 1700063}, {0, 1086006}, {0, 2797169},
86 : {0, 2019861}, {0, 883169}, {0, 1750363}, {0, 1721942}, {0, 5058071}, {0, 3225093},
87 : {0, 307451}, {0, 1653602}, {0, 2281488}, {0, 1947311}, {0, 4993782}, {0, 325324},
88 : {0, 6304803}, {0, 4880118}, {0, 1401148}, {0, 4640270}, {0, 2548166}, {0, 3369900},
89 : {0, 2800169}, {0, 3305191}, {0, 2122926}, {0, 336011}, {0, 1722772}, {0, 1044908},
90 : {0, 642154}, {0, 5835730}, {0, 164952}, {0, 1584353}, {0, 666367}, {0, 854797},
91 : {0, 2407599}, {0, 3328128}, {0, 245451}, {0, 2154593}, {0, 4043042}, {0, 2939387},
92 : {0, 3509685}, {0, 635871}, {0, 2645814}, {0, 1788871}, {0, 2263667}};
93 : constexpr static size_t blockinfo_size = sizeof(BLOCKINFO) / sizeof(BLOCKINFO[0]);
94 :
95 2 : static std::unique_ptr<CBlockIndex> CreateBlockIndex(int nHeight, CBlockIndex* active_chain_tip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
96 : {
97 2 : auto index{std::make_unique<CBlockIndex>()};
98 2 : index->nHeight = nHeight;
99 2 : index->pprev = active_chain_tip;
100 2 : return index;
101 2 : }
102 :
103 : // Test suite for ancestor feerate transaction selection.
104 : // Implemented as an additional function, rather than a separate test case,
105 : // to allow reusing the blockchain created in CreateNewBlock_validity.
106 1 : void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst)
107 : {
108 : // Disable free transactions, otherwise TX selection is non-deterministic
109 1 : gArgs.SoftSetArg("-blockprioritysize", "0");
110 :
111 : // Test the ancestor feerate transaction selection.
112 1 : TestMemPoolEntryHelper entry;
113 :
114 : // Test that a medium fee transaction will be selected after a higher fee
115 : // rate package with a low fee rate parent.
116 1 : CMutableTransaction tx;
117 1 : tx.vin.resize(1);
118 1 : tx.vin[0].scriptSig = CScript() << OP_1;
119 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
120 1 : tx.vin[0].prevout.n = 0;
121 1 : tx.vout.resize(1);
122 1 : tx.vout[0].nValue = 5000000000LL - 1000;
123 : // This tx has a low fee: 1000 satoshis
124 1 : uint256 hashParentTx = tx.GetHash(); // save this txid for later use
125 1 : m_node.mempool->addUnchecked(entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
126 :
127 : // This tx has a medium fee: 10000 satoshis
128 1 : tx.vin[0].prevout.hash = txFirst[1]->GetHash();
129 1 : tx.vout[0].nValue = 5000000000LL - 10000;
130 1 : uint256 hashMediumFeeTx = tx.GetHash();
131 1 : m_node.mempool->addUnchecked(entry.Fee(10000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
132 :
133 : // This tx has a high fee, but depends on the first transaction
134 1 : tx.vin[0].prevout.hash = hashParentTx;
135 1 : tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee
136 1 : uint256 hashHighFeeTx = tx.GetHash();
137 1 : m_node.mempool->addUnchecked(entry.Fee(50000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
138 :
139 : // Age transaction for InstantSend
140 1 : m_node.clhandler->UpdateTxFirstSeenMap({hashParentTx, hashMediumFeeTx, hashHighFeeTx}, std::chrono::duration_cast<std::chrono::seconds>(Now<NodeSeconds>().time_since_epoch()).count() - WAIT_FOR_ISLOCK_TIMEOUT);
141 1 : std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
142 1 : BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 4U);
143 1 : BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
144 1 : BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
145 1 : BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashMediumFeeTx);
146 :
147 : // Test that a package below the block min tx fee doesn't get included
148 1 : tx.vin[0].prevout.hash = hashHighFeeTx;
149 1 : tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee
150 1 : uint256 hashFreeTx = tx.GetHash();
151 : // Age transaction for InstantSend
152 1 : m_node.clhandler->UpdateTxFirstSeenMap({hashFreeTx}, std::chrono::duration_cast<std::chrono::seconds>(Now<NodeSeconds>().time_since_epoch()).count() - WAIT_FOR_ISLOCK_TIMEOUT);
153 1 : m_node.mempool->addUnchecked(entry.Fee(0).FromTx(tx));
154 1 : size_t freeTxSize = GetVirtualTransactionSize(CTransaction(tx));
155 :
156 : // Calculate a fee on child transaction that will put the package just
157 : // below the block min tx fee (assuming 1 child tx of the same size).
158 1 : CAmount feeToUse = blockMinFeeRate.GetFee(2*freeTxSize) - 1;
159 :
160 1 : tx.vin[0].prevout.hash = hashFreeTx;
161 1 : tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
162 1 : uint256 hashLowFeeTx = tx.GetHash();
163 1 : m_node.mempool->addUnchecked(entry.Fee(feeToUse).FromTx(tx));
164 1 : pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
165 : // Verify that the free tx and the low fee tx didn't get selected
166 5 : for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
167 4 : BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx);
168 4 : BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx);
169 4 : }
170 :
171 : // Test that packages above the min relay fee do get included, even if one
172 : // of the transactions is below the min relay fee
173 : // Remove the low fee transaction and replace with a higher fee transaction
174 1 : m_node.mempool->removeRecursive(CTransaction(tx), MemPoolRemovalReason::MANUAL);
175 1 : tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
176 1 : hashLowFeeTx = tx.GetHash();
177 1 : m_node.mempool->addUnchecked(entry.Fee(feeToUse+2).FromTx(tx));
178 : // Age transaction for InstantSend
179 1 : m_node.clhandler->UpdateTxFirstSeenMap({hashLowFeeTx}, std::chrono::duration_cast<std::chrono::seconds>(Now<NodeSeconds>().time_since_epoch()).count() - WAIT_FOR_ISLOCK_TIMEOUT);
180 1 : pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
181 1 : BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U);
182 1 : BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
183 1 : BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
184 :
185 : // Test that transaction selection properly updates ancestor fee
186 : // calculations as ancestor transactions get included in a block.
187 : // Add a 0-fee transaction that has 2 outputs.
188 1 : tx.vin[0].prevout.hash = txFirst[2]->GetHash();
189 1 : tx.vout.resize(2);
190 1 : tx.vout[0].nValue = 5000000000LL - 100000000;
191 1 : tx.vout[1].nValue = 100000000; // 1BTC output
192 1 : uint256 hashFreeTx2 = tx.GetHash();
193 1 : m_node.mempool->addUnchecked(entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
194 : // Age transaction for InstantSend
195 1 : m_node.clhandler->UpdateTxFirstSeenMap({tx.GetHash()}, std::chrono::duration_cast<std::chrono::seconds>(Now<NodeSeconds>().time_since_epoch()).count() - WAIT_FOR_ISLOCK_TIMEOUT);
196 :
197 : // This tx can't be mined by itself
198 1 : tx.vin[0].prevout.hash = hashFreeTx2;
199 1 : tx.vout.resize(1);
200 1 : feeToUse = blockMinFeeRate.GetFee(freeTxSize);
201 1 : tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
202 1 : uint256 hashLowFeeTx2 = tx.GetHash();
203 1 : m_node.mempool->addUnchecked(entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
204 : // Age transaction for InstantSend
205 1 : m_node.clhandler->UpdateTxFirstSeenMap({tx.GetHash()}, std::chrono::duration_cast<std::chrono::seconds>(Now<NodeSeconds>().time_since_epoch()).count() - WAIT_FOR_ISLOCK_TIMEOUT);
206 1 : pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
207 :
208 : // Verify that this tx isn't selected.
209 7 : for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
210 6 : BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx2);
211 6 : BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx2);
212 6 : }
213 :
214 : // This tx will be mineable, and should cause hashLowFeeTx2 to be selected
215 : // as well.
216 1 : tx.vin[0].prevout.n = 1;
217 1 : tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
218 1 : m_node.mempool->addUnchecked(entry.Fee(10000).FromTx(tx));
219 : // Age transaction for InstantSend
220 1 : m_node.clhandler->UpdateTxFirstSeenMap({tx.GetHash()}, std::chrono::duration_cast<std::chrono::seconds>(Now<NodeSeconds>().time_since_epoch()).count() - WAIT_FOR_ISLOCK_TIMEOUT);
221 1 : pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
222 1 : BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 9U);
223 1 : BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
224 1 : }
225 :
226 1 : void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst, int baseheight)
227 : {
228 1 : uint256 hash;
229 1 : CMutableTransaction tx;
230 1 : TestMemPoolEntryHelper entry;
231 1 : entry.nFee = 11;
232 1 : entry.nHeight = 11;
233 : // Just to make sure we can still make simple blocks
234 1 : auto pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
235 1 : BOOST_CHECK(pblocktemplate);
236 :
237 1 : const CAmount BLOCKSUBSIDY = 500*COIN;
238 1 : const CAmount LOWFEE = CENT;
239 1 : const CAmount HIGHFEE = COIN;
240 1 : const CAmount HIGHERFEE = 4*COIN;
241 :
242 : // block sigops > limit: 1000 CHECKMULTISIG + 1
243 1 : tx.vin.resize(1);
244 : // NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG
245 1 : tx.vin[0].scriptSig = CScript() << OP_0 << OP_0 << OP_0 << OP_NOP << OP_CHECKMULTISIG << OP_1;
246 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
247 1 : tx.vin[0].prevout.n = 0;
248 1 : tx.vout.resize(1);
249 1 : tx.vout[0].nValue = BLOCKSUBSIDY;
250 1002 : for (unsigned int i = 0; i < 1001; ++i)
251 : {
252 1001 : tx.vout[0].nValue -= LOWFEE;
253 1001 : hash = tx.GetHash();
254 : // Age transaction for InstantSend
255 1001 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, pblocktemplate->block.nTime - WAIT_FOR_ISLOCK_TIMEOUT);
256 1001 : bool spendsCoinbase = i == 0; // only first tx spends coinbase
257 : // If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
258 :
259 1001 : m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
260 1001 : tx.vin[0].prevout.hash = hash;
261 1001 : }
262 :
263 1 : BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops"));
264 1 : m_node.mempool->clear();
265 :
266 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
267 1 : tx.vout[0].nValue = BLOCKSUBSIDY;
268 1002 : for (unsigned int i = 0; i < 1001; ++i)
269 : {
270 1001 : tx.vout[0].nValue -= LOWFEE;
271 1001 : hash = tx.GetHash();
272 1001 : bool spendsCoinbase = i == 0; // only first tx spends coinbase
273 : // If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
274 : // Age transaction for InstantSend
275 1001 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, pblocktemplate->block.nTime - WAIT_FOR_ISLOCK_TIMEOUT);
276 1001 : m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).SigOps(20).FromTx(tx));
277 1001 : tx.vin[0].prevout.hash = hash;
278 1001 : }
279 1 : BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
280 1 : m_node.mempool->clear();
281 :
282 : // block size > limit
283 1 : tx.vin[0].scriptSig = CScript();
284 : // 18 * (520char + DROP) + OP_1 = 9433 bytes
285 1 : std::vector<unsigned char> vchData(520);
286 19 : for (unsigned int i = 0; i < 18; ++i)
287 18 : tx.vin[0].scriptSig << vchData << OP_DROP;
288 1 : tx.vin[0].scriptSig << OP_1;
289 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
290 1 : tx.vout[0].nValue = BLOCKSUBSIDY;
291 129 : for (unsigned int i = 0; i < 128; ++i)
292 : {
293 128 : tx.vout[0].nValue -= LOWFEE;
294 128 : hash = tx.GetHash();
295 128 : bool spendsCoinbase = i == 0; // only first tx spends coinbase
296 128 : m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
297 128 : tx.vin[0].prevout.hash = hash;
298 128 : }
299 1 : BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
300 1 : m_node.mempool->clear();
301 :
302 : // orphan in mempool, template creation fails
303 1 : hash = tx.GetHash();
304 1 : m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).FromTx(tx));
305 : // Age transaction for InstantSend
306 1 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, pblocktemplate->block.nTime - WAIT_FOR_ISLOCK_TIMEOUT);
307 1 : BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
308 1 : m_node.mempool->clear();
309 :
310 : // child with higher feerate than parent
311 1 : tx.vin[0].scriptSig = CScript() << OP_1;
312 1 : tx.vin[0].prevout.hash = txFirst[1]->GetHash();
313 1 : tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
314 1 : hash = tx.GetHash();
315 1 : m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
316 1 : tx.vin[0].prevout.hash = hash;
317 1 : tx.vin.resize(2);
318 1 : tx.vin[1].scriptSig = CScript() << OP_1;
319 1 : tx.vin[1].prevout.hash = txFirst[0]->GetHash();
320 1 : tx.vin[1].prevout.n = 0;
321 1 : tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee
322 1 : hash = tx.GetHash();
323 1 : m_node.mempool->addUnchecked(entry.Fee(HIGHERFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
324 1 : BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
325 1 : m_node.mempool->clear();
326 :
327 : // coinbase in mempool, template creation fails
328 1 : tx.vin.resize(1);
329 1 : tx.vin[0].prevout.SetNull();
330 1 : tx.vin[0].scriptSig = CScript() << OP_0 << OP_1;
331 1 : tx.vout[0].nValue = 0;
332 1 : hash = tx.GetHash();
333 : // Age transaction for InstantSend
334 1 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, pblocktemplate->block.nTime - WAIT_FOR_ISLOCK_TIMEOUT);
335 : // give it a fee so it'll get mined
336 1 : m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
337 : // Should throw bad-cb-multiple
338 1 : BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple"));
339 1 : m_node.mempool->clear();
340 :
341 : // double spend txn pair in mempool, template creation fails
342 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
343 1 : tx.vin[0].scriptSig = CScript() << OP_1;
344 1 : tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
345 1 : tx.vout[0].scriptPubKey = CScript() << OP_1;
346 1 : hash = tx.GetHash();
347 1 : m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
348 1 : tx.vout[0].scriptPubKey = CScript() << OP_2;
349 1 : hash = tx.GetHash();
350 : // Age transaction for InstantSend
351 1 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, pblocktemplate->block.nTime - WAIT_FOR_ISLOCK_TIMEOUT);
352 1 : m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
353 1 : BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
354 1 : m_node.mempool->clear();
355 :
356 : // subsidy changing
357 : // int nHeight = m_node.chainman->ActiveChain().Height();
358 : // // Create an actual 209999-long block chain (without valid blocks).
359 : // while (m_node.chainman->ActiveChain().Tip()->nHeight < 209999) {
360 : // CBlockIndex* prev = m_node.chainman->ActiveChain().Tip();
361 : // CBlockIndex* next = new CBlockIndex();
362 : // next->phashBlock = new uint256(InsecureRand256());
363 : // pcoinsTip->SetBestBlock(next->GetBlockHash());
364 : // next->pprev = prev;
365 : // next->nHeight = prev->nHeight + 1;
366 : // next->BuildSkip();
367 : // m_node.chainman->ActiveChain().SetTip(*next);
368 : // }
369 : //BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey));
370 : // // Extend to a 210000-long block chain.
371 : // while (m_node.chainman->ActiveChain().Tip()->nHeight < 210000) {
372 : // CBlockIndex* prev = m_node.chainman->ActiveChain().Tip();
373 : // CBlockIndex* next = new CBlockIndex();
374 : // next->phashBlock = new uint256(InsecureRand256());
375 : // pcoinsTip->SetBestBlock(next->GetBlockHash());
376 : // next->pprev = prev;
377 : // next->nHeight = prev->nHeight + 1;
378 : // next->BuildSkip();
379 : // m_node.chainman->ActiveChain().SetTip(*next);
380 : // }
381 : //BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey));
382 :
383 : // invalid (pre-p2sh) txn in mempool, template creation fails
384 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
385 1 : tx.vin[0].prevout.n = 0;
386 1 : tx.vin[0].scriptSig = CScript() << OP_1;
387 1 : tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE;
388 1 : CScript script = CScript() << OP_0;
389 1 : tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script));
390 1 : hash = tx.GetHash();
391 : // Age transaction for InstantSend
392 1 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, pblocktemplate->block.nTime - WAIT_FOR_ISLOCK_TIMEOUT);
393 1 : m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
394 1 : tx.vin[0].prevout.hash = hash;
395 1 : tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
396 1 : tx.vout[0].nValue -= LOWFEE;
397 1 : hash = tx.GetHash();
398 : // Age transaction for InstantSend
399 1 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, pblocktemplate->block.nTime - WAIT_FOR_ISLOCK_TIMEOUT);
400 1 : m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
401 : // Should throw block-validation-failed
402 1 : BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
403 1 : m_node.mempool->clear();
404 :
405 : // // Delete the dummy blocks again.
406 : // while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) {
407 : // CBlockIndex* del = m_node.chainman->ActiveChain().Tip();
408 : // m_node.chainman->ActiveChain().SetTip(*Assert(del->pprev));
409 : // m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(del->pprev->GetBlockHash());
410 : // delete del->phashBlock;
411 : // delete del;
412 : // }
413 :
414 : // non-final txs in mempool
415 1 : SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1);
416 1 : int64_t mocked_time_for_is = m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() - WAIT_FOR_ISLOCK_TIMEOUT;
417 1 : const int flags{LOCKTIME_VERIFY_SEQUENCE};
418 : // height map
419 1 : std::vector<int> prevheights;
420 :
421 : // relative height locked
422 1 : tx.nVersion = 2;
423 1 : tx.vin.resize(1);
424 1 : prevheights.resize(1);
425 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash(); // only 1 transaction
426 1 : tx.vin[0].prevout.n = 0;
427 1 : tx.vin[0].scriptSig = CScript() << OP_1;
428 1 : tx.vin[0].nSequence = m_node.chainman->ActiveChain().Tip()->nHeight + 1; // txFirst[0] is the 2nd block
429 1 : prevheights[0] = baseheight + 1;
430 1 : tx.vout.resize(1);
431 1 : tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
432 1 : tx.vout[0].scriptPubKey = CScript() << OP_1;
433 1 : tx.nLockTime = 0;
434 1 : hash = tx.GetHash();
435 : // Age transaction for InstantSend
436 1 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, mocked_time_for_is);
437 1 : m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
438 1 : BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
439 1 : BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
440 :
441 : {
442 1 : CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
443 1 : BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, *CreateBlockIndex(active_chain_tip->nHeight + 2, active_chain_tip))); // Sequence locks pass on 2nd block
444 : }
445 :
446 : // relative time locked
447 1 : tx.vin[0].prevout.hash = txFirst[1]->GetHash();
448 1 : 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
449 1 : prevheights[0] = baseheight + 2;
450 1 : hash = tx.GetHash();
451 : // Age transaction for InstantSend
452 1 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, mocked_time_for_is);
453 1 : m_node.mempool->addUnchecked(entry.Time(Now<NodeSeconds>()).FromTx(tx));
454 1 : BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
455 1 : BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
456 :
457 1 : const int SEQUENCE_LOCK_TIME = 512; // Sequence locks pass 512 seconds later
458 12 : for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i)
459 11 : m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += SEQUENCE_LOCK_TIME; // Trick the MedianTimePast
460 : {
461 1 : CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
462 1 : BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, *CreateBlockIndex(active_chain_tip->nHeight + 1, active_chain_tip)));
463 : }
464 :
465 12 : for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i) {
466 11 : CBlockIndex* ancestor{Assert(m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i))};
467 11 : ancestor->nTime -= SEQUENCE_LOCK_TIME; // undo tricked MTP
468 11 : }
469 :
470 : // absolute height locked
471 1 : tx.vin[0].prevout.hash = txFirst[2]->GetHash();
472 1 : tx.vin[0].nSequence = CTxIn::MAX_SEQUENCE_NONFINAL;
473 1 : prevheights[0] = baseheight + 3;
474 1 : tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
475 1 : hash = tx.GetHash();
476 : // Age transaction for InstantSend
477 1 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, mocked_time_for_is);
478 1 : m_node.mempool->addUnchecked(entry.Time(Now<NodeSeconds>()).FromTx(tx));
479 1 : BOOST_CHECK(!CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime fails
480 1 : BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
481 1 : BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
482 :
483 : // absolute time locked
484 1 : tx.vin[0].prevout.hash = txFirst[3]->GetHash();
485 1 : tx.nLockTime = m_node.chainman->ActiveChain().Tip()->GetMedianTimePast();
486 1 : prevheights.resize(1);
487 1 : prevheights[0] = baseheight + 4;
488 1 : hash = tx.GetHash();
489 : // Age transaction for InstantSend
490 1 : m_node.clhandler->UpdateTxFirstSeenMap({hash}, mocked_time_for_is);
491 1 : m_node.mempool->addUnchecked(entry.Time(Now<NodeSeconds>()).FromTx(tx));
492 1 : BOOST_CHECK(!CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime fails
493 1 : BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
494 1 : BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
495 :
496 : // mempool-dependent transactions (not added)
497 1 : tx.vin[0].prevout.hash = hash;
498 1 : prevheights[0] = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
499 1 : tx.nLockTime = 0;
500 1 : tx.vin[0].nSequence = 0;
501 1 : BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
502 1 : BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
503 1 : tx.vin[0].nSequence = 1;
504 1 : BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
505 1 : tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
506 1 : BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
507 1 : tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
508 1 : BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
509 :
510 1 : BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
511 :
512 : // None of the of the absolute height/time locked tx should have made
513 : // it into the template because we still check IsFinalTx in CreateNewBlock,
514 : // but relative locked txs will if inconsistently added to mempool.
515 : // For now these will still generate a valid template until BIP68 soft fork
516 1 : BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3U);
517 : // However if we advance height by 1 and time by SEQUENCE_LOCK_TIME, all of them should be mined
518 12 : for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i) {
519 11 : CBlockIndex* ancestor{Assert(m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i))};
520 11 : ancestor->nTime += SEQUENCE_LOCK_TIME; // Trick the MedianTimePast
521 11 : }
522 6 : }
523 :
524 1 : void MinerTestingSetup::TestPrioritisedMining(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst)
525 : {
526 1 : TestMemPoolEntryHelper entry;
527 :
528 : // Test that a tx below min fee but prioritised is included
529 1 : CMutableTransaction tx;
530 1 : tx.vin.resize(1);
531 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
532 1 : tx.vin[0].prevout.n = 0;
533 1 : tx.vin[0].scriptSig = CScript() << OP_1;
534 1 : tx.vout.resize(1);
535 1 : tx.vout[0].nValue = 5000000000LL; // 0 fee
536 1 : uint256 hashFreePrioritisedTx = tx.GetHash();
537 1 : m_node.mempool->addUnchecked(entry.Fee(0).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
538 1 : m_node.mempool->PrioritiseTransaction(hashFreePrioritisedTx, 5 * COIN);
539 :
540 1 : tx.vin[0].prevout.hash = txFirst[1]->GetHash();
541 1 : tx.vin[0].prevout.n = 0;
542 1 : tx.vout[0].nValue = 5000000000LL - 1000;
543 : // This tx has a low fee: 1000 satoshis
544 1 : uint256 hashParentTx = tx.GetHash(); // save this txid for later use
545 1 : m_node.mempool->addUnchecked(entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
546 :
547 : // This tx has a medium fee: 10000 satoshis
548 1 : tx.vin[0].prevout.hash = txFirst[2]->GetHash();
549 1 : tx.vout[0].nValue = 5000000000LL - 10000;
550 1 : uint256 hashMediumFeeTx = tx.GetHash();
551 1 : m_node.mempool->addUnchecked(entry.Fee(10000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
552 1 : m_node.mempool->PrioritiseTransaction(hashMediumFeeTx, -5 * COIN);
553 :
554 : // This tx also has a low fee, but is prioritised
555 1 : tx.vin[0].prevout.hash = hashParentTx;
556 1 : tx.vout[0].nValue = 5000000000LL - 1000 - 1000; // 1000 satoshi fee
557 1 : uint256 hashPrioritsedChild = tx.GetHash();
558 1 : m_node.mempool->addUnchecked(entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
559 1 : m_node.mempool->PrioritiseTransaction(hashPrioritsedChild, 2 * COIN);
560 :
561 : // Test that transaction selection properly updates ancestor fee calculations as prioritised
562 : // parents get included in a block. Create a transaction with two prioritised ancestors, each
563 : // included by itself: FreeParent <- FreeChild <- FreeGrandchild.
564 : // When FreeParent is added, a modified entry will be created for FreeChild + FreeGrandchild
565 : // FreeParent's prioritisation should not be included in that entry.
566 : // When FreeChild is included, FreeChild's prioritisation should also not be included.
567 1 : tx.vin[0].prevout.hash = txFirst[3]->GetHash();
568 1 : tx.vout[0].nValue = 5000000000LL; // 0 fee
569 1 : uint256 hashFreeParent = tx.GetHash();
570 1 : m_node.mempool->addUnchecked(entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
571 1 : m_node.mempool->PrioritiseTransaction(hashFreeParent, 10 * COIN);
572 :
573 1 : tx.vin[0].prevout.hash = hashFreeParent;
574 1 : tx.vout[0].nValue = 5000000000LL; // 0 fee
575 1 : uint256 hashFreeChild = tx.GetHash();
576 1 : m_node.mempool->addUnchecked(entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
577 1 : m_node.mempool->PrioritiseTransaction(hashFreeChild, 1 * COIN);
578 :
579 1 : tx.vin[0].prevout.hash = hashFreeChild;
580 1 : tx.vout[0].nValue = 5000000000LL; // 0 fee
581 1 : uint256 hashFreeGrandchild = tx.GetHash();
582 1 : m_node.mempool->addUnchecked(entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
583 :
584 : // Age transaction for InstantSend
585 1 : m_node.clhandler->UpdateTxFirstSeenMap({hashMediumFeeTx, hashPrioritsedChild, hashParentTx, hashFreeParent, hashFreeChild, hashFreeGrandchild, hashFreePrioritisedTx}, std::chrono::duration_cast<std::chrono::seconds>(Now<NodeSeconds>().time_since_epoch()).count() - WAIT_FOR_ISLOCK_TIMEOUT);
586 1 : auto pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
587 1 : BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U);
588 1 : BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashFreeParent);
589 1 : BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashFreePrioritisedTx);
590 1 : BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashParentTx);
591 1 : BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashPrioritsedChild);
592 1 : BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashFreeChild);
593 7 : for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
594 : // The FreeParent and FreeChild's prioritisations should not impact the child.
595 6 : BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeGrandchild);
596 : // De-prioritised transaction should not be included.
597 6 : BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashMediumFeeTx);
598 6 : }
599 1 : }
600 :
601 : // NOTE: These tests rely on CreateNewBlock doing its own self-validation!
602 148 : BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
603 : {
604 : // Note that by default, these tests run with size accounting enabled.
605 1 : const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
606 1 : const CChainParams& chainparams = *chainParams;
607 1 : CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
608 1 : std::unique_ptr<CBlockTemplate> pblocktemplate, pemptyblocktemplate;
609 :
610 : // Simple block creation, nothing special yet:
611 1 : BOOST_CHECK(pemptyblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
612 :
613 : // We can't make transactions until we have inputs
614 : // Therefore, load 100 blocks :)
615 1 : int baseheight = 0;
616 1 : std::vector<CTransactionRef> txFirst;
617 :
618 121 : auto createAndProcessEmptyBlock = [&]() {
619 120 : int i = m_node.chainman->ActiveChain().Height() % blockinfo_size;
620 120 : CBlock *pblock = &pemptyblocktemplate->block; // pointer for convenience
621 : {
622 120 : LOCK(cs_main);
623 120 : pblock->nVersion = VERSIONBITS_TOP_BITS;
624 120 : pblock->nTime = m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1;
625 120 : CMutableTransaction txCoinbase(*pblock->vtx[0]);
626 120 : txCoinbase.nVersion = 1;
627 120 : txCoinbase.vin[0].scriptSig = CScript{} << (m_node.chainman->ActiveChain().Height() + 1) << BLOCKINFO[i].extranonce;
628 120 : txCoinbase.vout[0].scriptPubKey = CScript();
629 120 : pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
630 120 : if (txFirst.size() == 0)
631 1 : baseheight = m_node.chainman->ActiveChain().Height();
632 120 : if (txFirst.size() < 4)
633 4 : txFirst.push_back(pblock->vtx[0]);
634 120 : pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
635 120 : pblock->nNonce = BLOCKINFO[i].nonce;
636 :
637 : // This will usually succeed in the first round as we take the nonce from BLOCKINFO
638 : // It's however useful when adding new blocks with unknown nonces (you should add the found block to BLOCKINFO)
639 582678 : while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, chainparams.GetConsensus())) {
640 582558 : pblock->nNonce++;
641 : }
642 120 : }
643 120 : std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
644 120 : BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, nullptr));
645 120 : pblock->hashPrevBlock = pblock->GetHash();
646 120 : };
647 :
648 120 : for ([[maybe_unused]] const auto& _ : BLOCKINFO) {
649 119 : createAndProcessEmptyBlock();
650 : }
651 :
652 :
653 : {
654 1 : LOCK(cs_main);
655 1 : LOCK(m_node.mempool->cs);
656 :
657 1 : TestBasicMining(chainparams, scriptPubKey, txFirst, baseheight);
658 1 : }
659 :
660 : // Mine an empty block
661 1 : createAndProcessEmptyBlock();
662 :
663 : {
664 1 : LOCK(cs_main);
665 :
666 1 : SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1);
667 :
668 1 : BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
669 1 : BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
670 1 : } // unlock cs_main while calling InvalidateBlock
671 :
672 1 : BlockValidationState state;
673 2 : m_node.chainman->ActiveChainstate().InvalidateBlock(state, WITH_LOCK(cs_main, return m_node.chainman->ActiveChain().Tip()));
674 :
675 1 : SetMockTime(0);
676 1 : m_node.mempool->clear();
677 :
678 1 : LOCK2(cs_main, m_node.mempool->cs);
679 1 : TestPackageSelection(chainparams, scriptPubKey, txFirst);
680 :
681 1 : m_node.chainman->ActiveChain().Tip()->nHeight--;
682 1 : SetMockTime(0);
683 1 : m_node.mempool->clear();
684 :
685 1 : TestPrioritisedMining(chainparams, scriptPubKey, txFirst);
686 1 : }
687 :
688 146 : BOOST_AUTO_TEST_SUITE_END()
|