signer.py
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)