Handle lost noscript lock transaction.
This commit is contained in:
parent
6860279faa
commit
2a9e423eaa
@ -1,3 +1,3 @@
|
||||
name = "basicswap"
|
||||
|
||||
__version__ = "0.11.53"
|
||||
__version__ = "0.11.54"
|
||||
|
@ -3065,6 +3065,33 @@ class BasicSwap(BaseApp):
|
||||
return sum_unspent
|
||||
return None
|
||||
|
||||
def findTxB(self, ci_to, xmr_swap, bid, session) -> bool:
|
||||
bid_changed = False
|
||||
# Have to use findTxB instead of relying on the first seen height to detect chain reorgs
|
||||
found_tx = ci_to.findTxB(xmr_swap.vkbv, xmr_swap.pkbs, bid.amount_to, ci_to.blocks_confirmed, bid.chain_b_height_start, bid.was_sent)
|
||||
|
||||
if isinstance(found_tx, int) and found_tx == -1:
|
||||
if self.countBidEvents(bid, EventLogTypes.LOCK_TX_B_INVALID, session) < 1:
|
||||
self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_B_INVALID, 'Detected invalid lock tx B', session)
|
||||
bid_changed = True
|
||||
elif found_tx is not None:
|
||||
if bid.xmr_b_lock_tx is None or not bid.xmr_b_lock_tx.chain_height:
|
||||
self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_B_SEEN, '', session)
|
||||
if bid.xmr_b_lock_tx is None:
|
||||
self.log.debug('Found {} lock tx in chain'.format(ci_to.coin_name()))
|
||||
xmr_swap.b_lock_tx_id = bytes.fromhex(found_tx['txid'])
|
||||
bid.xmr_b_lock_tx = SwapTx(
|
||||
bid_id=bid.bid_id,
|
||||
tx_type=TxTypes.XMR_SWAP_B_LOCK,
|
||||
txid=xmr_swap.b_lock_tx_id,
|
||||
chain_height=found_tx['height'],
|
||||
)
|
||||
bid_changed = True
|
||||
else:
|
||||
bid.xmr_b_lock_tx.chain_height = found_tx['height']
|
||||
bid_changed = True
|
||||
return bid_changed
|
||||
|
||||
def checkXmrBidState(self, bid_id, bid, offer):
|
||||
rv = False
|
||||
|
||||
@ -3176,6 +3203,13 @@ class BasicSwap(BaseApp):
|
||||
rv = True # Remove from swaps_in_progress
|
||||
elif state == BidStates.XMR_SWAP_FAILED_SWIPED:
|
||||
rv = True # Remove from swaps_in_progress
|
||||
elif state == BidStates.XMR_SWAP_FAILED:
|
||||
if bid.was_sent and bid.xmr_b_lock_tx:
|
||||
if self.countQueuedActions(session, bid_id, ActionTypes.RECOVER_XMR_SWAP_LOCK_TX_B) < 1:
|
||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||
self.log.info('Recovering xmr swap chain B lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createActionInSession(delay, ActionTypes.RECOVER_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
session.commit()
|
||||
elif state == BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX:
|
||||
if bid.xmr_a_lock_tx is None:
|
||||
return rv
|
||||
@ -3217,33 +3251,7 @@ class BasicSwap(BaseApp):
|
||||
session.commit()
|
||||
|
||||
elif state == BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED:
|
||||
if bid.was_sent and bid.xmr_b_lock_tx is None:
|
||||
return rv
|
||||
|
||||
bid_changed = False
|
||||
# Have to use findTxB instead of relying on the first seen height to detect chain reorgs
|
||||
found_tx = ci_to.findTxB(xmr_swap.vkbv, xmr_swap.pkbs, bid.amount_to, ci_to.blocks_confirmed, bid.chain_b_height_start, bid.was_sent)
|
||||
|
||||
if isinstance(found_tx, int) and found_tx == -1:
|
||||
if self.countBidEvents(bid, EventLogTypes.LOCK_TX_B_INVALID, session) < 1:
|
||||
self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_B_INVALID, 'Detected invalid lock tx B', session)
|
||||
bid_changed = True
|
||||
elif found_tx is not None:
|
||||
if bid.xmr_b_lock_tx is None or not bid.xmr_b_lock_tx.chain_height:
|
||||
self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_B_SEEN, '', session)
|
||||
if bid.xmr_b_lock_tx is None:
|
||||
self.log.debug('Found {} lock tx in chain'.format(ci_to.coin_name()))
|
||||
xmr_swap.b_lock_tx_id = bytes.fromhex(found_tx['txid'])
|
||||
bid.xmr_b_lock_tx = SwapTx(
|
||||
bid_id=bid_id,
|
||||
tx_type=TxTypes.XMR_SWAP_B_LOCK,
|
||||
txid=xmr_swap.b_lock_tx_id,
|
||||
chain_height=found_tx['height'],
|
||||
)
|
||||
bid_changed = True
|
||||
else:
|
||||
bid.xmr_b_lock_tx.chain_height = found_tx['height']
|
||||
bid_changed = True
|
||||
bid_changed = self.findTxB(ci_to, xmr_swap, bid, session)
|
||||
|
||||
if bid.xmr_b_lock_tx and bid.xmr_b_lock_tx.chain_height is not None and bid.xmr_b_lock_tx.chain_height > 0:
|
||||
chain_height = ci_to.getChainHeight()
|
||||
@ -4715,6 +4723,14 @@ class BasicSwap(BaseApp):
|
||||
ci_from = self.ci(Coins(offer.coin_from))
|
||||
ci_to = self.ci(Coins(offer.coin_to))
|
||||
|
||||
if self.findTxB(ci_to, xmr_swap, bid, session) is True:
|
||||
self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer)
|
||||
return
|
||||
|
||||
if bid.xmr_b_lock_tx:
|
||||
self.log.warning('Coin B lock tx {} exists for xmr bid {}'.format(bid.xmr_b_lock_tx.b_lock_tx_id, bid_id.hex()))
|
||||
return
|
||||
|
||||
if bid.debug_ind == DebugTypes.BID_STOP_AFTER_COIN_A_LOCK:
|
||||
self.log.debug('XMR bid %s: Stalling bid for testing: %d.', bid_id.hex(), bid.debug_ind)
|
||||
bid.setState(BidStates.BID_STALLED_FOR_TEST)
|
||||
@ -4723,7 +4739,7 @@ class BasicSwap(BaseApp):
|
||||
return
|
||||
|
||||
unlock_time = 0
|
||||
if bid.debug_ind == DebugTypes.CREATE_INVALID_COIN_B_LOCK:
|
||||
if bid.debug_ind in (DebugTypes.CREATE_INVALID_COIN_B_LOCK, DebugTypes.B_LOCK_TX_MISSED_SEND):
|
||||
bid.amount_to -= int(bid.amount_to * 0.1)
|
||||
self.log.debug('XMR bid %s: Debug %d - Reducing lock b txn amount by 10%% to %s.', bid_id.hex(), bid.debug_ind, ci_to.format_amount(bid.amount_to))
|
||||
self.logBidEvent(bid.bid_id, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
|
||||
@ -4731,8 +4747,13 @@ class BasicSwap(BaseApp):
|
||||
unlock_time = 10000
|
||||
self.log.debug('XMR bid %s: Debug %d - Sending locked XMR.', bid_id.hex(), bid.debug_ind)
|
||||
self.logBidEvent(bid.bid_id, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
|
||||
|
||||
try:
|
||||
b_lock_tx_id = ci_to.publishBLockTx(xmr_swap.pkbv, xmr_swap.pkbs, bid.amount_to, xmr_offer.b_fee_rate, unlock_time=unlock_time)
|
||||
if bid.debug_ind == DebugTypes.B_LOCK_TX_MISSED_SEND:
|
||||
self.log.debug('XMR bid %s: Debug %d - Losing xmr lock tx %s.', bid_id.hex(), bid.debug_ind, b_lock_tx_id.hex())
|
||||
self.logBidEvent(bid.bid_id, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
|
||||
raise TemporaryError('Fail for debug event')
|
||||
except Exception as ex:
|
||||
if self.debug:
|
||||
self.log.error(traceback.format_exc())
|
||||
|
@ -189,6 +189,7 @@ class DebugTypes(IntEnum):
|
||||
DONT_SPEND_ITX = auto()
|
||||
SKIP_LOCK_TX_REFUND = auto()
|
||||
SEND_LOCKED_XMR = auto()
|
||||
B_LOCK_TX_MISSED_SEND = auto()
|
||||
|
||||
|
||||
def strOfferState(state):
|
||||
@ -322,8 +323,6 @@ def getLockName(lock_type):
|
||||
|
||||
|
||||
def describeEventEntry(event_type, event_msg):
|
||||
if event_type == EventLogTypes.FAILED_TX_B_LOCK_PUBLISH:
|
||||
return 'Failed to publish lock tx B'
|
||||
if event_type == EventLogTypes.FAILED_TX_B_LOCK_PUBLISH:
|
||||
return 'Failed to publish lock tx B'
|
||||
if event_type == EventLogTypes.LOCK_TX_A_PUBLISHED:
|
||||
@ -456,4 +455,6 @@ def isActiveBidState(state):
|
||||
return True
|
||||
if state == BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX:
|
||||
return True
|
||||
if state == BidStates.XMR_SWAP_FAILED:
|
||||
return True
|
||||
return False
|
||||
|
@ -1186,7 +1186,7 @@ class BTCInterface(CoinInterface):
|
||||
|
||||
return True if address_hash == pubkey_hash else False
|
||||
|
||||
def showLockTransfers(self, Kbv, Kbs):
|
||||
def showLockTransfers(self, kbv, Kbs, restore_height):
|
||||
raise ValueError('Unimplemented')
|
||||
|
||||
def getLockTxSwapOutputValue(self, bid, xmr_swap):
|
||||
|
@ -20,12 +20,18 @@ class DASHInterface(BTCInterface):
|
||||
def coin_type():
|
||||
return Coins.DASH
|
||||
|
||||
def __init__(self, coin_settings, network, swap_client=None):
|
||||
super().__init__(coin_settings, network, swap_client)
|
||||
self._wallet_passphrase = ''
|
||||
|
||||
def seedToMnemonic(self, key):
|
||||
return Mnemonic('english').to_mnemonic(key)
|
||||
|
||||
def initialiseWallet(self, key):
|
||||
words = self.seedToMnemonic(key)
|
||||
self.rpc_callback('upgradetohd', [words, ])
|
||||
|
||||
mnemonic_passphrase = ''
|
||||
self.rpc_callback('upgradetohd', [words, mnemonic_passphrase, self._wallet_passphrase])
|
||||
|
||||
def decodeAddress(self, address):
|
||||
return decodeAddress(address)[1:]
|
||||
@ -70,3 +76,12 @@ class DASHInterface(BTCInterface):
|
||||
return {'txid': txid_hex, 'amount': 0, 'height': block_height}
|
||||
|
||||
return None
|
||||
|
||||
def unlockWallet(self, password: str):
|
||||
super().unlockWallet(password)
|
||||
# Store password for initialiseWallet
|
||||
self._wallet_passphrase = password
|
||||
|
||||
def lockWallet(self):
|
||||
super().lockWallet()
|
||||
self._wallet_passphrase = ''
|
||||
|
@ -5,7 +5,6 @@
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
|
||||
@ -100,7 +99,6 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
try:
|
||||
# Can't reopen the same wallet in windows, !is_keys_file_locked()
|
||||
if os.name == 'nt':
|
||||
self.rpc_wallet_cb('close_wallet')
|
||||
except Exception:
|
||||
pass
|
||||
@ -263,6 +261,7 @@ class XMRInterface(CoinInterface):
|
||||
def publishBLockTx(self, Kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
self.rpc_wallet_cb('refresh')
|
||||
|
||||
shared_addr = xmr_util.encode_address(Kbv, Kbs)
|
||||
|
||||
@ -276,8 +275,8 @@ class XMRInterface(CoinInterface):
|
||||
if self._sc.debug:
|
||||
i = 0
|
||||
while not self._sc.delay_event.is_set():
|
||||
params = {'out': True, 'pending': True, 'failed': True, 'pool': True, }
|
||||
rv = self.rpc_wallet_cb('get_transfers', params)
|
||||
gt_params = {'out': True, 'pending': True, 'failed': True, 'pool': True, }
|
||||
rv = self.rpc_wallet_cb('get_transfers', gt_params)
|
||||
self._log.debug('get_transfers {}'.format(dumpj(rv)))
|
||||
if 'pending' not in rv:
|
||||
break
|
||||
@ -292,11 +291,6 @@ class XMRInterface(CoinInterface):
|
||||
Kbv = self.getPubkey(kbv)
|
||||
address_b58 = xmr_util.encode_address(Kbv, Kbs)
|
||||
|
||||
try:
|
||||
self.rpc_wallet_cb('close_wallet')
|
||||
except Exception as e:
|
||||
self._log.warning('close_wallet failed %s', str(e))
|
||||
|
||||
kbv_le = kbv[::-1]
|
||||
params = {
|
||||
'restore_height': restore_height,
|
||||
@ -328,8 +322,12 @@ class XMRInterface(CoinInterface):
|
||||
rv = None
|
||||
if 'transfers' in transfers:
|
||||
for transfer in transfers['transfers']:
|
||||
# unlocked <- wallet->is_transfer_unlocked() checks unlock_time and CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE
|
||||
if not transfer['unlocked']:
|
||||
self._log.warning('Coin b lock txn is locked: {}'.format(transfer['tx_hash']))
|
||||
full_tx = self.rpc_wallet_cb('get_transfer_by_txid', {'txid': transfer['tx_hash']})
|
||||
unlock_time = full_tx['transfer']['unlock_time']
|
||||
if unlock_time != 0:
|
||||
self._log.warning('Coin b lock txn is locked: {}, unlock_time {}'.format(transfer['tx_hash'], unlock_time))
|
||||
rv = -1
|
||||
continue
|
||||
if transfer['amount'] == cb_swap_value:
|
||||
@ -367,11 +365,6 @@ class XMRInterface(CoinInterface):
|
||||
Kbs = self.getPubkey(kbs)
|
||||
address_b58 = xmr_util.encode_address(Kbv, Kbs)
|
||||
|
||||
try:
|
||||
self.rpc_wallet_cb('close_wallet')
|
||||
except Exception as e:
|
||||
self._log.warning('close_wallet failed %s', str(e))
|
||||
|
||||
wallet_filename = address_b58 + '_spend'
|
||||
|
||||
params = {
|
||||
@ -446,16 +439,29 @@ class XMRInterface(CoinInterface):
|
||||
rv = self.rpc_wallet_cb('transfer', params)
|
||||
return rv['tx_hash']
|
||||
|
||||
def showLockTransfers(self, Kbv, Kbs):
|
||||
def showLockTransfers(self, kbv, Kbs, restore_height):
|
||||
with self._mx_wallet:
|
||||
try:
|
||||
Kbv = self.getPubkey(kbv)
|
||||
address_b58 = xmr_util.encode_address(Kbv, Kbs)
|
||||
wallet_file = address_b58 + '_spend'
|
||||
try:
|
||||
self.openWallet(wallet_file)
|
||||
except Exception:
|
||||
wallet_file = address_b58
|
||||
try:
|
||||
self.openWallet(wallet_file)
|
||||
except Exception:
|
||||
self._log.info(f'showLockTransfers trying to create wallet for address {address_b58}.')
|
||||
kbv_le = kbv[::-1]
|
||||
params = {
|
||||
'restore_height': restore_height,
|
||||
'filename': address_b58,
|
||||
'address': address_b58,
|
||||
'viewkey': b2h(kbv_le),
|
||||
}
|
||||
self.createWallet(params)
|
||||
self.openWallet(address_b58)
|
||||
|
||||
self.rpc_wallet_cb('refresh')
|
||||
|
||||
|
@ -168,11 +168,11 @@ def js_offers(self, url_split, post_string, is_json, sent=False):
|
||||
filters['limit'] = int(get_data_entry(post_data, 'limit'))
|
||||
assert (filters['limit'] > 0 and filters['limit'] <= PAGE_LIMIT), 'Invalid limit'
|
||||
|
||||
offers = self.server.swap_client.listOffers(sent, filters)
|
||||
offers = swap_client.listOffers(sent, filters)
|
||||
rv = []
|
||||
for o in offers:
|
||||
ci_from = self.server.swap_client.ci(o.coin_from)
|
||||
ci_to = self.server.swap_client.ci(o.coin_to)
|
||||
ci_from = swap_client.ci(o.coin_from)
|
||||
ci_to = swap_client.ci(o.coin_to)
|
||||
rv.append({
|
||||
'addr_from': o.addr_from,
|
||||
'addr_to': o.addr_to,
|
||||
@ -494,6 +494,10 @@ def js_lock(self, url_split, post_string, is_json):
|
||||
return bytes(json.dumps({'success': True}), 'UTF-8')
|
||||
|
||||
|
||||
def js_404(self, url_split, post_string, is_json):
|
||||
return bytes(json.dumps({'Error': 'path unknown'}), 'UTF-8')
|
||||
|
||||
|
||||
def js_help(self, url_split, post_string, is_json):
|
||||
# TODO: Add details and examples
|
||||
commands = []
|
||||
@ -528,5 +532,5 @@ pages = {
|
||||
|
||||
def js_url_to_function(url_split):
|
||||
if len(url_split) > 2:
|
||||
return pages.get(url_split[2], js_index)
|
||||
return pages.get(url_split[2], js_404)
|
||||
return js_index
|
||||
|
@ -91,6 +91,24 @@ def getChainBSplitKey(swap_client, bid, xmr_swap, offer):
|
||||
return ci_to.encodeKey(swap_client.getPathKey(offer.coin_from, offer.coin_to, bid.created_at, xmr_swap.contract_count, key_type, True if offer.coin_to == Coins.XMR else False))
|
||||
|
||||
|
||||
def getChainBRemoteSplitKey(swap_client, bid, xmr_swap, offer):
|
||||
ci_from = swap_client.ci(offer.coin_from)
|
||||
ci_to = swap_client.ci(offer.coin_to)
|
||||
|
||||
if bid.was_sent:
|
||||
if xmr_swap.a_lock_refund_spend_tx:
|
||||
af_lock_refund_spend_tx_sig = ci_from.extractFollowerSig(xmr_swap.a_lock_refund_spend_tx)
|
||||
kbsl = ci_from.recoverEncKey(xmr_swap.af_lock_refund_spend_tx_esig, af_lock_refund_spend_tx_sig, xmr_swap.pkasl)
|
||||
return ci_to.encodeKey(kbsl)
|
||||
else:
|
||||
if xmr_swap.a_lock_spend_tx:
|
||||
al_lock_spend_tx_sig = ci_from.extractLeaderSig(xmr_swap.a_lock_spend_tx)
|
||||
kbsf = ci_from.recoverEncKey(xmr_swap.al_lock_spend_tx_esig, al_lock_spend_tx_sig, xmr_swap.pkasf)
|
||||
return ci_to.encodeKey(kbsf)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class XmrSwapInterface(ProtocolInterface):
|
||||
swap_type = SwapTypes.XMR_SWAP
|
||||
|
||||
|
@ -349,7 +349,7 @@
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<button name="edit_bid_submit" value="Submit" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md shadow-button focus:ring-0 focus:outline-none">
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#556987" stroke-linejoin="round" ><line x1="2" y1="23" x2="22" y2="23" stroke="#556987"></line> <line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line> <polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon></g></svg> Submit Edit Bid </button>
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#556987" stroke-linejoin="round" ><line x1="2" y1="23" x2="22" y2="23" stroke="#556987"></line> <line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line> <polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon></g></svg> Submit Edit </button>
|
||||
</div>
|
||||
{% else %}
|
||||
{% if data.show_bidder_seq_diagram %}
|
||||
@ -393,7 +393,7 @@
|
||||
{% endif %}
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<button name="edit_bid" type="submit" value="Edit Bid" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md shadow-button focus:ring-0 focus:outline-none">
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#556987" stroke-linejoin="round" ><line x1="2" y1="23" x2="22" y2="23" stroke="#556987"></line> <line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line> <polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon></g></svg> Edit bit </button>
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#556987" stroke-linejoin="round" ><line x1="2" y1="23" x2="22" y2="23" stroke="#556987"></line> <line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line> <polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon></g></svg> Edit bid </button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if data.was_received == 'True' %}
|
||||
|
@ -305,10 +305,16 @@
|
||||
{% endif %}
|
||||
{% if data.xmr_b_half_privatekey %}
|
||||
<tr class="bg-white border-t hover:bg-gray-50">
|
||||
<td class="py-4 px-6 bold">Key Half:</td>
|
||||
<td class="py-4 px-6 bold">Key Half (WARNING key data!):</td>
|
||||
<td class="py-4 monospace">{{ data.xmr_b_half_privatekey }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if data.xmr_b_half_privatekey_remote %}
|
||||
<tr class="bg-white border-t hover:bg-gray-50">
|
||||
<td class="py-4 px-6 bold">Remote Key Half:</td>
|
||||
<td class="py-4 monospace">{{ data.xmr_b_half_privatekey_remote }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@ -503,7 +509,7 @@
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<button name="edit_bid_submit" value="Submit" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md shadow-button focus:ring-0 focus:outline-none">
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#556987" stroke-linejoin="round" ><line x1="2" y1="23" x2="22" y2="23" stroke="#556987"></line> <line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line> <polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon></g></svg> Submit Edit Bid </button>
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#556987" stroke-linejoin="round" ><line x1="2" y1="23" x2="22" y2="23" stroke="#556987"></line> <line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line> <polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon></g></svg> Submit Edit </button>
|
||||
</div>
|
||||
{% else %}
|
||||
{% if data.show_bidder_seq_diagram %}
|
||||
@ -547,7 +553,7 @@
|
||||
{% endif %}
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<button name="edit_bid" type="submit" value="Edit Bid" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md shadow-button focus:ring-0 focus:outline-none">
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#556987" stroke-linejoin="round" ><line x1="2" y1="23" x2="22" y2="23" stroke="#556987"></line> <line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line> <polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon></g></svg> Edit bit </button>
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#556987" stroke-linejoin="round" ><line x1="2" y1="23" x2="22" y2="23" stroke="#556987"></line> <line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line> <polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon></g></svg> Edit bid </button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if data.was_received == 'True' %}
|
||||
|
@ -213,7 +213,16 @@ def parseOfferFormData(swap_client, form_data, page_data, options={}):
|
||||
|
||||
def postNewOfferFromParsed(swap_client, parsed_data):
|
||||
swap_type = SwapTypes.SELLER_FIRST
|
||||
if parsed_data['coin_to'] in (Coins.XMR, Coins.PART_ANON):
|
||||
|
||||
if swap_type in parsed_data:
|
||||
str_swap_type = parsed_data['swap_type'].lower()
|
||||
if str_swap_type == 'seller_first':
|
||||
swap_type = SwapTypes.SELLER_FIRST
|
||||
elif str_swap_type == 'xmr_swap':
|
||||
swap_type = SwapTypes.XMR_SWAP
|
||||
else:
|
||||
raise ValueError('Unknown swap type')
|
||||
elif parsed_data['coin_to'] in (Coins.XMR, Coins.PART_ANON):
|
||||
swap_type = SwapTypes.XMR_SWAP
|
||||
|
||||
if swap_client.coin_clients[parsed_data['coin_from']]['use_csv'] and swap_client.coin_clients[parsed_data['coin_to']]['use_csv']:
|
||||
|
@ -28,7 +28,7 @@ from basicswap.basicswap_util import (
|
||||
getLastBidState,
|
||||
)
|
||||
|
||||
from basicswap.protocols.xmr_swap_1 import getChainBSplitKey
|
||||
from basicswap.protocols.xmr_swap_1 import getChainBSplitKey, getChainBRemoteSplitKey
|
||||
|
||||
PAGE_LIMIT = 50
|
||||
invalid_coins_from = (Coins.XMR, Coins.PART_ANON)
|
||||
@ -302,12 +302,16 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
||||
if swap_client.debug_ui:
|
||||
try:
|
||||
data['xmr_b_half_privatekey'] = getChainBSplitKey(swap_client, bid, xmr_swap, offer)
|
||||
|
||||
remote_split_key = getChainBRemoteSplitKey(swap_client, bid, xmr_swap, offer)
|
||||
if remote_split_key:
|
||||
data['xmr_b_half_privatekey_remote'] = remote_split_key
|
||||
except Exception as e:
|
||||
swap_client.log.error(traceback.format_exc())
|
||||
|
||||
if show_lock_transfers:
|
||||
if xmr_swap.pkbs:
|
||||
data['lock_transfers'] = json.dumps(ci_to.showLockTransfers(xmr_swap.pkbv, xmr_swap.pkbs), indent=4)
|
||||
data['lock_transfers'] = json.dumps(ci_to.showLockTransfers(xmr_swap.vkbv, xmr_swap.pkbs, bid.chain_b_height_start), indent=4)
|
||||
else:
|
||||
data['lock_transfers'] = 'Shared address not yet known.'
|
||||
else:
|
||||
|
@ -3,6 +3,24 @@
|
||||
==============
|
||||
|
||||
|
||||
0.0.54
|
||||
==============
|
||||
|
||||
- If the XMR daemon is busy the wallet can fail a transfer, later sending the tx unknown to bsx.
|
||||
- Check for existing transfers before trying to send the chain b lock tx.
|
||||
- Check for transfers in XMR_SWAP_SCRIPT_COIN_LOCKED state when bid is sent.
|
||||
- Continually try refund noscript lock tx in XMR_SWAP_FAILED state.
|
||||
- showLockTransfers will attempt to create a wallet if none exists.
|
||||
- tests:
|
||||
- Add B_LOCK_TX_MISSED_SEND debug event and test.
|
||||
- Store the Dash wallet password in memory for use in upgradetohd
|
||||
- Remove false positive warning. Check for unlock_time transfer is not unlocked.
|
||||
- ui:
|
||||
- Add 'Remote Key Half' to Show More Info section (with debug_ui on)
|
||||
- api:
|
||||
- An unknown path will return an error instead of the default/index data.
|
||||
|
||||
|
||||
0.0.32
|
||||
==============
|
||||
|
||||
|
@ -1318,6 +1318,26 @@ class Test(BaseTest):
|
||||
assert (txin['txid'] == itx_after['vin'][i]['txid'])
|
||||
assert (txin['vout'] == itx_after['vin'][i]['vout'])
|
||||
|
||||
def test_15_missed_xmr_send(self):
|
||||
logging.info('---------- Test PART to XMR B lock tx is lost')
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
amt_swap = make_int(random.uniform(0.1, 10.0), scale=8, r=1)
|
||||
rate_swap = make_int(random.uniform(2.0, 20.0), scale=12, r=1)
|
||||
offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=28)
|
||||
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[1].getOffer(offer_id)
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
|
||||
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.B_LOCK_TX_MISSED_SEND)
|
||||
swap_clients[0].acceptXmrBid(bid_id)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=1800)
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=1800, sent=True)
|
||||
|
||||
def test_98_withdraw_all(self):
|
||||
logging.info('---------- Test XMR withdrawal all')
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user