Example #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(u"curve25519").pub().key_to_bin()

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

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

        BamiBlock.__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)
Example #2
0
    def __init__(self,
                 data: List = None,
                 serializer=default_serializer) -> None:
        """
        Create a new PlexusBlock or load from an existing database entry.

        :param data: Optional data to initialize this block with.
        :type data: Block.Data or list
        :param serializer: An optional custom serializer to use for this block.
        :type serializer: Serializer
        """
        super(BamiBlock, self).__init__()
        self.serializer = serializer
        if data is None:
            # data
            self.type = b"unknown"
            self.transaction = b""
            # block identity
            self.public_key = EMPTY_PK
            self.sequence_number = GENESIS_SEQ

            # previous hash in the personal chain
            self.previous = GENESIS_LINK
            self._previous = encode_links(self.previous)

            # Linked blocks => links to the block in other chains
            self.links = GENESIS_LINK
            self._links = encode_links(self.links)

            # Metadata for community identifiers
            self.com_prefix = b""
            self.com_id = EMPTY_PK
            self.com_seq_num: int = UNKNOWN_SEQ

            # Creation timestamp
            self.timestamp = int(time.time() * 1000)
            # Signature for the block
            self.signature = EMPTY_SIG
            # debug stuff
            self.insert_time = None
        else:
            self.transaction = data[1] if isinstance(data[1],
                                                     bytes) else bytes(data[1])
            self._previous = (BytesLinks(data[4]) if isinstance(
                data[4], bytes) else bytes(data[4]))
            self._links = (BytesLinks(data[5])
                           if isinstance(data[5], bytes) else bytes(data[5]))

            self.previous = decode_links(self._previous)
            self.links = decode_links(self._links)

            self.type, self.public_key, self.sequence_number = data[0], data[
                2], data[3]
            self.com_prefix, self.com_id, self.com_seq_num = (
                data[6],
                data[7],
                int(data[8]),
            )
            self.signature, self.timestamp, self.insert_time = (
                data[9],
                data[10],
                data[11],
            )

            self.type = (self.type if isinstance(self.type, bytes) else str(
                self.type).encode("utf-8"))
            self.public_key = (self.public_key if isinstance(
                self.public_key, bytes) else bytes(self.public_key))
            self.signature = (self.signature if isinstance(
                self.signature, bytes) else bytes(self.signature))

        self.hash = self.calculate_hash()
        self.crypto = default_eccrypto
        self._logger = logging.getLogger(self.__class__.__name__)
Example #3
0
    def create(
        cls,
        block_type: bytes,
        transaction: bytes,
        database: BaseDB,
        public_key: bytes,
        com_prefix: bytes = b"",
        com_id: bytes = None,
        com_links: Links = None,
        pers_links: Links = None,
        use_consistent_links: bool = True,
    ):
        """
        Create PlexusBlock wrt local database knowledge.

        Args:
            block_type: type of the block in bytes
            transaction: transaction blob bytes
            database: local database with chains
            public_key: public key of the block creator
            com_prefix: prefix for the chain identification [optional]
            com_id: id of the community which block is part of [optional]
            com_links: Explicitly link with these blocks [optional]
            pers_links: Create a block at a certain [optional]
            use_consistent_links: Build on top of blocks that are known. By default: True

        Returns:
            PlexusBlock

        """

        if public_key == com_id:
            full_pers_chain_id = com_prefix + public_key
        else:
            full_pers_chain_id = public_key
        personal_chain = database.get_chain(full_pers_chain_id)
        # Decide to link blocks in the personal chain:
        if not personal_chain:
            # There are no blocks in the personal chain yet
            last_link = Links((GENESIS_DOT, ))
        else:
            last_link = (personal_chain.consistent_terminal
                         if use_consistent_links else personal_chain.terminal)

        # Fork personal chain at the
        if pers_links:
            # There is an explicit link for the previous link
            last_link = pers_links

        per_seq_num = max(last_link)[0] + 1

        # TODO: Add link filtering and choose links
        ret = cls()
        ret.type = block_type
        ret.transaction = transaction
        ret.sequence_number = per_seq_num
        ret.previous = last_link

        # --- Community related logic ---
        if com_id:
            ret.com_id = com_id
            # There is community specified => will base block on the latest known information + filters
            if com_links:
                last_com_links = com_links
                com_seq_num = max(last_com_links)[0]
            else:
                com_chain = database.get_chain(com_prefix + com_id)
                if not com_chain:
                    last_com_links = Links((GENESIS_DOT, ))
                else:
                    last_com_links = (com_chain.consistent_terminal
                                      if use_consistent_links else
                                      com_chain.terminal)
                # TODO: add link filtering here
                com_seq_num = max(last_com_links)[0] + 1

            ret.links = last_com_links
            ret.com_seq_num = com_seq_num
            ret.com_id = com_id
            ret.com_prefix = com_prefix

        ret._links = encode_links(ret.links)
        ret._previous = encode_links(ret.previous)

        ret.public_key = public_key
        ret.signature = EMPTY_SIG
        ret.hash = ret.calculate_hash()
        return ret
Example #4
0
def test_encode_decode_links(keys_fixture):
    links = Links(((1, shorten(keys_fixture)), ))
    raw_bytes = encode_links(links)
    assert decode_links(raw_bytes) == links