signer.py (4308B)
1 # standard imports 2 import re 3 import os 4 import sys 5 import json 6 import logging 7 import argparse 8 from urllib.parse import urlparse 9 10 # external imports 11 import confini 12 from jsonrpc.exceptions import * 13 14 # local imports 15 from funga.eth.signer import EIP155Signer 16 from funga.eth.cli.handle import SignRequestHandler 17 18 logging.basicConfig(level=logging.WARNING) 19 logg = logging.getLogger() 20 21 script_dir = os.path.dirname(os.path.realpath(__file__)) 22 data_dir = os.path.join(script_dir, '..', 'data') 23 config_dir = os.path.join(data_dir, 'config') 24 25 db = None 26 signer = None 27 session = None 28 chainId = 8995 29 socket_path = '/run/crypto-dev-signer/jsonrpc.ipc' 30 31 32 argparser = argparse.ArgumentParser() 33 argparser.add_argument('-c', type=str, default=config_dir, help='config file') 34 argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration') 35 argparser.add_argument('-i', type=int, help='default chain id for EIP155') 36 argparser.add_argument('-k', '--keystore-type', dest='keystore_type', type=str, choices=['dict', 'sql'], default='dict', help='keystore backend type') 37 argparser.add_argument('-s', type=str, help='socket path') 38 argparser.add_argument('-v', action='store_true', help='be verbose') 39 argparser.add_argument('-vv', action='store_true', help='be more verbose') 40 args = argparser.parse_args() 41 42 if args.vv: 43 logging.getLogger().setLevel(logging.DEBUG) 44 elif args.v: 45 logging.getLogger().setLevel(logging.INFO) 46 47 config = confini.Config(args.c, args.env_prefix) 48 config.process() 49 config.censor('PASSWORD', 'DATABASE') 50 config.censor('SECRET', 'SIGNER') 51 logg.debug('config loaded from {}:\n{}'.format(config_dir, config)) 52 53 if args.i: 54 chainId = args.i 55 if args.s: 56 socket_url = urlparse(args.s) 57 elif config.get('SIGNER_SOCKET_PATH'): 58 socket_url = urlparse(config.get('SIGNER_SOCKET_PATH')) 59 60 61 # connect to database 62 dsn = 'postgresql://{}:{}@{}:{}/{}'.format( 63 config.get('DATABASE_USER'), 64 config.get('DATABASE_PASSWORD'), 65 config.get('DATABASE_HOST'), 66 config.get('DATABASE_PORT'), 67 config.get('DATABASE_NAME'), 68 ) 69 70 logg.info('using dsn {}'.format(dsn)) 71 logg.info('using socket {}'.format(config.get('SIGNER_SOCKET_PATH'))) 72 73 re_http = r'^http' 74 re_tcp = r'^tcp' 75 re_unix = r'^ipc' 76 77 class MissingSecretError(Exception): 78 pass 79 80 81 def main(): 82 83 secret_hex = config.get('SIGNER_SECRET') 84 if secret_hex == None: 85 raise MissingSecretError('please provide a valid hex value for the SIGNER_SECRET configuration variable') 86 87 secret = bytes.fromhex(secret_hex) 88 kw = { 89 'symmetric_key': secret, 90 } 91 if args.keystore_type == 'sql': 92 logg.info('using sql keystore: ' + dsn) 93 from funga.eth.keystore.sql import SQLKeystore 94 SignRequestHandler.keystore = SQLKeystore(dsn, **kw) 95 else: 96 logg.warning('using volatile dict keystore - all keys will be lost when you quit') 97 from funga.eth.keystore.dict import DictKeystore 98 SignRequestHandler.keystore = DictKeystore() 99 SignRequestHandler.signer = EIP155Signer(SignRequestHandler.keystore) 100 101 arg = None 102 try: 103 arg = json.loads(sys.argv[1]) 104 except: 105 logg.info('no json rpc command detected, starting socket server {}'.format(socket_url)) 106 scheme = 'ipc' 107 if socket_url.scheme != '': 108 scheme = socket_url.scheme 109 if re.match(re_tcp, socket_url.scheme): 110 from funga.eth.cli.socket import start_server_tcp 111 socket_spec = socket_url.netloc.split(':') 112 host = socket_spec[0] 113 port = int(socket_spec[1]) 114 start_server_tcp((host, port)) 115 elif re.match(re_http, socket_url.scheme): 116 from funga.eth.cli.http import start_server_http 117 socket_spec = socket_url.netloc.split(':') 118 host = socket_spec[0] 119 port = int(socket_spec[1]) 120 start_server_http((host, port)) 121 else: 122 from funga.eth.cli.socket import start_server_unix 123 start_server_unix(socket_url.path) 124 sys.exit(0) 125 126 (rpc_id, response) = process_input(arg) 127 r = jsonrpc_ok(rpc_id, response) 128 sys.stdout.write(json.dumps(r)) 129 130 131 if __name__ == '__main__': 132 main()