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