diff --git a/basicswap/__init__.py b/basicswap/__init__.py index 2d5aca7..943a286 100644 --- a/basicswap/__init__.py +++ b/basicswap/__init__.py @@ -1,3 +1,3 @@ name = "basicswap" -__version__ = "0.0.28" +__version__ = "0.0.29" diff --git a/basicswap/http_server.py b/basicswap/http_server.py index cdfe373..e99389c 100644 --- a/basicswap/http_server.py +++ b/basicswap/http_server.py @@ -1213,7 +1213,7 @@ class HttpHandler(BaseHTTPRequestHandler): swap_client.updateIdentity(identity_address, new_label) messages.append('Updated') except Exception as e: - messages.append('Error')\ + messages.append('Error') try: identity = swap_client.getIdentity(identity_address) diff --git a/basicswap/interface_part.py b/basicswap/interface_part.py index dbeae82..9ff72ca 100644 --- a/basicswap/interface_part.py +++ b/basicswap/interface_part.py @@ -664,7 +664,7 @@ class PARTInterfaceAnon(PARTInterface): return -1 return None - def spendBLockTx(self, chain_b_lock_txid, address_to, kbv, kbs, cb_swap_value, b_fee, restore_height): + def spendBLockTx(self, chain_b_lock_txid, address_to, kbv, kbs, cb_swap_value, b_fee, restore_height, spend_actual_balance=False): Kbv = self.getPubkey(kbv) Kbs = self.getPubkey(kbs) sx_addr = self.formatStealthAddress(Kbv, Kbs) @@ -678,13 +678,18 @@ class PARTInterfaceAnon(PARTInterface): self._log.info('Rescanning chain from height: {}'.format(restore_height)) self.rpc_callback('rescanblockchain', [restore_height]) - autxos = self.rpc_callback('listunspentanon') + autxos = self.rpc_callback('listunspentanon', [1, 9999999, [sx_addr]]) + if len(autxos) < 1: raise TemporaryError('No spendable outputs') elif len(autxos) > 1: raise ValueError('Too many spendable outputs') utxo = autxos[0] + utxo_sats = make_int(utxo['amount']) + if spend_actual_balance and utxo_sats != cb_swap_value: + self._log.warning('Spending actual balance {}, not swap value {}.'.format(utxo_sats, cb_swap_value)) + cb_swap_value = utxo_sats inputs = [{'tx': utxo['txid'], 'n': utxo['vout']}, ] params = ['anon', 'anon', diff --git a/basicswap/interface_xmr.py b/basicswap/interface_xmr.py index 8c92027..5269f20 100644 --- a/basicswap/interface_xmr.py +++ b/basicswap/interface_xmr.py @@ -373,7 +373,7 @@ class XMRInterface(CoinInterface): return None - def spendBLockTx(self, chain_b_lock_txid, address_to, kbv, kbs, cb_swap_value, b_fee_rate, restore_height): + def spendBLockTx(self, chain_b_lock_txid, address_to, kbv, kbs, cb_swap_value, b_fee_rate, restore_height, spend_actual_balance=False): with self._mx_wallet: Kbv = self.getPubkey(kbv) Kbs = self.getPubkey(kbs) @@ -403,6 +403,7 @@ class XMRInterface(CoinInterface): self.rpc_wallet_cb('refresh') rv = self.rpc_wallet_cb('get_balance') + if rv['balance'] < cb_swap_value: self._log.warning('Balance is too low, checking for existing spend.') txns = self.rpc_wallet_cb('get_transfers', {'out': True})['out'] @@ -414,7 +415,13 @@ class XMRInterface(CoinInterface): return bytes.fromhex(txid) self._log.error('wallet {} balance {}, expected {}'.format(wallet_filename, rv['balance'], cb_swap_value)) - raise TemporaryError('Invalid balance') + + if not spend_actual_balance: + raise TemporaryError('Invalid balance') + + if spend_actual_balance and rv['balance'] != cb_swap_value: + self._log.warning('Spending actual balance {}, not swap value {}.'.format(rv['balance'], cb_swap_value)) + cb_swap_value = rv['balance'] if rv['unlocked_balance'] < cb_swap_value: self._log.error('wallet {} balance {}, expected {}, blocks_to_unlock {}'.format(wallet_filename, rv['unlocked_balance'], cb_swap_value, rv['blocks_to_unlock'])) raise TemporaryError('Invalid unlocked_balance') diff --git a/basicswap/protocols/xmr_swap_1.py b/basicswap/protocols/xmr_swap_1.py index ebdf8a4..0292dfd 100644 --- a/basicswap/protocols/xmr_swap_1.py +++ b/basicswap/protocols/xmr_swap_1.py @@ -55,8 +55,13 @@ def recoverNoScriptTxnWithKey(self, bid_id, encoded_key): ensure(ci_to.verifyKey(kbsf), 'Invalid kbsf') vkbs = ci_to.sumKeys(kbsl, kbsf) - address_to = self.getCachedMainWalletAddress(ci_to) - txid = ci_to.spendBLockTx(xmr_swap.b_lock_tx_id, address_to, xmr_swap.vkbv, vkbs, bid.amount_to, xmr_offer.b_fee_rate, bid.chain_b_height_start) + if offer.coin_to == Coins.XMR: + address_to = self.getCachedMainWalletAddress(ci_to) + else: + address_to = self.getCachedStealthAddressForCoin(offer.coin_to) + + amount = bid.amount_to + txid = ci_to.spendBLockTx(xmr_swap.b_lock_tx_id, address_to, xmr_swap.vkbv, vkbs, bid.amount_to, xmr_offer.b_fee_rate, bid.chain_b_height_start, spend_actual_balance=True) self.log.debug('Submitted lock B spend txn %s to %s chain for bid %s', txid.hex(), ci_to.coin_name(), bid_id.hex()) self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_B_SPEND_TX_PUBLISHED, txid.hex(), session) session.commit() diff --git a/basicswap/ui.py b/basicswap/ui.py index 89c5b03..7e68434 100644 --- a/basicswap/ui.py +++ b/basicswap/ui.py @@ -5,6 +5,7 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import json +import traceback from .util import ( make_int, format_timestamp, @@ -284,7 +285,10 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b data['xmr_b_shared_address'] = ci_to.encodeSharedAddress(xmr_swap.pkbv, xmr_swap.pkbs) if xmr_swap.pkbs else None if swap_client.debug_ui: - data['xmr_b_half_privatekey'] = getChainBSplitKey(swap_client, bid, xmr_swap, offer) + try: + data['xmr_b_half_privatekey'] = getChainBSplitKey(swap_client, bid, xmr_swap, offer) + except Exception as e: + swap_client.log.error(traceback.format_exc()) if show_lock_transfers: if xmr_swap.pkbs: