def test_chaindb_get_score(chaindb, sample_beacon_block_params): genesis = BeaconBlock(**sample_beacon_block_params).copy( parent_root=GENESIS_PARENT_HASH, slot=0, ) chaindb.persist_block(genesis) genesis_score_key = SchemaV1.make_block_root_to_score_lookup_key( genesis.root) genesis_score = rlp.decode(chaindb.db.get(genesis_score_key), sedes=rlp.sedes.big_endian_int) assert genesis_score == 0 assert chaindb.get_score(genesis.root) == 0 block1 = BeaconBlock(**sample_beacon_block_params).copy( parent_root=genesis.root, slot=1, ) chaindb.persist_block(block1) block1_score_key = SchemaV1.make_block_root_to_score_lookup_key( block1.root) block1_score = rlp.decode(chaindb.db.get(block1_score_key), sedes=rlp.sedes.big_endian_int) assert block1_score == 1 assert chaindb.get_score(block1.root) == 1
def _persist_block_chain( cls, db: BaseDB, blocks: Iterable[BaseBeaconBlock], block_class: Type[BaseBeaconBlock] ) -> Tuple[Tuple[BaseBeaconBlock, ...], Tuple[BaseBeaconBlock, ...]]: try: first_block = first(blocks) except StopIteration: return tuple(), tuple() else: for parent, child in sliding_window(2, blocks): if parent.root != child.parent_root: raise ValidationError( "Non-contiguous chain. Expected {} to have {} as parent but was {}" .format( encode_hex(child.root), encode_hex(parent.root), encode_hex(child.parent_root), )) is_genesis = first_block.parent_root == GENESIS_PARENT_HASH if not is_genesis and not cls._block_exists( db, first_block.parent_root): raise ParentNotFound( "Cannot persist block ({}) with unknown parent ({})". format(encode_hex(first_block.root), encode_hex(first_block.parent_root))) if is_genesis: score = 0 else: score = cls._get_score(db, first_block.parent_root) for block in blocks: db.set( block.root, rlp.encode(block), ) # TODO: It's a stub before we implement fork choice rule score = block.slot db.set( SchemaV1.make_block_root_to_score_lookup_key(block.root), rlp.encode(score, sedes=rlp.sedes.big_endian_int), ) try: previous_canonical_head = cls._get_canonical_head(db, block_class).root head_score = cls._get_score(db, previous_canonical_head) except CanonicalHeadNotFound: return cls._set_as_canonical_chain_head(db, block.root, block_class) if score > head_score: return cls._set_as_canonical_chain_head(db, block.root, block_class) else: return tuple(), tuple()
def _get_score(db: BaseDB, block_root: Hash32) -> int: try: encoded_score = db[SchemaV1.make_block_root_to_score_lookup_key( block_root)] except KeyError: raise BlockNotFound("No block with hash {0} found".format( encode_hex(block_root))) return rlp.decode(encoded_score, sedes=rlp.sedes.big_endian_int)
def _set_block_scores_to_db(cls, db: BaseDB, block: BaseBeaconBlock) -> None: # TODO: It's a stub before we implement fork choice rule score = block.slot db.set( SchemaV1.make_block_root_to_score_lookup_key(block.root), rlp.encode(score, sedes=rlp.sedes.big_endian_int), )
def test_chaindb_persist_block_and_slot_to_root(chaindb, block): with pytest.raises(BlockNotFound): chaindb.get_block_by_root(block.root, block.__class__) slot_to_root_key = SchemaV1.make_block_root_to_score_lookup_key(block.root) assert not chaindb.exists(slot_to_root_key) chaindb.persist_block(block, block.__class__) assert chaindb.get_block_by_root(block.root, block.__class__) == block assert chaindb.exists(slot_to_root_key)
def test_chaindb_persist_block_and_block_to_root(chaindb, block): block_to_root_key = SchemaV1.make_block_root_to_score_lookup_key(block.root) assert not chaindb.exists(block_to_root_key) chaindb.persist_block(block, block.__class__) assert chaindb.exists(block_to_root_key)