Example #1
0
    def __compute_hash_chain_step__(self, node: Node,
                                    origin_node: Node) -> Node:
        """
        Recursive function called to compute the hash chain.
        The hash chain is computed bottom (z_i) to top (root).
        This function only compute a "step" or level in the hash chain.
        As implemented the Node class _need_ a hash value so the clone node have the same value as the "reference" node.
        :param node: The node at the level we are at (must have origin_node as left or right child node)
        :type node: Node
        :param origin_node: The node from which this function call originated (must have node for parent)
        :type origin_node: Node
        :return: None if called at root level or a clone of the node we started at
        """
        # Current cloned node (the level we are at)
        current_node = None

        # This algorithm shall end when trying to be above the root
        if not node:
            return current_node

        node.set_mark_compute()
        # Apply the same algorithm for our parent
        parent_node = self.__compute_hash_chain_step__(node.parent, node)

        # If the call originate from the left child
        if node.left_child is origin_node:
            node.right_child.set_mark()
        else:
            node.left_child.set_mark()

        right_node = copy(node.right_child)  # type: Node
        left_node = copy(node.left_child)  # type: Node

        current_node = copy(node)  # type: Node
        current_node.left_child = left_node
        current_node.right_child = right_node
        current_node.set_mark_compute()

        if parent_node:
            # Link the parent's left child node to the current node
            if parent_node.left_child.hash == current_node.hash:
                parent_node.left_child = current_node

            # Link the parent's right child node to the current node
            elif parent_node.right_child.hash == current_node.hash:
                parent_node.right_child = current_node

        # Link current node to it's parent
        current_node.parent = parent_node

        return current_node
Example #2
0
    def __compute_hash_chain_step__(self, node: Node, origin_node: Node) -> Node:
        """
        Recursive function called to compute the hash chain.
        The hash chain is computed bottom (z_i) to top (root).
        This function only compute a "step" or level in the hash chain.
        As implemented the Node class _need_ a hash value so the clone node have the same value as the "reference" node.
        :param node: The node at the level we are at (must have origin_node as left or right child node)
        :type node: Node
        :param origin_node: The node from which this function call originated (must have node for parent)
        :type origin_node: Node
        :return: None if called at root level or a clone of the node we started at
        """
        # Current cloned node (the level we are at)
        current_node = None

        # This algorithm shall end when trying to be above the root
        if not node:
            return current_node

        node.set_mark_compute()
        # Apply the same algorithm for our parent
        parent_node = self.__compute_hash_chain_step__(node.parent, node)

        # If the call originate from the left child
        if node.left_child is origin_node:
            node.right_child.set_mark()
        else:
            node.left_child.set_mark()

        right_node = copy(node.right_child)  # type: Node
        left_node = copy(node.left_child)  # type: Node

        current_node = copy(node)  # type: Node
        current_node.left_child = left_node
        current_node.right_child = right_node
        current_node.set_mark_compute()

        if parent_node:
            # Link the parent's left child node to the current node
            if parent_node.left_child.hash == current_node.hash:
                parent_node.left_child = current_node

            # Link the parent's right child node to the current node
            elif parent_node.right_child.hash == current_node.hash:
                parent_node.right_child = current_node

        # Link current node to it's parent
        current_node.parent = parent_node

        return current_node
Example #3
0
    def __compute_hash_chain__(self, z_i: Node, pair_i: bool) -> Node:
        """
        Clone the nodes used in the hash chain (z_i to root of the Merkle tree).
        :param z_i: The node at which to start the hash chain (bottom to top)
        :type z_i: Node
        :param pair_i: True if the index of z_i is pair (i.e. this is a special case, see the class documentation)
        :type pair_i: bool
        :return: The root of the hash chain
        :rtype: Node
        """
        assert isinstance(z_i, Node)
        assert isinstance(z_i.parent, Node)

        # i is pair so z_i is a special case
        if pair_i:
            z_i.set_mark_z_i()
            # Go up one level
            z_i = z_i.parent
            assert isinstance(z_i.parent, Node)

        # Call the recursive function to clone nodes on the hash chain
        hash_chain_node = self.__compute_hash_chain_step__(z_i.parent, z_i)
        z_i.set_mark_z_i()

        # Set the z_i mark on the hash chain (left child)
        if hash_chain_node.left_child and hash_chain_node.left_child.uuid == z_i.uuid:
            if not pair_i:
                hash_chain_node.left_child.set_mark_z_i()

            # Set the exception mark
            if hash_chain_node.right_child:
                hash_chain_node.right_child.set_mark_exception()
                z_i.parent.right_child.set_mark_exception()

        if pair_i:
            z_i.set_mark_exception()
            # Go down one level
            z_i = z_i.right_child
            # This node was left-out with the call to __compute_hash_chain_step__() so we need to add it ourselves
            tmp = copy(z_i)
            # Link tmp to its parent
            tmp.parent = hash_chain_node.right_child
            # Link the parent to tmp
            hash_chain_node.right_child.right_child = tmp
            hash_chain_node.right_child.set_mark_exception()

        # Set the z_i mark on the hash chain (right child)
        if hash_chain_node.right_child and hash_chain_node.right_child.uuid == z_i.uuid:
            hash_chain_node.right_child.set_mark_z_i()

        # We want the whole tree so we need to get to the root of it
        while hash_chain_node.parent:
            hash_chain_node = hash_chain_node.parent

        return hash_chain_node
Example #4
0
    def __compute_hash_chain__(self, z_i: Node, pair_i: bool) -> Node:
        """
        Clone the nodes used in the hash chain (z_i to root of the Merkle tree).
        :param z_i: The node at which to start the hash chain (bottom to top)
        :type z_i: Node
        :param pair_i: True if the index of z_i is pair (i.e. this is a special case, see the class documentation)
        :type pair_i: bool
        :return: The root of the hash chain
        :rtype: Node
        """
        assert isinstance(z_i, Node)
        assert isinstance(z_i.parent, Node)

        # i is pair so z_i is a special case
        if pair_i:
            z_i.set_mark_z_i()
            # Go up one level
            z_i = z_i.parent
            assert isinstance(z_i.parent, Node)

        # Call the recursive function to clone nodes on the hash chain
        hash_chain_node = self.__compute_hash_chain_step__(z_i.parent, z_i)
        z_i.set_mark_z_i()

        # Set the z_i mark on the hash chain (left child)
        if hash_chain_node.left_child and hash_chain_node.left_child.uuid == z_i.uuid:
            if not pair_i:
                hash_chain_node.left_child.set_mark_z_i()

            # Set the exception mark
            if hash_chain_node.right_child:
                hash_chain_node.right_child.set_mark_exception()
                z_i.parent.right_child.set_mark_exception()

        if pair_i:
            z_i.set_mark_exception()
            # Go down one level
            z_i = z_i.right_child
            # This node was left-out with the call to __compute_hash_chain_step__() so we need to add it ourselves
            tmp = copy(z_i)
            # Link tmp to its parent
            tmp.parent = hash_chain_node.right_child
            # Link the parent to tmp
            hash_chain_node.right_child.right_child = tmp
            hash_chain_node.right_child.set_mark_exception()

        # Set the z_i mark on the hash chain (right child)
        if hash_chain_node.right_child and hash_chain_node.right_child.uuid == z_i.uuid:
            hash_chain_node.right_child.set_mark_z_i()

        # We want the whole tree so we need to get to the root of it
        while hash_chain_node.parent:
            hash_chain_node = hash_chain_node.parent

        return hash_chain_node
Example #5
0
 def test_coverage(self):
     # For total coverage
     with self.assertRaises(AttributeError):
         Node()