コード例 #1
0
def test_hexary_trie_missing_traversal_node_with_traverse_from():
    db = {}
    trie = HexaryTrie(db, prune=True)

    key1 = to_bytes(0x0123)
    trie.set(
        key1,
        b'use a value long enough that it must be hashed according to trie spec'
    )

    key2 = to_bytes(0x1234)
    trie.set(key2, b'val2')

    # delete first child of the root
    root_node = trie.root_node

    first_child_hash = root_node.raw[0]

    del db[first_child_hash]

    # Get exception with relevant info about lookup nibbles
    with pytest.raises(MissingTraversalNode) as exc_info:
        trie.traverse_from(root_node, (0, 1, 2, 3))

    exception = exc_info.value
    assert exception.nibbles_traversed == (0, )
    assert encode_hex(first_child_hash) in str(exception)

    # Other keys are still traversable
    node = trie.traverse((1, ))
    assert node.value == b'val2'
    assert node.sub_segments == ()
コード例 #2
0
    def traverse_via_cache(parent_prefix, parent_node, child_extension):
        if parent_node is None:
            # Can't traverse_from to the root node
            node = traversal_trie.traverse(())
        elif not len(child_extension):
            assert False, "For all but the root node, the child extension must not be empty"
        else:
            logging_db = KeyAccessLogger(db)
            single_access_trie = HexaryTrie(logging_db)
            node = single_access_trie.traverse_from(parent_node,
                                                    child_extension)
            # Traversing from parent to child should touch at most one node (the child)
            # It might touch 0 nodes, if the child was embedded inside the parent
            assert len(logging_db.read_keys) in {0, 1}

            # Validate that traversal from the root gives you the same result:
            slow_node = traversal_trie.traverse(parent_prefix +
                                                child_extension)
            assert node == slow_node

        if node.value:
            found_values.add(node.value)

        for new_child in node.sub_segments:
            # traverse into children
            traverse_via_cache(parent_prefix + child_extension, node,
                               new_child)
コード例 #3
0
def test_traverse_from_partial_path(trie_items, traverse_key, path_to_node,
                                    sub_segments, node_val):
    """
    What happens when you try to traverse_from() into an extension or leaf node
    """
    db = {}
    trie = HexaryTrie(db)
    for key, val in trie_items:
        trie[key] = val

    root = trie.root_node
    with pytest.raises(TraversedPartialPath) as excinfo:
        trie.traverse_from(root, traverse_key)

    exc = excinfo.value
    assert exc.nibbles_traversed == path_to_node
    assert exc.node.sub_segments == sub_segments
    assert exc.node.value == node_val
コード例 #4
0
def test_traverse_non_matching_leaf():
    trie = HexaryTrie({})
    EMPTY_NODE = trie.root_node

    trie[b'\xFFleaf-at-root'] = b'some-value'
    final_root = trie.root_node

    # Traversing partway into the leaf raises the TraversedPartialPath exception
    with pytest.raises(TraversedPartialPath):
        trie.traverse((0xf, ))
    with pytest.raises(TraversedPartialPath):
        trie.traverse_from(final_root, (0xf, ))

    # But traversing to any *non*-matching nibble should return a blank node, because no
    #   children reside underneath that nibble. Returning the leaf with a mismatched nibble
    #   would be a bug.
    for nibble in range(0xf):
        # Note that we do not want to look at the 0xf nibble, because that's the one that
        #   should raise the exception above
        assert trie.traverse((nibble, )) == EMPTY_NODE
        assert trie.traverse_from(final_root, (nibble, )) == EMPTY_NODE