Add generic wire methods for signer

This commit is contained in:
nolash 2021-08-24 17:55:01 +02:00
parent ffcde95e5f
commit 418c54e9c7
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
8 changed files with 71 additions and 26 deletions

View File

@ -17,9 +17,17 @@ from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
# local imports # local imports
from chainlib.eth.address import AddressChecksum from chainlib.eth.address import AddressChecksum
from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.connection import EthHTTPConnection
from chainlib.eth.gas import (
OverrideGasOracle,
RPCGasOracle,
)
from chainlib.eth.nonce import (
OverrideNonceOracle,
RPCNonceOracle,
)
script_dir = os.path.dirname(os.path.realpath(__file__)) script_dir = os.path.dirname(os.path.realpath(__file__))
class Wallet(BaseWallet): class Wallet(BaseWallet):
"""Convenience constructor to set Ethereum defaults for chainlib cli Wallet object """Convenience constructor to set Ethereum defaults for chainlib cli Wallet object
@ -32,11 +40,42 @@ class Wallet(BaseWallet):
class Rpc(BaseRpc): class Rpc(BaseRpc):
"""Convenience constructor to set Ethereum defaults for chainlib cli Rpc object """Convenience constructor to set Ethereum defaults for chainlib cli Rpc object
""" """
def __init__(self, wallet=None): def __init__(self, wallet=None):
super(Rpc, self).__init__(EthHTTPConnection, wallet=wallet) super(Rpc, self).__init__(EthHTTPConnection, wallet=wallet)
def connect_by_config(self, config):
"""
If the standard arguments for nonce and fee price/price have been defined (which generate the configuration keys "_NONCE", "_FEE_PRICE" and "_FEE_LIMIT" respectively) , the corresponding overrides for fee and nonce generators will be defined.
"""
super(Rpc, self).connect_by_config(config)
if self.can_sign():
nonce = config.get('_NONCE')
if nonce != None:
self.nonce_oracle = OverrideNonceOracle(self.get_sender_address(), nonce, id_generator=self.id_generator)
else:
self.nonce_oracle = RPCNonceOracle(self.get_sender_address(), self.conn, id_generator=self.id_generator)
fee_price = config.get('_FEE_PRICE')
fee_limit = config.get('_FEE_LIMIT')
if fee_price != None or fee_limit != None:
self.fee_oracle = OverrideGasOracle(price=fee_price, limit=fee_limit, conn=self.conn, id_generator=self.id_generator)
else:
self.fee_oracle = RPCGasOracle(self.conn, id_generator=self.id_generator)
return self.conn
def get_gas_oracle(self):
return self.get_fee_oracle()
class Config(BaseConfig): class Config(BaseConfig):
"""Convenience constructor to set Ethereum defaults for the chainlib cli config object """Convenience constructor to set Ethereum defaults for the chainlib cli config object
""" """

View File

@ -179,13 +179,13 @@ class EthUnixSignerConnection(EthUnixConnection):
"""Connects rpc signer methods to Unix socket connection interface """Connects rpc signer methods to Unix socket connection interface
""" """
def sign_transaction_to_rlp(self, tx): def sign_transaction_to_wire(self, tx):
"""Sign transaction using unix socket rpc. """Sign transaction using unix socket rpc.
:param tx: Transaction object :param tx: Transaction object
:type tx: dict :type tx: dict
:rtype: See chainlin.eth.connection.sign_transaction_to_rlp :rtype: See chainlib.eth.connection.sign_transaction_to_rlp
:returns: See chainlin.eth.connection.sign_transaction_to_rlp :returns: Serialized signature
""" """
return sign_transaction_to_rlp(self.chain_spec, self.do, tx) return sign_transaction_to_rlp(self.chain_spec, self.do, tx)
@ -203,13 +203,13 @@ class EthUnixSignerConnection(EthUnixConnection):
class EthHTTPSignerConnection(EthHTTPConnection): class EthHTTPSignerConnection(EthHTTPConnection):
def sign_transaction_to_rlp(self, tx): def sign_transaction_to_wire(self, tx):
"""Sign transaction using http json-rpc. """Sign transaction using http json-rpc.
:param tx: Transaction object :param tx: Transaction object
:type tx: dict :type tx: dict
:rtype: See chainlin.eth.connection.sign_transaction_to_rlp :rtype: See chainlin.eth.connection.sign_transaction_to_rlp
:returns: See chainlin.eth.connection.sign_transaction_to_rlp :returns: Serialized signature
""" """
return sign_transaction_to_rlp(self.chain_spec, self.do, tx) return sign_transaction_to_rlp(self.chain_spec, self.do, tx)

View File

@ -9,6 +9,7 @@ from hexathon import (
from crypto_dev_signer.eth.transaction import EIP155Transaction from crypto_dev_signer.eth.transaction import EIP155Transaction
# local imports # local imports
from chainlib.fee import FeeOracle
from chainlib.hash import keccak256_hex_to_hex from chainlib.hash import keccak256_hex_to_hex
from chainlib.jsonrpc import JSONRPCRequest from chainlib.jsonrpc import JSONRPCRequest
from chainlib.eth.tx import ( from chainlib.eth.tx import (
@ -100,7 +101,7 @@ class Gas(TxFactory):
if data != None: if data != None:
tx['data'] = data tx['data'] = data
txe = EIP155Transaction(tx, tx['nonce'], tx['chainId']) txe = EIP155Transaction(tx, tx['nonce'], tx['chainId'])
tx_raw = self.signer.sign_transaction_to_rlp(txe) tx_raw = self.signer.sign_transaction_to_wire(txe)
tx_raw_hex = add_0x(tx_raw.hex()) tx_raw_hex = add_0x(tx_raw.hex())
tx_hash_hex = add_0x(keccak256_hex_to_hex(tx_raw_hex)) tx_hash_hex = add_0x(keccak256_hex_to_hex(tx_raw_hex))
@ -114,7 +115,7 @@ class Gas(TxFactory):
class RPCGasOracle: class RPCGasOracle(FeeOracle):
"""JSON-RPC only gas parameter helper. """JSON-RPC only gas parameter helper.
:param conn: RPC connection :param conn: RPC connection
@ -128,13 +129,13 @@ class RPCGasOracle:
""" """
def __init__(self, conn, code_callback=None, min_price=1, id_generator=None): def __init__(self, conn, code_callback=None, min_price=1, id_generator=None):
super(RPCGasOracle, self).__init__(code_callback=code_callback)
self.conn = conn self.conn = conn
self.code_callback = code_callback
self.min_price = min_price self.min_price = min_price
self.id_generator = id_generator self.id_generator = id_generator
def get_gas(self, code=None, input_data=None): def get_fee(self, code=None, input_data=None):
"""Retrieve gas parameters from node. """Retrieve gas parameters from node.
If code is given, the set code callback will be used to estimate gas usage. If code is given, the set code callback will be used to estimate gas usage.
@ -163,6 +164,10 @@ class RPCGasOracle:
return (gas_price, fee_units) return (gas_price, fee_units)
def get_gas(self, code=None, input_data=None):
return self.get_fee(code=code, input_data=input_data)
class RPCPureGasOracle(RPCGasOracle): class RPCPureGasOracle(RPCGasOracle):
"""Convenience constructor for rpc gas oracle without minimum price. """Convenience constructor for rpc gas oracle without minimum price.
@ -213,14 +218,12 @@ class OverrideGasOracle(RPCGasOracle):
super(OverrideGasOracle, self).__init__(price_conn, code_callback, id_generator=id_generator) super(OverrideGasOracle, self).__init__(price_conn, code_callback, id_generator=id_generator)
def get_gas(self, code=None): def get_fee(self, code=None, input_data=None):
"""See chainlib.eth.gas.RPCGasOracle.
"""
r = None r = None
fee_units = None fee_units = None
fee_price = None fee_price = None
rpc_results = super(OverrideGasOracle, self).get_gas(code) rpc_results = super(OverrideGasOracle, self).get_fee(code)
if self.limit != None: if self.limit != None:
fee_units = self.limit fee_units = self.limit
@ -245,4 +248,8 @@ class OverrideGasOracle(RPCGasOracle):
return (fee_price, fee_units) return (fee_price, fee_units)
def get_gas(self, code=None, input_data=None):
return self.get_fee(code=code, input_data=input_data)
DefaultGasOracle = RPCGasOracle DefaultGasOracle = RPCGasOracle

View File

@ -5,6 +5,7 @@ from hexathon import (
) )
# local imports # local imports
from chainlib.nonce import NonceOracle as BaseNonceOracle
from chainlib.jsonrpc import JSONRPCRequest from chainlib.jsonrpc import JSONRPCRequest
@ -22,7 +23,6 @@ def nonce(address, confirmed=False, id_generator=None):
o = j.template() o = j.template()
o['method'] = 'eth_getTransactionCount' o['method'] = 'eth_getTransactionCount'
o['params'].append(address) o['params'].append(address)
o['params'].append('pending')
if confirmed: if confirmed:
o['params'].append('latest') o['params'].append('latest')
else: else:
@ -34,7 +34,7 @@ def nonce_confirmed(address, id_generator=None):
return nonce(address, confirmed=True, id_generator=id_generator) return nonce(address, confirmed=True, id_generator=id_generator)
class NonceOracle: class NonceOracle(BaseNonceOracle):
"""Base class for the nonce parameter helpers. """Base class for the nonce parameter helpers.
:param address: Address to retireve nonce for, in hex :param address: Address to retireve nonce for, in hex
@ -43,9 +43,8 @@ class NonceOracle:
:type id_generator: chainlib.connection.JSONRPCIdGenerator :type id_generator: chainlib.connection.JSONRPCIdGenerator
""" """
def __init__(self, address, id_generator=None): def __init__(self, address, id_generator=None):
self.address = address
self.id_generator = id_generator self.id_generator = id_generator
self.nonce = self.get_nonce() super(NonceOracle, self).__init__(address)
def get_nonce(self): def get_nonce(self):

View File

@ -299,7 +299,7 @@ class TxFactory:
:param chain_spec: Chain spec to use for signer. :param chain_spec: Chain spec to use for signer.
:type chain_spec: chainlib.chain.ChainSpec :type chain_spec: chainlib.chain.ChainSpec
:param signer: Signer middleware. :param signer: Signer middleware.
:type param: Object implementing interface ofchainlib.eth.connection.sign_transaction_to_rlp. :type param: Object implementing interface ofchainlib.eth.connection.sign_transaction_to_wire
:param gas_oracle: Backend to generate gas parameters :param gas_oracle: Backend to generate gas parameters
:type gas_oracle: Object implementing chainlib.eth.gas.GasOracle interface :type gas_oracle: Object implementing chainlib.eth.gas.GasOracle interface
:param nonce_oracle: Backend to generate gas parameters :param nonce_oracle: Backend to generate gas parameters
@ -328,7 +328,7 @@ class TxFactory:
if tx['to'] == None or tx['to'] == '': if tx['to'] == None or tx['to'] == '':
tx['to'] = '0x' tx['to'] = '0x'
txe = EIP155Transaction(tx, tx['nonce'], tx['chainId']) txe = EIP155Transaction(tx, tx['nonce'], tx['chainId'])
tx_raw = self.signer.sign_transaction_to_rlp(txe) tx_raw = self.signer.sign_transaction_to_wire(txe)
tx_raw_hex = add_0x(tx_raw.hex()) tx_raw_hex = add_0x(tx_raw.hex())
tx_hash_hex = add_0x(keccak256_hex_to_hex(tx_raw_hex)) tx_hash_hex = add_0x(keccak256_hex_to_hex(tx_raw_hex))
return (tx_hash_hex, tx_raw_hex) return (tx_hash_hex, tx_raw_hex)

View File

@ -176,7 +176,7 @@ class TestRPCConnection(RPCConnection):
tx_dict = p[0] tx_dict = p[0]
tx = EIP155Transaction(tx_dict, tx_dict['nonce'], tx_dict['chainId']) tx = EIP155Transaction(tx_dict, tx_dict['nonce'], tx_dict['chainId'])
passphrase = p[1] passphrase = p[1]
r = self.signer.sign_transaction_to_rlp(tx, passphrase) r = self.signer.sign_transaction_to_wire(tx, passphrase)
return r return r
@ -192,9 +192,9 @@ class TestRPCConnection(RPCConnection):
return self.signer.sign_transaction(tx, passphrase) return self.signer.sign_transaction(tx, passphrase)
def sign_transaction_to_rlp(self, tx, passphrase=''): def sign_transaction_to_wire(self, tx, passphrase=''):
self.__verify_signer(tx, passphrase) self.__verify_signer(tx, passphrase)
return self.signer.sign_transaction_to_rlp(tx, passphrase) return self.signer.sign_transaction_to_wire(tx, passphrase)
def disconnect(self): def disconnect(self):

View File

@ -1,7 +1,7 @@
crypto-dev-signer>=0.4.14b7,<=0.4.14 crypto-dev-signer>=0.4.15a1,<=0.4.15
pysha3==1.0.2 pysha3==1.0.2
hexathon~=0.0.1a8 hexathon~=0.0.1a8
websocket-client==0.57.0 websocket-client==0.57.0
potaahto~=0.0.1a1 potaahto~=0.0.1a1
chainlib==0.0.8a2 chainlib==0.0.9a2
confini>=0.4.1a1,<0.5.0 confini>=0.4.1a1,<0.5.0

View File

@ -1,6 +1,6 @@
[metadata] [metadata]
name = chainlib-eth name = chainlib-eth
version = 0.0.8a2 version = 0.0.9a2
description = Ethereum implementation of the chainlib interface description = Ethereum implementation of the chainlib interface
author = Louis Holbrook author = Louis Holbrook
author_email = dev@holbrook.no author_email = dev@holbrook.no