/ test / functional / rpc_signer.py
rpc_signer.py
 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          assert_equal({'fingerprint': '00000001', 'name': 'trezor_t'} in self.nodes[1].enumeratesigners()['signers'], True)
76  
77  if __name__ == '__main__':
78      RPCSignerTest(__file__).main()