diff --git a/scripts/server.py b/scripts/server.py index 1dd186b..355d1ad 100644 --- a/scripts/server.py +++ b/scripts/server.py @@ -7,7 +7,7 @@ import os from jsonrpc.exceptions import * from signer import ReferenceSigner -from keystore import ReferenceDatabase +from keystore import ReferenceKeystore from transaction import Transaction logging.basicConfig(level=logging.DEBUG) @@ -128,7 +128,7 @@ def init(): kw = { 'symmetric_key': secret, } - db = ReferenceDatabase('cic_signer', **kw) + db = ReferenceKeystore('cic_signer', **kw) signer = ReferenceSigner(db) diff --git a/scripts/web3_middleware.py b/scripts/web3_middleware.py index a671dbe..3623649 100644 --- a/scripts/web3_middleware.py +++ b/scripts/web3_middleware.py @@ -1,92 +1,11 @@ -import logging -import re -import socket -import uuid -import json +from web3ext import Web3 -from web3 import Web3, WebsocketProvider, IPCProvider - - -logging.basicConfig(level=logging.DEBUG) -logg = logging.getLogger('foo') - - -def jsonrpc_request(method, params): - uu = uuid.uuid4() - return { - "jsonrpc": "2.0", - "id": str(uu), - "method": method, - "params": params, - } - -class PlatformMiddleware: - - # id for the request is not available, meaning we cannot easily short-circuit - # hack workaround - id_seq = -1 - re_personal = re.compile('^personal_.*') - ipcaddr = '/tmp/foo.ipc' - - - def __init__(self, make_request, w3): - self.w3 = w3 - self.make_request = make_request - - - # TODO: understand what format input params come in - # single entry input gives a tuple on params, wtf... - # dict input comes as [{}] and fails if not passed on as an array - @staticmethod - def _translate_params(params): - if params.__class__.__name__ == 'tuple': - r = [] - for p in params: - r.append(p) - return r - - if params.__class__.__name__ == 'list' and len(params) > 0: - return params[0] - - return params - - - def __call__(self, method, suspect_params): - - self.id_seq += 1 - logg.debug('in middleware method {} params {}'.format(method, suspect_params)) - - if self.re_personal.match(method) != None: - params = PlatformMiddleware._translate_params(suspect_params) - # multiple providers is broken in web3.py 5.12.0 - # https://github.com/ethereum/web3.py/issues/1701 - # hack workaround - s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0) - ipc_provider_workaround = s.connect(self.ipcaddr) - - logg.info('redirecting method {} params {} original params {}'.format(method, params, suspect_params)) - o = jsonrpc_request(method, params) - j = json.dumps(o) - logg.debug('send {}'.format(j)) - s.send(j.encode('utf-8')) - r = s.recv(4096) - s.close() - logg.debug('got recv {}'.format(str(r))) - jr = json.loads(r) - jr['id'] = self.id_seq - #return str(json.dumps(jr)) - return jr - - r = self.make_request(method, suspect_params) - return r - - -w3 = Web3(WebsocketProvider('ws://127.0.0.1:8546')) -w3.eth.personal = w3.geth.personal -w3.middleware_onion.add(PlatformMiddleware) -print(w3.eth.personal.newAccount('foo')) -print(w3.eth.blockNumber) -#print(w3.eth.sendTransaction({'to': '0xd3CdA913deB6f67967B99D67aCDFa1712C293601','from': '0xc305c901078781C232A2a521C2aF7980f8385ee9','value': 1000})) +# TODO: remove and replace with test +if __name__ == '__main__': + w3 = Web3(['ws://127.0.0.1:8546']) + print(w3.eth.personal.newAccount('foo')) + print(w3.eth.blockNumber) + #print(w3.eth.sendTransaction({'to': '0xd3CdA913deB6f67967B99D67aCDFa1712C293601','from': '0xc305c901078781C232A2a521C2aF7980f8385ee9','value': 1000})) diff --git a/src/web3ext/__init__.py b/src/web3ext/__init__.py new file mode 100644 index 0000000..207ef1d --- /dev/null +++ b/src/web3ext/__init__.py @@ -0,0 +1,31 @@ +import re + +from web3 import Web3 as Web3super +from web3 import WebsocketProvider, HTTPProvider +from web3ext.middleware import PlatformMiddleware + +re_websocket = re.compile('^wss?://') +re_http = re.compile('^https?://') + + +#def create_middleware(ipcaddr='/var/run/cic-platform/cic.ipc'): +def create_middleware(ipcaddr='/tmp/foo.ipc'): + PlatformMiddleware.ipcaddr = ipcaddr + return PlatformMiddleware + + +# overrides the original Web3 constructor +def Web3(blockchain_providers=[], ipcaddr=None): + if len(blockchain_providers) > 1: + raise ValueError('backend only supports single provider') + provider = None + if re.match(re_websocket, blockchain_providers[0]) != None: + provider = WebsocketProvider(blockchain_providers[0]) + elif re.match(re_http, blockchain_providers[0]) != None: + provider = HTTPProvider(blockchain_providers[0]) + + w3 = Web3super(provider) + + w3.middleware_onion.add(create_middleware()) + w3.eth.personal = w3.geth.personal + return w3 diff --git a/src/web3ext/middleware.py b/src/web3ext/middleware.py new file mode 100644 index 0000000..0cf17bf --- /dev/null +++ b/src/web3ext/middleware.py @@ -0,0 +1,78 @@ +import logging +import re +import socket +import uuid +import json + +logging.basicConfig(level=logging.DEBUG) +logg = logging.getLogger('foo') + + +def jsonrpc_request(method, params): + uu = uuid.uuid4() + return { + "jsonrpc": "2.0", + "id": str(uu), + "method": method, + "params": params, + } + +class PlatformMiddleware: + + # id for the request is not available, meaning we cannot easily short-circuit + # hack workaround + id_seq = -1 + re_personal = re.compile('^personal_.*') + ipcaddr = '/tmp/foo.ipc' + + + def __init__(self, make_request, w3): + self.w3 = w3 + self.make_request = make_request + + + # TODO: understand what format input params come in + # single entry input gives a tuple on params, wtf... + # dict input comes as [{}] and fails if not passed on as an array + @staticmethod + def _translate_params(params): + if params.__class__.__name__ == 'tuple': + r = [] + for p in params: + r.append(p) + return r + + if params.__class__.__name__ == 'list' and len(params) > 0: + return params[0] + + return params + + + def __call__(self, method, suspect_params): + + self.id_seq += 1 + logg.debug('in middleware method {} params {}'.format(method, suspect_params)) + + if self.re_personal.match(method) != None: + params = PlatformMiddleware._translate_params(suspect_params) + # multiple providers is broken in web3.py 5.12.0 + # https://github.com/ethereum/web3.py/issues/1701 + # hack workaround + s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0) + ipc_provider_workaround = s.connect(self.ipcaddr) + + logg.info('redirecting method {} params {} original params {}'.format(method, params, suspect_params)) + o = jsonrpc_request(method, params) + j = json.dumps(o) + logg.debug('send {}'.format(j)) + s.send(j.encode('utf-8')) + r = s.recv(4096) + s.close() + logg.debug('got recv {}'.format(str(r))) + jr = json.loads(r) + jr['id'] = self.id_seq + #return str(json.dumps(jr)) + return jr + + r = self.make_request(method, suspect_params) + return r