diff --git a/chia/data_layer/data_store.py b/chia/data_layer/data_store.py index c9919485ac91..9fa25e1ad539 100644 --- a/chia/data_layer/data_store.py +++ b/chia/data_layer/data_store.py @@ -1737,41 +1737,32 @@ async def _get_one_ancestor_multiple_hashes( return [InternalNode.from_row(row=row) for row in rows] async def build_ancestor_table_for_latest_root(self, store_id: bytes32) -> None: - async with self.db_wrapper.writer() as writer: + async with self.db_wrapper.writer(): root = await self.get_tree_root(store_id=store_id) if root.node_hash is None: return + previous_root = await self.get_tree_root( + store_id=store_id, + generation=max(root.generation - 1, 0), + ) - await writer.execute( - """ - WITH RECURSIVE tree_from_root_hash AS ( - SELECT - node.hash, - node.left, - node.right, - NULL AS ancestor - FROM node - WHERE node.hash = :root_hash - UNION ALL - SELECT - node.hash, - node.left, - node.right, - tree_from_root_hash.hash AS ancestor - FROM node - JOIN tree_from_root_hash ON node.hash = tree_from_root_hash.left - OR node.hash = tree_from_root_hash.right + if previous_root.node_hash is not None: + previous_internal_nodes: List[InternalNode] = await self.get_internal_nodes( + store_id=store_id, + root_hash=previous_root.node_hash, ) - INSERT OR REPLACE INTO ancestors (hash, ancestor, tree_id, generation) - SELECT - tree_from_root_hash.hash, - tree_from_root_hash.ancestor, - :tree_id, - :generation - FROM tree_from_root_hash - """, - {"root_hash": root.node_hash, "tree_id": store_id, "generation": root.generation}, + known_hashes: Set[bytes32] = {node.hash for node in previous_internal_nodes} + else: + known_hashes = set() + internal_nodes: List[InternalNode] = await self.get_internal_nodes( + store_id=store_id, + root_hash=root.node_hash, ) + for node in internal_nodes: + # We already have the same values in ancestor tables, if we have the same internal node. + # Don't reinsert it so we can save DB space. + if node.hash not in known_hashes: + await self._insert_ancestor_table(node.left_hash, node.right_hash, store_id, root.generation) async def insert_root_with_ancestor_table( self, store_id: bytes32, node_hash: Optional[bytes32], status: Status = Status.PENDING