Skip to content

Commit 9dfc61d

Browse files
committed
test: detect no external signer connected
1 parent 0a4ee93 commit 9dfc61d

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

test/functional/mocks/no_signer.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2025-present The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
import argparse
7+
import json
8+
import sys
9+
10+
def enumerate(args):
11+
sys.stdout.write(json.dumps([]))
12+
13+
parser = argparse.ArgumentParser(prog='./no_signer.py', description='No external signer connected mock')
14+
15+
subparsers = parser.add_subparsers(description='Commands', dest='command')
16+
subparsers.required = True
17+
18+
parser_enumerate = subparsers.add_parser('enumerate', help='list available signers')
19+
parser_enumerate.set_defaults(func=enumerate)
20+
21+
22+
if not sys.stdin.isatty():
23+
buffer = sys.stdin.read()
24+
if buffer and buffer.rstrip() != "":
25+
sys.argv.extend(buffer.rstrip().split(" "))
26+
27+
args = parser.parse_args()
28+
29+
args.func(args)

test/functional/wallet_signer.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ def mock_signer_path(self):
2323
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mocks', 'signer.py')
2424
return sys.executable + " " + path
2525

26+
def mock_no_connected_signer_path(self):
27+
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mocks', 'no_signer.py')
28+
return sys.executable + " " + path
29+
2630
def mock_invalid_signer_path(self):
2731
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mocks', 'invalid_signer.py')
2832
return sys.executable + " " + path
@@ -52,6 +56,7 @@ def clear_mock_result(self, node):
5256

5357
def run_test(self):
5458
self.test_valid_signer()
59+
self.test_disconnected_signer()
5560
self.restart_node(1, [f"-signer={self.mock_invalid_signer_path()}", "-keypool=10"])
5661
self.test_invalid_signer()
5762
self.restart_node(1, [f"-signer={self.mock_multi_signers_path()}", "-keypool=10"])
@@ -234,6 +239,28 @@ def test_valid_signer(self):
234239
# )
235240
# self.clear_mock_result(self.nodes[4])
236241

242+
def test_disconnected_signer(self):
243+
self.log.info('Test disconnected external signer')
244+
245+
# First create a wallet with the signer connected
246+
self.nodes[1].createwallet(wallet_name='hww_disconnect', disable_private_keys=True, external_signer=True)
247+
hww = self.nodes[1].get_wallet_rpc('hww_disconnect')
248+
assert_equal(hww.getwalletinfo()["external_signer"], True)
249+
250+
# Fund wallet
251+
self.nodes[0].sendtoaddress(hww.getnewaddress(address_type="bech32m"), 1)
252+
self.generate(self.nodes[0], 1)
253+
254+
# Restart node with no signer connected
255+
self.log.debug(f"-signer={self.mock_no_connected_signer_path()}")
256+
self.restart_node(1, [f"-signer={self.mock_no_connected_signer_path()}", "-keypool=10"])
257+
self.nodes[1].loadwallet('hww_disconnect')
258+
hww = self.nodes[1].get_wallet_rpc('hww_disconnect')
259+
260+
# Try to spend
261+
dest = hww.getrawchangeaddress()
262+
assert_raises_rpc_error(-25, "External signer not found", hww.send, outputs=[{dest:0.5}])
263+
237264
def test_invalid_signer(self):
238265
self.log.debug(f"-signer={self.mock_invalid_signer_path()}")
239266
self.log.info('Test invalid external signer')

0 commit comments

Comments
 (0)