256 lines
7.9 KiB
Python
256 lines
7.9 KiB
Python
|
# standard imports
|
|||
|
import logging
|
|||
|
|
|||
|
logg = logging.getLogger(__name__)
|
|||
|
|
|||
|
|
|||
|
class ChainInterface:
|
|||
|
"""Common interface for all chain RPC query generators.
|
|||
|
|
|||
|
This class should be overridden for every implementation of chain architecture RPC.
|
|||
|
|
|||
|
It is up to the implementer which of the symbols to implement code for. Any implemented symbols should be associated using the ChainInterface.set method.
|
|||
|
|
|||
|
All implemented methods must generate RPC queries ready to submit using an implementation of chainlib.connection.RPCConnection
|
|||
|
"""
|
|||
|
|
|||
|
interface_name = 'custom'
|
|||
|
|
|||
|
def __unimplemented(*args, **kwargs):
|
|||
|
raise NotImplementedError()
|
|||
|
|
|||
|
|
|||
|
def __init__(self):
|
|||
|
self._block_latest = self.__unimplemented
|
|||
|
self._block_by_hash = self.__unimplemented
|
|||
|
self._block_by_number = self.__unimplemented
|
|||
|
self._block_from_src = self.__unimplemented
|
|||
|
self._block_to_src = self.__unimplemented
|
|||
|
self._tx_by_hash = self.__unimplemented
|
|||
|
self._tx_by_block = self.__unimplemented
|
|||
|
self._tx_receipt = self.__unimplemented
|
|||
|
self._tx_raw = self.__unimplemented
|
|||
|
self._tx_pack = self.__unimplemented
|
|||
|
self._tx_unpack = self.__unimplemented
|
|||
|
self._tx_from_src = self.__unimplemented
|
|||
|
self._tx_to_src = self.__unimplemented
|
|||
|
self._address_safe = self.__unimplemented
|
|||
|
self._address_normal = self.__unimplemented
|
|||
|
self._src_normalize = self.__unimplemented
|
|||
|
|
|||
|
|
|||
|
def block_latest(self, *args, **kwargs):
|
|||
|
"""Retrieve the last block known to the node.
|
|||
|
|
|||
|
:rtype: dict
|
|||
|
:returns: rpc query object
|
|||
|
"""
|
|||
|
return self._block_latest(*args, **kwargs)
|
|||
|
|
|||
|
|
|||
|
def block_by_hash(self, hsh, *args, **kwargs):
|
|||
|
"""Retrieve the block representation from the given block hash
|
|||
|
|
|||
|
:param hsh: Block hash, as hex
|
|||
|
:type hsh: str
|
|||
|
:param id_generator: JSONRPC id generator
|
|||
|
:type id_generator: JSONRPCIdGenerator
|
|||
|
:rtype: dict
|
|||
|
:returns: rpc query object
|
|||
|
"""
|
|||
|
return self._block_by_hash(hsh, *args, **kwargs)
|
|||
|
|
|||
|
|
|||
|
def block_by_number(self, idx, *args, **kwargs):
|
|||
|
"""Retrieve the block representation from the given block height index
|
|||
|
|
|||
|
:param idx: Block index number
|
|||
|
:type idx: int
|
|||
|
:param id_generator: JSONRPC id generator
|
|||
|
:type id_generator: JSONRPCIdGenerator
|
|||
|
:rtype: dict
|
|||
|
:returns: rpc query object
|
|||
|
"""
|
|||
|
return self._block_by_number(idx, *args, **kwargs)
|
|||
|
|
|||
|
|
|||
|
def block_from_src(self, src):
|
|||
|
"""Instantiate an implementation specific block object from the block representation returned from an RPC result
|
|||
|
|
|||
|
:param src: Block source
|
|||
|
:type src: dict
|
|||
|
:param id_generator: JSONRPC id generator
|
|||
|
:type id_generator: JSONRPCIdGenerator
|
|||
|
:rtype: chainlib.block.Block
|
|||
|
:returns: Block object
|
|||
|
"""
|
|||
|
return self._block_from_src(src)
|
|||
|
|
|||
|
|
|||
|
def block_to_src(self, block):
|
|||
|
"""Implementation specific serialization of a block object
|
|||
|
|
|||
|
:param block: Block object
|
|||
|
:type block: chainlib.block.Block
|
|||
|
:param id_generator: JSONRPC id generator
|
|||
|
:type id_generator: JSONRPCIdGenerator
|
|||
|
:rtype: dict
|
|||
|
:returns: Serialized block object
|
|||
|
"""
|
|||
|
return self._block_to_src()
|
|||
|
|
|||
|
|
|||
|
def tx_by_hash(self, hsh, *args, **kwargs):
|
|||
|
"""Retrieve the transaction representation by the given transaction hash
|
|||
|
|
|||
|
:param hsh: Transaction hash, as hex
|
|||
|
:type hsh: str
|
|||
|
:param id_generator: JSONRPC id generator
|
|||
|
:type id_generator: JSONRPCIdGenerator
|
|||
|
:rtype: dict
|
|||
|
:returns: rpc query object
|
|||
|
"""
|
|||
|
return self._tx_by_hash(hsh, *args, **kwargs)
|
|||
|
|
|||
|
|
|||
|
def tx_by_block(self, hsh, idx, *args, **kwargs):
|
|||
|
"""Retrieve the transaction representation by the given block hash and transaction index
|
|||
|
|
|||
|
:param hsh: Block hash, as hex
|
|||
|
:type hsh: str
|
|||
|
:param idx: Transaction index
|
|||
|
:type idx: int
|
|||
|
:param id_generator: JSONRPC id generator
|
|||
|
:type id_generator: JSONRPCIdGenerator
|
|||
|
:rtype: dict
|
|||
|
:returns: rpc query object
|
|||
|
|
|||
|
"""
|
|||
|
return self._tx_by_block(hsh, idx, *args, **kwargs)
|
|||
|
|
|||
|
|
|||
|
def tx_receipt(self, hsh, *args, **kwargs):
|
|||
|
"""Retrieve representation of confirmed transaction result for given transaction hash
|
|||
|
|
|||
|
:param hsh: Transaction hash, as hex
|
|||
|
:type hsh: str
|
|||
|
:param id_generator: JSONRPC id generator
|
|||
|
:type id_generator: JSONRPCIdGenerator
|
|||
|
:rtype: dict
|
|||
|
:returns: rpc query object
|
|||
|
"""
|
|||
|
return self._tx_receipt(hsh, *args, **kwargs)
|
|||
|
|
|||
|
|
|||
|
def tx_raw(self, data, *args, **kwargs):
|
|||
|
"""Create a raw transaction query from the given wire format
|
|||
|
|
|||
|
:param data: Transaction wire format, in hex
|
|||
|
:type data: str
|
|||
|
:param id_generator: JSONRPC id generator
|
|||
|
:type id_generator: JSONRPCIdGenerator
|
|||
|
:rtype: dict
|
|||
|
:returns: rpc query object
|
|||
|
|
|||
|
"""
|
|||
|
return self._tx_raw(data, *args, **kwargs)
|
|||
|
|
|||
|
|
|||
|
def tx_pack(self, tx, chain_spec):
|
|||
|
"""Generate wire format for transaction
|
|||
|
|
|||
|
:param tx: Transaction object
|
|||
|
:type tx: dict
|
|||
|
:param chain_spec: Chain spec to generate wire format for
|
|||
|
:type chain_spec: chainlib.chain.ChainSpec
|
|||
|
:rtype: bytes
|
|||
|
:returns: Wire format, in bytes
|
|||
|
"""
|
|||
|
return self._tx_pack(tx, chain_spec)
|
|||
|
|
|||
|
|
|||
|
def tx_unpack(self, data, chain_spec):
|
|||
|
"""Generate transaction representation from wire format.
|
|||
|
|
|||
|
:param data: Wire format, in bytes
|
|||
|
:type data: bytes
|
|||
|
:param chain_spec: Chain spec to parse wire format with
|
|||
|
:type chain_spec: chainlib.chain.ChainSpec
|
|||
|
:rtype: dict
|
|||
|
:returns: Transaction representation
|
|||
|
"""
|
|||
|
return self._tx_unpack(data, chain_spec)
|
|||
|
|
|||
|
|
|||
|
def tx_from_src(self, src, block=None):
|
|||
|
"""Instantiate transaction object from implementation specific transaction representation.
|
|||
|
|
|||
|
:param src: Transaction representation
|
|||
|
:type src: dict
|
|||
|
:param block: Block object which transaction has been included in
|
|||
|
:type block: chainlib.block.Block
|
|||
|
:rtype: chainlib.tx.Tx
|
|||
|
:returns: Transaction object
|
|||
|
"""
|
|||
|
return self._tx_from_src(src, block)
|
|||
|
|
|||
|
|
|||
|
def tx_to_src(self, tx):
|
|||
|
"""Generate implementation specific transaction representation from transaction object.
|
|||
|
|
|||
|
:param tx: Transaction object
|
|||
|
:type tx: chainlib.tx.Tx
|
|||
|
:rtype: dict
|
|||
|
:returns: Transaction representation
|
|||
|
"""
|
|||
|
return self._tx_to_src(tx)
|
|||
|
|
|||
|
|
|||
|
def address_safe(self, address):
|
|||
|
"""Generate implementation specific checksummed version of a crypto address.
|
|||
|
|
|||
|
:param address: Potentially unsafe address
|
|||
|
:type address: str
|
|||
|
:rtype: str
|
|||
|
:returns: Checksummed address
|
|||
|
"""
|
|||
|
return self._address_safe(address)
|
|||
|
|
|||
|
|
|||
|
def address_normal(self, address):
|
|||
|
"""Generate normalized version of a crypto address.
|
|||
|
|
|||
|
:param address: Crypto address
|
|||
|
:type address: str
|
|||
|
:rtype: str
|
|||
|
:returns: Normalized address
|
|||
|
"""
|
|||
|
return self._address_normal(address)
|
|||
|
|
|||
|
|
|||
|
def src_normalize(self, src):
|
|||
|
"""Generate a normalized source of an object representation.
|
|||
|
|
|||
|
:param src: Object representation source
|
|||
|
:type src: dict
|
|||
|
:rtype: dict
|
|||
|
:returns: Normalized representation
|
|||
|
"""
|
|||
|
return self._src_normalize(src)
|
|||
|
|
|||
|
|
|||
|
def set(self, method, target):
|
|||
|
"""Associate object with method symbol.
|
|||
|
|
|||
|
:param method: Method string
|
|||
|
:type method: str
|
|||
|
:param target: Target method
|
|||
|
:type target: object
|
|||
|
:raises AttributeError: Invalid method
|
|||
|
"""
|
|||
|
imethod = '_' + method
|
|||
|
if not hasattr(self, imethod):
|
|||
|
raise AttributeError('invalid method {}'.format(imethod))
|
|||
|
setattr(self, imethod, target)
|
|||
|
logg.debug('set method {} on interface {}'.format(method, self.interface_name))
|