From e4356f6a6c18e5027a064a4d3a5deda27985f584 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Tue, 28 Apr 2020 09:26:09 +0200 Subject: [PATCH] Testcase for wallet issue with orphaned rewards. This adds a new test case demonstrating the wallet issue when block rewards are orphaned (https://github.com/bitcoin/bitcoin/issues/14148). --- test/functional/test_runner.py | 1 + test/functional/wallet_orphanedreward.py | 61 ++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100755 test/functional/wallet_orphanedreward.py diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 49f269f8b4f..93a852ac793 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -283,6 +283,7 @@ BASE_SCRIPTS = [ 'feature_logging.py', 'feature_anchors.py', 'feature_coinstatsindex.py', + 'wallet_orphanedreward.py', 'p2p_node_network_limited.py', 'p2p_permissions.py', 'feature_blocksdir.py', diff --git a/test/functional/wallet_orphanedreward.py b/test/functional/wallet_orphanedreward.py new file mode 100755 index 00000000000..e1544cbb48d --- /dev/null +++ b/test/functional/wallet_orphanedreward.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# Copyright (c) 2020-2021 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test orphaned block rewards in the wallet.""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal + +class OrphanedBlockRewardTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 2 + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def run_test(self): + # Generate some blocks and obtain some coins on node 0. We send + # some balance to node 1, which will hold it as a single coin. + self.nodes[0].generate(150) + self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 10) + self.nodes[0].generate(1) + + # Get a block reward with node 1 and remember the block so we can orphan + # it later. + self.sync_blocks() + blk = self.nodes[1].generate(1)[0] + self.sync_blocks() + + # Let the block reward mature and send coins including both + # the existing balance and the block reward. + self.nodes[0].generate(150) + assert_equal(self.nodes[1].getbalance(), 10 + 25) + txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 30) + + # Orphan the block reward and make sure that the original coins + # from the wallet can still be spent. + self.nodes[0].invalidateblock(blk) + self.nodes[0].generate(152) + self.sync_blocks() + # Without the following abandontransaction call, the coins are + # not considered available yet. + assert_equal(self.nodes[1].getbalances()["mine"], { + "trusted": 0, + "untrusted_pending": 0, + "immature": 0, + }) + # The following abandontransaction is necessary to make the later + # lines succeed, and probably should not be needed; see + # https://github.com/bitcoin/bitcoin/issues/14148. + self.nodes[1].abandontransaction(txid) + assert_equal(self.nodes[1].getbalances()["mine"], { + "trusted": 10, + "untrusted_pending": 0, + "immature": 0, + }) + self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 9) + +if __name__ == '__main__': + OrphanedBlockRewardTest().main()