funga-eth

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

middleware.py (3996B)


      1 # standard imports
      2 import logging
      3 import re
      4 import socket
      5 import uuid
      6 import json
      7 
      8 logg = logging.getLogger(__file__)
      9 
     10 
     11 def jsonrpc_request(method, params):
     12     uu = uuid.uuid4()
     13     return {
     14         "jsonrpc": "2.0",
     15         "id": str(uu),
     16         "method": method,
     17         "params": params,
     18             }
     19 
     20 class PlatformMiddleware:
     21 
     22     # id for the request is not available, meaning we cannot easily short-circuit
     23     # hack workaround
     24     id_seq = -1
     25     re_personal = re.compile('^personal_.*')
     26     ipcaddr = None
     27 
     28 
     29     def __init__(self, make_request, w3):
     30         self.w3 = w3 
     31         self.make_request = make_request
     32         if self.ipcaddr == None:
     33             raise AttributeError('ipcaddr not set')
     34 
     35     
     36     # TODO: understand what format input params come in
     37     # single entry input gives a tuple on params, wtf...
     38     # dict input comes as [{}] and fails if not passed on as an array
     39     @staticmethod
     40     def _translate_params(params):
     41         #if params.__class__.__name__ == 'tuple':
     42         #    r = []
     43         #    for p in params:
     44         #        r.append(p)
     45         #    return r
     46 
     47         if params.__class__.__name__ == 'list' and len(params) > 0:
     48             return params[0]
     49 
     50         return params
     51 
     52 
     53     # TODO: DRY
     54     def __call__(self, method, suspect_params):
     55 
     56         self.id_seq += 1
     57         logg.debug('in middleware method {} params {} ipcpath {}'.format(method, suspect_params, self.ipcaddr))
     58 
     59         if self.re_personal.match(method) != None:
     60             params = PlatformMiddleware._translate_params(suspect_params)
     61             # multiple providers is removed in web3.py 5.12.0
     62             # https://github.com/ethereum/web3.py/issues/1701
     63             # thus we need a workaround to use the same web3 instance
     64             s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0)
     65             ipc_provider_workaround = s.connect(self.ipcaddr)
     66 
     67             logg.info('redirecting method {}  params {} original params {}'.format(method, params, suspect_params))
     68             o = jsonrpc_request(method, params[0])
     69             j = json.dumps(o)
     70             logg.debug('send {}'.format(j))
     71             s.send(j.encode('utf-8'))
     72             r = s.recv(4096)
     73             s.close()
     74             logg.debug('got recv {}'.format(str(r)))
     75             jr = json.loads(r)
     76             jr['id'] = self.id_seq
     77             #return str(json.dumps(jr))
     78             return jr
     79 
     80         elif method == 'eth_signTransaction':
     81             params = PlatformMiddleware._translate_params(suspect_params)
     82             s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0)
     83             ipc_provider_workaround = s.connect(self.ipcaddr)
     84             logg.info('redirecting method {}  params {} original params {}'.format(method, params, suspect_params))
     85             o = jsonrpc_request(method, params[0])
     86             j = json.dumps(o)
     87             logg.debug('send {}'.format(j))
     88             s.send(j.encode('utf-8'))
     89             r = s.recv(4096)
     90             s.close()
     91             logg.debug('got recv {}'.format(str(r)))
     92             jr = json.loads(r)
     93             jr['id'] = self.id_seq
     94             #return str(json.dumps(jr))
     95             return jr
     96 
     97         elif method == 'eth_sign':
     98             params = PlatformMiddleware._translate_params(suspect_params)
     99             s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0)
    100             ipc_provider_workaround = s.connect(self.ipcaddr)
    101             logg.info('redirecting method {}  params {} original params {}'.format(method, params, suspect_params))
    102             o = jsonrpc_request(method, params)
    103             j = json.dumps(o)
    104             logg.debug('send {}'.format(j))
    105             s.send(j.encode('utf-8'))
    106             r = s.recv(4096)
    107             s.close()
    108             logg.debug('got recv {}'.format(str(r)))
    109             jr = json.loads(r)
    110             jr['id'] = self.id_seq
    111             return jr
    112 
    113 
    114 
    115         r = self.make_request(method, suspect_params)
    116         return r