funga-eth

Ethereum implementation of the funga keystore and signer
Info | Log | Files | Refs | README | LICENSE

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()