diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 94aa67c..6e519b4 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -122,7 +122,9 @@ from .basicswap_util import ( getOfferProofOfFundsHash, getLastBidState, isActiveBidState) -from .protocols.xmr_swap_1 import recoverNoScriptTxnWithKey +from .protocols.xmr_swap_1 import ( + addLockRefundSigs, + recoverNoScriptTxnWithKey) non_script_type_coins = (Coins.XMR, Coins.PART_ANON) @@ -2965,7 +2967,6 @@ class BasicSwap(BaseApp): self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_A_SEEN, '', session) block_header = ci_from.getBlockHeaderFromHeight(lock_tx_chain_info['height']) - bid.xmr_a_lock_tx.block_hash = bytes.fromhex(block_header['hash']) bid.xmr_a_lock_tx.block_height = block_header['height'] bid.xmr_a_lock_tx.block_time = block_header['time'] # Or median_time? @@ -3065,6 +3066,21 @@ class BasicSwap(BaseApp): bid.setState(BidStates.SWAP_COMPLETED) self.saveBidInSession(bid_id, bid, session, xmr_swap) session.commit() + elif state == BidStates.XMR_SWAP_SCRIPT_TX_PREREFUND: + if TxTypes.XMR_SWAP_A_LOCK_REFUND in bid.txns: + refund_tx = bid.txns[TxTypes.XMR_SWAP_A_LOCK_REFUND] + if refund_tx.block_time is None: + a_lock_refund_tx_dest = ci_from.getScriptDest(xmr_swap.a_lock_refund_tx_script) + p2wsh_addr = ci_from.encode_p2wsh(a_lock_refund_tx_dest) + lock_refund_tx_chain_info = ci_from.getLockTxHeight(refund_tx.txid, p2wsh_addr, 0, bid.chain_a_height_start) + + block_header = ci_from.getBlockHeaderFromHeight(lock_refund_tx_chain_info['height']) + refund_tx.block_hash = bytes.fromhex(block_header['hash']) + refund_tx.block_height = block_header['height'] + refund_tx.block_time = block_header['time'] # Or median_time? + + self.saveBidInSession(bid_id, bid, session, xmr_swap) + session.commit() except Exception as ex: raise ex @@ -4269,7 +4285,7 @@ class BasicSwap(BaseApp): prevout_amount = ci_from.getLockTxSwapOutputValue(bid, xmr_swap) xmr_swap.af_lock_refund_tx_sig = ci_from.signTx(kaf, xmr_swap.a_lock_refund_tx, 0, xmr_swap.a_lock_tx_script, prevout_amount) - self.addLockRefundSigs(xmr_swap, ci_from) + addLockRefundSigs(self, xmr_swap, ci_from) msg_buf = XmrBidLockTxSigsMessage( bid_msg_id=bid_id, @@ -4679,7 +4695,7 @@ class BasicSwap(BaseApp): v = ci_from.verifyTxSig(xmr_swap.a_lock_refund_spend_tx, xmr_swap.af_lock_refund_spend_tx_sig, xmr_swap.pkaf, 0, xmr_swap.a_lock_refund_tx_script, prevout_amount) ensure(v, 'Invalid signature for lock refund spend txn') - self.addLockRefundSigs(xmr_swap, ci_from) + addLockRefundSigs(self, xmr_swap, ci_from) delay = random.randrange(self.min_delay_event, self.max_delay_event) self.log.info('Sending coin A lock tx for xmr bid %s in %d seconds', bid_id.hex(), delay) @@ -5527,19 +5543,6 @@ class BasicSwap(BaseApp): session.remove() self.mxDB.release() - def addLockRefundSigs(self, xmr_swap, ci): - self.log.debug('Setting lock refund tx sigs') - witness_stack = [ - b'', - xmr_swap.al_lock_refund_tx_sig, - xmr_swap.af_lock_refund_tx_sig, - xmr_swap.a_lock_tx_script, - ] - - signed_tx = ci.setTxSignature(xmr_swap.a_lock_refund_tx, witness_stack) - ensure(signed_tx, 'setTxSignature failed') - xmr_swap.a_lock_refund_tx = signed_tx - def createCoinALockRefundSwipeTx(self, ci, bid, offer, xmr_swap, xmr_offer): self.log.debug('Creating %s lock refund swipe tx', ci.coin_name()) diff --git a/basicswap/protocols/xmr_swap_1.py b/basicswap/protocols/xmr_swap_1.py index a248c93..ebdf8a4 100644 --- a/basicswap/protocols/xmr_swap_1.py +++ b/basicswap/protocols/xmr_swap_1.py @@ -18,6 +18,20 @@ from basicswap.basicswap_util import ( ) +def addLockRefundSigs(self, xmr_swap, ci): + self.log.debug('Setting lock refund tx sigs') + witness_stack = [ + b'', + xmr_swap.al_lock_refund_tx_sig, + xmr_swap.af_lock_refund_tx_sig, + xmr_swap.a_lock_tx_script, + ] + + signed_tx = ci.setTxSignature(xmr_swap.a_lock_refund_tx, witness_stack) + ensure(signed_tx, 'setTxSignature failed') + xmr_swap.a_lock_refund_tx = signed_tx + + def recoverNoScriptTxnWithKey(self, bid_id, encoded_key): # Manually recover txn if other key is known session = scoped_session(self.session_factory) diff --git a/basicswap/templates/bid_xmr.html b/basicswap/templates/bid_xmr.html index 6cc55d8..040c1b5 100644 --- a/basicswap/templates/bid_xmr.html +++ b/basicswap/templates/bid_xmr.html @@ -28,6 +28,9 @@ Received{{ data.was_received }} {% if data.coin_a_lock_refund_tx_est_final != 'None' %} {{ data.ticker_from }} lock refund tx valid at{{ data.coin_a_lock_refund_tx_est_final | formatts }} +{% if data.coin_a_lock_refund_swipe_tx_est_final != 'None' %} +{{ data.ticker_from }} lock refund tx swipeable at{{ data.coin_a_lock_refund_swipe_tx_est_final | formatts }} +{% endif %} {{ data.ticker_from }} chain median time{{ data.coin_a_last_median_time | formatts }} {% endif %} diff --git a/basicswap/ui.py b/basicswap/ui.py index 196938d..89c5b03 100644 --- a/basicswap/ui.py +++ b/basicswap/ui.py @@ -304,13 +304,22 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b if offer.swap_type == SwapTypes.XMR_SWAP: data['coin_a_lock_refund_tx_est_final'] = 'None' - if bid.xmr_a_lock_tx and bid.xmr_a_lock_tx.block_time: - if offer.lock_type == TxLockTypes.SEQUENCE_LOCK_TIME: + data['coin_a_lock_refund_swipe_tx_est_final'] = 'None' + + if offer.lock_type == TxLockTypes.SEQUENCE_LOCK_TIME: + if bid.xmr_a_lock_tx and bid.xmr_a_lock_tx.block_time: raw_sequence = ci_from.getExpectedSequence(offer.lock_type, offer.lock_value) seconds_locked = ci_from.decodeSequence(raw_sequence) data['coin_a_lock_refund_tx_est_final'] = bid.xmr_a_lock_tx.block_time + seconds_locked data['coin_a_last_median_time'] = swap_client.coin_clients[offer.coin_from]['chain_median_time'] + if TxTypes.XMR_SWAP_A_LOCK_REFUND in bid.txns: + refund_tx = bid.txns[TxTypes.XMR_SWAP_A_LOCK_REFUND] + if refund_tx.block_time is not None: + raw_sequence = ci_from.getExpectedSequence(offer.lock_type, offer.lock_value) + seconds_locked = ci_from.decodeSequence(raw_sequence) + data['coin_a_lock_refund_swipe_tx_est_final'] = refund_tx.block_time + seconds_locked + if view_tx_ind: data['view_tx_ind'] = view_tx_ind view_tx_id = bytes.fromhex(view_tx_ind)