Ejemplo n.º 1
0
    def __init__(
        self,
        transaction: bytes = None,
        previous: Links = None,
        key: LibNaCLSK = None,
        links: Links = None,
        com_prefix: bytes = b"",
        com_id: Any = None,
        block_type: bytes = b"test",
    ):
        crypto = default_eccrypto
        if not links:
            links = GENESIS_LINK
            com_seq_num = 1
        else:
            com_seq_num = max(links)[0] + 1

        if not previous:
            previous = GENESIS_LINK
        pers_seq_num = max(previous)[0] + 1

        if not com_id:
            com_id = crypto.generate_key("curve25519").pub().key_to_bin()

        if key:
            self.key = key
        else:
            self.key = crypto.generate_key("curve25519")

        if not transaction:
            transaction = encode_raw({"id": 42})

        PlexusBlock.__init__(
            self,
            (
                block_type,
                transaction,
                self.key.pub().key_to_bin(),
                pers_seq_num,
                encode_links(previous),
                encode_links(links),
                com_prefix,
                com_id,
                com_seq_num,
                EMPTY_SIG,
                0,
                0,
            ),
        )
        self.sign(self.key)
Ejemplo n.º 2
0
    def test_create_next_pers(self, monkeypatch):
        """
        Test creating a block that points towards a previous block
        """
        db = MockDBManager()
        prev = FakeBlock()

        monkeypatch.setattr(
            MockDBManager,
            "get_chain",
            lambda _, chain_id: MockChain(),
        )
        monkeypatch.setattr(
            MockChain,
            "consistent_terminal",
            Links((prev.pers_dot, )),
        )

        block = PlexusBlock.create(b"test", encode_raw({b"id": 42}), db,
                                   prev.public_key)

        assert block.previous == Links((prev.pers_dot, ))
        assert block.sequence_number == prev.sequence_number + 1
        assert block.public_key == prev.public_key
        assert block.signature == EMPTY_SIG
        assert block.type == b"test"
        assert block.transaction == encode_raw({b"id": 42})
        assert block.com_id == EMPTY_PK
        assert block.com_seq_num == UNKNOWN_SEQ
Ejemplo n.º 3
0
def insert_to_chain_or_blk_store(
    chain_obj: Union[BaseChain, BaseDB],
    blk: PlexusBlock,
    personal_chain: bool = True,
):
    if isinstance(chain_obj, BaseChain):
        yield from insert_to_chain(chain_obj, blk, personal_chain)
    else:
        yield chain_obj.add_block(blk.pack(), blk)
Ejemplo n.º 4
0
 def get_block_and_blob_by_dot(self, chain_id: bytes,
                               dot: Dot) -> Tuple[bytes, PlexusBlock]:
     """Get blob and serialized block and by the chain_id and dot.
     Can raise DatabaseDesynchronizedException if no block found."""
     blk_blob = self.persistence.get_block_blob_by_dot(chain_id, dot)
     if not blk_blob:
         raise DatabaseDesynchronizedException(
             "Block is not found in db: {chain_id}, {dot}".format(
                 chain_id=chain_id, dot=dot))
     block = PlexusBlock.unpack(blk_blob, self.serializer)
     return blk_blob, block
Ejemplo n.º 5
0
    def validate_persist_block(self, block: PlexusBlock, peer: Peer = None) -> bool:
        """
        Validate a block and if it's valid, persist it.
        Raises:
            InvalidBlockException - if block is not valid
        """
        block = (
            PlexusBlock.unpack(block, self.serializer)
            if type(block) is bytes
            else block
        )
        block_blob = block if type(block) is bytes else block.pack()

        if not block.block_invariants_valid():
            # React on invalid block
            raise InvalidBlockException("Block invalid", str(block), peer)
        else:
            if not self.persistence.has_block(block.hash):
                self.process_block_unordered(block, peer)
                chain_id = block.com_id
                prefix = block.com_prefix
                if (
                    self.persistence.get_chain(prefix + chain_id)
                    and self.persistence.get_chain(prefix + chain_id).versions.get(
                        block.com_seq_num
                    )
                    and block.short_hash
                    in self.persistence.get_chain(prefix + chain_id).versions[
                        block.com_seq_num
                    ]
                ):
                    raise Exception(
                        "Inconsisistency between block store and chain store",
                        self.persistence.get_chain(prefix + chain_id).versions,
                        block.com_dot,
                    )
                self.persistence.add_block(block_blob, block)
Ejemplo n.º 6
0
    def __init__(self, chain_factory: BaseChainFactory, block_store: BaseBlockStore):
        super().__init__()
        self._chain_factory = chain_factory
        self._block_store = block_store

        self.chains = dict()
        self.last_reconcile_seq_num = defaultdict(lambda: defaultdict(int))
        self.last_frontier = defaultdict(
            lambda: defaultdict(
                lambda: Frontier(terminal=GENESIS_LINK, holes=(), inconsistencies=())
            )
        )

        # Sync chains with block store
        for block_blob in self._block_store.iterate_blocks():
            self.add_block(block_blob[1], PlexusBlock.unpack(block_blob[1]))
Ejemplo n.º 7
0
    def test_create_genesis(self):
        """
        Test creating a genesis block
        """
        key = default_eccrypto.generate_key(u"curve25519")
        db = MockDBManager()
        block = PlexusBlock.create(b"test", encode_raw({b"id": 42}), db,
                                   key.pub().key_to_bin())

        assert block.previous == Links((GENESIS_DOT, ))
        assert block.sequence_number == GENESIS_SEQ
        assert block.public_key == key.pub().key_to_bin()
        assert block.signature == EMPTY_SIG
        assert block.type == b"test"
        assert block.transaction == encode_raw({b"id": 42})
        assert block.com_id == EMPTY_PK
        assert block.com_seq_num == UNKNOWN_SEQ
Ejemplo n.º 8
0
    def create_signed_block(
        self,
        block_type: bytes = b"unknown",
        transaction: Optional[bytes] = None,
        prefix: bytes = b"",
        com_id: bytes = None,
        links: Links = None,
        personal_links: Links = None,
        use_consistent_links: bool = True,
    ) -> PlexusBlock:
        """
        This function will create, sign, persist block with given parameters.
        Args:
            block_type: bytes of the block
            transaction: bytes blob of the transaction, or None to indicate an empty transaction payload
            prefix: prefix for the community id. For example b'w' - for witnessing transactions
            com_id: sub-community id if applicable
            links: explicitly link to certain links in the sub-community. Warning - may lead to forks!
            personal_links: explicitly link to certain blocks in the own chain. Warning - may lead to forks!
            use_consistent_links ():
        Returns:
            signed block
        """
        if not transaction:
            transaction = encode_raw(b"")

        block = PlexusBlock.create(
            block_type,
            transaction,
            self.persistence,
            self.my_pub_key_bin,
            com_id=com_id,
            com_links=links,
            pers_links=personal_links,
            com_prefix=prefix,
            use_consistent_links=use_consistent_links,
        )
        block.sign(self.my_peer_key)
        self.validate_persist_block(block, self.my_peer)
        return block
Ejemplo n.º 9
0
    def test_create_link_to_pers(self, monkeypatch):
        """
        Test creating a linked half block
        """
        key = default_eccrypto.generate_key(u"curve25519")
        db = MockDBManager()
        link = FakeBlock()

        monkeypatch.setattr(
            MockDBManager,
            "get_chain",
            lambda _, chain_id: MockChain()
            if chain_id == link.public_key else None,
        )
        monkeypatch.setattr(
            MockChain,
            "consistent_terminal",
            Links((link.pers_dot, )),
        )
        block = PlexusBlock.create(
            b"test",
            encode_raw({"id": 42}),
            db,
            key.pub().key_to_bin(),
            com_id=link.public_key,
        )

        # include the personal community

        # Attach to the
        assert block.links == Links((link.pers_dot, ))
        assert block.previous == Links((GENESIS_DOT, ))
        assert block.sequence_number == GENESIS_SEQ
        assert block.com_seq_num == link.sequence_number + 1
        assert block.public_key == key.pub().key_to_bin()
        assert block.signature == EMPTY_SIG
        assert block.type == b"test"
        assert block.transaction == encode_raw({"id": 42})
        assert block.com_id == link.public_key
Ejemplo n.º 10
0
 def received_block_broadcast(self, peer: Peer, payload: BlockBroadcastPayload):
     block = PlexusBlock.from_payload(payload, self.serializer)
     self.validate_persist_block(block, peer)
     self.process_broadcast_block(block, payload.ttl)
Ejemplo n.º 11
0
 def received_raw_block_broadcast(
     self, peer: Peer, payload: RawBlockBroadcastPayload
 ) -> None:
     block = PlexusBlock.unpack(payload.block_bytes, self.serializer)
     self.validate_persist_block(block, peer)
     self.process_broadcast_block(block, payload.ttl)
Ejemplo n.º 12
0
 def received_block(self, peer: Peer, payload: BlockPayload):
     block = PlexusBlock.from_payload(payload, self.serializer)
     self.logger.debug(
         "Received block from push gossip %s from peer %s", block.com_dot, peer
     )
     self.validate_persist_block(block, peer)
Ejemplo n.º 13
0
 def received_raw_block(self, peer: Peer, payload: RawBlockPayload) -> None:
     block = PlexusBlock.unpack(payload.block_bytes, self.serializer)
     self.logger.debug(
         "Received block from pull gossip %s from peer %s", block.com_dot, peer
     )
     self.validate_persist_block(block, peer)
Ejemplo n.º 14
0
 def test_pack_unpack(self):
     blk = FakeBlock()
     blk_bytes = blk.pack()
     blk2 = PlexusBlock.unpack(blk_bytes, blk.serializer)
     assert blk == blk2
Ejemplo n.º 15
0
 def test_block_payload(self):
     blk = FakeBlock()
     blk_bytes = blk.pack()
     payload = blk.serializer.unpack_serializable(BlockPayload, blk_bytes)
     blk2 = PlexusBlock.from_payload(payload[0])
     assert blk2 == blk