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