mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-05 18:38:09 +01:00
preparescript: Add WALLET_ENCRYPTION_PWD env var.
Removed unnecessary START_DAEMONS env var. Remove all cached addresses from the basicswap db for a wallet after reseeding. Check that addresses retreived from the db are owned by teh wallet before they're used/displayed
This commit is contained in:
@@ -656,7 +656,11 @@ class BasicSwap(BaseApp):
|
||||
self.log.error('Sanity checks failed: %s', str(e))
|
||||
|
||||
elif c == Coins.XMR:
|
||||
ci.ensureWalletExists()
|
||||
try:
|
||||
ci.ensureWalletExists()
|
||||
except Exception as e:
|
||||
self.log.warning('Can\'t open XMR wallet, could be locked.')
|
||||
continue
|
||||
|
||||
self.checkWalletSeed(c)
|
||||
|
||||
@@ -740,7 +744,7 @@ class BasicSwap(BaseApp):
|
||||
yield c
|
||||
|
||||
def changeWalletPasswords(self, old_password, new_password):
|
||||
|
||||
# Only the main wallet password is changed for monero, avoid issues by preventing until active swaps are complete
|
||||
if len(self.swaps_in_progress) > 0:
|
||||
raise ValueError('Can\'t change passwords while swaps are in progress')
|
||||
|
||||
@@ -767,6 +771,7 @@ class BasicSwap(BaseApp):
|
||||
if coin_type == Coins.PART:
|
||||
return
|
||||
ci = self.ci(coin_type)
|
||||
db_key_coin_name = ci.coin_name().lower()
|
||||
self.log.info('Initialising {} wallet.'.format(ci.coin_name()))
|
||||
|
||||
if coin_type == Coins.XMR:
|
||||
@@ -775,7 +780,7 @@ class BasicSwap(BaseApp):
|
||||
ci.initialiseWallet(key_view, key_spend)
|
||||
root_address = ci.getAddressFromKeys(key_view, key_spend)
|
||||
|
||||
key_str = 'main_wallet_addr_' + ci.coin_name().lower()
|
||||
key_str = 'main_wallet_addr_' + db_key_coin_name
|
||||
self.setStringKV(key_str, root_address)
|
||||
return
|
||||
|
||||
@@ -789,9 +794,23 @@ class BasicSwap(BaseApp):
|
||||
self.log.error('initialiseWallet failed: {}'.format(str(e)))
|
||||
if raise_errors:
|
||||
raise e
|
||||
return
|
||||
|
||||
key_str = 'main_wallet_seedid_' + ci.coin_name().lower()
|
||||
self.setStringKV(key_str, root_hash.hex())
|
||||
try:
|
||||
session = self.openSession()
|
||||
key_str = 'main_wallet_seedid_' + db_key_coin_name
|
||||
self.setStringKV(key_str, root_hash.hex(), session)
|
||||
|
||||
# Clear any saved addresses
|
||||
self.clearStringKV('receive_addr_' + db_key_coin_name, session)
|
||||
self.clearStringKV('stealth_addr_' + db_key_coin_name, session)
|
||||
|
||||
coin_id = int(coin_type)
|
||||
info_type = 1 # wallet
|
||||
query_str = f'DELETE FROM wallets WHERE coin_id = {coin_id} AND balance_type = {info_type}'
|
||||
session.execute(query_str)
|
||||
finally:
|
||||
self.closeSession(session)
|
||||
|
||||
def updateIdentityBidState(self, session, address, bid):
|
||||
identity_stats = session.query(KnownIdentity).filter_by(address=address).first()
|
||||
@@ -831,20 +850,18 @@ class BasicSwap(BaseApp):
|
||||
session.remove()
|
||||
self.mxDB.release()
|
||||
|
||||
def setStringKV(self, str_key, str_val):
|
||||
with self.mxDB:
|
||||
try:
|
||||
session = scoped_session(self.session_factory)
|
||||
kv = session.query(DBKVString).filter_by(key=str_key).first()
|
||||
if not kv:
|
||||
kv = DBKVString(key=str_key, value=str_val)
|
||||
else:
|
||||
kv.value = str_val
|
||||
session.add(kv)
|
||||
session.commit()
|
||||
finally:
|
||||
session.close()
|
||||
session.remove()
|
||||
def setStringKV(self, str_key, str_val, session=None):
|
||||
try:
|
||||
use_session = self.openSession(session)
|
||||
kv = use_session.query(DBKVString).filter_by(key=str_key).first()
|
||||
if not kv:
|
||||
kv = DBKVString(key=str_key, value=str_val)
|
||||
else:
|
||||
kv.value = str_val
|
||||
use_session.add(kv)
|
||||
finally:
|
||||
if session is None:
|
||||
self.closeSession(use_session)
|
||||
|
||||
def getStringKV(self, str_key):
|
||||
self.mxDB.acquire()
|
||||
@@ -859,6 +876,16 @@ class BasicSwap(BaseApp):
|
||||
session.remove()
|
||||
self.mxDB.release()
|
||||
|
||||
def clearStringKV(self, str_key, str_val):
|
||||
with self.mxDB:
|
||||
try:
|
||||
session = scoped_session(self.session_factory)
|
||||
session.execute('DELETE FROM kv_string WHERE key = "{}" '.format(str_key))
|
||||
session.commit()
|
||||
finally:
|
||||
session.close()
|
||||
session.remove()
|
||||
|
||||
def activateBid(self, session, bid):
|
||||
if bid.bid_id in self.swaps_in_progress:
|
||||
self.log.debug('Bid %s is already in progress', bid.bid_id.hex())
|
||||
@@ -1442,6 +1469,7 @@ class BasicSwap(BaseApp):
|
||||
record.bid_id = bid_id
|
||||
record.tx_type = tx_type
|
||||
addr = record.addr
|
||||
ensure(self.ci(coin_type).isAddressMine(addr), 'Pool address not owned by wallet!')
|
||||
session.add(record)
|
||||
session.commit()
|
||||
finally:
|
||||
@@ -1539,6 +1567,7 @@ class BasicSwap(BaseApp):
|
||||
if expect_address is None:
|
||||
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():
|
||||
ci.setWalletSeedWarning(False)
|
||||
return True
|
||||
|
||||
@@ -188,6 +188,7 @@ class BTCInterface(CoinInterface):
|
||||
self._connection_type = coin_settings['connection_type']
|
||||
self._sc = swap_client
|
||||
self._log = self._sc.log if self._sc and self._sc.log else logging
|
||||
self._expect_seedid_hex = None
|
||||
|
||||
def using_segwit(self):
|
||||
return self._use_segwit
|
||||
@@ -297,6 +298,7 @@ class BTCInterface(CoinInterface):
|
||||
return self.rpc_callback('getwalletinfo')['hdseedid']
|
||||
|
||||
def checkExpectedSeed(self, expect_seedid):
|
||||
self._expect_seedid_hex = expect_seedid
|
||||
return expect_seedid == self.getWalletSeedID()
|
||||
|
||||
def getNewAddress(self, use_segwit, label='swap_receive'):
|
||||
@@ -305,6 +307,15 @@ class BTCInterface(CoinInterface):
|
||||
args.append('bech32')
|
||||
return self.rpc_callback('getnewaddress', args)
|
||||
|
||||
def isAddressMine(self, address):
|
||||
addr_info = self.rpc_callback('getaddressinfo', [address])
|
||||
return addr_info['ismine']
|
||||
|
||||
def checkAddressMine(self, address):
|
||||
addr_info = self.rpc_callback('getaddressinfo', [address])
|
||||
ensure(addr_info['ismine'], 'ismine is false')
|
||||
ensure(addr_info['hdseedid'] == self._expect_seedid_hex, 'unexpected seedid')
|
||||
|
||||
def get_fee_rate(self, conf_target=2):
|
||||
try:
|
||||
fee_rate = self.rpc_callback('estimatesmartfee', [conf_target])['feerate']
|
||||
|
||||
@@ -55,6 +55,10 @@ class FIROInterface(BTCInterface):
|
||||
addr_info = self.rpc_callback('validateaddress', [address])
|
||||
return addr_info['iswatchonly']
|
||||
|
||||
def isAddressMine(self, address):
|
||||
addr_info = self.rpc_callback('validateaddress', [address])
|
||||
return addr_info['ismine']
|
||||
|
||||
def getSCLockScriptAddress(self, lock_script):
|
||||
lock_tx_dest = self.getScriptDest(lock_script)
|
||||
address = self.encodeScriptDest(lock_tx_dest)
|
||||
|
||||
@@ -75,6 +75,7 @@ class XMRInterface(CoinInterface):
|
||||
self._sc = swap_client
|
||||
self._log = self._sc.log if self._sc and self._sc.log else logging
|
||||
self._wallet_password = None
|
||||
self._have_checked_seed = False
|
||||
|
||||
def setFeePriority(self, new_priority):
|
||||
ensure(new_priority >= 0 and new_priority < 4, 'Invalid fee_priority value')
|
||||
@@ -534,6 +535,13 @@ class XMRInterface(CoinInterface):
|
||||
self._log.info('unlockWallet - {}'.format(self.ticker()))
|
||||
self._wallet_password = password
|
||||
|
||||
if not self._have_checked_seed:
|
||||
self._sc.checkWalletSeed(self.coin_type())
|
||||
|
||||
def lockWallet(self):
|
||||
self._log.info('lockWallet - {}'.format(self.ticker()))
|
||||
self._wallet_password = None
|
||||
|
||||
def isAddressMine(self, address):
|
||||
# TODO
|
||||
return True
|
||||
|
||||
@@ -32,6 +32,7 @@ from .ui.util import (
|
||||
have_data_entry,
|
||||
tickerToCoinId,
|
||||
listOldBidStates,
|
||||
checkAddressesOwned,
|
||||
)
|
||||
from .ui.page_offers import postNewOffer
|
||||
from .protocols.xmr_swap_1 import recoverNoScriptTxnWithKey, getChainBSplitKey
|
||||
@@ -117,8 +118,10 @@ def js_wallets(self, url_split, post_string, is_json):
|
||||
|
||||
rv = swap_client.getWalletInfo(coin_type)
|
||||
rv.update(swap_client.getBlockchainInfo(coin_type))
|
||||
ci = swap_client.ci(coin_type)
|
||||
checkAddressesOwned(ci, rv)
|
||||
return bytes(json.dumps(rv), 'UTF-8')
|
||||
return bytes(json.dumps(self.server.swap_client.getWalletsInfo({'ticker_key': True})), 'UTF-8')
|
||||
return bytes(json.dumps(swap_client.getWalletsInfo({'ticker_key': True})), 'UTF-8')
|
||||
|
||||
|
||||
def js_offers(self, url_split, post_string, is_json, sent=False):
|
||||
|
||||
@@ -170,12 +170,18 @@
|
||||
<tr class="bg-white border-t hover:bg-gray-50">
|
||||
<td class="py-4 px-6 bold">Bootstrapping:</td>
|
||||
<td>{{ w.bootstrapping }}</td>
|
||||
</tr>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if w.encrypted %}
|
||||
<tr class="bg-white border-t hover:bg-gray-50">
|
||||
<td class="py-4 px-6 bold">Locked:</td>
|
||||
<td>{{ w.locked }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<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 %}
|
||||
{% if w.expected_seed != true %} {# Only show addresses if wallet seed is correct #}
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -411,4 +417,4 @@
|
||||
</div>
|
||||
{% include 'footer.html' %}
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -82,7 +82,9 @@
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium">Last Updated:</h4> <span class="inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500">{{ w.lastupdated }}</span></div>{% if w.bootstrapping %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium">Bootstrapping:</h4> <span class="inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500">{{ w.bootstrapping }}</span></div>{% endif %}
|
||||
<h4 class="text-xs font-medium">Bootstrapping:</h4> <span class="inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500">{{ w.bootstrapping }}</span></div>{% endif %}{% if w.encrypted %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium">Locked:</h4> <span class="inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500">{{ w.locked }}</span></div>{% endif %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium">Expected Seed:</h4> <span class="inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500">{{ w.expected_seed }}</span></div>
|
||||
<div class="flex justify-between mb-1 mt-10"> <span class="text-xs font-medium text-blue-700">Blockchain</span> <span class="text-xs font-medium text-blue-700">{{ w.synced }}%</span></div>
|
||||
@@ -109,4 +111,4 @@
|
||||
</div>
|
||||
{% include 'footer.html' %}
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -9,6 +9,7 @@ import traceback
|
||||
from .util import (
|
||||
get_data_entry,
|
||||
have_data_entry,
|
||||
checkAddressesOwned,
|
||||
)
|
||||
from basicswap.util import (
|
||||
ensure,
|
||||
@@ -31,6 +32,8 @@ def format_wallet_data(ci, w):
|
||||
'blocks': w.get('blocks', '?'),
|
||||
'synced': w.get('synced', '?'),
|
||||
'expected_seed': w.get('expected_seed', '?'),
|
||||
'encrypted': w.get('encrypted', '?'),
|
||||
'locked': w.get('locked', '?'),
|
||||
'updating': w.get('updating', '?'),
|
||||
'havedata': True,
|
||||
}
|
||||
@@ -55,6 +58,8 @@ def format_wallet_data(ci, w):
|
||||
wf['anon_balance'] = w.get('anon_balance', '?')
|
||||
if 'anon_pending' in w and float(w['anon_pending']) > 0.0:
|
||||
wf['anon_pending'] = w['anon_pending']
|
||||
|
||||
checkAddressesOwned(ci, wf)
|
||||
return wf
|
||||
|
||||
|
||||
@@ -297,7 +302,6 @@ def page_wallet(self, url_split, post_string):
|
||||
|
||||
if show_utxo_groups:
|
||||
utxo_groups = ''
|
||||
|
||||
unspent_by_addr = ci.getUnspentsByAddr()
|
||||
|
||||
sorted_unspent_by_addr = sorted(unspent_by_addr.items(), key=lambda x: x[1], reverse=True)
|
||||
@@ -307,6 +311,8 @@ def page_wallet(self, url_split, post_string):
|
||||
wallet_data['show_utxo_groups'] = True
|
||||
wallet_data['utxo_groups'] = utxo_groups
|
||||
|
||||
checkAddressesOwned(ci, wallet_data)
|
||||
|
||||
template = server.env.get_template('wallet.html')
|
||||
return self.render_template(template, {
|
||||
'messages': messages,
|
||||
|
||||
@@ -423,3 +423,17 @@ def listAvailableCoins(swap_client, with_variants=True, split_from=False):
|
||||
if split_from:
|
||||
return coins_from, coins
|
||||
return coins
|
||||
|
||||
|
||||
def checkAddressesOwned(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 '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'
|
||||
|
||||
Reference in New Issue
Block a user