mirror of
https://github.com/basicswap/basicswap.git
synced 2025-01-22 02:24:31 +00:00
Replaced watched_outputs tuple with class.
This commit is contained in:
parent
2d4131d4ee
commit
9b4a0dd276
3 changed files with 50 additions and 30 deletions
|
@ -348,6 +348,15 @@ def replaceAddrPrefix(addr, coin_type, chain_name, addr_type='pubkey_address'):
|
||||||
return encodeAddress(bytes((chainparams[coin_type][chain_name][addr_type],)) + decodeAddress(addr)[1:])
|
return encodeAddress(bytes((chainparams[coin_type][chain_name][addr_type],)) + decodeAddress(addr)[1:])
|
||||||
|
|
||||||
|
|
||||||
|
class WatchedOutput():
|
||||||
|
def __init__(self, bid_id, txid_hex, vout, tx_type, swap_type):
|
||||||
|
self.bid_id = bid_id
|
||||||
|
self.txid_hex = txid_hex
|
||||||
|
self.vout = vout
|
||||||
|
self.tx_type = tx_type
|
||||||
|
self.swap_type = swap_type
|
||||||
|
|
||||||
|
|
||||||
class BasicSwap(BaseApp):
|
class BasicSwap(BaseApp):
|
||||||
def __init__(self, fp, data_dir, settings, chain, log_name='BasicSwap'):
|
def __init__(self, fp, data_dir, settings, chain, log_name='BasicSwap'):
|
||||||
super().__init__(fp, data_dir, settings, chain, log_name)
|
super().__init__(fp, data_dir, settings, chain, log_name)
|
||||||
|
@ -674,6 +683,7 @@ class BasicSwap(BaseApp):
|
||||||
if bid.participate_tx and bid.participate_tx.txid:
|
if bid.participate_tx and bid.participate_tx.txid:
|
||||||
self.addWatchedOutput(coin_to, bid.bid_id, bid.participate_tx.txid.hex(), bid.participate_tx.vout, BidStates.SWAP_PARTICIPATING)
|
self.addWatchedOutput(coin_to, bid.bid_id, bid.participate_tx.txid.hex(), bid.participate_tx.vout, BidStates.SWAP_PARTICIPATING)
|
||||||
|
|
||||||
|
# TODO: watch for xmr bid outputs
|
||||||
if self.coin_clients[coin_from]['last_height_checked'] < 1:
|
if self.coin_clients[coin_from]['last_height_checked'] < 1:
|
||||||
if bid.initiate_tx and bid.initiate_tx.chain_height:
|
if bid.initiate_tx and bid.initiate_tx.chain_height:
|
||||||
self.coin_clients[coin_from]['last_height_checked'] = bid.initiate_tx.chain_height
|
self.coin_clients[coin_from]['last_height_checked'] = bid.initiate_tx.chain_height
|
||||||
|
@ -685,6 +695,7 @@ class BasicSwap(BaseApp):
|
||||||
|
|
||||||
def deactivateBid(self, offer, bid):
|
def deactivateBid(self, offer, bid):
|
||||||
# Remove from in progress
|
# Remove from in progress
|
||||||
|
self.log.debug('Removing bid from in-progress: %s', bid.bid_id.hex())
|
||||||
self.swaps_in_progress.pop(bid.bid_id, None)
|
self.swaps_in_progress.pop(bid.bid_id, None)
|
||||||
|
|
||||||
# Remove any watched outputs
|
# Remove any watched outputs
|
||||||
|
@ -693,13 +704,15 @@ class BasicSwap(BaseApp):
|
||||||
|
|
||||||
if bid.state == BidStates.BID_ABANDONED or bid.state == BidStates.SWAP_COMPLETED:
|
if bid.state == BidStates.BID_ABANDONED or bid.state == BidStates.SWAP_COMPLETED:
|
||||||
# Return unused addrs to pool
|
# Return unused addrs to pool
|
||||||
if bid.getITxState() != TxStates.TX_REDEEMED:
|
itx_state = bid.getITxState()
|
||||||
|
ptx_state = bid.getPTxState()
|
||||||
|
if itx_state is not None and itx_state != TxStates.TX_REDEEMED:
|
||||||
self.returnAddressToPool(bid.bid_id, TxTypes.ITX_REDEEM)
|
self.returnAddressToPool(bid.bid_id, TxTypes.ITX_REDEEM)
|
||||||
if bid.getITxState() != TxStates.TX_REFUNDED:
|
if itx_state is not None and itx_state != TxStates.TX_REFUNDED:
|
||||||
self.returnAddressToPool(bid.bid_id, TxTypes.ITX_REFUND)
|
self.returnAddressToPool(bid.bid_id, TxTypes.ITX_REFUND)
|
||||||
if bid.getPTxState() != TxStates.TX_REDEEMED:
|
if ptx_state is not None and ptx_state != TxStates.TX_REDEEMED:
|
||||||
self.returnAddressToPool(bid.bid_id, TxTypes.PTX_REDEEM)
|
self.returnAddressToPool(bid.bid_id, TxTypes.PTX_REDEEM)
|
||||||
if bid.getPTxState() != TxStates.TX_REFUNDED:
|
if ptx_state is not None and ptx_state != TxStates.TX_REFUNDED:
|
||||||
self.returnAddressToPool(bid.bid_id, TxTypes.PTX_REFUND)
|
self.returnAddressToPool(bid.bid_id, TxTypes.PTX_REFUND)
|
||||||
|
|
||||||
def loadFromDB(self):
|
def loadFromDB(self):
|
||||||
|
@ -2636,9 +2649,9 @@ class BasicSwap(BaseApp):
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def addWatchedOutput(self, coin_type, bid_id, txid_hex, vout, tx_type):
|
def addWatchedOutput(self, coin_type, bid_id, txid_hex, vout, tx_type, swap_type=None):
|
||||||
self.log.debug('Adding watched output %s bid %s tx %s type %s', coin_type, bid_id.hex(), txid_hex, tx_type)
|
self.log.debug('Adding watched output %s bid %s tx %s type %s', coin_type, bid_id.hex(), txid_hex, tx_type)
|
||||||
self.coin_clients[coin_type]['watched_outputs'].append((bid_id, txid_hex, vout, tx_type))
|
self.coin_clients[coin_type]['watched_outputs'].append(WatchedOutput(bid_id, txid_hex, vout, tx_type, swap_type))
|
||||||
|
|
||||||
def removeWatchedOutput(self, coin_type, bid_id, txid_hex):
|
def removeWatchedOutput(self, coin_type, bid_id, txid_hex):
|
||||||
# Remove all for bid if txid is None
|
# Remove all for bid if txid is None
|
||||||
|
@ -2646,9 +2659,9 @@ class BasicSwap(BaseApp):
|
||||||
old_len = len(self.coin_clients[coin_type]['watched_outputs'])
|
old_len = len(self.coin_clients[coin_type]['watched_outputs'])
|
||||||
for i in range(old_len - 1, -1, -1):
|
for i in range(old_len - 1, -1, -1):
|
||||||
wo = self.coin_clients[coin_type]['watched_outputs'][i]
|
wo = self.coin_clients[coin_type]['watched_outputs'][i]
|
||||||
if wo[0] == bid_id and (txid_hex is None or wo[1] == txid_hex):
|
if wo.bid_id == bid_id and (txid_hex is None or wo.txid_hex == txid_hex):
|
||||||
del self.coin_clients[coin_type]['watched_outputs'][i]
|
del self.coin_clients[coin_type]['watched_outputs'][i]
|
||||||
self.log.debug('Removed watched output %s %s %s', str(coin_type), bid_id.hex(), wo[1])
|
self.log.debug('Removed watched output %s %s %s', str(coin_type), bid_id.hex(), wo.txid_hex)
|
||||||
|
|
||||||
def initiateTxnSpent(self, bid_id, spend_txid, spend_n, spend_txn):
|
def initiateTxnSpent(self, bid_id, spend_txid, spend_n, spend_txn):
|
||||||
self.log.debug('Bid %s initiate txn spent by %s %d', bid_id.hex(), spend_txid, spend_n)
|
self.log.debug('Bid %s initiate txn spent by %s %d', bid_id.hex(), spend_txid, spend_n)
|
||||||
|
@ -2716,28 +2729,36 @@ class BasicSwap(BaseApp):
|
||||||
self.removeWatchedOutput(coin_to, bid_id, bid.participate_tx.txid.hex())
|
self.removeWatchedOutput(coin_to, bid_id, bid.participate_tx.txid.hex())
|
||||||
self.saveBid(bid_id, bid)
|
self.saveBid(bid_id, bid)
|
||||||
|
|
||||||
|
def processSpentOutput(self, coin_type, watched_output, spend_txid_hex, spend_n, spend_txn):
|
||||||
|
if watched_output.swap_type == SwapTypes.XMR_SWAP:
|
||||||
|
|
||||||
|
self.removeWatchedOutput(coin_type, watched_output.bid_id, watched_output.txid_hex)
|
||||||
|
return
|
||||||
|
|
||||||
|
if watched_output.tx_type == BidStates.SWAP_PARTICIPATING:
|
||||||
|
self.participateTxnSpent(watched_output.bid_id, spend_txid_hex, spend_n, spend_txn)
|
||||||
|
else:
|
||||||
|
self.initiateTxnSpent(watched_output.bid_id, spend_txid_hex, spend_n, spend_txn)
|
||||||
|
|
||||||
def checkForSpends(self, coin_type, c):
|
def checkForSpends(self, coin_type, c):
|
||||||
# assert(self.mxDB.locked()) self.log.debug('checkForSpends %s', coin_type)
|
# assert(self.mxDB.locked()) self.log.debug('checkForSpends %s', coin_type)
|
||||||
|
self.log.debug('checkForSpends %s', coin_type)
|
||||||
|
|
||||||
if coin_type == Coins.PART:
|
if coin_type == Coins.PART:
|
||||||
# TODO: batch getspentinfo
|
# TODO: batch getspentinfo
|
||||||
for o in c['watched_outputs']:
|
for o in c['watched_outputs']:
|
||||||
found_spend = None
|
found_spend = None
|
||||||
try:
|
try:
|
||||||
found_spend = self.callcoinrpc(Coins.PART, 'getspentinfo', [{'txid': o[1], 'index': o[2]}])
|
found_spend = self.callcoinrpc(Coins.PART, 'getspentinfo', [{'txid': o.txid_hex, 'index': o.vout}])
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
if 'Unable to get spent info' not in str(ex):
|
if 'Unable to get spent info' not in str(ex):
|
||||||
self.log.warning('getspentinfo %s', str(ex))
|
self.log.warning('getspentinfo %s', str(ex))
|
||||||
if found_spend is not None:
|
if found_spend is not None:
|
||||||
self.log.debug('Found spend in spentindex %s %d in %s %d', o[1], o[2], found_spend['txid'], found_spend['index'])
|
self.log.debug('Found spend in spentindex %s %d in %s %d', o.txid_hex, o.vout, found_spend['txid'], found_spend['index'])
|
||||||
bid_id = o[0]
|
|
||||||
spend_txid = found_spend['txid']
|
spend_txid = found_spend['txid']
|
||||||
spend_n = found_spend['index']
|
spend_n = found_spend['index']
|
||||||
spend_txn = self.callcoinrpc(Coins.PART, 'getrawtransaction', [spend_txid, True])
|
spend_txn = self.callcoinrpc(Coins.PART, 'getrawtransaction', [spend_txid, True])
|
||||||
if o[3] == BidStates.SWAP_PARTICIPATING:
|
self.processSpentOutput(coin_type, o, spend_txid, spend_n, spend_txn)
|
||||||
self.participateTxnSpent(bid_id, spend_txid, spend_n, spend_txn)
|
|
||||||
else:
|
|
||||||
self.initiateTxnSpent(bid_id, spend_txid, spend_n, spend_txn)
|
|
||||||
else:
|
else:
|
||||||
chain_blocks = self.callcoinrpc(coin_type, 'getblockchaininfo')['blocks']
|
chain_blocks = self.callcoinrpc(coin_type, 'getblockchaininfo')['blocks']
|
||||||
last_height_checked = c['last_height_checked']
|
last_height_checked = c['last_height_checked']
|
||||||
|
@ -2752,13 +2773,9 @@ class BasicSwap(BaseApp):
|
||||||
inp_txid = inp.get('txid', None)
|
inp_txid = inp.get('txid', None)
|
||||||
if inp_txid is None: # Coinbase
|
if inp_txid is None: # Coinbase
|
||||||
continue
|
continue
|
||||||
if inp_txid == o[1] and inp['vout'] == o[2]:
|
if inp_txid == o.txid_hex and inp['vout'] == o.vout:
|
||||||
self.log.debug('Found spend from search %s %d in %s %d', o[1], o[2], tx['txid'], i)
|
self.log.debug('Found spend from search %s %d in %s %d', o.txid_hex, o.vout, tx['txid'], i)
|
||||||
bid_id = o[0]
|
self.processSpentOutput(coin_type, o, tx['txid'], i, tx)
|
||||||
if o[3] == BidStates.SWAP_PARTICIPATING:
|
|
||||||
self.participateTxnSpent(bid_id, tx['txid'], i, tx)
|
|
||||||
else:
|
|
||||||
self.initiateTxnSpent(bid_id, tx['txid'], i, tx)
|
|
||||||
last_height_checked += 1
|
last_height_checked += 1
|
||||||
if c['last_height_checked'] != last_height_checked:
|
if c['last_height_checked'] != last_height_checked:
|
||||||
c['last_height_checked'] = last_height_checked
|
c['last_height_checked'] = last_height_checked
|
||||||
|
@ -3306,7 +3323,7 @@ class BasicSwap(BaseApp):
|
||||||
xmr_swap.al_lock_refund_tx_sig = msg_data.al_lock_refund_tx_sig
|
xmr_swap.al_lock_refund_tx_sig = msg_data.al_lock_refund_tx_sig
|
||||||
|
|
||||||
check_a_lock_tx_inputs = True
|
check_a_lock_tx_inputs = True
|
||||||
xmr_swap.a_lock_tx_id, lock_tx_vout = ci_from.verifyLockTx(
|
xmr_swap.a_lock_tx_id, xmr_swap.a_lock_tx_vout = ci_from.verifyLockTx(
|
||||||
xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script,
|
xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script,
|
||||||
bid.amount,
|
bid.amount,
|
||||||
xmr_swap.sh,
|
xmr_swap.sh,
|
||||||
|
@ -3317,9 +3334,11 @@ class BasicSwap(BaseApp):
|
||||||
)
|
)
|
||||||
a_lock_tx_dest = ci_from.getScriptDest(xmr_swap.a_lock_tx_script)
|
a_lock_tx_dest = ci_from.getScriptDest(xmr_swap.a_lock_tx_script)
|
||||||
|
|
||||||
|
self.addWatchedOutput(coin_from, bid.bid_id, xmr_swap.a_lock_tx_id, xmr_swap.a_lock_tx_vout, TxTypes.XMR_SWAP_A_LOCK, SwapTypes.XMR_SWAP)
|
||||||
|
|
||||||
lock_refund_tx_id, xmr_swap.a_swap_refund_value = ci_from.verifyLockRefundTx(
|
lock_refund_tx_id, xmr_swap.a_swap_refund_value = ci_from.verifyLockRefundTx(
|
||||||
xmr_swap.a_lock_refund_tx, xmr_swap.a_lock_refund_tx_script,
|
xmr_swap.a_lock_refund_tx, xmr_swap.a_lock_refund_tx_script,
|
||||||
xmr_swap.a_lock_tx_id, lock_tx_vout, xmr_offer.lock_time_1, xmr_swap.a_lock_tx_script,
|
xmr_swap.a_lock_tx_id, xmr_swap.a_lock_tx_vout, xmr_offer.lock_time_1, xmr_swap.a_lock_tx_script,
|
||||||
xmr_swap.pkarl, xmr_swap.pkarf,
|
xmr_swap.pkarl, xmr_swap.pkarf,
|
||||||
xmr_offer.lock_time_2,
|
xmr_offer.lock_time_2,
|
||||||
xmr_swap.pkaf,
|
xmr_swap.pkaf,
|
||||||
|
@ -3889,16 +3908,15 @@ class BasicSwap(BaseApp):
|
||||||
for bid_id, v in self.swaps_in_progress.items():
|
for bid_id, v in self.swaps_in_progress.items():
|
||||||
try:
|
try:
|
||||||
if self.checkBidState(bid_id, v[0], v[1]) is True:
|
if self.checkBidState(bid_id, v[0], v[1]) is True:
|
||||||
to_remove.append(bid_id)
|
to_remove.append((bid_id, v[0], v[1]))
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
self.log.error('checkBidState %s %s', bid_id.hex(), str(ex))
|
self.log.error('checkBidState %s %s', bid_id.hex(), str(ex))
|
||||||
if self.debug:
|
if self.debug:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
self.setBidError(bid_id, v[0], str(ex))
|
self.setBidError(bid_id, v[0], str(ex))
|
||||||
|
|
||||||
for bid_id in to_remove:
|
for bid_id, bid, offer in to_remove:
|
||||||
self.log.debug('Removing bid from in-progress: %s', bid_id.hex())
|
self.deactivateBid(offer, bid)
|
||||||
del self.swaps_in_progress[bid_id]
|
|
||||||
self._last_checked_progress = now
|
self._last_checked_progress = now
|
||||||
|
|
||||||
if now - self._last_checked_watched >= self.check_watched_seconds:
|
if now - self._last_checked_watched >= self.check_watched_seconds:
|
||||||
|
@ -4136,7 +4154,7 @@ class BasicSwap(BaseApp):
|
||||||
if self.coin_clients[c]['connection_type'] == 'rpc':
|
if self.coin_clients[c]['connection_type'] == 'rpc':
|
||||||
rv_heights.append((c, v['last_height_checked']))
|
rv_heights.append((c, v['last_height_checked']))
|
||||||
for o in v['watched_outputs']:
|
for o in v['watched_outputs']:
|
||||||
rv.append((c, o[0], o[1], o[2], o[3]))
|
rv.append((c, o.bid_id, o.txid_hex, o.vout, o.tx_type))
|
||||||
return (rv, rv_heights)
|
return (rv, rv_heights)
|
||||||
finally:
|
finally:
|
||||||
self.mxDB.release()
|
self.mxDB.release()
|
||||||
|
|
|
@ -274,6 +274,8 @@ class XmrSwap(Base):
|
||||||
|
|
||||||
a_lock_tx = sa.Column(sa.LargeBinary)
|
a_lock_tx = sa.Column(sa.LargeBinary)
|
||||||
a_lock_tx_script = sa.Column(sa.LargeBinary)
|
a_lock_tx_script = sa.Column(sa.LargeBinary)
|
||||||
|
a_lock_tx_id = sa.Column(sa.LargeBinary)
|
||||||
|
a_lock_tx_vout = sa.Column(sa.Integer)
|
||||||
|
|
||||||
a_lock_refund_tx = sa.Column(sa.LargeBinary)
|
a_lock_refund_tx = sa.Column(sa.LargeBinary)
|
||||||
a_lock_refund_tx_script = sa.Column(sa.LargeBinary)
|
a_lock_refund_tx_script = sa.Column(sa.LargeBinary)
|
||||||
|
|
|
@ -569,7 +569,7 @@ class Test(unittest.TestCase):
|
||||||
end_xmr = float(js_0_end['6']['balance']) + float(js_0_end['6']['unconfirmed'])
|
end_xmr = float(js_0_end['6']['balance']) + float(js_0_end['6']['unconfirmed'])
|
||||||
assert(end_xmr > 10.9 and end_xmr < 11.0)
|
assert(end_xmr > 10.9 and end_xmr < 11.0)
|
||||||
|
|
||||||
self.delay_for(600)
|
self.delay_for(600) # [rm]
|
||||||
|
|
||||||
def test_02_leader_recover_a_lock_tx(self):
|
def test_02_leader_recover_a_lock_tx(self):
|
||||||
logging.info('---------- Test PART to XMR leader recovers coin a lock tx')
|
logging.info('---------- Test PART to XMR leader recovers coin a lock tx')
|
||||||
|
|
Loading…
Reference in a new issue