Example #1
0
    def new_block_procedure(self, block, txs):
        self.log.critical(
            "\n***\nDONE COLLECTING BLOCK DATA FROM NODES. Storing new block.\n***\n"
        )

        hash_of_nodes = MerkleTree.hash_nodes(block.nodes)
        tree = b"".join(block.nodes).hex()
        signatures = "".join(
            [merk_sig.signature for merk_sig in block.signatures])

        # Store the block + transaction data
        block_num = -1
        with DB() as db:
            tables = db.tables
            q = insert(tables.blocks).values(hash=hash_of_nodes,
                                             tree=tree,
                                             signatures=signatures)
            q_result = db.execute(q)
            block_num = q_result.lastrowid

            for key, value in txs.items():
                tx = {'key': key, 'value': value}
                qq = insert(tables.transactions).values(tx)
                db.execute(qq)

        assert block_num > 0, "Block num must be greater than 0! Was it not set in the DB() context session?"

        # Notify delegates of new block
        self.log.info(
            "Masternode sending NewBlockNotification to delegates with new block hash {} and block num {}"
            .format(hash_of_nodes, block_num))
        notif = NewBlockNotification.create(new_block_hash=hash_of_nodes.hex(),
                                            new_block_num=block_num)
        self.parent.composer.send_pub_msg(
            filter=Constants.ZmqFilters.MasternodeDelegate, message=notif)
Example #2
0
    def _validate_sigs(self, block: BlockContender) -> bool:
        signatures = block.signatures
        msg = MerkleTree.hash_nodes(block.merkle_leaves)

        for sig in signatures:
            # TODO -- ensure that the sender belongs to the top delegate pool
            self.log.debug("mn verifying signature: {}".format(sig))
            if not sig.verify(msg, sig.sender):
                self.log.error("Masternode could not verify signature!!! Sig={}".format(sig))
                return False
        return True
Example #3
0
    def validate_block_contender(self, block: BlockContender) -> bool:
        """
        Helper method to validate a block contender. For a block contender to be valid it must:
        1) Have a provable merkle tree, ie. all nodes must be hash of (left child + right child)
        2) Be signed by at least 2/3 of the top 32 delegates
        :param block_contender: The BlockContender to validate
        :return: True if the BlockContender is valid, false otherwise
        """
        def _validate_sigs(signatures, msg) -> bool:
            for sig in signatures:
                self.log.info("mn verifying signature: {}".format(sig))
                if not sig.verify(msg, sig.sender):
                    self.log.error(
                        "!!!! Oh no why couldnt we verify sig {}???".format(
                            sig))
                    return False
            return True

        # Development sanity checks (these should be removed in production)
        assert len(
            block.nodes
        ) >= 1, "Masternode got block contender with no nodes! {}".format(
            block)
        assert len(block.signatures) >= Constants.Testnet.Majority, \
            "Received a block contender with only {} signatures (which is less than a majority of {}"\
            .format(len(block.signatures), Constants.Testnet.Majority)

        # TODO -- ensure that this block contender's previous block is this Masternode's current block...

        # Prove Merkle Tree
        hash_of_nodes = MerkleTree.hash_nodes(block.nodes)
        tx_hashes = block.nodes[len(block.nodes) // 2:]
        if not MerkleTree.verify_tree(tx_hashes, hash_of_nodes):
            self.log.error(
                "\n\n\n\nCOULD NOT VERIFY MERKLE TREE FOR BLOCK CONTENDER {}\n\n\n"
                .format(block))
            return False

        # Validate signatures
        if not _validate_sigs(block.signatures, hash_of_nodes):
            self.log.error(
                "MN COULD NOT VALIDATE SIGNATURES FOR CONTENDER {}".format(
                    block))
            return False

        return True