Added restrict_unknown_seed_wallets setting.

This commit is contained in:
tecnovert 2023-02-19 21:52:22 +02:00
parent 5b0c1e9b51
commit 09cc523ac3
No known key found for this signature in database
GPG key ID: 8ED6D8750C4E3F93
12 changed files with 55 additions and 89 deletions

View file

@ -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)))

View file

@ -321,6 +321,7 @@ class BTCInterface(CoinInterface):
def checkAddressMine(self, address: str) -> None:
addr_info = self.rpc_callback('getaddressinfo', [address])
ensure(addr_info['ismine'], 'ismine is false')
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):

View file

@ -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')

View file

@ -181,7 +181,7 @@
<tr class="bg-white border-t hover:bg-gray-50">
<td class="py-4 px-6 bold">Expected Seed:</td>
<td>{{ w.expected_seed }}</td>
{% 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 #}
</tr>
</table>
</div>

View file

@ -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 {}<br/>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 {}<br/>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,
})

View file

@ -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']):
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']):
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'

View file

@ -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

View file

@ -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)

View file

@ -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:

View file

@ -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)

View file

@ -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)

View file

@ -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: