chainlib-eth

Ethereum implementation of the chainlib interface
Info | Log | Files | Refs | README | LICENSE

block.py (4851B)


      1 # standard imports
      2 import logging
      3 import datetime
      4 
      5 # external imports
      6 from chainlib.jsonrpc import JSONRPCRequest
      7 from chainlib.block import Block as BaseBlock
      8 from hexathon import (
      9         add_0x,
     10         strip_0x,
     11         compact,
     12         to_int as hex_to_int,
     13         )
     14 
     15 # local imports
     16 from chainlib.eth.tx import Tx
     17 from chainlib.eth.tx import eth_dialect_filter
     18 from .src import Src
     19 
     20 logg = logging.getLogger(__name__)
     21 
     22 
     23 def block_latest(id_generator=None):
     24     """Implements chainlib.interface.ChainInterface method
     25     """
     26     j = JSONRPCRequest(id_generator)
     27     o = j.template()
     28     o['method'] = 'eth_blockNumber'
     29     return j.finalize(o)
     30 
     31 
     32 def block_by_hash(hsh, include_tx=True, id_generator=None):
     33     """Implements chainlib.interface.ChainInterface method
     34     """
     35     j = JSONRPCRequest(id_generator)
     36     o = j.template()
     37     o['method'] = 'eth_getBlockByHash'
     38     o['params'].append(hsh)
     39     o['params'].append(include_tx)
     40     return j.finalize(o)
     41 
     42 
     43 def block_by_number(n, include_tx=True, id_generator=None):
     44     """Implements chainlib.interface.ChainInterface method
     45     """
     46     hx = strip_0x(hex(n))
     47     nhx = add_0x(compact(hx), compact_value=True)
     48     j = JSONRPCRequest(id_generator)
     49     o = j.template()
     50     o['method'] = 'eth_getBlockByNumber'
     51     o['params'].append(nhx)
     52     o['params'].append(include_tx)
     53     return j.finalize(o)
     54 
     55 
     56 def transaction_count(block_hash, id_generator=None):
     57     """Generate json-rpc query to get transaction count of block
     58 
     59     :param block_hash: Block hash, in hex
     60     :type block_hash: str
     61     :param id_generator: JSONRPC id generator
     62     :type id_generator: JSONRPCIdGenerator
     63     :rtype: dict
     64     :returns: rpc query object
     65     """
     66     j = JSONRPCRequest(id_generator)
     67     o = j.template()
     68     o['method'] = 'eth_getBlockTransactionCountByHash'
     69     o['params'].append(block_hash)
     70     return j.finalize(o)
     71 
     72 
     73 def syncing(id_generator=None):
     74     """Request the syncing state of the node
     75 
     76     :param id_generator: JSONRPC id generator
     77     :type id_generator: JSONRPCIdGenerator
     78     :rtype: dict
     79     :returns: rpc query object
     80     """
     81     j = JSONRPCRequest(id_generator)
     82     o = j.template()
     83     o['method'] = 'eth_syncing'
     84     return j.finalize(o)
     85 
     86 
     87 class Block(BaseBlock, Src):
     88     """Encapsulates an Ethereum block
     89 
     90     :param src: Block representation data
     91     :type src: dict
     92     :todo: Add hex to number parse to normalize
     93     """
     94    
     95     tx_generator = Tx
     96 
     97     def __init__(self, src=None, dialect_filter=None):
     98         super(Block, self).__init__(src=src, dialect_filter=dialect_filter)
     99 
    100 
    101     def __parse_author(self, src):
    102         author = None
    103         try:
    104             author = self.src['author']
    105         except KeyError:
    106             pass
    107         if author:
    108             return author
    109 
    110         try:
    111             author = self.src['miner']
    112         except KeyError:
    113             pass
    114         if author:
    115             return author
    116 
    117         return self.src['coinbase']
    118 
    119 
    120     def load_src(self, dialect_filter=None):
    121         if dialect_filter != None:
    122             dialect_filter.apply_block(self)
    123 
    124         self.set_hash(self.src['hash'])
    125         try:
    126             self.number = int(strip_0x(self.src['number']), 16)
    127         except TypeError:
    128             self.number = int(self.src['number'])
    129         self.txs = self.src['transactions']
    130         self.block_src = self.src
    131         try:
    132             self.timestamp = int(strip_0x(self.src['timestamp']), 16)
    133         except TypeError:
    134             self.timestamp = int(self.src['timestamp'])
    135 
    136         self.author = self.__parse_author(self.src)
    137 
    138 
    139     def tx_by_index(self, idx, dialect_filter=eth_dialect_filter):
    140         return super(Block, self).tx_by_index(idx, dialect_filter=dialect_filter)
    141 
    142 
    143     def tx_index_by_hash(self, tx_hash):
    144         i = 0
    145         idx = -1
    146         tx_hash = add_0x(tx_hash)
    147         for tx in self.txs:
    148             tx_hash_block = None
    149             try:
    150                 tx_hash_block = add_0x(tx['hash'])
    151             except TypeError:
    152                 tx_hash_block = add_0x(tx)
    153             if tx_hash_block == tx_hash:
    154                 idx = i
    155                 break
    156             i += 1
    157         if idx == -1:
    158             raise AttributeError('tx {} not found in block {}'.format(tx_hash, self.hash))
    159         return idx
    160 
    161 
    162     def to_human(self):
    163         try:
    164             self.fee_limit = hex_to_int(self.fee_limit)
    165         except TypeError:
    166             pass
    167 
    168         try:
    169             self.fee_cost = hex_to_int(self.fee_cost)
    170         except TypeError:
    171             pass
    172 
    173         s = """hash: {}
    174 number: {}
    175 parent: {}
    176 timestamp: {}
    177 time: {}
    178 author: {}
    179 gas_limit: {}
    180 gas_used: {}
    181 txs: {}
    182 """.format(
    183     self.hash,
    184     self.number,
    185     self.parent_hash,
    186     self.timestamp,
    187     datetime.datetime.fromtimestamp(self.timestamp),
    188     self.author,
    189     self.fee_limit,
    190     self.fee_cost,
    191     len(self.txs),
    192         )
    193 
    194         return s
    195