Пример #1
0
def test_get_common_prefix_length(left, right, expected):
    actual_a = get_common_prefix_length(left, right)
    actual_b = get_common_prefix_length(right, left)
    assert actual_a == actual_b == expected
Пример #2
0
 def _set_kv_node(self,
                  keypath,
                  node_hash,
                  node_type,
                  left_child,
                  right_child,
                  value,
                  if_delete_subtrie=False):
     # Keypath prefixes match
     if if_delete_subtrie:
         if len(keypath) < len(
                 left_child) and keypath == left_child[:len(keypath)]:
             return BLANK_HASH
     if keypath[:len(left_child)] == left_child:
         # Recurse into child
         subnode_hash = self._set(
             right_child,
             keypath[len(left_child):],
             value,
             if_delete_subtrie,
         )
         # If child is empty
         if subnode_hash == BLANK_HASH:
             return BLANK_HASH
         subnodetype, sub_left_child, sub_right_child = parse_node(
             self.db[subnode_hash])
         # If the child is a key-value node, compress together the keypaths
         # into one node
         if subnodetype == KV_TYPE:
             return self._hash_and_save(
                 encode_kv_node(left_child + sub_left_child,
                                sub_right_child))
         else:
             return self._hash_and_save(
                 encode_kv_node(left_child, subnode_hash))
     # Keypath prefixes don't match. Here we will be converting a key-value node
     # of the form (k, CHILD) into a structure of one of the following forms:
     # 1.    (k[:-1], (NEWCHILD, CHILD))
     # 2.    (k[:-1], ((k2, NEWCHILD), CHILD))
     # 3.    (k1, ((k2, CHILD), NEWCHILD))
     # 4.    (k1, ((k2, CHILD), (k2', NEWCHILD))
     # 5.    (CHILD, NEWCHILD)
     # 6.    ((k[1:], CHILD), (k', NEWCHILD))
     # 7.    ((k[1:], CHILD), NEWCHILD)
     # 8.    (CHILD, (k[1:], NEWCHILD))
     else:
         common_prefix_len = get_common_prefix_length(
             left_child, keypath[:len(left_child)])
         # New key-value pair can not contain empty value
         # Or one can not delete non-exist subtrie
         if not value or if_delete_subtrie:
             return node_hash
         # valnode: the child node that has the new value we are adding
         # Case 1: keypath prefixes almost match, so we are in case (1), (2), (5), (6)
         if len(keypath) == common_prefix_len + 1:
             valnode = self._hash_and_save(encode_leaf_node(value))
         # Case 2: keypath prefixes mismatch in the middle, so we need to break
         # the keypath in half. We are in case (3), (4), (7), (8)
         else:
             valnode = self._hash_and_save(
                 encode_kv_node(
                     keypath[common_prefix_len + 1:],
                     self._hash_and_save(encode_leaf_node(value)),
                 ))
         # oldnode: the child node the has the old child value
         # Case 1: (1), (3), (5), (6)
         if len(left_child) == common_prefix_len + 1:
             oldnode = right_child
         # (2), (4), (6), (8)
         else:
             oldnode = self._hash_and_save(
                 encode_kv_node(left_child[common_prefix_len + 1:],
                                right_child))
         # Create the new branch node (because the key paths diverge, there has to
         # be some "first bit" at which they diverge, so there must be a branch
         # node somewhere)
         if keypath[common_prefix_len:common_prefix_len + 1] == BYTE_1:
             newsub = self._hash_and_save(
                 encode_branch_node(oldnode, valnode))
         else:
             newsub = self._hash_and_save(
                 encode_branch_node(valnode, oldnode))
         # Case 1: keypath prefixes match in the first bit, so we still need
         # a kv node at the top
         # (1) (2) (3) (4)
         if common_prefix_len:
             return self._hash_and_save(
                 encode_kv_node(left_child[:common_prefix_len], newsub))
         # Case 2: keypath prefixes diverge in the first bit, so we replace the
         # kv node with a branch node
         # (5) (6) (7) (8)
         else:
             return newsub