Merge pull request #296 from nahuhh/xmr_open

xmr: detect corrupt wallets
This commit is contained in:
tecnovert
2025-04-14 17:18:17 +00:00
committed by GitHub
4 changed files with 130 additions and 11 deletions

View File

@@ -1067,7 +1067,9 @@ class BasicSwap(BaseApp):
elif c in (Coins.XMR, Coins.WOW):
try:
ci.ensureWalletExists()
except Exception as e: # noqa: F841
except Exception as e:
if "invalid signature" in str(e): # wallet is corrupt
raise
self.log.warning(
f"Can't open {ci.coin_name()} wallet, could be locked."
)

View File

@@ -30,3 +30,27 @@ class WOWInterface(XMRInterface):
@staticmethod
def depth_spendable() -> int:
return 3
# below only needed until wow is rebased to monero v0.18.4.0+
def openWallet(self, filename):
params = {"filename": filename}
if self._wallet_password is not None:
params["password"] = self._wallet_password
try:
self.rpc_wallet("open_wallet", params)
except Exception as e:
if "no connection to daemon" in str(e):
self._log.debug(f"{self.coin_name()} {e}")
return # bypass refresh error to allow startup with a busy daemon
try:
# TODO Remove `store` after upstream fix to autosave on close_wallet
self.rpc_wallet("store")
self.rpc_wallet("close_wallet")
self._log.debug(f"Attempt to save and close {self.coin_name()} wallet")
except Exception as e: # noqa: F841
pass
self.rpc_wallet("open_wallet", params)
self._log.debug(f"Reattempt to open {self.coin_name()} wallet")

View File

@@ -7,6 +7,7 @@
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import logging
import os
import basicswap.contrib.ed25519_fast as edf
import basicswap.ed25519_fast_util as edu
@@ -204,18 +205,54 @@ class XMRInterface(CoinInterface):
except Exception as e:
if "no connection to daemon" in str(e):
self._log.debug(f"{self.coin_name()} {e}")
return # bypass refresh error to allow startup with a busy daemon
try:
# TODO Remove `store` after upstream fix to autosave on close_wallet
self.rpc_wallet("store")
self.rpc_wallet("close_wallet")
self._log.debug(f"Attempt to save and close {self.coin_name()} wallet")
except Exception as e: # noqa: F841
pass
return # Bypass refresh error to allow startup with a busy daemon
if any(
x in str(e)
for x in (
"invalid signature",
"std::bad_alloc",
"basic_string::_M_replace_aux",
)
):
self._log.error(f"{self.coin_name()} wallet is corrupt.")
chain_client_settings = self._sc.getChainClientSettings(
self.coin_type()
) # basicswap.json
if chain_client_settings.get("manage_wallet_daemon", False):
self._log.info(f"Renaming {self.coin_name()} wallet cache file.")
walletpath = os.path.join(
chain_client_settings.get("datadir", "none"),
"wallets",
filename,
)
if not os.path.isfile(walletpath):
self._log.warning(
f"Could not find {self.coin_name()} wallet cache file."
)
raise
bkp_path = walletpath + ".corrupt"
for i in range(100):
if not os.path.exists(bkp_path):
break
bkp_path = walletpath + f".corrupt{i}"
if os.path.exists(bkp_path):
self._log.error(
f"Could not find backup path for {self.coin_name()} wallet."
)
raise
os.rename(walletpath, bkp_path)
# Drop through to open_wallet
else:
raise
else:
try:
self.rpc_wallet("close_wallet")
self._log.debug(f"Closing {self.coin_name()} wallet")
except Exception as e: # noqa: F841
pass
self.rpc_wallet("open_wallet", params)
self._log.debug(f"Reattempt to open {self.coin_name()} wallet")
self._log.debug(f"Attempting to open {self.coin_name()} wallet")
def initialiseWallet(
self, key_view: bytes, key_spend: bytes, restore_height=None