Use tag instead of chain spec for rpc connection constructor registration
This commit is contained in:
parent
9356ef53b2
commit
b9581e83e7
@ -22,7 +22,7 @@ from .jsonrpc import (
|
|||||||
)
|
)
|
||||||
from .http import PreemptiveBasicAuthHandler
|
from .http import PreemptiveBasicAuthHandler
|
||||||
|
|
||||||
logg = logging.getLogger(__name__)
|
logg = logging.getLogger().getChild(__name__)
|
||||||
|
|
||||||
error_parser = DefaultErrorParser()
|
error_parser = DefaultErrorParser()
|
||||||
|
|
||||||
@ -65,19 +65,14 @@ def str_to_connspec(s):
|
|||||||
raise ValueError('unknown connection type {}'.format(s))
|
raise ValueError('unknown connection type {}'.format(s))
|
||||||
|
|
||||||
|
|
||||||
def from_conntype(t):
|
|
||||||
if t in [ConnType.HTTP, ConnType.HTTP_SSL]:
|
|
||||||
return JSONRPCHTTPConnection
|
|
||||||
elif t in [ConnType.UNIX]:
|
|
||||||
return JSONRPCUnixConnection
|
|
||||||
raise NotImplementedError(t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RPCConnection():
|
class RPCConnection():
|
||||||
|
|
||||||
__locations = {}
|
__locations = {}
|
||||||
__constructors = {}
|
__constructors = {
|
||||||
|
'default': {
|
||||||
|
},
|
||||||
|
}
|
||||||
|
__constructors_for_chains = {}
|
||||||
|
|
||||||
def __init__(self, url=None, chain_spec=None):
|
def __init__(self, url=None, chain_spec=None):
|
||||||
self.chain_spec = chain_spec
|
self.chain_spec = chain_spec
|
||||||
@ -104,34 +99,40 @@ class RPCConnection():
|
|||||||
logg.debug('parsed url {} to location {}'.format(url, self.location))
|
logg.debug('parsed url {} to location {}'.format(url, self.location))
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_conntype(t, tag='default'):
|
||||||
|
return RPCConnection.__constructors[tag][t]
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def register_constructor(t, c, tag='default'):
|
||||||
|
if RPCConnection.__constructors.get(tag) == None:
|
||||||
|
RPCConnection.__constructors[tag] = {}
|
||||||
|
RPCConnection.__constructors[tag][t] = c
|
||||||
|
logg.info('registered RPC connection constructor {} for type {} tag {}'.format(c, t, tag))
|
||||||
|
|
||||||
|
|
||||||
# TODO: constructor needs to be constructor-factory, that itself can select on url type
|
# TODO: constructor needs to be constructor-factory, that itself can select on url type
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def register_location(location, chain_spec, tag='default', constructor=None, exist_ok=False):
|
def register_location(location, chain_spec, tag='default', exist_ok=False):
|
||||||
chain_str = str(chain_spec)
|
chain_str = str(chain_spec)
|
||||||
if RPCConnection.__locations.get(chain_str) == None:
|
if RPCConnection.__locations.get(chain_str) == None:
|
||||||
RPCConnection.__locations[chain_str] = {}
|
RPCConnection.__locations[chain_str] = {}
|
||||||
RPCConnection.__constructors[chain_str] = {}
|
|
||||||
elif not exist_ok:
|
elif not exist_ok:
|
||||||
v = RPCConnection.__locations[chain_str].get(tag)
|
v = RPCConnection.__locations[chain_str].get(tag)
|
||||||
if v != None:
|
if v != None:
|
||||||
raise ValueError('duplicate registration of tag {}:{}, requested {} already had {}'.format(chain_str, tag, location, v))
|
raise ValueError('duplicate registration of tag {}:{}, requested {} already had {}'.format(chain_str, tag, location, v))
|
||||||
conntype = str_to_connspec(location)
|
conntype = str_to_connspec(location)
|
||||||
RPCConnection.__locations[chain_str][tag] = (conntype, location)
|
RPCConnection.__locations[chain_str][tag] = (conntype, location)
|
||||||
if constructor != None:
|
logg.info('registered rpc connection {} ({}/{}) as {}'.format(location, chain_str, tag, conntype))
|
||||||
RPCConnection.__constructors[chain_str][tag] = constructor
|
|
||||||
logg.info('registered rpc connection {} ({}:{}) as {} with custom constructor {}'.format(location, chain_str, tag, conntype, constructor))
|
|
||||||
else:
|
|
||||||
logg.info('registered rpc connection {} ({}:{}) as {}'.format(location, chain_str, tag, conntype))
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def connect(chain_spec, tag='default'):
|
def connect(chain_spec, tag='default'):
|
||||||
chain_str = str(chain_spec)
|
chain_str = str(chain_spec)
|
||||||
c = RPCConnection.__locations[chain_str][tag]
|
c = RPCConnection.__locations[chain_str][tag]
|
||||||
constructor = RPCConnection.__constructors[chain_str].get(tag)
|
constructor = RPCConnection.from_conntype(c[0], tag=tag)
|
||||||
if constructor == None:
|
logg.debug('rpc connect {} {} {}'.format(constructor, c, tag))
|
||||||
constructor = from_conntype(c[0])
|
|
||||||
logg.debug('cons {} {}'.format(constructor, c))
|
|
||||||
return constructor(url=c[1], chain_spec=chain_spec)
|
return constructor(url=c[1], chain_spec=chain_spec)
|
||||||
|
|
||||||
|
|
||||||
@ -215,3 +216,7 @@ class JSONRPCUnixConnection(UnixConnection):
|
|||||||
|
|
||||||
return jsonrpc_result(result, error_parser)
|
return jsonrpc_result(result, error_parser)
|
||||||
|
|
||||||
|
|
||||||
|
RPCConnection.register_constructor(ConnType.HTTP, JSONRPCHTTPConnection, tag='default')
|
||||||
|
RPCConnection.register_constructor(ConnType.HTTP_SSL, JSONRPCHTTPConnection, tag='default')
|
||||||
|
RPCConnection.register_constructor(ConnType.UNIX, JSONRPCUnixConnection, tag='default')
|
||||||
|
@ -25,6 +25,8 @@ from .sign import (
|
|||||||
sign_transaction,
|
sign_transaction,
|
||||||
)
|
)
|
||||||
from chainlib.connection import (
|
from chainlib.connection import (
|
||||||
|
ConnType,
|
||||||
|
RPCConnection,
|
||||||
JSONRPCHTTPConnection,
|
JSONRPCHTTPConnection,
|
||||||
JSONRPCUnixConnection,
|
JSONRPCUnixConnection,
|
||||||
error_parser,
|
error_parser,
|
||||||
@ -82,23 +84,47 @@ class EthUnixConnection(JSONRPCUnixConnection):
|
|||||||
raise NotImplementedError('Not yet implemented for unix socket')
|
raise NotImplementedError('Not yet implemented for unix socket')
|
||||||
|
|
||||||
|
|
||||||
|
def sign_transaction_to_rlp(chain_spec, doer, tx):
|
||||||
|
txs = tx.serialize()
|
||||||
|
logg.debug('serializing {}'.format(txs))
|
||||||
|
# TODO: because some rpc servers may fail when chainId is included, we are forced to spend cpu here on this
|
||||||
|
chain_id = txs.get('chainId') or 1
|
||||||
|
if chain_spec != None:
|
||||||
|
chain_id = chain_spec.chain_id()
|
||||||
|
txs['chainId'] = add_0x(chain_id.to_bytes(2, 'big').hex())
|
||||||
|
txs['from'] = add_0x(tx.sender)
|
||||||
|
o = sign_transaction(txs)
|
||||||
|
r = doer(o)
|
||||||
|
logg.debug('sig got {}'.format(r))
|
||||||
|
return bytes.fromhex(strip_0x(r))
|
||||||
|
|
||||||
|
|
||||||
|
def sign_message(doer, msg):
|
||||||
|
o = sign_message(msg)
|
||||||
|
return doer(o)
|
||||||
|
|
||||||
|
|
||||||
class EthUnixSignerConnection(EthUnixConnection):
|
class EthUnixSignerConnection(EthUnixConnection):
|
||||||
|
|
||||||
def sign_transaction_to_rlp(self, tx):
|
def sign_transaction_to_rlp(self, tx):
|
||||||
txs = tx.serialize()
|
return sign_transaction_to_rlp(self.chain_spec, self.do, tx)
|
||||||
logg.debug('serializing {}'.format(txs))
|
|
||||||
# TODO: because some rpc servers may fail when chainId is included, we are forced to spend cpu here on this
|
|
||||||
chain_id = txs.get('chainId') or 1
|
|
||||||
if self.chain_spec != None:
|
|
||||||
chain_id = self.chain_spec.chain_id()
|
|
||||||
txs['chainId'] = add_0x(chain_id.to_bytes(2, 'big').hex())
|
|
||||||
txs['from'] = add_0x(tx.sender)
|
|
||||||
o = sign_transaction(txs)
|
|
||||||
r = self.do(o)
|
|
||||||
logg.debug('sig got {}'.format(r))
|
|
||||||
return bytes.fromhex(strip_0x(r))
|
|
||||||
|
|
||||||
|
|
||||||
def sign_message(self, msg):
|
def sign_message(self, tx):
|
||||||
o = sign_message(msg)
|
return sign_message(self.do, tx)
|
||||||
return self.do(o)
|
|
||||||
|
|
||||||
|
class EthHTTPSignerConnection(EthHTTPConnection):
|
||||||
|
|
||||||
|
def sign_transaction_to_rlp(self, tx):
|
||||||
|
return sign_transaction_to_rlp(self.chain_spec, self.do, tx)
|
||||||
|
|
||||||
|
|
||||||
|
def sign_message(self, tx):
|
||||||
|
return sign_message(self.do, tx)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RPCConnection.register_constructor(ConnType.HTTP, EthHTTPConnection, tag='eth_default')
|
||||||
|
RPCConnection.register_constructor(ConnType.HTTP_SSL, EthHTTPConnection, tag='eth_default')
|
||||||
|
RPCConnection.register_constructor(ConnType.UNIX, EthUnixConnection, tag='eth_default')
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = chainlib
|
name = chainlib
|
||||||
version = 0.0.2a16
|
version = 0.0.2a17
|
||||||
description = Generic blockchain access library and tooling
|
description = Generic blockchain access library and tooling
|
||||||
author = Louis Holbrook
|
author = Louis Holbrook
|
||||||
author_email = dev@holbrook.no
|
author_email = dev@holbrook.no
|
||||||
|
Loading…
Reference in New Issue
Block a user