Move middleware to web3 override package

This commit is contained in:
nolash 2020-08-07 11:37:20 +02:00
parent 0fa2dc1efa
commit b9a88de30c
Signed by: lash
GPG Key ID: 93EC1C676274C889
4 changed files with 118 additions and 90 deletions

View File

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

View File

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

31
src/web3ext/__init__.py Normal file
View File

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

78
src/web3ext/middleware.py Normal file
View File

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