Пример #1
0
    def _validate_block_data(cls, block_data: dict):
        """
        Validates the block_data dictionary. 'block_data' should be a strict subset of the 'block' dictionary, keys for all
        columns in the block table EXCEPT 'number' and 'hash'. If any validation fails, an exception is raised.
        For a block_data dictionary to be valid, it must:
         - Have a key for each block data column specified in BLOCK_DATA_COLS (at top of blocks.py)
         - BlockContender successfully validates with the Merkle root (meaning all signatures in the BlockContender
           can be verified using the Merkle root as the message)
         - Merkle leaves contained in BlockContender (block_contender.nodes) match Merkle leaves in block_data dict
         - Merkle root is correct root if a Merkle tree is built from Merkle leaves
         - Masternode signature is valid (signature is valid using Merkle root as message and masternode_vk as vk)

        :param block_data: The dictionary containing a key for each column in BLOCK_DATA_COLS
        (ie 'merkle_root', 'prev_block_hash', .. ect)
        :raises: An BlockStorageValidationException (or subclass) if any validation fails
        """
        # Check block_data has all the necessary keys
        expected_keys = set(BLOCK_DATA_COLS.keys())
        actual_keys = set(block_data.keys())
        missing_keys = expected_keys - actual_keys
        extra_keys = actual_keys - expected_keys

        # Check for missing keys
        if len(missing_keys) > 0:
            raise BlockStorageValidationException(
                "block_data keys {} missing key(s) {}".format(
                    actual_keys, missing_keys))
        # Check for extra (unrecognized) keys
        if len(extra_keys) > 0:
            raise BlockStorageValidationException(
                "block_data keys {} has unrecognized keys {}".format(
                    actual_keys, extra_keys))

        # Validate Merkle Tree
        tree = MerkleTree.from_leaves_hex_str(block_data['merkle_leaves'])
        if tree.root_as_hex != block_data['merkle_root']:
            raise InvalidMerkleTreeException(
                "Merkle Tree could not be validated for block_data {}".format(
                    block_data))

        # Validate BlockContender nodes match merkle leaves
        block_leaves = block_data['block_contender'].merkle_leaves
        if len(block_leaves) != len(tree.leaves):
            raise InvalidBlockContenderException(
                "Number of Merkle leaves on BlockContender {} does not match number of"
                " leaves in MerkleTree {}".format(len(block_leaves),
                                                  len(tree.leaves)))
        for block_leaf, merkle_leaf in zip(block_leaves, tree.leaves_as_hex):
            if block_leaf != merkle_leaf:
                raise InvalidBlockContenderException(
                    "BlockContender leaves do not match Merkle leaves\nblock leaves = "
                    "{}\nmerkle leaves = {}".format(block_leaves,
                                                    tree.leaves_as_hex))

        # Validate MerkleSignatures inside BlockContender match Merkle leaves from raw transactions
        bc = block_data['block_contender']
        if not bc.validate_signatures():
            raise InvalidBlockContenderException(
                "BlockContender signatures could not be validated! BC = {}".
                format(bc))

        # TODO validate MerkleSignatures are infact signed by valid delegates
        # this is tricky b/c we would need to know who the delegates were at the time of the block, not necessarily the
        # current delegates

        # Validate Masternode Signature
        if not is_valid_hex(block_data['masternode_vk'], length=64):
            raise InvalidBlockSignatureException(
                "Invalid verifying key for field masternode_vk: {}".format(
                    block_data['masternode_vk']))
        if not ED25519Wallet.verify(block_data['masternode_vk'],
                                    bytes.fromhex(block_data['merkle_root']),
                                    block_data['masternode_signature']):
            raise InvalidBlockSignatureException(
                "Could not validate Masternode's signature on block data")
Пример #2
0
 def verify_signature(future):
     signature, verifying_key = future.result()
     if ED25519Wallet.verify(verifying_key, self.merkle, signature):
         self.signatures.append(future.result())