signer.py raw
1 #!/usr/bin/env python3
2 # Copyright (c) 2018-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
6 import os
7 import sys
8 import argparse
9 import json
10
11 def perform_pre_checks():
12 mock_result_path = os.path.join(os.getcwd(), "mock_result")
13 if os.path.isfile(mock_result_path):
14 with open(mock_result_path, "r") as f:
15 mock_result = f.read()
16 if mock_result[0]:
17 sys.stdout.write(mock_result[2:])
18 sys.exit(int(mock_result[0]))
19
20 def enumerate(args):
21 sys.stdout.write(json.dumps([{"fingerprint": "00000001", "type": "trezor", "model": "trezor_t"}]))
22
23 def getdescriptors(args):
24 xpub = "tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B"
25
26 sys.stdout.write(json.dumps({
27 "receive": [
28 "pkh([00000001/44h/1h/" + args.account + "']" + xpub + "/0/*)#aqllu46s",
29 "sh(wpkh([00000001/49h/1h/" + args.account + "']" + xpub + "/0/*))#5dh56mgg",
30 "wpkh([00000001/84h/1h/" + args.account + "']" + xpub + "/0/*)#h62dxaej",
31 "tr([00000001/86h/1h/" + args.account + "']" + xpub + "/0/*)#pcd5w87f"
32 ],
33 "internal": [
34 "pkh([00000001/44h/1h/" + args.account + "']" + xpub + "/1/*)#v567pq2g",
35 "sh(wpkh([00000001/49h/1h/" + args.account + "']" + xpub + "/1/*))#pvezzyah",
36 "wpkh([00000001/84h/1h/" + args.account + "']" + xpub + "/1/*)#xw0vmgf2",
37 "tr([00000001/86h/1h/" + args.account + "']" + xpub + "/1/*)#svg4njw3"
38
39 ]
40 }))
41
42
43 def displayaddress(args):
44 if args.fingerprint != "00000001":
45 return sys.stdout.write(json.dumps({"error": "Unexpected fingerprint", "fingerprint": args.fingerprint}))
46
47 expected_desc = {
48 "wpkh([00000001/84h/1h/0h/0/0]02c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7)#3te6hhy7": "bcrt1qm90ugl4d48jv8n6e5t9ln6t9zlpm5th68x4f8g",
49 "sh(wpkh([00000001/49h/1h/0h/0/0]02c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7))#kz9y5w82": "2N2gQKzjUe47gM8p1JZxaAkTcoHPXV6YyVp",
50 "pkh([00000001/44h/1h/0h/0/0]02c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7)#q3pqd8wh": "n1LKejAadN6hg2FrBXoU1KrwX4uK16mco9",
51 "tr([00000001/86h/1h/0h/0/0]c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7)#puqqa90m": "tb1phw4cgpt6cd30kz9k4wkpwm872cdvhss29jga2xpmftelhqll62mscq0k4g",
52 "wpkh([00000001/84h/1h/0h/0/1]03a20a46308be0b8ded6dff0a22b10b4245c587ccf23f3b4a303885be3a524f172)#aqpjv5xr": "wrong_address",
53 }
54 if args.desc not in expected_desc:
55 return sys.stdout.write(json.dumps({"error": "Unexpected descriptor", "desc": args.desc}))
56
57 return sys.stdout.write(json.dumps({"address": expected_desc[args.desc]}))
58
59 def signtx(args):
60 if args.fingerprint != "00000001":
61 return sys.stdout.write(json.dumps({"error": "Unexpected fingerprint", "fingerprint": args.fingerprint}))
62
63 with open(os.path.join(os.getcwd(), "mock_psbt"), "r") as f:
64 mock_psbt = f.read()
65
66 if args.fingerprint == "00000001" :
67 sys.stdout.write(json.dumps({
68 "psbt": mock_psbt,
69 "complete": True
70 }))
71 else:
72 sys.stdout.write(json.dumps({"psbt": args.psbt}))
73
74 parser = argparse.ArgumentParser(prog='./signer.py', description='External signer mock')
75 parser.add_argument('--fingerprint')
76 parser.add_argument('--chain', default='main')
77 parser.add_argument('--stdin', action='store_true')
78
79 subparsers = parser.add_subparsers(description='Commands', dest='command')
80 subparsers.required = True
81
82 parser_enumerate = subparsers.add_parser('enumerate', help='list available signers')
83 parser_enumerate.set_defaults(func=enumerate)
84
85 parser_getdescriptors = subparsers.add_parser('getdescriptors')
86 parser_getdescriptors.set_defaults(func=getdescriptors)
87 parser_getdescriptors.add_argument('--account', metavar='account')
88
89 parser_displayaddress = subparsers.add_parser('displayaddress', help='display address on signer')
90 parser_displayaddress.add_argument('--desc', metavar='desc')
91 parser_displayaddress.set_defaults(func=displayaddress)
92
93 parser_signtx = subparsers.add_parser('signtx')
94 parser_signtx.add_argument('psbt', metavar='psbt')
95
96 parser_signtx.set_defaults(func=signtx)
97
98 if not sys.stdin.isatty():
99 buffer = sys.stdin.read()
100 if buffer and buffer.rstrip() != "":
101 sys.argv.extend(buffer.rstrip().split(" "))
102
103 args = parser.parse_args()
104
105 perform_pre_checks()
106
107 args.func(args)
108