|
4 | 4 | # file COPYING or http://www.opensource.org/licenses/mit-license.php. |
5 | 5 | """Test the IPC (multiprocess) Mining interface.""" |
6 | 6 | import asyncio |
| 7 | +import time |
7 | 8 | from contextlib import AsyncExitStack |
8 | 9 | from io import BytesIO |
9 | 10 | from test_framework.blocktools import NULL_OUTPOINT |
10 | 11 | from test_framework.messages import ( |
| 12 | + CBlockHeader, |
11 | 13 | CTransaction, |
12 | 14 | CTxIn, |
13 | 15 | CTxOut, |
14 | 16 | CTxInWitness, |
15 | 17 | ser_uint256, |
16 | 18 | COIN, |
| 19 | + from_hex, |
| 20 | + msg_headers, |
17 | 21 | ) |
18 | 22 | from test_framework.script import ( |
19 | 23 | CScript, |
|
22 | 26 | from test_framework.test_framework import BitcoinTestFramework |
23 | 27 | from test_framework.util import ( |
24 | 28 | assert_equal, |
| 29 | + assert_greater_than_or_equal, |
25 | 30 | assert_not_equal |
26 | 31 | ) |
27 | 32 | from test_framework.wallet import MiniWallet |
| 33 | +from test_framework.p2p import P2PInterface |
28 | 34 | from test_framework.ipc_util import ( |
29 | 35 | destroying, |
30 | 36 | mining_create_block_template, |
@@ -155,18 +161,36 @@ def run_block_template_test(self): |
155 | 161 |
|
156 | 162 | async def async_routine(): |
157 | 163 | ctx, mining = await self.make_mining_ctx() |
158 | | - blockref = await mining.getTip(ctx) |
159 | 164 |
|
160 | 165 | async with AsyncExitStack() as stack: |
| 166 | + self.log.debug("createNewBlock() should wait if tip is still updating") |
| 167 | + self.disconnect_nodes(0, 1) |
| 168 | + node1_block_hash = self.generate(self.nodes[1], 1, sync_fun=self.no_op)[0] |
| 169 | + header = from_hex(CBlockHeader(), self.nodes[1].getblockheader(node1_block_hash, False)) |
| 170 | + header_only_peer = self.nodes[0].add_p2p_connection(P2PInterface()) |
| 171 | + header_only_peer.send_and_ping(msg_headers([header])) |
| 172 | + start = time.time() |
| 173 | + async with destroying((await mining.createNewBlock(ctx, self.default_block_create_options, cooldown=True)).result, ctx): |
| 174 | + pass |
| 175 | + # Lower-bound only: a heavily loaded CI host might still exceed 0.9s |
| 176 | + # even without the cooldown, so this can miss regressions but avoids |
| 177 | + # spurious failures. |
| 178 | + assert_greater_than_or_equal(time.time() - start, 0.9) |
| 179 | + |
| 180 | + header_only_peer.peer_disconnect() |
| 181 | + self.connect_nodes(0, 1) |
| 182 | + self.sync_all() |
| 183 | + |
161 | 184 | self.log.debug("Create a template") |
162 | 185 | template = await mining_create_block_template(mining, stack, ctx, self.default_block_create_options) |
163 | 186 |
|
164 | 187 | self.log.debug("Test some inspectors of Template") |
165 | 188 | header = (await template.getBlockHeader(ctx)).result |
166 | 189 | assert_equal(len(header), block_header_size) |
167 | 190 | block = await mining_get_block(template, ctx) |
168 | | - assert_equal(ser_uint256(block.hashPrevBlock), blockref.result.hash) |
169 | | - assert len(block.vtx) >= 1 |
| 191 | + current_tip = self.nodes[0].getbestblockhash() |
| 192 | + assert_equal(ser_uint256(block.hashPrevBlock), ser_uint256(int(current_tip, 16))) |
| 193 | + assert_greater_than_or_equal(len(block.vtx), 1) |
170 | 194 | txfees = await template.getTxFees(ctx) |
171 | 195 | assert_equal(len(txfees.result), 0) |
172 | 196 | txsigops = await template.getTxSigops(ctx) |
@@ -232,7 +256,7 @@ async def async_routine(): |
232 | 256 | current_block_height = self.nodes[0].getchaintips()[0]["height"] |
233 | 257 | check_opts = self.capnp_modules['mining'].BlockCheckOptions() |
234 | 258 |
|
235 | | - async with destroying((await mining.createNewBlock(ctx, self.default_block_create_options)).result, ctx) as template: |
| 259 | + async with destroying((await mining.createNewBlock(ctx, self.default_block_create_options, cooldown=True)).result, ctx) as template: |
236 | 260 | block = await mining_get_block(template, ctx) |
237 | 261 | balance = self.miniwallet.get_balance() |
238 | 262 | coinbase = await self.build_coinbase_test(template, ctx, self.miniwallet) |
|
0 commit comments