def _remove_transaction_from_canonical_chain( db: DatabaseAPI, transaction_hash: Hash32) -> None: """ Removes the transaction specified by the given hash from the canonical chain. """ db.delete( SchemaV1.make_transaction_hash_to_block_lookup_key( transaction_hash))
def _get_canonical_block_hash(db: DatabaseAPI, block_number: BlockNumber) -> Hash32: validate_block_number(block_number) number_to_hash_key = SchemaV1.make_block_number_to_hash_lookup_key(block_number) try: encoded_key = db[number_to_hash_key] except KeyError: raise HeaderNotFound( f"No canonical header for block number #{block_number}" ) else: return rlp.decode(encoded_key, sedes=rlp.sedes.binary)
def _add_block_number_to_hash_lookup(db: DatabaseAPI, header: BlockHeaderAPI) -> None: """ Sets a record in the database to allow looking up this header by its block number. """ block_number_to_hash_key = SchemaV1.make_block_number_to_hash_lookup_key( header.block_number ) db.set( block_number_to_hash_key, rlp.encode(header.hash, sedes=rlp.sedes.binary), )
def get_transaction_index( self, transaction_hash: Hash32) -> Tuple[BlockNumber, int]: key = SchemaV1.make_transaction_hash_to_block_lookup_key( transaction_hash) try: encoded_key = self.db[key] except KeyError: raise TransactionNotFound( f"Transaction {encode_hex(transaction_hash)} not found in canonical chain" ) transaction_key = rlp.decode(encoded_key, sedes=TransactionKey) return (transaction_key.block_number, transaction_key.index)
def _set_hash_scores_to_db( cls, db: DatabaseAPI, header: BlockHeaderAPI, score: int ) -> int: new_score = score + header.difficulty db.set( SchemaV1.make_block_hash_to_score_lookup_key(header.hash), rlp.encode(new_score, sedes=rlp.sedes.big_endian_int), ) return new_score
def _add_transaction_to_canonical_chain(db: DatabaseAPI, transaction_hash: Hash32, block_header: BlockHeaderAPI, index: int) -> None: """ :param bytes transaction_hash: the hash of the transaction to add the lookup for :param block_header: The header of the block with the txn that is in the canonical chain :param int index: the position of the transaction in the block - add lookup from transaction hash to the block number and index that the body is stored at - remove transaction hash to body lookup in the pending pool """ transaction_key = TransactionKey(block_header.block_number, index) db.set( SchemaV1.make_transaction_hash_to_block_lookup_key( transaction_hash), rlp.encode(transaction_key), )
def _set_as_canonical_chain_head( cls, db: DatabaseAPI, header: BlockHeaderAPI, genesis_parent_hash: Hash32, ) -> Tuple[Tuple[BlockHeaderAPI, ...], Tuple[BlockHeaderAPI, ...]]: """ Sets the canonical chain HEAD to the block header as specified by the given block hash. :return: a tuple of the headers that are newly in the canonical chain, and the headers that are no longer in the canonical chain """ try: current_canonical_head = cls._get_canonical_head_hash(db) except CanonicalHeadNotFound: current_canonical_head = None new_canonical_headers: Tuple[BlockHeaderAPI, ...] old_canonical_headers: Tuple[BlockHeaderAPI, ...] if current_canonical_head and header.parent_hash == current_canonical_head: # the calls to _find_new_ancestors and _decanonicalize_old_headers are # relatively expensive, it's better to skip them in this case, where we're # extending the canonical chain by a header new_canonical_headers = (header,) old_canonical_headers = () else: new_canonical_headers = cast( Tuple[BlockHeaderAPI, ...], tuple(reversed(cls._find_new_ancestors(db, header, genesis_parent_hash))) ) old_canonical_headers = cls._decanonicalize_old_headers( db, new_canonical_headers ) for h in new_canonical_headers: cls._add_block_number_to_hash_lookup(db, h) db.set(SchemaV1.make_canonical_head_hash_lookup_key(), header.hash) return new_canonical_headers, old_canonical_headers
def _get_canonical_head_hash(cls, db: DatabaseAPI) -> Hash32: try: return Hash32(db[SchemaV1.make_canonical_head_hash_lookup_key()]) except KeyError: raise CanonicalHeadNotFound("No canonical head set for this chain")
def _get_score(db: DatabaseAPI, block_hash: Hash32) -> int: try: encoded_score = db[SchemaV1.make_block_hash_to_score_lookup_key(block_hash)] except KeyError: raise HeaderNotFound(f"No header with hash {encode_hex(block_hash)} found") return rlp.decode(encoded_score, sedes=rlp.sedes.big_endian_int)