diff options
author | MarcoFalke <falke.marco@gmail.com> | 2019-01-31 11:07:45 -0500 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2019-01-31 11:07:51 -0500 |
commit | 252fd15addf1cd061c3b6258ad916df7deeecf83 (patch) | |
tree | d47f3028534b6eed320da0dee5e317a067b2b9d8 /test/functional | |
parent | 4d661baf1aca4226d1c4ec89fe7e44c1f93f04da (diff) | |
parent | 3c3e31c3a49c657093cacdff2c1c5e25363902ce (diff) |
Merge #13926: [Tools] bitcoin-wallet - a tool for creating and managing wallets offline
3c3e31c3a4 [tests] Add wallet-tool test (João Barbosa)
49d2374acf [tools] Add wallet inspection and modification tool (Jonas Schnelli)
Pull request description:
Adds an offline tool `bitcoin-wallet-tool` for wallet creation and maintenance.
Currently this tool can create a new wallet file, display information on an existing wallet, and run the salvage and zapwallettxes maintenance tasks on an existing wallet. It can later be extended to support other common wallet maintenance tasks.
Doing wallet maintenance tasks in an offline tool makes much more sense (and is potentially safer) than having to spin up a full node.
Tree-SHA512: 75a28b8a58858d9d76c7532db40eacdefc5714ea5aab536fb1dc9756e2f7d750d69d68d59c50a68e633ce38fb5b8c3e3d4880db30fe01561e07ce58d42bceb2b
Diffstat (limited to 'test/functional')
-rwxr-xr-x | test/functional/test_framework/test_framework.py | 1 | ||||
-rwxr-xr-x | test/functional/test_runner.py | 3 | ||||
-rwxr-xr-x | test/functional/tool_wallet.py | 101 |
3 files changed, 104 insertions, 1 deletions
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 352fa32b5b..6dcaff0696 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -139,6 +139,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): config = configparser.ConfigParser() config.read_file(open(self.options.configfile)) + self.config = config self.options.bitcoind = os.getenv("BITCOIND", default=config["environment"]["BUILDDIR"] + '/src/bitcoind' + config["environment"]["EXEEXT"]) self.options.bitcoincli = os.getenv("BITCOINCLI", default=config["environment"]["BUILDDIR"] + '/src/bitcoin-cli' + config["environment"]["EXEEXT"]) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 8c6f6706e7..5c92370b85 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -108,6 +108,7 @@ BASE_SCRIPTS = [ 'interface_bitcoin_cli.py', 'mempool_resurrect.py', 'wallet_txn_doublespend.py --mineblock', + 'tool_wallet.py', 'wallet_txn_clone.py', 'wallet_txn_clone.py --segwit', 'rpc_getchaintips.py', @@ -562,7 +563,7 @@ class TestResult(): def check_script_prefixes(): """Check that test scripts start with one of the allowed name prefixes.""" - good_prefixes_re = re.compile("(example|feature|interface|mempool|mining|p2p|rpc|wallet)_") + good_prefixes_re = re.compile("(example|feature|interface|mempool|mining|p2p|rpc|wallet|tool)_") bad_script_names = [script for script in ALL_SCRIPTS if good_prefixes_re.match(script) is None] if bad_script_names: diff --git a/test/functional/tool_wallet.py b/test/functional/tool_wallet.py new file mode 100755 index 0000000000..fbcf21e729 --- /dev/null +++ b/test/functional/tool_wallet.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# Copyright (c) 2018 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 bitcoin-wallet.""" +import subprocess +import textwrap + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal + +class ToolWalletTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 1 + self.setup_clean_chain = True + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def bitcoin_wallet_process(self, *args): + binary = self.config["environment"]["BUILDDIR"] + '/src/bitcoin-wallet' + self.config["environment"]["EXEEXT"] + args = ['-datadir={}'.format(self.nodes[0].datadir), '-regtest'] + list(args) + return subprocess.Popen([binary] + args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + + def assert_raises_tool_error(self, error, *args): + p = self.bitcoin_wallet_process(*args) + stdout, stderr = p.communicate() + assert_equal(p.poll(), 1) + assert_equal(stdout, '') + assert_equal(stderr.strip(), error) + + def assert_tool_output(self, output, *args): + p = self.bitcoin_wallet_process(*args) + stdout, stderr = p.communicate() + assert_equal(p.poll(), 0) + assert_equal(stderr, '') + assert_equal(stdout, output) + + def run_test(self): + + self.assert_raises_tool_error('Invalid command: foo', 'foo') + # `bitcoin-wallet help` is an error. Use `bitcoin-wallet -help` + self.assert_raises_tool_error('Invalid command: help', 'help') + self.assert_raises_tool_error('Error: two methods provided (info and create). Only one method should be provided.', 'info', 'create') + self.assert_raises_tool_error('Error parsing command line arguments: Invalid parameter -foo', '-foo') + self.assert_raises_tool_error('Error loading wallet.dat. Is wallet being used by other process?', '-wallet=wallet.dat', 'info') + self.assert_raises_tool_error('Error: no wallet file at nonexistent.dat', '-wallet=nonexistent.dat', 'info') + + # stop the node to close the wallet to call info command + self.stop_node(0) + + out = textwrap.dedent('''\ + Wallet info + =========== + Encrypted: no + HD (hd seed available): yes + Keypool Size: 2 + Transactions: 0 + Address Book: 3 + ''') + self.assert_tool_output(out, '-wallet=wallet.dat', 'info') + + # mutate the wallet to check the info command output changes accordingly + self.start_node(0) + self.nodes[0].generate(1) + self.stop_node(0) + + out = textwrap.dedent('''\ + Wallet info + =========== + Encrypted: no + HD (hd seed available): yes + Keypool Size: 2 + Transactions: 1 + Address Book: 3 + ''') + self.assert_tool_output(out, '-wallet=wallet.dat', 'info') + + out = textwrap.dedent('''\ + Topping up keypool... + Wallet info + =========== + Encrypted: no + HD (hd seed available): yes + Keypool Size: 2000 + Transactions: 0 + Address Book: 0 + ''') + self.assert_tool_output(out, '-wallet=foo', 'create') + + self.start_node(0, ['-wallet=foo']) + out = self.nodes[0].getwalletinfo() + self.stop_node(0) + + assert_equal(0, out['txcount']) + assert_equal(1000, out['keypoolsize']) + assert_equal(1000, out['keypoolsize_hd_internal']) + assert_equal(True, 'hdseedid' in out) + +if __name__ == '__main__': + ToolWalletTest().main() |