Add middleware example in scripts

This commit is contained in:
nolash 2020-08-06 09:41:42 +02:00
parent 7c3208de4c
commit d3627d81fd
Signed by: lash
GPG Key ID: 93EC1C676274C889
2 changed files with 106 additions and 5 deletions

View File

@ -53,9 +53,10 @@ methods = {
} }
def jsonrpc_error(id, err): def jsonrpc_error(rpc_id, err):
return { return {
'json-rpc': '2.0', 'json-rpc': '2.0',
'id': rpc_id,
'error': { 'error': {
'code': err.CODE, 'code': err.CODE,
'message': err.MESSAGE, '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): def process_input(j):
rpc_id = j['id'] rpc_id = j['id']
@ -81,20 +88,33 @@ def process_input(j):
def start_server(): 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 = socket.socket(family = socket.AF_UNIX, type = socket.SOCK_STREAM)
s.bind('/tmp/foo.ipc') s.bind('/tmp/foo.ipc')
s.listen(10) s.listen(10)
while True: while True:
(csock, caddr) = s.accept() (csock, caddr) = s.accept()
d = csock.recv(4096) d = csock.recv(4096)
j = None
try: try:
j = json.loads(b) j = json.loads(d)
process_input(j) is_valid_json(j)
logg.debug('{}'.format(d.decode('utf-8'))) logg.debug('{}'.format(d.decode('utf-8')))
csock.send(json.dumps(jsonrpc_ok(0, [])).encode('utf-8'))
except: except:
csock.send(json.dumps(jsonrpc_error(None, JSONRPCParseError)).encode('utf-8')) 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() csock.close()
s.close() s.close()

View File

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