示例#1
0
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
示例#2
0
def test_chaindb_get_score(chaindb, sample_beacon_block_params):
    genesis = BaseBeaconBlock(**sample_beacon_block_params).copy(
        ancestor_hashes=(GENESIS_PARENT_HASH, ),
        slot=0,
    )
    chaindb.persist_block(genesis)

    genesis_score_key = SchemaV1.make_block_hash_to_score_lookup_key(
        genesis.hash)
    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.hash) == 0

    block1 = BaseBeaconBlock(**sample_beacon_block_params).copy(
        ancestor_hashes=(genesis.hash, ),
        slot=1,
    )
    chaindb.persist_block(block1)

    block1_score_key = SchemaV1.make_block_hash_to_score_lookup_key(
        block1.hash)
    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.hash) == 1
示例#3
0
 def _get_canonical_head(cls, db: BaseDB) -> BaseBeaconBlock:
     try:
         canonical_head_hash = db[
             SchemaV1.make_canonical_head_hash_lookup_key()]
     except KeyError:
         raise CanonicalHeadNotFound("No canonical head set for this chain")
     return cls._get_block_by_hash(db, canonical_head_hash)
示例#4
0
    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()
示例#5
0
 def _get_score(db: BaseDB, block_hash: Hash32) -> int:
     try:
         encoded_score = db[SchemaV1.make_block_hash_to_score_lookup_key(
             block_hash)]
     except KeyError:
         raise BlockNotFound("No block with hash {0} found".format(
             encode_hex(block_hash)))
     return rlp.decode(encoded_score, sedes=rlp.sedes.big_endian_int)
示例#6
0
    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),
        )
示例#7
0
 def _get_canonical_head(
         cls, db: BaseDB,
         block_class: Type[BaseBeaconBlock]) -> BaseBeaconBlock:
     try:
         canonical_head_root = db[
             SchemaV1.make_canonical_head_root_lookup_key()]
     except KeyError:
         raise CanonicalHeadNotFound("No canonical head set for this chain")
     return cls._get_block_by_root(db, Hash32(canonical_head_root),
                                   block_class)
示例#8
0
 def _set_deletatable_state(
         db: BaseDB, deletable_state_roots: Iterable[Hash32]) -> None:
     """
     Set deletable_state_roots.
     """
     lookup_key = SchemaV1.make_deletable_state_roots_lookup_key()
     db.set(
         lookup_key,
         rlp.encode(deletable_state_roots, sedes=CountableList(hash32)),
     )
示例#9
0
 def _get_canonical_block_hash(db: BaseDB, slot: int) -> Hash32:
     validate_slot(slot)
     slot_to_hash_key = SchemaV1.make_block_slot_to_hash_lookup_key(slot)
     try:
         encoded_key = db[slot_to_hash_key]
     except KeyError:
         raise BlockNotFound(
             "No canonical block for block slot #{0}".format(slot))
     else:
         return rlp.decode(encoded_key, sedes=rlp.sedes.binary)
示例#10
0
def test_chaindb_persist_block_and_slot_to_hash(chaindb, block):
    with pytest.raises(BlockNotFound):
        chaindb.get_block_by_hash(block.hash)
    slot_to_hash_key = SchemaV1.make_block_hash_to_score_lookup_key(block.hash)
    assert not chaindb.exists(slot_to_hash_key)

    chaindb.persist_block(block)

    assert chaindb.get_block_by_hash(block.hash) == block
    assert chaindb.exists(slot_to_hash_key)
示例#11
0
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)
示例#12
0
 def _get_canonical_crystallized_state_root(db: BaseDB,
                                            slot: int) -> Hash32:
     validate_slot(slot)
     slot_to_hash_key = SchemaV1.make_slot_to_crystallized_state_lookup_key(
         slot)
     try:
         encoded_key = db[slot_to_hash_key]
     except KeyError:
         raise StateRootNotFound(
             "No canonical crystallized state for slot #{0}".format(slot))
     else:
         return rlp.decode(encoded_key, sedes=rlp.sedes.binary)
示例#13
0
 def _add_block_slot_to_hash_lookup(db: BaseDB,
                                    block: BaseBeaconBlock) -> None:
     """
     Set a record in the database to allow looking up this block by its
     block slot.
     """
     block_slot_to_hash_key = SchemaV1.make_block_slot_to_hash_lookup_key(
         block.slot_number)
     db.set(
         block_slot_to_hash_key,
         rlp.encode(block.hash, sedes=rlp.sedes.binary),
     )
示例#14
0
 def _get_active_state_root_by_crystallized(
         db: BaseDB, crystallized_state_root: Hash32) -> Hash32:
     state_root_to_hash_key = SchemaV1.make_crystallized_to_active_state_root_lookup_key(
         crystallized_state_root)
     try:
         encoded_key = db[state_root_to_hash_key]
     except KeyError:
         raise StateRootNotFound(
             "No canonical active state for crystallized_state_root #{0}".
             format(state_root_to_hash_key))
     else:
         return rlp.decode(encoded_key, sedes=rlp.sedes.binary)
示例#15
0
 def _add_crystallized_to_active_state_lookup(
         cls, db: BaseDB, active_state: ActiveState,
         crystallized_state_root: Hash32) -> None:
     """
     Set a record in the database to allow looking up this block by its
     last state recalculation slot.
     """
     slot_to_hash_key = SchemaV1.make_crystallized_to_active_state_root_lookup_key(
         crystallized_state_root, )
     db.set(
         slot_to_hash_key,
         rlp.encode(active_state.hash, sedes=rlp.sedes.binary),
     )
示例#16
0
    def _get_deletable_state_roots(db: BaseDB) -> Tuple[Hash32]:
        """
        Return deletable_state_roots.
        """
        lookup_key = SchemaV1.make_deletable_state_roots_lookup_key()
        if not db.exists(lookup_key):
            db.set(
                lookup_key,
                rlp.encode((), sedes=CountableList(hash32)),
            )
        deletable_state_roots = rlp.decode(db[lookup_key],
                                           sedes=CountableList(hash32))

        return deletable_state_roots
示例#17
0
    def _set_as_canonical_chain_head(
        cls, db: BaseDB, block_hash: Hash32
    ) -> Tuple[Tuple[BaseBeaconBlock, ...], Tuple[BaseBeaconBlock, ...]]:
        """
        Set the canonical chain HEAD to the block as specified by the
        given block hash.

        :return: a tuple of the blocks that are newly in the canonical chain, and the blocks that
            are no longer in the canonical chain
        """
        try:
            block = cls._get_block_by_hash(db, block_hash)
        except BlockNotFound:
            raise ValueError(
                "Cannot use unknown block hash as canonical head: {}".format(
                    block_hash))

        new_canonical_blocks = tuple(
            reversed(cls._find_new_ancestors(db, block)))
        old_canonical_blocks = []

        for block in new_canonical_blocks:
            try:
                old_canonical_hash = cls._get_canonical_block_hash(
                    db, block.slot_number)
            except BlockNotFound:
                # no old_canonical block, and no more possible
                break
            else:
                old_canonical_block = cls._get_block_by_hash(
                    db, old_canonical_hash)
                old_canonical_blocks.append(old_canonical_block)

        for block in new_canonical_blocks:
            cls._add_block_slot_to_hash_lookup(db, block)

        db.set(SchemaV1.make_canonical_head_hash_lookup_key(), block.hash)

        return new_canonical_blocks, tuple(old_canonical_blocks)
示例#18
0
    def _add_slot_to_crystallized_state_lookup(
            cls, db: BaseDB, crystallized_state: CrystallizedState) -> None:
        """
        Set a record in the database to allow looking up this block by its
        last state recalculation slot.

        If it's a fork, store the old state root in `deletable_state_roots`.
        """
        slot_to_hash_key = SchemaV1.make_slot_to_crystallized_state_lookup_key(
            crystallized_state.last_state_recalc)
        if db.exists(slot_to_hash_key):
            deletable_state_roots = cls._get_deletable_state_roots(db)
            replaced_state_root = rlp.decode(db[slot_to_hash_key],
                                             sedes=rlp.sedes.binary)
            cls._set_deletatable_state(
                db,
                deletable_state_roots + (replaced_state_root, ),
            )
        db.set(
            slot_to_hash_key,
            rlp.encode(crystallized_state.hash, sedes=rlp.sedes.binary),
        )
示例#19
0
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)
示例#20
0
def test_chaindb_add_block_number_to_hash_lookup(chaindb, block):
    block_slot_to_hash_key = SchemaV1.make_block_slot_to_hash_lookup_key(
        block.slot_number)
    assert not chaindb.exists(block_slot_to_hash_key)
    chaindb.persist_block(block)
    assert chaindb.exists(block_slot_to_hash_key)
示例#21
0
def test_chaindb_add_block_number_to_root_lookup(chaindb, block):
    block_slot_to_root_key = SchemaV1.make_block_slot_to_root_lookup_key(block.slot)
    assert not chaindb.exists(block_slot_to_root_key)
    chaindb.persist_block(block, block.__class__)
    assert chaindb.exists(block_slot_to_root_key)
示例#22
0
def test_chaindb_persist_block_and_block_to_hash(chaindb, block):
    block_to_hash_key = SchemaV1.make_block_hash_to_score_lookup_key(
        block.hash)
    assert not chaindb.exists(block_to_hash_key)
    chaindb.persist_block(block)
    assert chaindb.exists(block_to_hash_key)