Source code for remerkleable.history
from remerkleable.tree import Gindex, Node, get_anchor_gindex, ROOT_GINDEX
from typing import List as Iterable, Tuple, TypeVar
K = TypeVar('K')
History = Iterable[Tuple[K, Node]]
[docs]def get_target_history(history: History, target: Gindex) -> History:
"""
Fetch an ordered, keyed, history of nodes at the given target.
The sequential equal values are reduced into a single value, and keyed by the first occurrence.
This is done efficiently by first comparing the top of the tree,
de-duplicating, and then recursively going deeper into the tree.
:param history: An ordered keyed series of nodes, the root nodes to get the target from
:param target: The target node to look up, pointing to the values to return.
:return: the target values, keyed by the keys of the top nodes the target values first occurred in.
"""
anchor = get_anchor_gindex(target)
pivot = anchor >> 1
unanchor = target ^ anchor
direction_left = unanchor < pivot
# Don't go deeper than the anchor. In this case we just return the (duplicate reduced) history.
is_anchor = (anchor == ROOT_GINDEX)
out = []
last = None
for key, node in history:
if is_anchor:
child_node = node
else:
if direction_left:
child_node = node.get_left()
else:
child_node = node.get_right()
if last is None or child_node.merkle_root() == last:
continue
out.append((key, child_node))
last = child_node
if not is_anchor:
out = get_target_history(out, Gindex(pivot | unanchor))
return out