Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#!/usr/bin/env python32# Copyright (c) 2017-present The Bitcoin Core developers3# Distributed under the MIT software license, see the accompanying4# file COPYING or http://www.opensource.org/licenses/mit-license.php.5"""Test external signer.7Verify that a bitcoind node can use an external signer command.8See also wallet_signer.py for tests that require wallet context.9"""10import os11import platform12import sys14from test_framework.test_framework import BitcoinTestFramework15from test_framework.util import (16assert_equal,17assert_raises_rpc_error,18)21class RPCSignerTest(BitcoinTestFramework):22def mock_signer_path(self):23path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mocks', 'signer.py')24return sys.executable + " " + path26def set_test_params(self):27self.num_nodes = 429self.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]36def skip_test_if_missing_module(self):37self.skip_if_no_external_signer()39def set_mock_result(self, node, res):40with open(os.path.join(node.cwd, "mock_result"), "w") as f:41f.write(res)43def clear_mock_result(self, node):44os.remove(os.path.join(node.cwd, "mock_result"))46def run_test(self):47self.log.debug(f"-signer={self.mock_signer_path()}")49assert_raises_rpc_error(-1, 'Error: restart bitcoind with -signer=<cmd>',50self.nodes[0].enumeratesigners51)53# Handle script missing:54assert_raises_rpc_error(55-1,56"CreateProcess failed: The system cannot find the file specified."57if platform.system() == "Windows"58else "execve failed: No such file or directory",59self.nodes[3].enumeratesigners,60)62# Handle error thrown by script63self.set_mock_result(self.nodes[1], "2")64assert_raises_rpc_error(-1, 'RunCommandParseJSON error',65self.nodes[1].enumeratesigners66)67self.clear_mock_result(self.nodes[1])69self.set_mock_result(self.nodes[1], '0 [{"type": "trezor", "model": "trezor_t", "error": "fingerprint not found"}]')70assert_raises_rpc_error(-1, 'fingerprint not found',71self.nodes[1].enumeratesigners72)73self.clear_mock_result(self.nodes[1])75# Duplicate fingerprints76self.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']')82assert_equal(self.nodes[1].enumeratesigners(), {"signers": [83{"fingerprint": "00000001", "name": "trezor_t"},84{"fingerprint": "00000002", "name": "trezor_one"},85]})86self.clear_mock_result(self.nodes[1])88# Invalid fingerprints are rejected89for fingerprint in ["", "0000001", "000000001", "0000000g", "zzzzzzzz"]:90self.set_mock_result(self.nodes[1], '0 [{"type": "trezor", "model": "trezor_t", "fingerprint": "%s"}]' % fingerprint)91assert_raises_rpc_error(-1, 'invalid fingerprint', self.nodes[1].enumeratesigners)92self.clear_mock_result(self.nodes[1])94assert_equal({'fingerprint': '00000001', 'name': 'trezor_t'} in self.nodes[1].enumeratesigners()['signers'], True)96if __name__ == '__main__':97RPCSignerTest(__file__).main()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.