def test_chaindb_get_score(chaindb):
    genesis = BlockHeader(difficulty=1, block_number=0, gas_limit=0)
    chaindb.persist_header(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 == 1
    assert chaindb.get_score(genesis.hash) == 1

    block1 = BlockHeader(
        difficulty=10,
        block_number=1,
        gas_limit=0,
        parent_hash=genesis.hash,
        timestamp=genesis.timestamp + 1,
    )
    chaindb.persist_header(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 == 11
    assert chaindb.get_score(block1.hash) == 11
Beispiel #2
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 HeaderNotFound("No header with hash {0} found".format(
             encode_hex(block_hash)))
     return rlp.decode(encoded_score, sedes=rlp.sedes.big_endian_int)
def test_chaindb_persist_block(chaindb, block):
    block = block.copy(header=set_empty_root(chaindb, block.header))
    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)
    def _persist_header_chain(
        cls, db: BaseDB, headers: Iterable[BlockHeader]
    ) -> Tuple[Tuple[BlockHeader, ...], Tuple[BlockHeader, ...]]:
        try:
            first_header = first(headers)
        except StopIteration:
            return tuple(), tuple()
        else:

            for parent, child in sliding_window(2, headers):
                if parent.hash != child.parent_hash:
                    raise ValidationError(
                        "Non-contiguous chain. Expected {} to have {} as parent but was {}"
                        .format(
                            encode_hex(child.hash),
                            encode_hex(parent.hash),
                            encode_hex(child.parent_hash),
                        ))

            is_genesis = first_header.parent_hash == GENESIS_PARENT_HASH
            if not is_genesis and not cls._header_exists(
                    db, first_header.parent_hash):
                raise ParentNotFound(
                    "Cannot persist block header ({}) with unknown parent ({})"
                    .format(encode_hex(first_header.hash),
                            encode_hex(first_header.parent_hash)))

            score = 0 if is_genesis else cls._get_score(
                db, first_header.parent_hash)

        for header in headers:
            db.set(
                header.hash,
                rlp.encode(header),
            )

            score += header.difficulty

            db.set(
                SchemaV1.make_block_hash_to_score_lookup_key(header.hash),
                rlp.encode(score, sedes=rlp.sedes.big_endian_int),
            )

        try:
            previous_canonical_head = cls._get_canonical_head(db).hash
            head_score = cls._get_score(db, previous_canonical_head)
        except CanonicalHeadNotFound:
            (new_canonical_headers,
             old_canonical_headers) = cls._set_as_canonical_chain_head(
                 db, header.hash)
        else:
            if score > head_score:
                (new_canonical_headers,
                 old_canonical_headers) = cls._set_as_canonical_chain_head(
                     db, header.hash)
            else:
                new_canonical_headers = tuple()
                old_canonical_headers = tuple()

        return new_canonical_headers, old_canonical_headers
    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
Beispiel #6
0
def test_chaindb_persist_header(chaindb, header):
    with pytest.raises(HeaderNotFound):
        chaindb.get_block_header_by_hash(header.hash)
    number_to_hash_key = SchemaV1.make_block_hash_to_score_lookup_key(header.hash)
    assert not chaindb.exists(number_to_hash_key)

    chaindb.persist_header(header)

    assert chaindb.get_block_header_by_hash(header.hash) == header
    assert chaindb.exists(number_to_hash_key)
Beispiel #7
0
    def persist_header(
        self, header: BlockHeader
    ) -> Tuple[Tuple[BlockHeader, ...], Tuple[BlockHeader, ...]]:
        """
        :returns: iterable of headers newly on the canonical chain
        """
        if header.parent_hash != GENESIS_PARENT_HASH:
            try:
                self.get_block_header_by_hash(header.parent_hash)
            except HeaderNotFound:
                raise ParentNotFound(
                    "Cannot persist block header ({}) with unknown parent ({})"
                    .format(encode_hex(header.hash),
                            encode_hex(header.parent_hash)))

        self.db.set(
            header.hash,
            rlp.encode(header),
        )

        if header.parent_hash == GENESIS_PARENT_HASH:
            score = header.difficulty
        else:
            score = self.get_score(header.parent_hash) + header.difficulty

        self.db.set(
            SchemaV1.make_block_hash_to_score_lookup_key(header.hash),
            rlp.encode(score, sedes=rlp.sedes.big_endian_int),
        )

        try:
            head_score = self.get_score(self.get_canonical_head().hash)
        except CanonicalHeadNotFound:
            new_canonical_headers, old_canonical_headers = self._set_as_canonical_chain_head(
                header.hash, )
        else:
            if score > head_score:
                new_canonical_headers, old_canonical_headers = self._set_as_canonical_chain_head(
                    header.hash)
            else:
                new_canonical_headers = tuple()
                old_canonical_headers = tuple()

        return new_canonical_headers, old_canonical_headers
Beispiel #8
0
    def persist_header_chain(
        self, headers: Iterable[BlockHeader]
    ) -> Tuple[Tuple[BlockHeader, ...], Tuple[BlockHeader, ...]]:
        """
        Return two iterable of headers, the first containing the new canonical headers,
        the second containing the old canonical headers
        """

        try:
            first_header = first(headers)
        except StopIteration:
            return tuple(), tuple()
        else:

            for parent, child in sliding_window(2, headers):
                if parent.hash != child.parent_hash:
                    raise ValidationError(
                        "Non-contiguous chain. Expected {} to have {} as parent but was {}"
                        .format(
                            encode_hex(child.hash),
                            encode_hex(parent.hash),
                            encode_hex(child.parent_hash),
                        ))

            is_genesis = first_header.parent_hash == GENESIS_PARENT_HASH
            if not is_genesis and not self.header_exists(
                    first_header.parent_hash):
                raise ParentNotFound(
                    "Cannot persist block header ({}) with unknown parent ({})"
                    .format(encode_hex(first_header.hash),
                            encode_hex(first_header.parent_hash)))

            score = 0 if is_genesis else self.get_score(
                first_header.parent_hash)

        for header in headers:
            self.db.set(
                header.hash,
                rlp.encode(header),
            )

            score += header.difficulty

            self.db.set(
                SchemaV1.make_block_hash_to_score_lookup_key(header.hash),
                rlp.encode(score, sedes=rlp.sedes.big_endian_int),
            )

        try:
            head_score = self.get_score(self.get_canonical_head().hash)
        except CanonicalHeadNotFound:
            (new_canonical_headers,
             old_canonical_headers) = self._set_as_canonical_chain_head(
                 header.hash)
        else:
            if score > head_score:
                (new_canonical_headers,
                 old_canonical_headers) = self._set_as_canonical_chain_head(
                     header.hash)
            else:
                new_canonical_headers = tuple()
                old_canonical_headers = tuple()

        return new_canonical_headers, old_canonical_headers