aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/config.ini.in1
-rwxr-xr-xtest/functional/feature_blockfilterindex_prune.py8
-rwxr-xr-xtest/functional/mocks/signer.py102
-rwxr-xr-xtest/functional/rpc_blockchain.py19
-rwxr-xr-xtest/functional/rpc_help.py5
-rwxr-xr-xtest/functional/test_framework/test_framework.py17
-rwxr-xr-xtest/functional/test_framework/test_node.py4
-rw-r--r--test/functional/test_framework/wallet.py9
-rwxr-xr-xtest/functional/test_runner.py1
-rwxr-xr-xtest/functional/wallet_signer.py217
-rwxr-xr-xtest/functional/wallet_txn_clone.py7
-rwxr-xr-xtest/functional/wallet_txn_doublespend.py7
12 files changed, 375 insertions, 22 deletions
diff --git a/test/config.ini.in b/test/config.ini.in
index 77c9a720c3..e3872181cd 100644
--- a/test/config.ini.in
+++ b/test/config.ini.in
@@ -23,3 +23,4 @@ RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py
@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true
@ENABLE_FUZZ_TRUE@ENABLE_FUZZ=true
@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=true
+@ENABLE_EXTERNAL_SIGNER_TRUE@ENABLE_EXTERNAL_SIGNER=true
diff --git a/test/functional/feature_blockfilterindex_prune.py b/test/functional/feature_blockfilterindex_prune.py
index 455073ef9c..6648e8ecd9 100755
--- a/test/functional/feature_blockfilterindex_prune.py
+++ b/test/functional/feature_blockfilterindex_prune.py
@@ -5,8 +5,9 @@
"""Test blockfilterindex in conjunction with prune."""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
- assert_raises_rpc_error,
+ assert_equal,
assert_greater_than,
+ assert_raises_rpc_error,
)
@@ -16,17 +17,18 @@ class FeatureBlockfilterindexPruneTest(BitcoinTestFramework):
self.extra_args = [["-fastprune", "-prune=1"], ["-fastprune", "-prune=1", "-blockfilterindex=1"]]
def run_test(self):
- # test basic pruning compatibility & filter access of pruned blocks
self.log.info("check if we can access a blockfilter when pruning is enabled but no blocks are actually pruned")
+ self.wait_until(lambda: self.nodes[1].getindexinfo() == {'basic block filter index': {'synced': True, 'best_block_height': 200}})
assert len(self.nodes[1].getblockfilter(self.nodes[1].getbestblockhash())['filter']) > 0
# Mine two batches of blocks to avoid hitting NODE_NETWORK_LIMITED_MIN_BLOCKS disconnection
self.nodes[1].generate(250)
self.sync_all()
self.nodes[1].generate(250)
self.sync_all()
+ self.wait_until(lambda: self.nodes[1].getindexinfo() == {'basic block filter index': {'synced': True, 'best_block_height': 700}})
self.log.info("prune some blocks")
pruneheight = self.nodes[1].pruneblockchain(400)
- assert pruneheight != 0
+ assert_equal(pruneheight, 250)
self.log.info("check if we can access the tips blockfilter when we have pruned some blocks")
assert len(self.nodes[1].getblockfilter(self.nodes[1].getbestblockhash())['filter']) > 0
self.log.info("check if we can access the blockfilter of a pruned block")
diff --git a/test/functional/mocks/signer.py b/test/functional/mocks/signer.py
new file mode 100755
index 0000000000..676d0a0a4d
--- /dev/null
+++ b/test/functional/mocks/signer.py
@@ -0,0 +1,102 @@
+#!/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.
+
+import os
+import sys
+import argparse
+import json
+
+def perform_pre_checks():
+ mock_result_path = os.path.join(os.getcwd(), "mock_result")
+ if(os.path.isfile(mock_result_path)):
+ with open(mock_result_path, "r", encoding="utf8") as f:
+ mock_result = f.read()
+ if mock_result[0]:
+ sys.stdout.write(mock_result[2:])
+ sys.exit(int(mock_result[0]))
+
+def enumerate(args):
+ sys.stdout.write(json.dumps([{"fingerprint": "00000001", "type": "trezor", "model": "trezor_t"}, {"fingerprint": "00000002"}]))
+
+def getdescriptors(args):
+ xpub = "tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B"
+
+ sys.stdout.write(json.dumps({
+ "receive": [
+ "pkh([00000001/44'/1'/" + args.account + "']" + xpub + "/0/*)#vt6w3l3j",
+ "sh(wpkh([00000001/49'/1'/" + args.account + "']" + xpub + "/0/*))#r0grqw5x",
+ "wpkh([00000001/84'/1'/" + args.account + "']" + xpub + "/0/*)#x30uthjs"
+ ],
+ "internal": [
+ "pkh([00000001/44'/1'/" + args.account + "']" + xpub + "/1/*)#all0v2p2",
+ "sh(wpkh([00000001/49'/1'/" + args.account + "']" + xpub + "/1/*))#kwx4c3pe",
+ "wpkh([00000001/84'/1'/" + args.account + "']" + xpub + "/1/*)#h92akzzg"
+ ]
+ }))
+
+
+def displayaddress(args):
+ # Several descriptor formats are acceptable, so allowing for potential
+ # changes to InferDescriptor:
+ if args.fingerprint != "00000001":
+ return sys.stdout.write(json.dumps({"error": "Unexpected fingerprint", "fingerprint": args.fingerprint}))
+
+ expected_desc = [
+ "wpkh([00000001/84'/1'/0'/0/0]02c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7)#0yneg42r"
+ ]
+ if args.desc not in expected_desc:
+ return sys.stdout.write(json.dumps({"error": "Unexpected descriptor", "desc": args.desc}))
+
+ return sys.stdout.write(json.dumps({"address": "bcrt1qm90ugl4d48jv8n6e5t9ln6t9zlpm5th68x4f8g"}))
+
+def signtx(args):
+ if args.fingerprint != "00000001":
+ return sys.stdout.write(json.dumps({"error": "Unexpected fingerprint", "fingerprint": args.fingerprint}))
+
+ with open(os.path.join(os.getcwd(), "mock_psbt"), "r", encoding="utf8") as f:
+ mock_psbt = f.read()
+
+ if args.fingerprint == "00000001" :
+ sys.stdout.write(json.dumps({
+ "psbt": mock_psbt,
+ "complete": True
+ }))
+ else:
+ sys.stdout.write(json.dumps({"psbt": args.psbt}))
+
+parser = argparse.ArgumentParser(prog='./signer.py', description='External signer mock')
+parser.add_argument('--fingerprint')
+parser.add_argument('--chain', default='main')
+parser.add_argument('--stdin', action='store_true')
+
+subparsers = parser.add_subparsers(description='Commands', dest='command')
+subparsers.required = True
+
+parser_enumerate = subparsers.add_parser('enumerate', help='list available signers')
+parser_enumerate.set_defaults(func=enumerate)
+
+parser_getdescriptors = subparsers.add_parser('getdescriptors')
+parser_getdescriptors.set_defaults(func=getdescriptors)
+parser_getdescriptors.add_argument('--account', metavar='account')
+
+parser_displayaddress = subparsers.add_parser('displayaddress', help='display address on signer')
+parser_displayaddress.add_argument('--desc', metavar='desc')
+parser_displayaddress.set_defaults(func=displayaddress)
+
+parser_signtx = subparsers.add_parser('signtx')
+parser_signtx.add_argument('psbt', metavar='psbt')
+
+parser_signtx.set_defaults(func=signtx)
+
+if not sys.stdin.isatty():
+ buffer = sys.stdin.read()
+ if buffer and buffer.rstrip() != "":
+ sys.argv.extend(buffer.rstrip().split(" "))
+
+args = parser.parse_args()
+
+perform_pre_checks()
+
+args.func(args)
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index 84ca1b99c2..e090030205 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -23,6 +23,7 @@ import http.client
import os
import subprocess
+from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE
from test_framework.blocktools import (
create_block,
create_coinbase,
@@ -71,11 +72,10 @@ class BlockchainTest(BitcoinTestFramework):
def mine_chain(self):
self.log.info('Create some old blocks')
- address = self.nodes[0].get_deterministic_priv_key().address
for t in range(TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK + 200 * 600, 600):
# ten-minute steps from genesis block time
self.nodes[0].setmocktime(t)
- self.nodes[0].generatetoaddress(1, address)
+ self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_P2WSH_OP_TRUE)
assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200)
def _test_getblockchaininfo(self):
@@ -227,7 +227,7 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(res['transactions'], 200)
assert_equal(res['height'], 200)
assert_equal(res['txouts'], 200)
- assert_equal(res['bogosize'], 15000),
+ assert_equal(res['bogosize'], 16800),
assert_equal(res['bestblock'], node.getblockhash(200))
size = res['disk_size']
assert size > 6400
@@ -316,6 +316,9 @@ class BlockchainTest(BitcoinTestFramework):
header.calc_sha256()
assert_equal(header.hash, besthash)
+ assert 'previousblockhash' not in node.getblockheader(node.getblockhash(0))
+ assert 'nextblockhash' not in node.getblockheader(node.getbestblockhash())
+
def _test_getdifficulty(self):
difficulty = self.nodes[0].getdifficulty()
# 1 hash in 2 should be valid, so difficulty should be 1/2**31
@@ -329,12 +332,12 @@ class BlockchainTest(BitcoinTestFramework):
def _test_stopatheight(self):
assert_equal(self.nodes[0].getblockcount(), 200)
- self.nodes[0].generatetoaddress(6, self.nodes[0].get_deterministic_priv_key().address)
+ self.nodes[0].generatetoaddress(6, ADDRESS_BCRT1_P2WSH_OP_TRUE)
assert_equal(self.nodes[0].getblockcount(), 206)
self.log.debug('Node should not stop at this height')
assert_raises(subprocess.TimeoutExpired, lambda: self.nodes[0].process.wait(timeout=3))
try:
- self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address)
+ self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_P2WSH_OP_TRUE)
except (ConnectionError, http.client.BadStatusLine):
pass # The node already shut down before response
self.log.debug('Node should stop at this height...')
@@ -384,8 +387,7 @@ class BlockchainTest(BitcoinTestFramework):
node = self.nodes[0]
miniwallet = MiniWallet(node)
- miniwallet.generate(5)
- node.generate(100)
+ miniwallet.scan_blocks(num=5)
fee_per_byte = Decimal('0.00000010')
fee_per_kb = 1000 * fee_per_byte
@@ -420,6 +422,9 @@ class BlockchainTest(BitcoinTestFramework):
# Restore chain state
move_block_file('rev_wrong', 'rev00000.dat')
+ assert 'previousblockhash' not in node.getblock(node.getblockhash(0))
+ assert 'nextblockhash' not in node.getblock(node.getbestblockhash())
+
if __name__ == '__main__':
BlockchainTest().main()
diff --git a/test/functional/rpc_help.py b/test/functional/rpc_help.py
index 1eefd109f8..de21f43747 100755
--- a/test/functional/rpc_help.py
+++ b/test/functional/rpc_help.py
@@ -105,10 +105,13 @@ class HelpRpcTest(BitcoinTestFramework):
if self.is_wallet_compiled():
components.append('Wallet')
+ if self.is_external_signer_compiled():
+ components.append('Signer')
+
if self.is_zmq_compiled():
components.append('Zmq')
- assert_equal(titles, components)
+ assert_equal(titles, sorted(components))
def dump_help(self):
dump_dir = os.path.join(self.options.tmpdir, 'rpc_help_dump')
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 70a9798449..02eb10b5a4 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -19,6 +19,7 @@ import tempfile
import time
from typing import List
+from .address import ADDRESS_BCRT1_P2WSH_OP_TRUE
from .authproxy import JSONRPCException
from . import coverage
from .p2p import NetworkThread
@@ -732,16 +733,17 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
# Set a time in the past, so that blocks don't end up in the future
cache_node.setmocktime(cache_node.getblockheader(cache_node.getbestblockhash())['time'])
- # Create a 199-block-long chain; each of the 4 first nodes
+ # Create a 199-block-long chain; each of the 3 first nodes
# gets 25 mature blocks and 25 immature.
- # The 4th node gets only 24 immature blocks so that the very last
+ # The 4th address gets 25 mature and only 24 immature blocks so that the very last
# block in the cache does not age too much (have an old tip age).
# This is needed so that we are out of IBD when the test starts,
# see the tip age check in IsInitialBlockDownload().
+ gen_addresses = [k.address for k in TestNode.PRIV_KEYS] + [ADDRESS_BCRT1_P2WSH_OP_TRUE]
for i in range(8):
cache_node.generatetoaddress(
nblocks=25 if i != 7 else 24,
- address=TestNode.PRIV_KEYS[i % 4].address,
+ address=gen_addresses[i % 4],
)
assert_equal(cache_node.getblockchaininfo()["blocks"], 199)
@@ -827,10 +829,19 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.options.previous_releases_path))
return self.options.prev_releases
+ def skip_if_no_external_signer(self):
+ """Skip the running test if external signer support has not been compiled."""
+ if not self.is_external_signer_compiled():
+ raise SkipTest("external signer support has not been compiled.")
+
def is_cli_compiled(self):
"""Checks whether bitcoin-cli was compiled."""
return self.config["components"].getboolean("ENABLE_CLI")
+ def is_external_signer_compiled(self):
+ """Checks whether external signer support was compiled."""
+ return self.config["components"].getboolean("ENABLE_EXTERNAL_SIGNER")
+
def is_wallet_compiled(self):
"""Checks whether the wallet module was compiled."""
return self.config["components"].getboolean("ENABLE_WALLET")
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index b820c36e6e..ce9c1bc024 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -678,10 +678,10 @@ class RPCOverloadWrapper():
def __getattr__(self, name):
return getattr(self.rpc, name)
- def createwallet(self, wallet_name, disable_private_keys=None, blank=None, passphrase='', avoid_reuse=None, descriptors=None, load_on_startup=None):
+ def createwallet(self, wallet_name, disable_private_keys=None, blank=None, passphrase='', avoid_reuse=None, descriptors=None, load_on_startup=None, external_signer=None):
if descriptors is None:
descriptors = self.descriptors
- return self.__getattr__('createwallet')(wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors, load_on_startup)
+ return self.__getattr__('createwallet')(wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors, load_on_startup, external_signer)
def importprivkey(self, privkey, label=None, rescan=None):
wallet_info = self.getwalletinfo()
diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py
index edd7792608..38fbf3c1a6 100644
--- a/test/functional/test_framework/wallet.py
+++ b/test/functional/test_framework/wallet.py
@@ -32,6 +32,15 @@ class MiniWallet:
self._address = ADDRESS_BCRT1_P2WSH_OP_TRUE
self._scriptPubKey = hex_str_to_bytes(self._test_node.validateaddress(self._address)['scriptPubKey'])
+ def scan_blocks(self, *, start=1, num):
+ """Scan the blocks for self._address outputs and add them to self._utxos"""
+ for i in range(start, start + num):
+ block = self._test_node.getblock(blockhash=self._test_node.getblockhash(i), verbosity=2)
+ for tx in block['tx']:
+ for out in tx['vout']:
+ if out['scriptPubKey']['hex'] == self._scriptPubKey.hex():
+ self._utxos.append({'txid': tx['txid'], 'vout': out['n'], 'value': out['value']})
+
def generate(self, num_blocks):
"""Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list"""
blocks = self._test_node.generatetoaddress(num_blocks, self._address)
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index d742ef4eee..79ad2cf161 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -111,6 +111,7 @@ BASE_SCRIPTS = [
'wallet_listtransactions.py --legacy-wallet',
'wallet_listtransactions.py --descriptors',
'feature_taproot.py',
+ 'wallet_signer.py --descriptors',
# vv Tests less than 60s vv
'p2p_sendheaders.py',
'wallet_importmulti.py --legacy-wallet',
diff --git a/test/functional/wallet_signer.py b/test/functional/wallet_signer.py
new file mode 100755
index 0000000000..9dd080dca9
--- /dev/null
+++ b/test/functional/wallet_signer.py
@@ -0,0 +1,217 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017-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 external signer.
+
+Verify that a bitcoind node can use an external signer command
+"""
+import os
+import platform
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+)
+
+
+class SignerTest(BitcoinTestFramework):
+ def mock_signer_path(self):
+ path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mocks', 'signer.py')
+ if platform.system() == "Windows":
+ return "py " + path
+ else:
+ return path
+
+ def set_test_params(self):
+ self.num_nodes = 4
+
+ self.extra_args = [
+ [],
+ [f"-signer={self.mock_signer_path()}", '-keypool=10'],
+ [f"-signer={self.mock_signer_path()}", '-keypool=10'],
+ ["-signer=fake.py"],
+ ]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+ self.skip_if_no_external_signer()
+
+ def set_mock_result(self, node, res):
+ with open(os.path.join(node.cwd, "mock_result"), "w", encoding="utf8") as f:
+ f.write(res)
+
+ def clear_mock_result(self, node):
+ os.remove(os.path.join(node.cwd, "mock_result"))
+
+ def run_test(self):
+ self.log.debug(f"-signer={self.mock_signer_path()}")
+
+ assert_raises_rpc_error(-4, 'Error: restart bitcoind with -signer=<cmd>',
+ self.nodes[0].enumeratesigners
+ )
+
+ # Handle script missing:
+ assert_raises_rpc_error(-1, 'execve failed: No such file or directory',
+ self.nodes[3].enumeratesigners
+ )
+
+ # Handle error thrown by script
+ self.set_mock_result(self.nodes[1], "2")
+ assert_raises_rpc_error(-1, 'RunCommandParseJSON error',
+ self.nodes[1].enumeratesigners
+ )
+ self.clear_mock_result(self.nodes[1])
+
+ self.set_mock_result(self.nodes[1], '0 [{"type": "trezor", "model": "trezor_t", "error": "fingerprint not found"}]')
+ assert_raises_rpc_error(-4, 'fingerprint not found',
+ self.nodes[1].enumeratesigners
+ )
+ self.clear_mock_result(self.nodes[1])
+
+ # Create new wallets for an external signer.
+ # disable_private_keys and descriptors must be true:
+ assert_raises_rpc_error(-4, "Private keys must be disabled when using an external signer", self.nodes[1].createwallet, wallet_name='not_hww', disable_private_keys=False, descriptors=True, external_signer=True)
+ if self.is_bdb_compiled():
+ assert_raises_rpc_error(-4, "Descriptor support must be enabled when using an external signer", self.nodes[1].createwallet, wallet_name='not_hww', disable_private_keys=True, descriptors=False, external_signer=True)
+ else:
+ assert_raises_rpc_error(-4, "Compiled without bdb support (required for legacy wallets)", self.nodes[1].createwallet, wallet_name='not_hww', disable_private_keys=True, descriptors=False, external_signer=True)
+
+ self.nodes[1].createwallet(wallet_name='hww', disable_private_keys=True, descriptors=True, external_signer=True)
+ hww = self.nodes[1].get_wallet_rpc('hww')
+
+ result = hww.enumeratesigners()
+ assert_equal(len(result['signers']), 2)
+ assert_equal(result['signers'][0]["fingerprint"], "00000001")
+ assert_equal(result['signers'][0]["name"], "trezor_t")
+
+ # Flag can't be set afterwards (could be added later for non-blank descriptor based watch-only wallets)
+ self.nodes[1].createwallet(wallet_name='not_hww', disable_private_keys=True, descriptors=True, external_signer=False)
+ not_hww = self.nodes[1].get_wallet_rpc('not_hww')
+ assert_raises_rpc_error(-8, "Wallet flag is immutable: external_signer", not_hww.setwalletflag, "external_signer", True)
+
+ # assert_raises_rpc_error(-4, "Multiple signers found, please specify which to use", wallet_name='not_hww', disable_private_keys=True, descriptors=True, external_signer=True)
+
+ # TODO: Handle error thrown by script
+ # self.set_mock_result(self.nodes[1], "2")
+ # assert_raises_rpc_error(-1, 'Unable to parse JSON',
+ # self.nodes[1].createwallet, wallet_name='not_hww2', disable_private_keys=True, descriptors=True, external_signer=False
+ # )
+ # self.clear_mock_result(self.nodes[1])
+
+ assert_equal(hww.getwalletinfo()["keypoolsize"], 30)
+
+ address1 = hww.getnewaddress(address_type="bech32")
+ assert_equal(address1, "bcrt1qm90ugl4d48jv8n6e5t9ln6t9zlpm5th68x4f8g")
+ address_info = hww.getaddressinfo(address1)
+ assert_equal(address_info['solvable'], True)
+ assert_equal(address_info['ismine'], True)
+ assert_equal(address_info['hdkeypath'], "m/84'/1'/0'/0/0")
+
+ address2 = hww.getnewaddress(address_type="p2sh-segwit")
+ assert_equal(address2, "2N2gQKzjUe47gM8p1JZxaAkTcoHPXV6YyVp")
+ address_info = hww.getaddressinfo(address2)
+ assert_equal(address_info['solvable'], True)
+ assert_equal(address_info['ismine'], True)
+ assert_equal(address_info['hdkeypath'], "m/49'/1'/0'/0/0")
+
+ address3 = hww.getnewaddress(address_type="legacy")
+ assert_equal(address3, "n1LKejAadN6hg2FrBXoU1KrwX4uK16mco9")
+ address_info = hww.getaddressinfo(address3)
+ assert_equal(address_info['solvable'], True)
+ assert_equal(address_info['ismine'], True)
+ assert_equal(address_info['hdkeypath'], "m/44'/1'/0'/0/0")
+
+ self.log.info('Test signerdisplayaddress')
+ result = hww.signerdisplayaddress(address1)
+ assert_equal(result, {"address": address1})
+
+ # Handle error thrown by script
+ self.set_mock_result(self.nodes[1], "2")
+ assert_raises_rpc_error(-1, 'RunCommandParseJSON error',
+ hww.signerdisplayaddress, address1
+ )
+ self.clear_mock_result(self.nodes[1])
+
+ self.log.info('Prepare mock PSBT')
+ self.nodes[0].sendtoaddress(address1, 1)
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ # Load private key into wallet to generate a signed PSBT for the mock
+ self.nodes[1].createwallet(wallet_name="mock", disable_private_keys=False, blank=True, descriptors=True)
+ mock_wallet = self.nodes[1].get_wallet_rpc("mock")
+ assert mock_wallet.getwalletinfo()['private_keys_enabled']
+
+ result = mock_wallet.importdescriptors([{
+ "desc": "wpkh([00000001/84'/1'/0']tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0/*)#rweraev0",
+ "timestamp": 0,
+ "range": [0,1],
+ "internal": False,
+ "active": True
+ },
+ {
+ "desc": "wpkh([00000001/84'/1'/0']tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/*)#j6uzqvuh",
+ "timestamp": 0,
+ "range": [0, 0],
+ "internal": True,
+ "active": True
+ }])
+ assert_equal(result[0], {'success': True})
+ assert_equal(result[1], {'success': True})
+ assert_equal(mock_wallet.getwalletinfo()["txcount"], 1)
+ dest = self.nodes[0].getnewaddress(address_type='bech32')
+ mock_psbt = mock_wallet.walletcreatefundedpsbt([], {dest:0.5}, 0, {}, True)['psbt']
+ mock_psbt_signed = mock_wallet.walletprocesspsbt(psbt=mock_psbt, sign=True, sighashtype="ALL", bip32derivs=True)
+ mock_psbt_final = mock_wallet.finalizepsbt(mock_psbt_signed["psbt"])
+ mock_tx = mock_psbt_final["hex"]
+ assert(mock_wallet.testmempoolaccept([mock_tx])[0]["allowed"])
+
+ # # Create a new wallet and populate with specific public keys, in order
+ # # to work with the mock signed PSBT.
+ # self.nodes[1].createwallet(wallet_name="hww4", disable_private_keys=True, descriptors=True, external_signer=True)
+ # hww4 = self.nodes[1].get_wallet_rpc("hww4")
+ #
+ # descriptors = [{
+ # "desc": "wpkh([00000001/84'/1'/0']tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/0/*)#x30uthjs",
+ # "timestamp": "now",
+ # "range": [0, 1],
+ # "internal": False,
+ # "watchonly": True,
+ # "active": True
+ # },
+ # {
+ # "desc": "wpkh([00000001/84'/1'/0']tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/*)#h92akzzg",
+ # "timestamp": "now",
+ # "range": [0, 0],
+ # "internal": True,
+ # "watchonly": True,
+ # "active": True
+ # }]
+
+ # result = hww4.importdescriptors(descriptors)
+ # assert_equal(result[0], {'success': True})
+ # assert_equal(result[1], {'success': True})
+ assert_equal(hww.getwalletinfo()["txcount"], 1)
+
+ assert(hww.testmempoolaccept([mock_tx])[0]["allowed"])
+
+ with open(os.path.join(self.nodes[1].cwd, "mock_psbt"), "w", encoding="utf8") as f:
+ f.write(mock_psbt_signed["psbt"])
+
+ self.log.info('Test send using hww1')
+
+ res = hww.send(outputs={dest:0.5},options={"add_to_wallet": False})
+ assert(res["complete"])
+ assert_equal(res["hex"], mock_tx)
+
+ # # Handle error thrown by script
+ # self.set_mock_result(self.nodes[4], "2")
+ # assert_raises_rpc_error(-1, 'Unable to parse JSON',
+ # hww4.signerprocesspsbt, psbt_orig, "00000001"
+ # )
+ # self.clear_mock_result(self.nodes[4])
+
+if __name__ == '__main__':
+ SignerTest().main()
diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py
index 893a2d9617..6fc1d13c53 100755
--- a/test/functional/wallet_txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
@@ -11,9 +11,10 @@ from test_framework.util import (
)
from test_framework.messages import CTransaction, COIN
+
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
- self.num_nodes = 4
+ self.num_nodes = 3
self.supports_cli = False
def skip_test_if_missing_module(self):
@@ -38,9 +39,8 @@ class TxnMallTest(BitcoinTestFramework):
# All nodes should start with 1,250 BTC:
starting_balance = 1250
- for i in range(4):
+ for i in range(3):
assert_equal(self.nodes[i].getbalance(), starting_balance)
- self.nodes[i].getnewaddress() # bug workaround, coins generated assigned to first getnewaddress!
self.nodes[0].settxfee(.001)
@@ -139,5 +139,6 @@ class TxnMallTest(BitcoinTestFramework):
expected -= 50
assert_equal(self.nodes[0].getbalance(), expected)
+
if __name__ == '__main__':
TxnMallTest().main()
diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py
index c7f7a8546a..0cb7328948 100755
--- a/test/functional/wallet_txn_doublespend.py
+++ b/test/functional/wallet_txn_doublespend.py
@@ -11,9 +11,10 @@ from test_framework.util import (
find_output,
)
+
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
- self.num_nodes = 4
+ self.num_nodes = 3
self.supports_cli = False
def skip_test_if_missing_module(self):
@@ -39,9 +40,8 @@ class TxnMallTest(BitcoinTestFramework):
for n in self.nodes:
assert n.getblockchaininfo()["initialblockdownload"] == False
- for i in range(4):
+ for i in range(3):
assert_equal(self.nodes[i].getbalance(), starting_balance)
- self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress!
# Assign coins to foo and bar addresses:
node0_address_foo = self.nodes[0].getnewaddress()
@@ -136,5 +136,6 @@ class TxnMallTest(BitcoinTestFramework):
# Node1's balance should be its initial balance (1250 for 25 block rewards) plus the doublespend:
assert_equal(self.nodes[1].getbalance(), 1250 + 1240)
+
if __name__ == '__main__':
TxnMallTest().main()