`ObjectCache` provides a way to calculate and cache values for each node in a clvm object tree. It can be used to calculate the sha256 tree hash for an object and save the hash for all the child objects for building usage tables, for example. It also allows a function that's de
| 8 | |
| 9 | |
| 10 | class ObjectCache(Generic[T]): |
| 11 | """ |
| 12 | `ObjectCache` provides a way to calculate and cache values for each node |
| 13 | in a clvm object tree. It can be used to calculate the sha256 tree hash |
| 14 | for an object and save the hash for all the child objects for building |
| 15 | usage tables, for example. |
| 16 | |
| 17 | It also allows a function that's defined recursively on a clvm tree to |
| 18 | have a non-recursive implementation (as it keeps a stack of uncached |
| 19 | objects locally). |
| 20 | """ |
| 21 | |
| 22 | def __init__(self, f: Callable[["ObjectCache[T]", CLVMStorage], Optional[T]]): |
| 23 | """ |
| 24 | `f`: Callable[ObjectCache, CLVMObject] -> Union[None, T] |
| 25 | |
| 26 | The function `f` is expected to calculate its T value recursively based |
| 27 | on the T values for the left and right child for a pair. For an atom, the |
| 28 | function f must calculate the T value directly. |
| 29 | |
| 30 | If a pair is passed and one of the children does not have its T value cached |
| 31 | in `ObjectCache` yet, return `None` and f will be called with each child in turn. |
| 32 | Don't recurse in f; that's part of the point of this function. |
| 33 | """ |
| 34 | self.f = f |
| 35 | self.lookup: Dict[int, Tuple[T, CLVMStorage]] = dict() |
| 36 | |
| 37 | def get(self, obj: CLVMStorage) -> T: |
| 38 | obj_id = id(obj) |
| 39 | if obj_id not in self.lookup: |
| 40 | obj_list = [obj] |
| 41 | while obj_list: |
| 42 | node = obj_list.pop() |
| 43 | node_id = id(node) |
| 44 | if node_id not in self.lookup: |
| 45 | v = self.f(self, node) |
| 46 | if v is None: |
| 47 | if node.pair is None: |
| 48 | raise ValueError("f returned None for atom", node) |
| 49 | obj_list.append(node) |
| 50 | obj_list.append(node.pair[0]) |
| 51 | obj_list.append(node.pair[1]) |
| 52 | else: |
| 53 | self.lookup[node_id] = (v, node) |
| 54 | return self.lookup[obj_id][0] |
| 55 | |
| 56 | def contains(self, obj: CLVMStorage) -> bool: |
| 57 | return id(obj) in self.lookup |
| 58 | |
| 59 | |
| 60 | def treehash(cache: ObjectCache[bytes], obj: CLVMStorage) -> Optional[bytes]: |
no outgoing calls