rpc_signer.py raw
1 #!/usr/bin/env python3
2 # Copyright (c) 2017-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 """Test external signer.
6
7 Verify that a bitcoind node can use an external signer command.
8 See also wallet_signer.py for tests that require wallet context.
9 """
10 import os
11 import platform
12 import sys
13
14 from test_framework.test_framework import BitcoinTestFramework
15 from test_framework.util import (
16 assert_equal,
17 assert_raises_rpc_error,
18 )
19
20
21 class RPCSignerTest(BitcoinTestFramework):
22 def mock_signer_path(self):
23 path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mocks', 'signer.py')
24 return sys.executable + " " + path
25
26 def set_test_params(self):
27 self.num_nodes = 4
28
29 self.extra_args = [
30 [],
31 [f"-signer={self.mock_signer_path()}", '-keypool=10'],
32 [f"-signer={self.mock_signer_path()}", '-keypool=10'],
33 ["-signer=fake.py"],
34 ]
35
36 def skip_test_if_missing_module(self):
37 self.skip_if_no_external_signer()
38
39 def set_mock_result(self, node, res):
40 with open(os.path.join(node.cwd, "mock_result"), "w") as f:
41 f.write(res)
42
43 def clear_mock_result(self, node):
44 os.remove(os.path.join(node.cwd, "mock_result"))
45
46 def run_test(self):
47 self.log.debug(f"-signer={self.mock_signer_path()}")
48
49 assert_raises_rpc_error(-1, 'Error: restart bitcoind with -signer=<cmd>',
50 self.nodes[0].enumeratesigners
51 )
52
53 # Handle script missing:
54 assert_raises_rpc_error(
55 -1,
56 "CreateProcess failed: The system cannot find the file specified."
57 if platform.system() == "Windows"
58 else "execve failed: No such file or directory",
59 self.nodes[3].enumeratesigners,
60 )
61
62 # Handle error thrown by script
63 self.set_mock_result(self.nodes[1], "2")
64 assert_raises_rpc_error(-1, 'RunCommandParseJSON error',
65 self.nodes[1].enumeratesigners
66 )
67 self.clear_mock_result(self.nodes[1])
68
69 self.set_mock_result(self.nodes[1], '0 [{"type": "trezor", "model": "trezor_t", "error": "fingerprint not found"}]')
70 assert_raises_rpc_error(-1, 'fingerprint not found',
71 self.nodes[1].enumeratesigners
72 )
73 self.clear_mock_result(self.nodes[1])
74
75 # Duplicate fingerprints
76 self.set_mock_result(self.nodes[1],
77 '0 ['
78 '{"fingerprint": "00000001", "type": "trezor", "model": "trezor_t"}, '
79 '{"fingerprint": "00000001", "type": "trezor", "model": "trezor_t"}, '
80 '{"fingerprint": "00000002", "type": "trezor", "model": "trezor_one"}'
81 ']')
82 assert_equal(self.nodes[1].enumeratesigners(), {"signers": [
83 {"fingerprint": "00000001", "name": "trezor_t"},
84 {"fingerprint": "00000002", "name": "trezor_one"},
85 ]})
86 self.clear_mock_result(self.nodes[1])
87
88 assert_equal({'fingerprint': '00000001', 'name': 'trezor_t'} in self.nodes[1].enumeratesigners()['signers'], True)
89
90 if __name__ == '__main__':
91 RPCSignerTest(__file__).main()
92