Source code for ether_sql.models.blocks

import logging
from sqlalchemy import Column, String, Numeric, TIMESTAMP, Text
from sqlalchemy.orm import relationship
from sqlalchemy import func
from web3.utils.encoding import (to_int, to_hex)
from eth_utils import to_checksum_address
from ether_sql.models import base
from ether_sql.globals import get_current_session
logger = logging.getLogger(__name__)


[docs]class Blocks(base): """ Class mapping a block table in the psql database to a block in ethereum node. :param int block_number: Quantity equal to number of blocks behind the current block :param str block_hash: The Keccak 256-bit hash of this block :param str parent_hash: The Keccak 256-bit hash of the parent of this block :param int difficulty: Difficulty level of this block :param int gas_used: Total gas used by the transactions in this block :param str miner: Address to which all block rewards are transferred :param datetime timestamp: Unix time at the at this blocks inception :param str sha3uncles: Keccak 256-bit hash of the uncles portion of this block :param str extra_data: Byte array of 32 bytes or less containing extra data of this block :param int gas_limit: Current maximum gas expenditure per block :param int uncle_count: Number of uncles in this block :param int transaction_count: Number of transactions in this block """ __tablename__ = 'blocks' block_number = Column(Numeric, primary_key=True, index=True) block_hash = Column(String(66), unique=True, nullable=False) parent_hash = Column(String(66), unique=True, nullable=False) difficulty = Column(Numeric, nullable=False) gas_used = Column(Numeric, nullable=False) miner = Column(String(42), nullable=False) timestamp = Column(TIMESTAMP, unique=True, nullable=False) sha3uncles = Column(String(66), nullable=False) extra_data = Column(Text) gas_limit = Column(Numeric, nullable=False) uncle_count = Column(Numeric, nullable=False) transaction_count = Column(Numeric, nullable=False) transactions = relationship('Transactions', backref='blocks') uncles = relationship('Uncles', backref='blocks') logs = relationship('Logs', backref='blocks') traces = relationship('Traces', backref='blocks') state_diff = relationship('StateDiff', backref='blocks') def to_dict(self): return { 'block_number': self.block_number, 'block_hash': self.block_hash, 'parent_hash': self.parent_hash, 'difficulty': self.difficulty, 'gas_used': self.gas_used, 'miner': self.miner, 'timestamp': self.timestamp, 'sha3uncles': self.sha3uncles, 'extra_data': self.extra_data, 'gas_limit': self.gas_limit, 'uncle_count': self.uncle_count, 'transaction_count': self.transaction_count } def __repr__(self): return "<Block {}>".format(self.block_number)
[docs] @classmethod def add_block(cls, block_data, iso_timestamp): """ Creates a new block object from data received from JSON-RPC call eth_getBlockByNumber. :param dict block_data: data received from the JSON RPC call :param datetime iso_timestamp: timestamp when the block was mined """ block = cls(block_hash=to_hex(block_data['hash']), parent_hash=to_hex(block_data['parentHash']), difficulty=to_int(block_data['difficulty']), block_number=to_int(block_data['number']), gas_used=to_int(block_data['gasUsed']), miner=to_checksum_address(block_data['miner']), timestamp=iso_timestamp, sha3uncles=to_hex(block_data['sha3Uncles']), extra_data=to_hex(block_data['extraData']), gas_limit=to_int(block_data['gasLimit']), transaction_count=len(block_data['transactions']), uncle_count=len(block_data['uncles'])) return block
@classmethod def get_max_block_number(cls): current_session = get_current_session() with current_session.db_session_scope(): max_block_number = current_session.db_session.query( func.max(cls.block_number)).scalar() return max_block_number
[docs] @classmethod def missing_blocks(cls, max_block_number=None): """ Return missing blocks in the blocks table between 0 to block_number :param int max_block_number: Maximum block number that we want to find missing blocks from """ current_session = get_current_session() if max_block_number is None: max_block_number = cls.get_max_block_number() logger.debug(max_block_number) with current_session.db_session_scope(): stmt = current_session.db_session.query( func.generate_series(0, max_block_number).label('i')).subquery() joined = stmt.outerjoin(cls, cls.block_number == stmt.c.i) missing_blocks = current_session.db_session.query(stmt.c.i.label('block_number')).\ select_from(joined).filter(cls.block_number == None).all() return missing_blocks