def test_invalid_TraversedPartialPath_untraversed_nibbles( invalid_nibbles, node_key, exception, key_encoding): if node_key == (): node = annotate_node(b'') else: node = annotate_node([key_encoding(node_key), b'some-val']) # Handle special case: leaf nodes are permitted to have the untraversed tail equal the suffix if len(node.suffix) > 0 and node.suffix == invalid_nibbles: # So in this one case, make sure we don't raise an exception TraversedPartialPath((), node, invalid_nibbles) else: with pytest.raises(exception): TraversedPartialPath((), node, invalid_nibbles)
def test_valid_TraversedPartialPath_traversed_nibbles(valid_nibbles, key_encoding): some_node_key = (1, 2) node = annotate_node([key_encoding(some_node_key), b'random-value']) exception = TraversedPartialPath(valid_nibbles, node, some_node_key[:1]) assert exception.nibbles_traversed == valid_nibbles assert str(Nibbles(valid_nibbles)) in repr(exception)
def root_node(self) -> HexaryTrieNode: try: raw_node = self.get_node(self.root_hash) except KeyError: raise MissingTraversalNode(self.root_hash, nibbles_traversed=()) else: return annotate_node(raw_node)
def test_valid_TraversedPartialPath_untraversed_nibbles( valid_nibbles, key_encoding): # This exception means that the actual node key should have more than the untraversed amount # So we simulate some longer key for the given node longer_key = valid_nibbles + (0, ) node = annotate_node([key_encoding(longer_key), b'random-value']) exception = TraversedPartialPath((), node, valid_nibbles) assert exception.untraversed_tail == valid_nibbles assert str(Nibbles(valid_nibbles)) in repr(exception)
def test_TraversedPartialPath_keeps_node_value(key_encoding): node_key = (0, 0xf, 9) untraversed_tail = node_key[:1] remaining_key = node_key[1:] node_value = b'unicorns' node = annotate_node([key_encoding(node_key), node_value]) tpp = TraversedPartialPath(node_key, node, untraversed_tail) simulated_node = tpp.simulated_node assert simulated_node.raw[1] == node_value if key_encoding is compute_leaf_key: assert simulated_node.sub_segments == () assert simulated_node.suffix == remaining_key assert simulated_node.raw[0] == compute_leaf_key(remaining_key) assert simulated_node.value == node_value elif key_encoding is compute_extension_key: assert simulated_node.sub_segments == (remaining_key, ) assert simulated_node.suffix == () assert simulated_node.raw[0] == compute_extension_key(remaining_key) else: raise Exception("Unsupported way to encode keys: {key_encoding}")
def traverse(self, trie_key_input: NibblesInput) -> HexaryTrieNode: """ Find the node at the path of nibbles provided. The most trivial example is to get the root node, using ``traverse(())``. :param trie_key_input: the series of nibbles to traverse to arrive at the node of interest :return: annotated node at the given path :raises MissingTraversalNode: if a node body is missing from the database :raises TraversedPartialPath: if trie key extends part-way down an extension or leaf node """ trie_key = Nibbles(trie_key_input) node, remaining_key = self._traverse(self.root_hash, trie_key) annotated_node = annotate_node(node) if remaining_key: path_to_node = trie_key[:len(trie_key) - len(remaining_key)] raise TraversedPartialPath(path_to_node, annotated_node) else: return annotated_node
def traverse_from(self, parent_node: HexaryTrieNode, trie_key_input: Nibbles) -> HexaryTrieNode: """ Find the node at the path of nibbles provided. You cannot navigate to the root node this way (without already having the root node body, to supply as the argument). The trie does *not* re-verify the path/hashes from the node prefix to the node. :param trie_key_input: the sub-key used to traverse from the given node to the returned node :raises MissingTraversalNode: if a node body is missing from the database :raises TraversedPartialPath: if trie key extends part-way down an extension or leaf node """ trie_key = Nibbles(trie_key_input) node, remaining_key = self._traverse_from(parent_node.raw, trie_key) annotated_node = annotate_node(node) if remaining_key: path_to_node = trie_key[:len(trie_key) - len(remaining_key)] raise TraversedPartialPath(path_to_node, annotated_node) else: return annotated_node
def test_invalid_TraversedPartialPath_nibbles(invalid_nibbles, exception): with pytest.raises(exception): TraversedPartialPath(invalid_nibbles, annotate_node(b''))