From 401c98fd846785bb6c68b2dafafeff5899518ead Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 5 Dec 2025 07:26:32 -0800 Subject: [PATCH 1/2] Add optional creation to `get_dl_wallet` --- chia/wallet/wallet_rpc_api.py | 38 ++++++++++++----------------- chia/wallet/wallet_state_manager.py | 17 ++++++------- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/chia/wallet/wallet_rpc_api.py b/chia/wallet/wallet_rpc_api.py index 7feeea0cd750..1f3a1749239b 100644 --- a/chia/wallet/wallet_rpc_api.py +++ b/chia/wallet/wallet_rpc_api.py @@ -16,7 +16,7 @@ from chia.consensus.block_rewards import calculate_base_farmer_reward from chia.data_layer.data_layer_errors import LauncherCoinNotFoundError from chia.data_layer.data_layer_util import DLProof, VerifyProofResponse, dl_verify_proof -from chia.data_layer.data_layer_wallet import DataLayerWallet, Mirror +from chia.data_layer.data_layer_wallet import Mirror from chia.pools.pool_wallet import PoolWallet from chia.pools.pool_wallet_info import FARMING_TO_POOL, PoolState, PoolWalletInfo, create_pool_state from chia.protocols.outbound_message import NodeType @@ -3490,11 +3490,7 @@ async def create_new_dl( if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - try: - dl_wallet = self.service.wallet_state_manager.get_dl_wallet() - except ValueError: - async with self.service.wallet_state_manager.lock: - dl_wallet = await DataLayerWallet.create_new_dl_wallet(self.service.wallet_state_manager) + dl_wallet = await self.service.wallet_state_manager.get_dl_wallet(create_if_not_found=True) async with self.service.wallet_state_manager.lock: launcher_id = await dl_wallet.generate_new_reporter( @@ -3512,13 +3508,9 @@ async def dl_track_new(self, request: DLTrackNew) -> Empty: """Initialize the DataLayer Wallet (only one can exist)""" if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - try: - dl_wallet = self.service.wallet_state_manager.get_dl_wallet() - except ValueError: - async with self.service.wallet_state_manager.lock: - dl_wallet = await DataLayerWallet.create_new_dl_wallet( - self.service.wallet_state_manager, - ) + + dl_wallet = await self.service.wallet_state_manager.get_dl_wallet(create_if_not_found=True) + peer_list = self.service.get_full_node_peers_in_order() peer_length = len(peer_list) for i, peer in enumerate(peer_list): @@ -3539,7 +3531,7 @@ async def dl_stop_tracking(self, request: DLStopTracking) -> Empty: if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - dl_wallet = self.service.wallet_state_manager.get_dl_wallet() + dl_wallet = await self.service.wallet_state_manager.get_dl_wallet() await dl_wallet.stop_tracking_singleton(request.launcher_id) return Empty() @@ -3549,7 +3541,7 @@ async def dl_latest_singleton(self, request: DLLatestSingleton) -> DLLatestSingl if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - wallet = self.service.wallet_state_manager.get_dl_wallet() + wallet = await self.service.wallet_state_manager.get_dl_wallet() record = await wallet.get_latest_singleton(request.launcher_id, request.only_confirmed) return DLLatestSingletonResponse(record) @@ -3559,7 +3551,7 @@ async def dl_singletons_by_root(self, request: DLSingletonsByRoot) -> DLSingleto if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - wallet = self.service.wallet_state_manager.get_dl_wallet() + wallet = await self.service.wallet_state_manager.get_dl_wallet() records = await wallet.get_singletons_by_root(request.launcher_id, request.root) return DLSingletonsByRootResponse(records) @@ -3575,7 +3567,7 @@ async def dl_update_root( if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - wallet = self.service.wallet_state_manager.get_dl_wallet() + wallet = await self.service.wallet_state_manager.get_dl_wallet() async with self.service.wallet_state_manager.lock: await wallet.create_update_state_spend( request.launcher_id, @@ -3604,7 +3596,7 @@ async def dl_update_multiple( if self.service.wallet_state_manager is None: raise RuntimeError("not initialized") - wallet = self.service.wallet_state_manager.get_dl_wallet() + wallet = await self.service.wallet_state_manager.get_dl_wallet() async with self.service.wallet_state_manager.lock: # TODO: This method should optionally link the singletons with announcements. # Otherwise spends are vulnerable to signature subtraction. @@ -3631,7 +3623,7 @@ async def dl_history(self, request: DLHistory) -> DLHistoryResponse: if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - wallet = self.service.wallet_state_manager.get_dl_wallet() + wallet = await self.service.wallet_state_manager.get_dl_wallet() additional_kwargs = {} if request.min_generation is not None: @@ -3650,7 +3642,7 @@ async def dl_owned_singletons(self, request: Empty) -> DLOwnedSingletonsResponse if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - wallet = self.service.wallet_state_manager.get_dl_wallet() + wallet = await self.service.wallet_state_manager.get_dl_wallet() singletons = await wallet.get_owned_singletons() return DLOwnedSingletonsResponse(singletons, uint32(len(singletons))) @@ -3661,7 +3653,7 @@ async def dl_get_mirrors(self, request: DLGetMirrors) -> DLGetMirrorsResponse: if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - wallet = self.service.wallet_state_manager.get_dl_wallet() + wallet = await self.service.wallet_state_manager.get_dl_wallet() return DLGetMirrorsResponse(await wallet.get_mirrors_for_launcher(request.launcher_id)) @tx_endpoint(push=True) @@ -3676,7 +3668,7 @@ async def dl_new_mirror( if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - dl_wallet = self.service.wallet_state_manager.get_dl_wallet() + dl_wallet = await self.service.wallet_state_manager.get_dl_wallet() async with self.service.wallet_state_manager.lock: await dl_wallet.create_new_mirror( request.launcher_id, @@ -3705,7 +3697,7 @@ async def dl_delete_mirror( if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - dl_wallet = self.service.wallet_state_manager.get_dl_wallet() + dl_wallet = await self.service.wallet_state_manager.get_dl_wallet() async with self.service.wallet_state_manager.lock: await dl_wallet.delete_mirror( request.coin_id, diff --git a/chia/wallet/wallet_state_manager.py b/chia/wallet/wallet_state_manager.py index c923963022df..c988605f66a8 100644 --- a/chia/wallet/wallet_state_manager.py +++ b/chia/wallet/wallet_state_manager.py @@ -1700,7 +1700,7 @@ async def _add_coin_states( elif coin_state.created_height is not None: wallet_identifier, coin_data = await self.determine_coin_type(peer, coin_state, fork_height) try: - dl_wallet = self.get_dl_wallet() + dl_wallet = await self.get_dl_wallet() except ValueError: pass else: @@ -2012,12 +2012,7 @@ async def _add_coin_states( and inner_puzhash is not None and (await self.puzzle_store.puzzle_hash_exists(inner_puzhash)) ): - try: - dl_wallet = self.get_dl_wallet() - except ValueError: - dl_wallet = await DataLayerWallet.create_new_dl_wallet( - self, - ) + dl_wallet = await self.get_dl_wallet(create_if_not_found=True) await dl_wallet.track_new_launcher_id( child.coin.name(), peer, @@ -2591,14 +2586,18 @@ async def convert_puzzle_hash(self, wallet_id: uint32, puzzle_hash: bytes32) -> return puzzle_hash - def get_dl_wallet(self) -> DataLayerWallet: + async def get_dl_wallet(self, *, create_if_not_found: bool = False) -> DataLayerWallet: for wallet in self.wallets.values(): if wallet.type() == WalletType.DATA_LAYER.value: assert isinstance(wallet, DataLayerWallet), ( f"WalletType.DATA_LAYER should be a DataLayerWallet instance got: {type(wallet).__name__}" ) return wallet - raise ValueError("DataLayerWallet not available") + if create_if_not_found: + async with self.lock: + return await DataLayerWallet.create_new_dl_wallet(self) + else: + raise ValueError("DataLayerWallet not available") async def get_or_create_vc_wallet(self) -> VCWallet: for _, wallet in self.wallets.items(): From ef2037384b7b575b68a569cbb791d4f95c9bd793 Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 5 Dec 2025 07:35:44 -0800 Subject: [PATCH 2/2] Extract `track_new_launcher_id` from `dl_track_new` --- chia/data_layer/data_layer_wallet.py | 27 ++++++++++++++++++++++++++- chia/wallet/wallet_rpc_api.py | 17 +++-------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/chia/data_layer/data_layer_wallet.py b/chia/data_layer/data_layer_wallet.py index 351f99384dae..6e31ead97d25 100644 --- a/chia/data_layer/data_layer_wallet.py +++ b/chia/data_layer/data_layer_wallet.py @@ -210,7 +210,7 @@ async def get_launcher_coin_state(self, launcher_id: bytes32, peer: WSChiaConnec return coin_states[0] # This is the entry point for non-owned singletons - async def track_new_launcher_id( + async def _track_new_launcher_id( self, launcher_id: bytes32, peer: WSChiaConnection, @@ -863,6 +863,31 @@ async def stop_tracking_singleton(self, launcher_id: bytes32) -> None: await self.wallet_state_manager.dl_store.delete_singleton_records_by_launcher_id(launcher_id) await self.wallet_state_manager.dl_store.delete_launcher(launcher_id) + async def track_new_launcher_id( + self, + launcher_id: bytes32, + peer: WSChiaConnection | None = None, + spend: CoinSpend | None = None, + height: uint32 | None = None, + ) -> None: + if peer is None: + peer_list = self.wallet_state_manager.wallet_node.get_full_node_peers_in_order() + else: + peer_list = [peer] + peer_length = len(peer_list) + for i, peer_to_try in enumerate(peer_list): + try: + await self._track_new_launcher_id( + launcher_id, + peer_to_try, + spend, + height, + ) + except LauncherCoinNotFoundError as e: + if i == peer_length - 1: + raise e # raise the error if we've tried all peers + continue # try some other peers, maybe someone has it + ########### # UTILITY # ########### diff --git a/chia/wallet/wallet_rpc_api.py b/chia/wallet/wallet_rpc_api.py index 1f3a1749239b..1589cce583c9 100644 --- a/chia/wallet/wallet_rpc_api.py +++ b/chia/wallet/wallet_rpc_api.py @@ -14,7 +14,6 @@ from clvm_tools.binutils import assemble from chia.consensus.block_rewards import calculate_base_farmer_reward -from chia.data_layer.data_layer_errors import LauncherCoinNotFoundError from chia.data_layer.data_layer_util import DLProof, VerifyProofResponse, dl_verify_proof from chia.data_layer.data_layer_wallet import Mirror from chia.pools.pool_wallet import PoolWallet @@ -3509,20 +3508,10 @@ async def dl_track_new(self, request: DLTrackNew) -> Empty: if self.service.wallet_state_manager is None: raise ValueError("The wallet service is not currently initialized") - dl_wallet = await self.service.wallet_state_manager.get_dl_wallet(create_if_not_found=True) + await (await self.service.wallet_state_manager.get_dl_wallet(create_if_not_found=True)).track_new_launcher_id( + request.launcher_id + ) - peer_list = self.service.get_full_node_peers_in_order() - peer_length = len(peer_list) - for i, peer in enumerate(peer_list): - try: - await dl_wallet.track_new_launcher_id( - request.launcher_id, - peer, - ) - except LauncherCoinNotFoundError as e: - if i == peer_length - 1: - raise e # raise the error if we've tried all peers - continue # try some other peers, maybe someone has it return Empty() @marshal