#!/usr/bin/env python2 # Copyright (c) 2016-2020 The Hush developers # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the GPLv3 software license, see the accompanying # file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html # Exercise the wallet keypool, and interaction with wallet encryption/locking # Add python-bitcoinrpc to module search path: from test_framework.authproxy import JSONRPCException from test_framework.util import check_json_precision, initialize_chain, \ start_nodes, start_node, stop_nodes, wait_bitcoinds, bitcoind_processes import os import sys import shutil import tempfile import traceback def check_array_result(object_array, to_match, expected): """ Pass in array of JSON objects, a dictionary with key/value pairs to match against, and another dictionary with expected key/value pairs. """ num_matched = 0 for item in object_array: all_match = True for key,value in to_match.items(): if item[key] != value: all_match = False if not all_match: continue for key,value in expected.items(): if item[key] != value: raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value))) num_matched = num_matched+1 if num_matched == 0: raise AssertionError("No objects matched %s"%(str(to_match))) def run_test(nodes, tmpdir): # Encrypt wallet and wait to terminate nodes[0].encryptwallet('test') bitcoind_processes[0].wait() # Restart node 0 nodes[0] = start_node(0, tmpdir) # Keep creating keys addr = nodes[0].getnewaddress() try: addr = nodes[0].getnewaddress() raise AssertionError('Keypool should be exhausted after one address') except JSONRPCException,e: assert(e.error['code']==-12) # put three new keys in the keypool nodes[0].walletpassphrase('test', 12000) nodes[0].keypoolrefill(3) nodes[0].walletlock() # drain the keys addr = set() addr.add(nodes[0].getrawchangeaddress()) addr.add(nodes[0].getrawchangeaddress()) addr.add(nodes[0].getrawchangeaddress()) addr.add(nodes[0].getrawchangeaddress()) # assert that four unique addresses were returned assert(len(addr) == 4) # the next one should fail try: addr = nodes[0].getrawchangeaddress() raise AssertionError('Keypool should be exhausted after three addresses') except JSONRPCException,e: assert(e.error['code']==-12) def main(): import optparse parser = optparse.OptionParser(usage="%prog [options]") parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true", help="Leave bitcoinds and test.* datadir on exit or error") parser.add_option("--srcdir", dest="srcdir", default="../../src", help="Source directory containing bitcoind/bitcoin-cli (default: %default%)") parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), help="Root directory for datadirs") (options, args) = parser.parse_args() os.environ['PATH'] = options.srcdir+":"+os.environ['PATH'] check_json_precision() success = False nodes = [] try: print("Initializing test directory "+options.tmpdir) if not os.path.isdir(options.tmpdir): os.makedirs(options.tmpdir) initialize_chain(options.tmpdir) nodes = start_nodes(1, options.tmpdir, extra_args=[['-experimentalfeatures', '-developerencryptwallet']]) run_test(nodes, options.tmpdir) success = True except AssertionError as e: print("Assertion failed: "+e.message) except JSONRPCException as e: print("JSONRPC error: "+e.error['message']) traceback.print_tb(sys.exc_info()[2]) except Exception as e: print("Unexpected exception caught during testing: "+str(sys.exc_info()[0])) traceback.print_tb(sys.exc_info()[2]) if not options.nocleanup: print("Cleaning up") stop_nodes(nodes) wait_bitcoinds() shutil.rmtree(options.tmpdir) if success: print("Tests successful") sys.exit(0) else: print("Failed") sys.exit(1) if __name__ == '__main__': main()