commit d3627d81fd135a1fc7334403e20b141fb4bcd663
parent 7c3208de4c800def824d17391f72735180ab8353
Author: nolash <dev@holbrook.no>
Date: Thu, 6 Aug 2020 09:41:42 +0200
Add middleware example in scripts
Diffstat:
2 files changed, 106 insertions(+), 5 deletions(-)
diff --git a/scripts/server.py b/scripts/server.py
@@ -53,9 +53,10 @@ methods = {
}
-def jsonrpc_error(id, err):
+def jsonrpc_error(rpc_id, err):
return {
'json-rpc': '2.0',
+ 'id': rpc_id,
'error': {
'code': err.CODE,
'message': err.MESSAGE,
@@ -71,6 +72,12 @@ def jsonrpc_ok(rpc_id, response):
}
+def is_valid_json(j):
+ if j.get('id') == 'None':
+ raise ValueError('id missing')
+ return True
+
+
def process_input(j):
rpc_id = j['id']
@@ -81,20 +88,33 @@ def process_input(j):
def start_server():
- os.unlink('/tmp/foo.ipc')
+ try:
+ os.unlink('/tmp/foo.ipc')
+ except FileNotFoundError:
+ pass
s = socket.socket(family = socket.AF_UNIX, type = socket.SOCK_STREAM)
s.bind('/tmp/foo.ipc')
s.listen(10)
while True:
(csock, caddr) = s.accept()
d = csock.recv(4096)
+ j = None
try:
- j = json.loads(b)
- process_input(j)
+ j = json.loads(d)
+ is_valid_json(j)
logg.debug('{}'.format(d.decode('utf-8')))
- csock.send(json.dumps(jsonrpc_ok(0, [])).encode('utf-8'))
except:
csock.send(json.dumps(jsonrpc_error(None, JSONRPCParseError)).encode('utf-8'))
+ csock.close()
+ continue
+
+ try:
+ (rpc_id, r) = process_input(j)
+ csock.send(json.dumps(jsonrpc_ok(rpc_id, r)).encode('utf-8'))
+ except:
+ # TODO: handle cases to give better error context to caller
+ csock.send(json.dumps(jsonrpc_error(j['id'], JSONRPCServerError)).encode('utf-8'))
+
csock.close()
s.close()
diff --git a/scripts/web3_middleware.py b/scripts/web3_middleware.py
@@ -0,0 +1,81 @@
+import logging
+import re
+import socket
+import uuid
+import json
+
+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
+
+
+ # single entry input gives a tuple on params, wtf...
+ @staticmethod
+ def _translate_params(params):
+ if params.__class__.__name__ == 'tuple':
+ r = []
+ for p in params:
+ r.append(p)
+ return r
+
+
+ def __call__(self, method, suspect_params):
+ self.id_seq += 1
+ params = PlatformMiddleware._translate_params(suspect_params)
+
+ logg.debug('method {} params {} original paramsĀ {}'.format(method, params, suspect_params))
+ if self.re_personal.match(method) != None:
+ # 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.debug('redirecting method {}'.format(method))
+ 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, params)
+ logg.debug('retular response {}'.format(r))
+ 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)