chainlib

Generic blockchain access library and tooling
Log | Files | Refs | README | LICENSE

commit b9581e83e7af82be129870e01631685bea1987f3
parent 9356ef53b22cacc6bac26675f270c8202a901ad4
Author: nolash <dev@holbrook.no>
Date:   Sat, 24 Apr 2021 07:36:45 +0200

Use tag instead of chain spec for rpc connection constructor registration

Diffstat:
Mchainlib/connection.py | 49+++++++++++++++++++++++++++----------------------
Mchainlib/eth/connection.py | 60+++++++++++++++++++++++++++++++++++++++++++-----------------
Msetup.cfg | 2+-
3 files changed, 71 insertions(+), 40 deletions(-)

diff --git a/chainlib/connection.py b/chainlib/connection.py @@ -22,7 +22,7 @@ from .jsonrpc import ( ) from .http import PreemptiveBasicAuthHandler -logg = logging.getLogger(__name__) +logg = logging.getLogger().getChild(__name__) error_parser = DefaultErrorParser() @@ -65,19 +65,14 @@ def str_to_connspec(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(): __locations = {} - __constructors = {} + __constructors = { + 'default': { + }, + } + __constructors_for_chains = {} def __init__(self, url=None, chain_spec=None): self.chain_spec = chain_spec @@ -104,34 +99,40 @@ class RPCConnection(): 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 @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) if RPCConnection.__locations.get(chain_str) == None: RPCConnection.__locations[chain_str] = {} - RPCConnection.__constructors[chain_str] = {} elif not exist_ok: v = RPCConnection.__locations[chain_str].get(tag) if v != None: raise ValueError('duplicate registration of tag {}:{}, requested {} already had {}'.format(chain_str, tag, location, v)) conntype = str_to_connspec(location) RPCConnection.__locations[chain_str][tag] = (conntype, location) - if constructor != None: - 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)) + logg.info('registered rpc connection {} ({}/{}) as {}'.format(location, chain_str, tag, conntype)) @staticmethod def connect(chain_spec, tag='default'): chain_str = str(chain_spec) c = RPCConnection.__locations[chain_str][tag] - constructor = RPCConnection.__constructors[chain_str].get(tag) - if constructor == None: - constructor = from_conntype(c[0]) - logg.debug('cons {} {}'.format(constructor, c)) + constructor = RPCConnection.from_conntype(c[0], tag=tag) + logg.debug('rpc connect {} {} {}'.format(constructor, c, tag)) return constructor(url=c[1], chain_spec=chain_spec) @@ -215,3 +216,7 @@ class JSONRPCUnixConnection(UnixConnection): 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') diff --git a/chainlib/eth/connection.py b/chainlib/eth/connection.py @@ -25,6 +25,8 @@ from .sign import ( sign_transaction, ) from chainlib.connection import ( + ConnType, + RPCConnection, JSONRPCHTTPConnection, JSONRPCUnixConnection, error_parser, @@ -82,23 +84,47 @@ class EthUnixConnection(JSONRPCUnixConnection): 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): def sign_transaction_to_rlp(self, 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 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): - o = sign_message(msg) - return self.do(o) + return sign_transaction_to_rlp(self.chain_spec, self.do, tx) + + + def sign_message(self, tx): + return sign_message(self.do, tx) + + +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') diff --git a/setup.cfg b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = chainlib -version = 0.0.2a16 +version = 0.0.2a17 description = Generic blockchain access library and tooling author = Louis Holbrook author_email = dev@holbrook.no