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