From 09cc523ac375fd2b7da3c9bcae60c49d0d678c9c Mon Sep 17 00:00:00 2001 From: tecnovert Date: Sun, 19 Feb 2023 21:52:22 +0200 Subject: [PATCH] Added restrict_unknown_seed_wallets setting. --- basicswap/basicswap.py | 23 +++++--- basicswap/interface/btc.py | 3 +- basicswap/js_server.py | 7 ++- basicswap/templates/wallet.html | 2 +- basicswap/ui/page_wallet.py | 71 +++--------------------- basicswap/ui/util.py | 23 +++++--- doc/release-notes.md | 2 + tests/basicswap/extended/test_dash.py | 3 +- tests/basicswap/extended/test_network.py | 3 +- tests/basicswap/extended/test_nmc.py | 3 +- tests/basicswap/extended/test_pivx.py | 3 +- tests/basicswap/test_xmr.py | 1 + 12 files changed, 55 insertions(+), 89 deletions(-) diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 6372e74..a285fb3 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -264,6 +264,8 @@ class BasicSwap(BaseApp): self.min_sequence_lock_seconds = self.settings.get('min_sequence_lock_seconds', 60 if self.debug else (1 * 60 * 60)) self.max_sequence_lock_seconds = self.settings.get('max_sequence_lock_seconds', 96 * 60 * 60) + self._restrict_unknown_seed_wallets = self.settings.get('restrict_unknown_seed_wallets', True) + self._bid_expired_leeway = 5 self.swaps_in_progress = dict() @@ -781,16 +783,19 @@ class BasicSwap(BaseApp): self.log.error('Can\'t connect to %s RPC, exiting.', coin_type) self.stopRunning(1) # systemd will try to restart the process if fail_code != 0 - def checkSynced(self, coin_from, coin_to) -> None: + def checkCoinsReady(self, coin_from, coin_to) -> None: check_coins = (coin_from, coin_to) for c in check_coins: + ci = self.ci(c) + if self._restrict_unknown_seed_wallets and not ci.knownWalletSeed(): + raise ValueError('{} has an unexpected wallet seed and "restrict_unknown_seed_wallets" is enabled.'.format(ci.coin_name())) if self.coin_clients[c]['connection_type'] != 'rpc': continue if c == Coins.XMR: continue # TODO - synced = round(self.ci(c).getBlockchainInfo()['verificationprogress'], 3) + synced = round(ci.getBlockchainInfo()['verificationprogress'], 3) if synced < 1.0: - raise ValueError('{} chain is still syncing, currently at {}.'.format(self.coin_clients[c]['name'], synced)) + raise ValueError('{} chain is still syncing, currently at {}.'.format(ci.coin_name(), synced)) def isSystemUnlocked(self) -> bool: # TODO - Check all active coins @@ -1405,7 +1410,7 @@ class BasicSwap(BaseApp): self.mxDB.acquire() session = None try: - self.checkSynced(coin_from_t, coin_to_t) + self.checkCoinsReady(coin_from_t, coin_to_t) offer_addr = self.newSMSGAddress(use_type=AddressTypes.OFFER)[0] if addr_send_from is None else addr_send_from offer_created_at = int(time.time()) @@ -1775,6 +1780,7 @@ class BasicSwap(BaseApp): def checkWalletSeed(self, c): ci = self.ci(c) if c == Coins.PART: + ci.setWalletSeedWarning(False) # All keys should be be derived from the Particl mnemonic return True # TODO if c == Coins.XMR: expect_address = self.getCachedMainWalletAddress(ci) @@ -1782,10 +1788,11 @@ class BasicSwap(BaseApp): self.log.warning('Can\'t find expected main wallet address for coin {}'.format(ci.coin_name())) return False ci._have_checked_seed = True - if expect_address == ci.getMainWalletAddress(): + wallet_address: str = ci.getMainWalletAddress() + if expect_address == wallet_address: ci.setWalletSeedWarning(False) return True - self.log.warning('Wallet for coin {} not derived from swap seed.'.format(ci.coin_name())) + self.log.warning('Wallet for coin {} not derived from swap seed.\n Expected {}\n Have {}'.format(ci.coin_name(), expect_address, wallet_address)) return False expect_seedid = self.getStringKV('main_wallet_seedid_' + ci.coin_name().lower()) @@ -2058,7 +2065,7 @@ class BasicSwap(BaseApp): ci_from = self.ci(coin_from) ci_to = self.ci(coin_to) - self.checkSynced(coin_from, coin_to) + self.checkCoinsReady(coin_from, coin_to) amount_to = int((msg_buf.amount * bid_rate) // ci_from.COIN()) @@ -2380,7 +2387,7 @@ class BasicSwap(BaseApp): self.validateBidValidTime(offer.swap_type, offer.coin_from, offer.coin_to, valid_for_seconds) self.validateBidAmount(offer, amount, bid_rate) - self.checkSynced(coin_from, coin_to) + self.checkCoinsReady(coin_from, coin_to) balance_to = ci_to.getSpendableBalance() ensure(balance_to > amount_to, '{} spendable balance is too low: {}'.format(ci_to.coin_name(), ci_to.format_amount(balance_to))) diff --git a/basicswap/interface/btc.py b/basicswap/interface/btc.py index ca79478..1f3b3c3 100644 --- a/basicswap/interface/btc.py +++ b/basicswap/interface/btc.py @@ -321,7 +321,8 @@ class BTCInterface(CoinInterface): def checkAddressMine(self, address: str) -> None: addr_info = self.rpc_callback('getaddressinfo', [address]) ensure(addr_info['ismine'], 'ismine is false') - ensure(addr_info['hdseedid'] == self._expect_seedid_hex, 'unexpected seedid') + if self.sc._restrict_unknown_seed_wallets: + ensure(addr_info['hdseedid'] == self._expect_seedid_hex, 'unexpected seedid') def get_fee_rate(self, conf_target=2): try: diff --git a/basicswap/js_server.py b/basicswap/js_server.py index 09d9e29..7a5a602 100644 --- a/basicswap/js_server.py +++ b/basicswap/js_server.py @@ -116,14 +116,17 @@ def js_wallets(self, url_split, post_string, is_json): value = ci.make_int(get_data_entry(post_data, 'value')) txid_hex, new_addr = ci.createUTXO(value) return bytes(json.dumps({'txid': txid_hex, 'address': new_addr}), 'UTF-8') - + if cmd == 'reseed': + swap_client.reseedWallet(coin_type) + return bytes(json.dumps({'reseeded': True}), 'UTF-8') raise ValueError('Unknown command') rv = swap_client.getWalletInfo(coin_type) rv.update(swap_client.getBlockchainInfo(coin_type)) ci = swap_client.ci(coin_type) - checkAddressesOwned(ci, rv) + checkAddressesOwned(swap_client, ci, rv) return bytes(json.dumps(rv), 'UTF-8') + return bytes(json.dumps(swap_client.getWalletsInfo({'ticker_key': True})), 'UTF-8') diff --git a/basicswap/templates/wallet.html b/basicswap/templates/wallet.html index 72f494f..d53b988 100644 --- a/basicswap/templates/wallet.html +++ b/basicswap/templates/wallet.html @@ -181,7 +181,7 @@ Expected Seed: {{ w.expected_seed }} - {% if w.expected_seed != true %} {# Only show addresses if wallet seed is correct #} + {% if block_unknown_seeds and w.expected_seed != true %} {# Only show addresses if wallet seed is correct #} diff --git a/basicswap/ui/page_wallet.py b/basicswap/ui/page_wallet.py index 9093a91..127998d 100644 --- a/basicswap/ui/page_wallet.py +++ b/basicswap/ui/page_wallet.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2022 tecnovert +# Copyright (c) 2022-2023 tecnovert # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -17,12 +17,11 @@ from basicswap.util import ( ) from basicswap.chainparams import ( Coins, - chainparams, getCoinIdFromTicker, ) -def format_wallet_data(ci, w): +def format_wallet_data(swap_client, ci, w): wf = { 'name': ci.coin_name(), 'version': w.get('version', '?'), @@ -59,7 +58,7 @@ def format_wallet_data(ci, w): if 'anon_pending' in w and float(w['anon_pending']) > 0.0: wf['anon_pending'] = w['anon_pending'] - checkAddressesOwned(ci, wf) + checkAddressesOwned(swap_client, ci, wf) return wf @@ -69,65 +68,8 @@ def page_wallets(self, url_split, post_string): swap_client.checkSystemStatus() summary = swap_client.getSummary() - page_data = {} messages = [] err_messages = [] - form_data = self.checkForm(post_string, 'wallets', err_messages) - if form_data: - for c in Coins: - if c not in chainparams: - continue - cid = str(int(c)) - - if bytes('newaddr_' + cid, 'utf-8') in form_data: - swap_client.cacheNewAddressForCoin(c) - elif bytes('reseed_' + cid, 'utf-8') in form_data: - try: - swap_client.reseedWallet(c) - messages.append('Reseed complete ' + str(c)) - except Exception as ex: - err_messages.append('Reseed failed ' + str(ex)) - swap_client.updateWalletsInfo(True, c) - elif bytes('withdraw_' + cid, 'utf-8') in form_data: - try: - value = form_data[bytes('amt_' + cid, 'utf-8')][0].decode('utf-8') - page_data['wd_value_' + cid] = value - except Exception as e: - err_messages.append('Missing value') - try: - address = form_data[bytes('to_' + cid, 'utf-8')][0].decode('utf-8') - page_data['wd_address_' + cid] = address - except Exception as e: - err_messages.append('Missing address') - - subfee = True if bytes('subfee_' + cid, 'utf-8') in form_data else False - page_data['wd_subfee_' + cid] = subfee - - if c == Coins.PART: - try: - type_from = form_data[bytes('withdraw_type_from_' + cid, 'utf-8')][0].decode('utf-8') - type_to = form_data[bytes('withdraw_type_to_' + cid, 'utf-8')][0].decode('utf-8') - page_data['wd_type_from_' + cid] = type_from - page_data['wd_type_to_' + cid] = type_to - except Exception as e: - err_messages.append('Missing type') - - if len(messages) == 0: - ci = swap_client.ci(c) - ticker = ci.ticker() - if c == Coins.PART: - try: - txid = swap_client.withdrawParticl(type_from, type_to, value, address, subfee) - messages.append('Withdrew {} {} ({} to {}) to address {}
In txid: {}'.format(value, ticker, type_from, type_to, address, txid)) - except Exception as e: - err_messages.append(str(e)) - else: - try: - txid = swap_client.withdrawCoin(c, value, address, subfee) - messages.append('Withdrew {} {} to address {}
In txid: {}'.format(value, ticker, address, txid)) - except Exception as e: - err_messages.append(str(e)) - swap_client.updateWalletsInfo(True, c) swap_client.updateWalletsInfo() wallets = swap_client.getCachedWalletsInfo() @@ -153,7 +95,7 @@ def page_wallets(self, url_split, post_string): continue ci = swap_client.ci(k) - wf = format_wallet_data(ci, w) + wf = format_wallet_data(swap_client, ci, w) wallets_formatted.append(wf) @@ -274,7 +216,7 @@ def page_wallet(self, url_split, post_string): ci = swap_client.ci(k) cid = str(int(coin_id)) - wallet_data = format_wallet_data(ci, w) + wallet_data = format_wallet_data(swap_client, ci, w) fee_rate, fee_src = swap_client.getFeeRateForCoin(k) est_fee = swap_client.estimateWithdrawFee(k, fee_rate) @@ -311,7 +253,7 @@ def page_wallet(self, url_split, post_string): wallet_data['show_utxo_groups'] = True wallet_data['utxo_groups'] = utxo_groups - checkAddressesOwned(ci, wallet_data) + checkAddressesOwned(swap_client, ci, wallet_data) template = server.env.get_template('wallet.html') return self.render_template(template, { @@ -319,4 +261,5 @@ def page_wallet(self, url_split, post_string): 'err_messages': err_messages, 'w': wallet_data, 'summary': summary, + 'block_unknown_seeds': swap_client._restrict_unknown_seed_wallets, }) diff --git a/basicswap/ui/util.py b/basicswap/ui/util.py index 9a11bb5..e676f56 100644 --- a/basicswap/ui/util.py +++ b/basicswap/ui/util.py @@ -429,15 +429,20 @@ def listAvailableCoins(swap_client, with_variants=True, split_from=False): return coins -def checkAddressesOwned(ci, wallet_info): +def checkAddressesOwned(swap_client, ci, wallet_info): if 'stealth_address' in wallet_info: - if wallet_info['stealth_address'] != '?' and \ - not ci.isAddressMine(wallet_info['stealth_address']): - ci._log.error('Unowned stealth address: {}'.format(wallet_info['stealth_address'])) - wallet_info['stealth_address'] = 'Error: unowned address' + + if wallet_info['stealth_address'] != '?': + if not ci.isAddressMine(wallet_info['stealth_address']): + ci._log.error('Unowned stealth address: {}'.format(wallet_info['stealth_address'])) + wallet_info['stealth_address'] = 'Error: unowned address' + elif swap_client._restrict_unknown_seed_wallets and not ci.knownWalletSeed(): + wallet_info['stealth_address'] = 'WARNING: Unknown wallet seed' if 'deposit_address' in wallet_info: - if wallet_info['deposit_address'] != 'Refresh necessary' and \ - not ci.isAddressMine(wallet_info['deposit_address']): - ci._log.error('Unowned deposit address: {}'.format(wallet_info['deposit_address'])) - wallet_info['deposit_address'] = 'Error: unowned address' + if wallet_info['deposit_address'] != 'Refresh necessary': + if not ci.isAddressMine(wallet_info['deposit_address']): + ci._log.error('Unowned deposit address: {}'.format(wallet_info['deposit_address'])) + wallet_info['deposit_address'] = 'Error: unowned address' + elif swap_client._restrict_unknown_seed_wallets and not ci.knownWalletSeed(): + wallet_info['deposit_address'] = 'WARNING: Unknown wallet seed' diff --git a/doc/release-notes.md b/doc/release-notes.md index 29ab2fb..4a4216f 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -21,6 +21,8 @@ - api: getcoinseed shows seed id. - ui: Can edit automation strategy data. - ui: Fix pagination clearing filters +- Added restrict_unknown_seed_wallets option. + - Set to false to disable unknown seed warnings. 0.0.54 diff --git a/tests/basicswap/extended/test_dash.py b/tests/basicswap/extended/test_dash.py index 34ef9e6..1498a81 100644 --- a/tests/basicswap/extended/test_dash.py +++ b/tests/basicswap/extended/test_dash.py @@ -203,7 +203,8 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey): 'min_delay_event_short': 1, 'max_delay_event_short': 3, 'min_delay_retry': 2, - 'max_delay_retry': 10 + 'max_delay_retry': 10, + 'restrict_unknown_seed_wallets': False } with open(settings_path, 'w') as fp: json.dump(settings, fp, indent=4) diff --git a/tests/basicswap/extended/test_network.py b/tests/basicswap/extended/test_network.py index c82c3a2..bd4f6b0 100644 --- a/tests/basicswap/extended/test_network.py +++ b/tests/basicswap/extended/test_network.py @@ -120,7 +120,8 @@ def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey): 'min_delay_event_short': 1, 'max_delay_event_short': 5, 'min_delay_retry': 2, - 'max_delay_retry': 10 + 'max_delay_retry': 10, + 'restrict_unknown_seed_wallets': False } with open(settings_path, 'w') as fp: diff --git a/tests/basicswap/extended/test_nmc.py b/tests/basicswap/extended/test_nmc.py index c4dcdb6..107b824 100644 --- a/tests/basicswap/extended/test_nmc.py +++ b/tests/basicswap/extended/test_nmc.py @@ -191,7 +191,8 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey): }, 'check_progress_seconds': 2, 'check_watched_seconds': 4, - 'check_expired_seconds': 60 + 'check_expired_seconds': 60, + 'restrict_unknown_seed_wallets': False, } with open(settings_path, 'w') as fp: json.dump(settings, fp, indent=4) diff --git a/tests/basicswap/extended/test_pivx.py b/tests/basicswap/extended/test_pivx.py index 005bdfe..9f6d5ee 100644 --- a/tests/basicswap/extended/test_pivx.py +++ b/tests/basicswap/extended/test_pivx.py @@ -209,7 +209,8 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey): 'min_delay_event_short': 1, 'max_delay_event_short': 3, 'min_delay_retry': 2, - 'max_delay_retry': 10 + 'max_delay_retry': 10, + 'restrict_unknown_seed_wallets': False } with open(settings_path, 'w') as fp: json.dump(settings, fp, indent=4) diff --git a/tests/basicswap/test_xmr.py b/tests/basicswap/test_xmr.py index 9aceed6..db9807b 100644 --- a/tests/basicswap/test_xmr.py +++ b/tests/basicswap/test_xmr.py @@ -207,6 +207,7 @@ def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey, with_c 'min_delay_retry': 2, 'max_delay_retry': 10, 'debug_ui': True, + 'restrict_unknown_seed_wallets': False, } if Coins.XMR in with_coins: