Repository: bitcoin/bitcoin
File: test/functional/interface_ipc.py (Python)

Code before:
                self.log.debug("Create a template")
                opts = self.capnp_modules['mining'].BlockCreateOptions()
                opts.useMempool = True
                opts.blockReservedWeight = 4000
                opts.coinbaseOutputMaxAdditionalSigops = 0
                template = await stack.enter_async_context(destroying((await mining.result.createNewBlock(opts)).result, ctx))
                self.log.debug("Test some inspectors of Template")
                header = await template.getBlockHeader(ctx)
                assert_equal(len(header.result), block_header_size)
                block = await self.parse_and_deserialize_block(template, ctx)
                assert_equal(ser_uint256(block.hashPrevBlock), newblockref.result.hash)
                assert len(block.vtx) >= 1
                txfees = await template.getTxFees(ctx)
                assert_equal(len(txfees.result), 0)
                txsigops = await template.getTxSigops(ctx)
                assert_equal(len(txsigops.result), 0)
                coinbase_data = BytesIO((await template.getCoinbaseTx(ctx)).result)
                coinbase = CTransaction()
                coinbase.deserialize(coinbase_data)
                assert_equal(coinbase.vin[0].prevout.hash, 0)
                self.log.debug("Wait for a new template")
                waitoptions = self.capnp_modules['mining'].BlockWaitOptions()
                waitoptions.timeout = timeout
                waitoptions.feeThreshold = 1
                self.generate(self.nodes[0], 1)
                template2 = await stack.enter_async_context(destroying((await template.waitNext(ctx, waitoptions)).result, ctx))
                block2 = await self.parse_and_deserialize_block(template2, ctx)
                assert_equal(len(block2.vtx), 1)
                self.log.debug("Wait for another, but time out")
                template3 = await template2.waitNext(ctx, waitoptions)
                assert_equal(template3.to_dict(), {})
                self.log.debug("Wait for another, get one after increase in fees in the mempool")
                miniwallet.send_self_transfer(fee_rate=10, from_node=self.nodes[0])
                template4 = await stack.enter_async_context(destroying((await template2.waitNext(ctx, waitoptions)).result, ctx))
                block3 = await self.parse_and_deserialize_block(template4, ctx)
                assert_equal(len(block3.vtx), 2)
                self.log.debug("Wait again, this should return the same template, since the fee threshold is zero")
                waitoptions.feeThreshold = 0
                template5 = await stack.enter_async_context(destroying((await template4.waitNext(ctx, waitoptions)).result, ctx))
                block4 = await self.parse_and_deserialize_block(template5, ctx)
                assert_equal(len(block4.vtx), 2)
                waitoptions.feeThreshold = 1
                self.log.debug("Wait for another, get one after increase in fees in the mempool")
                miniwallet.send_self_transfer(fee_rate=10, from_node=self.nodes[0])
                template6 = await stack.enter_async_context(destroying((await template5.waitNext(ctx, waitoptions)).result, ctx))
                block4 = await self.parse_and_deserialize_block(template6, ctx)
                assert_equal(len(block4.vtx), 3)
                self.log.debug("Wait for another, but time out, since the fee threshold is set now")
                template7 = await template6.waitNext(ctx, waitoptions)
                assert_equal(template7.to_dict(), {})


Review comment (suggestion):
In fac12f7cf9ebc0b906bbb20ae126cf7e7552fdbb _test: fix interface_ipc.py template destruction_:

I think the original intention here was to demonstrate that `generate` interrupts an ongoing `waitNext()`.

Now it only shows that `waitNext()` returns immediately if the tip has changes before calling. Though perhaps it always did that by accident.

Code after:
        self.log.info("Running mining test")
        block_hash_size = 32
        block_header_size = 80
        timeout = 1000.0 # 1000 milliseconds
        miniwallet = MiniWallet(self.nodes[0])

        async def async_routine():
            ctx, init = await self.make_capnp_init_ctx()
            self.log.debug("Create Mining proxy object")
            mining = init.makeMining(ctx).result
            self.log.debug("Test simple inspectors")
            assert (await mining.isTestChain(ctx)).result
            assert not (await mining.isInitialBlockDownload(ctx)).result
            blockref = await mining.getTip(ctx)
            assert blockref.hasResult
            assert_equal(len(blockref.result.hash), block_hash_size)
            current_block_height = self.nodes[0].getchaintips()[0]["height"]
            assert blockref.result.height == current_block_height
            self.log.debug("Mine a block")
            newblockref = (await wait_and_do(
                mining.waitTipChanged(ctx, blockref.result.hash, timeout),
                lambda: self.generate(self.nodes[0], 1))).result
            assert_equal(len(newblockref.hash), block_hash_size)
            assert_equal(newblockref.height, current_block_height + 1)
            self.log.debug("Wait for timeout")
            oldblockref = (await mining.waitTipChanged(ctx, newblockref.hash, timeout)).result
            assert_equal(len(newblockref.hash), block_hash_size)
            assert_equal(oldblockref.hash, newblockref.hash)
            assert_equal(oldblockref.height, newblockref.height)

            async with AsyncExitStack() as stack:
                self.log.debug("Create a template")
                opts = self.capnp_modules['mining'].BlockCreateOptions()
                opts.useMempool = True
                opts.blockReservedWeight = 4000
                opts.coinbaseOutputMaxAdditionalSigops = 0
                template = await create_block_template(mining, stack, ctx, opts)

                self.log.debug("Test some inspectors of Template")
                header = (await template.getBlockHeader(ctx)).result
                assert_equal(len(header), block_header_size)
                block = await self.parse_and_deserialize_block(template, ctx)
                assert_equal(ser_uint256(block.hashPrevBlock), newblockref.hash)
                assert len(block.vtx) >= 1
                txfees = await template.getTxFees(ctx)
                assert_equal(len(txfees.result), 0)
                txsigops = await template.getTxSigops(ctx)
                assert_equal(len(txsigops.result), 0)
                coinbase_data = BytesIO((await template.getCoinbaseTx(ctx)).result)
                coinbase = CTransaction()
                coinbase.deserialize(coinbase_data)