From c75b1edbb04dd56073d6f706819a901787a21d57 Mon Sep 17 00:00:00 2001 From: almog Date: Mon, 24 Jan 2022 14:53:56 +0200 Subject: [PATCH 1/3] get_keys_values by root hash --- chia/data_layer/data_layer.py | 4 ++-- chia/data_layer/data_store.py | 15 +++++++++------ chia/rpc/data_layer_rpc_api.py | 5 ++++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/chia/data_layer/data_layer.py b/chia/data_layer/data_layer.py index 02670b794c..868e205659 100644 --- a/chia/data_layer/data_layer.py +++ b/chia/data_layer/data_layer.py @@ -119,8 +119,8 @@ class DataLayer: return None return res.value - async def get_keys_values(self, store_id: bytes32) -> List[TerminalNode]: - res = await self.data_store.get_keys_values(store_id) + async def get_keys_values(self, store_id: bytes32, root_hash: Optional[bytes32]) -> List[TerminalNode]: + res = await self.data_store.get_keys_values(store_id, root_hash) if res is None: self.log.error("Failed to fetch keys values") return res diff --git a/chia/data_layer/data_store.py b/chia/data_layer/data_store.py index 01bb8604d6..d51563bdfb 100644 --- a/chia/data_layer/data_store.py +++ b/chia/data_layer/data_store.py @@ -370,12 +370,15 @@ class DataStore: return ancestors - async def get_keys_values(self, tree_id: bytes32, *, lock: bool = True) -> List[TerminalNode]: + async def get_keys_values( + self, tree_id: bytes32, root_hash: Optional[bytes32] = None, *, lock: bool = True + ) -> List[TerminalNode]: async with self.db_wrapper.locked_transaction(lock=lock): - root = await self.get_tree_root(tree_id=tree_id, lock=False) - - if root.node_hash is None: - return [] + if root_hash is None: + root = await self.get_tree_root(tree_id=tree_id, lock=False) + if root.node_hash is None: + return [] + root_hash = root.node_hash cursor = await self.db.execute( """ @@ -398,7 +401,7 @@ class DataStore: WHERE node_type == :node_type ORDER BY depth ASC, rights ASC """, - {"root_hash": root.node_hash.hex(), "node_type": NodeType.TERMINAL}, + {"root_hash": root_hash.hex(), "node_type": NodeType.TERMINAL}, ) terminal_nodes: List[TerminalNode] = [] diff --git a/chia/rpc/data_layer_rpc_api.py b/chia/rpc/data_layer_rpc_api.py index c7952213e2..a4893f5c30 100644 --- a/chia/rpc/data_layer_rpc_api.py +++ b/chia/rpc/data_layer_rpc_api.py @@ -75,9 +75,12 @@ class DataLayerRpcApi: async def get_keys_values(self, request: Dict[str, Any]) -> Dict[str, Any]: store_id = bytes32(hexstr_to_bytes(request["id"])) + root_hash = None + if "root_hash" in request: + root_hash = bytes32(hexstr_to_bytes(request["root_hash"])) if self.service is None: raise Exception("Data layer not created") - res = await self.service.get_keys_values(store_id) + res = await self.service.get_keys_values(store_id, root_hash) json_nodes = [] for node in res: json = recurse_jsonify(dataclasses.asdict(node)) # type: ignore[no-untyped-call] From 62b4e25c0ac938768b00aea28be27c11c8e2b3c1 Mon Sep 17 00:00:00 2001 From: almog Date: Mon, 24 Jan 2022 15:12:35 +0200 Subject: [PATCH 2/3] add test case for older root --- tests/core/data_layer/test_data_rpc.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/core/data_layer/test_data_rpc.py b/tests/core/data_layer/test_data_rpc.py index b0682caca2..06c6219ca4 100644 --- a/tests/core/data_layer/test_data_rpc.py +++ b/tests/core/data_layer/test_data_rpc.py @@ -258,6 +258,29 @@ async def test_keys_values_ancestors(one_wallet_node_and_rpc: nodes) -> None: # todo better assertions for get_ancestors result # assert val is not None # print(val) + res_before = await data_rpc_api.get_roots({"ids": [store_id.hex()]}) + key6 = b"tasdfsd" + value6 = b"\x08\x02" + changelist = [{"action": "insert", "key": key6.hex(), "value": value6.hex()}] + key7 = b"basdff" + value7 = b"\x09\x02" + changelist.append({"action": "insert", "key": key7.hex(), "value": value7.hex()}) + res = await data_rpc_api.batch_update({"id": store_id.hex(), "changelist": changelist}) + update_tx_rec0 = res["tx_id"] + await asyncio.sleep(1) + for i in range(0, num_blocks): + await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + await asyncio.sleep(0.2) + await time_out_assert(15, is_transaction_confirmed, True, "this is unused", wallet_rpc_api, update_tx_rec0) + res_after = await data_rpc_api.get_roots({"ids": [store_id.hex()]}) + pairs_before = await data_rpc_api.get_keys_values( + {"id": store_id.hex(), "root_hash": res_before["hashes"][0].hex()} + ) + pairs_after = await data_rpc_api.get_keys_values( + {"id": store_id.hex(), "root_hash": res_after["hashes"][0].hex()} + ) + assert len(pairs_before["keys_values"]) == 5 + assert len(pairs_after["keys_values"]) == 7 @pytest.mark.asyncio From a82ffac37728eeb74ed185ddb22b342e0b835fdc Mon Sep 17 00:00:00 2001 From: almog Date: Wed, 26 Jan 2022 16:56:33 +0200 Subject: [PATCH 3/3] pr fixes --- chia/data_layer/data_store.py | 3 +-- chia/rpc/data_layer_rpc_api.py | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/chia/data_layer/data_store.py b/chia/data_layer/data_store.py index d51563bdfb..a67cbdce37 100644 --- a/chia/data_layer/data_store.py +++ b/chia/data_layer/data_store.py @@ -377,9 +377,8 @@ class DataStore: if root_hash is None: root = await self.get_tree_root(tree_id=tree_id, lock=False) if root.node_hash is None: - return [] + raise Exception(f"Root hash is unspecified for tree ID: {tree_id.hex()}") root_hash = root.node_hash - cursor = await self.db.execute( """ WITH RECURSIVE diff --git a/chia/rpc/data_layer_rpc_api.py b/chia/rpc/data_layer_rpc_api.py index a4893f5c30..7c4d89adc4 100644 --- a/chia/rpc/data_layer_rpc_api.py +++ b/chia/rpc/data_layer_rpc_api.py @@ -75,9 +75,9 @@ class DataLayerRpcApi: async def get_keys_values(self, request: Dict[str, Any]) -> Dict[str, Any]: store_id = bytes32(hexstr_to_bytes(request["id"])) - root_hash = None - if "root_hash" in request: - root_hash = bytes32(hexstr_to_bytes(request["root_hash"])) + root_hash = request.get("root_hash") + if root_hash is not None: + root_hash = bytes32.from_hexstr(root_hash) if self.service is None: raise Exception("Data layer not created") res = await self.service.get_keys_values(store_id, root_hash)