|
7 | 7 | from io import BytesIO |
8 | 8 | from pathlib import Path |
9 | 9 | import shutil |
10 | | -from test_framework.messages import (CBlock, CTransaction, ser_uint256) |
| 10 | +from test_framework.messages import (CBlock, CTransaction, ser_uint256, COIN) |
11 | 11 | from test_framework.test_framework import (BitcoinTestFramework, assert_equal) |
12 | 12 | from test_framework.wallet import MiniWallet |
13 | 13 |
|
@@ -73,6 +73,12 @@ async def parse_and_deserialize_block(self, block_template, ctx): |
73 | 73 | block.deserialize(block_data) |
74 | 74 | return block |
75 | 75 |
|
| 76 | + async def parse_and_deserialize_coinbase_tx(self, block_template, ctx): |
| 77 | + coinbase_data = BytesIO((await block_template.result.getCoinbaseTx(ctx)).result) |
| 78 | + tx = CTransaction() |
| 79 | + tx.deserialize(coinbase_data) |
| 80 | + return tx |
| 81 | + |
76 | 82 | def run_echo_test(self): |
77 | 83 | self.log.info("Running echo test") |
78 | 84 | async def async_routine(): |
@@ -170,6 +176,41 @@ async def async_routine(): |
170 | 176 | self.log.debug("Wait for another, but time out, since the fee threshold is set now") |
171 | 177 | template7 = await template6.result.waitNext(ctx, waitoptions) |
172 | 178 | assert_equal(template7.to_dict(), {}) |
| 179 | + |
| 180 | + current_block_height = self.nodes[0].getchaintips()[0]["height"] |
| 181 | + check_opts = self.capnp_modules['mining'].BlockCheckOptions() |
| 182 | + template = await mining.result.createNewBlock(opts) |
| 183 | + block = await self.parse_and_deserialize_block(template, ctx) |
| 184 | + coinbase = await self.parse_and_deserialize_coinbase_tx(template, ctx) |
| 185 | + balance = miniwallet.get_balance() |
| 186 | + coinbase.vout[0].scriptPubKey = miniwallet.get_output_script() |
| 187 | + coinbase.vout[0].nValue = COIN |
| 188 | + block.vtx[0] = coinbase |
| 189 | + block.hashMerkleRoot = block.calc_merkle_root() |
| 190 | + original_version = block.nVersion |
| 191 | + self.log.debug("Submit a block with a bad version") |
| 192 | + block.nVersion = 0 |
| 193 | + block.solve() |
| 194 | + res = await mining.result.checkBlock(block.serialize(), check_opts) |
| 195 | + assert_equal(res.result, False) |
| 196 | + assert_equal(res.reason, "bad-version(0x00000000)") |
| 197 | + res = await template.result.submitSolution(ctx, block.nVersion, block.nTime, block.nNonce, coinbase.serialize()) |
| 198 | + assert_equal(res.result, False) |
| 199 | + self.log.debug("Submit a valid block") |
| 200 | + block.nVersion = original_version |
| 201 | + block.solve() |
| 202 | + res = await mining.result.checkBlock(block.serialize(), check_opts) |
| 203 | + assert_equal(res.result, True) |
| 204 | + res = await template.result.submitSolution(ctx, block.nVersion, block.nTime, block.nNonce, coinbase.serialize()) |
| 205 | + assert_equal(res.result, True) |
| 206 | + assert_equal(self.nodes[0].getchaintips()[0]["height"], current_block_height + 1) |
| 207 | + miniwallet.rescan_utxos() |
| 208 | + assert_equal(miniwallet.get_balance(), balance + 1) |
| 209 | + self.log.debug("Check block should fail now, since it is a duplicate") |
| 210 | + res = await mining.result.checkBlock(block.serialize(), check_opts) |
| 211 | + assert_equal(res.result, False) |
| 212 | + assert_equal(res.reason, "inconclusive-not-best-prevblk") |
| 213 | + |
173 | 214 | self.log.debug("Destroy template objects") |
174 | 215 | template.result.destroy(ctx) |
175 | 216 | template2.result.destroy(ctx) |
|
0 commit comments