Refactor participate_tx
This commit is contained in:
		
							parent
							
								
									4a07c891f6
								
							
						
					
					
						commit
						7ccf191192
					
				@ -11,13 +11,11 @@ import datetime as dt
 | 
			
		||||
import zmq
 | 
			
		||||
import threading
 | 
			
		||||
import traceback
 | 
			
		||||
import struct
 | 
			
		||||
import hashlib
 | 
			
		||||
import subprocess
 | 
			
		||||
import logging
 | 
			
		||||
import sqlalchemy as sa
 | 
			
		||||
from sqlalchemy.orm import sessionmaker, scoped_session
 | 
			
		||||
from sqlalchemy.ext.declarative import declarative_base
 | 
			
		||||
from enum import IntEnum, auto
 | 
			
		||||
 | 
			
		||||
from . import __version__
 | 
			
		||||
@ -504,8 +502,8 @@ class BasicSwap():
 | 
			
		||||
                    offer = session.query(Offer).filter_by(offer_id=bid.offer_id).first()
 | 
			
		||||
                    assert(offer), 'Offer not found'
 | 
			
		||||
 | 
			
		||||
                    bid.initiate_tx = session.query(SwapTx).filter(sa.and_(SwapTx.bid_id == bid_id, SwapTx.tx_type == TxTypes.ITX)).first()
 | 
			
		||||
                    bid.participate_tx = session.query(SwapTx).filter(sa.and_(SwapTx.bid_id == bid_id, SwapTx.tx_type == TxTypes.PTX)).first()
 | 
			
		||||
                    bid.initiate_tx = session.query(SwapTx).filter(sa.and_(SwapTx.bid_id == bid.bid_id, SwapTx.tx_type == TxTypes.ITX)).first()
 | 
			
		||||
                    bid.participate_tx = session.query(SwapTx).filter(sa.and_(SwapTx.bid_id == bid.bid_id, SwapTx.tx_type == TxTypes.PTX)).first()
 | 
			
		||||
 | 
			
		||||
                    self.swaps_in_progress[bid.bid_id] = (bid, offer)
 | 
			
		||||
 | 
			
		||||
@ -513,13 +511,13 @@ class BasicSwap():
 | 
			
		||||
                    coin_to = Coins(offer.coin_to)
 | 
			
		||||
                    if bid.initiate_tx:
 | 
			
		||||
                        self.addWatchedOutput(coin_from, bid.bid_id, bid.initiate_tx.txid.hex(), bid.initiate_tx.vout, BidStates.SWAP_INITIATED)
 | 
			
		||||
                    if bid.participate_txid:
 | 
			
		||||
                        self.addWatchedOutput(coin_to, bid.bid_id, bid.participate_txid.hex(), bid.participate_txn_n, BidStates.SWAP_PARTICIPATING)
 | 
			
		||||
                    if bid.participate_tx:
 | 
			
		||||
                        self.addWatchedOutput(coin_to, bid.bid_id, bid.participate_tx.txid.hex(), bid.participate_tx.vout, BidStates.SWAP_PARTICIPATING)
 | 
			
		||||
 | 
			
		||||
                    if self.coin_clients[coin_from]['last_height_checked'] < 1:
 | 
			
		||||
                        self.coin_clients[coin_from]['last_height_checked'] = bid.initiate_tx.chain_height
 | 
			
		||||
                    if self.coin_clients[coin_to]['last_height_checked'] < 1:
 | 
			
		||||
                        self.coin_clients[coin_to]['last_height_checked'] = bid.participate_txn_height
 | 
			
		||||
                        self.coin_clients[coin_to]['last_height_checked'] = bid.participate_tx.chain_height
 | 
			
		||||
 | 
			
		||||
        finally:
 | 
			
		||||
            session.close()
 | 
			
		||||
@ -1023,7 +1021,6 @@ class BasicSwap():
 | 
			
		||||
 | 
			
		||||
        p2sh = self.callcoinrpc(Coins.PART, 'decodescript', [script.hex()])['p2sh']
 | 
			
		||||
 | 
			
		||||
        #bid.initiate_script = script
 | 
			
		||||
        bid.pkhash_seller = pkhash_refund
 | 
			
		||||
 | 
			
		||||
        txn = self.createInitiateTxn(coin_from, bid_id, bid, script)
 | 
			
		||||
@ -1064,7 +1061,6 @@ class BasicSwap():
 | 
			
		||||
            accept_msg_id = bytes.fromhex(msg_id)
 | 
			
		||||
 | 
			
		||||
            bid.accept_msg_id = accept_msg_id
 | 
			
		||||
            #bid.initiate_txid = bytes.fromhex(txid)
 | 
			
		||||
            bid.setState(BidStates.BID_ACCEPTED)
 | 
			
		||||
 | 
			
		||||
            self.log.info('Sent BID_ACCEPT %s', accept_msg_id.hex())
 | 
			
		||||
@ -1116,9 +1112,9 @@ class BasicSwap():
 | 
			
		||||
                self.returnAddressToPool(bid_id, TxTypes.ITX_REDEEM)
 | 
			
		||||
            if bid.getITxState() != TxStates.TX_REFUNDED:
 | 
			
		||||
                self.returnAddressToPool(bid_id, TxTypes.ITX_REFUND)
 | 
			
		||||
            if bid.participate_txn_state != TxStates.TX_REDEEMED:
 | 
			
		||||
            if bid.getPTxState() != TxStates.TX_REDEEMED:
 | 
			
		||||
                self.returnAddressToPool(bid_id, TxTypes.PTX_REDEEM)
 | 
			
		||||
            if bid.participate_txn_state != TxStates.TX_REFUNDED:
 | 
			
		||||
            if bid.getPTxState() != TxStates.TX_REFUNDED:
 | 
			
		||||
                self.returnAddressToPool(bid_id, TxTypes.PTX_REFUND)
 | 
			
		||||
        finally:
 | 
			
		||||
            session.close()
 | 
			
		||||
@ -1176,7 +1172,7 @@ class BasicSwap():
 | 
			
		||||
        lock_value = offer.lock_value // 2
 | 
			
		||||
        if offer.lock_type < ABS_LOCK_BLOCKS:
 | 
			
		||||
            sequence = getExpectedSequence(offer.lock_type, lock_value, coin_to)
 | 
			
		||||
            bid.participate_script = buildContractScript(sequence, secret_hash, pkhash_seller, pkhash_buyer_refund)
 | 
			
		||||
            participate_script = buildContractScript(sequence, secret_hash, pkhash_seller, pkhash_buyer_refund)
 | 
			
		||||
        else:
 | 
			
		||||
            # Lock from the height or time of the block containing the initiate txn
 | 
			
		||||
            coin_from = Coins(offer.coin_from)
 | 
			
		||||
@ -1207,9 +1203,10 @@ class BasicSwap():
 | 
			
		||||
                self.log.debug('Setting lock value from time of block %s %s', coin_from, initiate_tx_block_hash)
 | 
			
		||||
                contract_lock_value = initiate_tx_block_time + lock_value
 | 
			
		||||
            self.log.debug('participate %s lock_value %d %d', coin_to, lock_value, contract_lock_value)
 | 
			
		||||
            bid.participate_script = buildContractScript(contract_lock_value, secret_hash, pkhash_seller, pkhash_buyer_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
 | 
			
		||||
            participate_script = buildContractScript(contract_lock_value, secret_hash, pkhash_seller, pkhash_buyer_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
 | 
			
		||||
        return participate_script
 | 
			
		||||
 | 
			
		||||
    def createParticipateTxn(self, bid_id, bid, offer):
 | 
			
		||||
    def createParticipateTxn(self, bid_id, bid, offer, participate_script):
 | 
			
		||||
        self.log.debug('createParticipateTxn')
 | 
			
		||||
 | 
			
		||||
        offer_id = bid.offer_id
 | 
			
		||||
@ -1223,10 +1220,10 @@ class BasicSwap():
 | 
			
		||||
        assert(amount_to == (bid.amount * offer.rate) // COIN)
 | 
			
		||||
 | 
			
		||||
        if self.coin_clients[coin_to]['use_segwit']:
 | 
			
		||||
            p2wsh = getP2WSH(bid.participate_script)
 | 
			
		||||
            p2wsh = getP2WSH(participate_script)
 | 
			
		||||
            addr_to = self.encodeSegwitP2WSH(coin_to, p2wsh)
 | 
			
		||||
        else:
 | 
			
		||||
            addr_to = self.getScriptAddress(coin_to, bid.participate_script)
 | 
			
		||||
            addr_to = self.getScriptAddress(coin_to, participate_script)
 | 
			
		||||
 | 
			
		||||
        txn = self.callcoinrpc(coin_to, 'createrawtransaction', [[], {addr_to: format8(amount_to)}])
 | 
			
		||||
        options = {
 | 
			
		||||
@ -1236,7 +1233,7 @@ class BasicSwap():
 | 
			
		||||
        txn_funded = self.callcoinrpc(coin_to, 'fundrawtransaction', [txn, options])['hex']
 | 
			
		||||
        txn_signed = self.callcoinrpc(coin_to, 'signrawtransactionwithwallet', [txn_funded])['hex']
 | 
			
		||||
 | 
			
		||||
        refund_txn = self.createRefundTxn(coin_to, txn_signed, offer, bid, bid.participate_script, tx_type=TxTypes.PTX_REFUND)
 | 
			
		||||
        refund_txn = self.createRefundTxn(coin_to, txn_signed, offer, bid, participate_script, tx_type=TxTypes.PTX_REFUND)
 | 
			
		||||
        bid.participate_txn_refund = bytes.fromhex(refund_txn)
 | 
			
		||||
 | 
			
		||||
        chain_height = self.callcoinrpc(coin_to, 'getblockchaininfo')['blocks']
 | 
			
		||||
@ -1248,6 +1245,7 @@ class BasicSwap():
 | 
			
		||||
        else:
 | 
			
		||||
            vout = getVoutByAddress(txjs, addr_to)
 | 
			
		||||
        self.addParticipateTxn(bid_id, bid, coin_to, txid, vout, chain_height)
 | 
			
		||||
        bid.participate_tx.script = participate_script
 | 
			
		||||
 | 
			
		||||
        return txn_signed
 | 
			
		||||
 | 
			
		||||
@ -1265,9 +1263,9 @@ class BasicSwap():
 | 
			
		||||
        self.log.debug('createRedeemTxn for coin %s', str(coin_type))
 | 
			
		||||
 | 
			
		||||
        if for_txn_type == 'participate':
 | 
			
		||||
            prev_txnid = bid.participate_txid.hex()
 | 
			
		||||
            prev_n = bid.participate_txn_n
 | 
			
		||||
            txn_script = bid.participate_script
 | 
			
		||||
            prev_txnid = bid.participate_tx.txid.hex()
 | 
			
		||||
            prev_n = bid.participate_tx.vout
 | 
			
		||||
            txn_script = bid.participate_tx.script
 | 
			
		||||
            prev_amount = bid.amount_to
 | 
			
		||||
        else:
 | 
			
		||||
            prev_txnid = bid.initiate_tx.txid.hex()
 | 
			
		||||
@ -1478,15 +1476,21 @@ class BasicSwap():
 | 
			
		||||
        bid.setITxState(TxStates.TX_CONFIRMED)
 | 
			
		||||
 | 
			
		||||
        # Seller first mode, buyer participates
 | 
			
		||||
        self.deriveParticipateScript(bid_id, bid, offer)
 | 
			
		||||
        participate_script = self.deriveParticipateScript(bid_id, bid, offer)
 | 
			
		||||
        if bid.was_sent:
 | 
			
		||||
            self.log.debug('Preparing participate txn for bid %s', bid_id.hex())
 | 
			
		||||
 | 
			
		||||
            coin_to = Coins(offer.coin_to)
 | 
			
		||||
            txn = self.createParticipateTxn(bid_id, bid, offer)
 | 
			
		||||
            txn = self.createParticipateTxn(bid_id, bid, offer, participate_script)
 | 
			
		||||
            txid = self.submitTxn(coin_to, txn)
 | 
			
		||||
            self.log.debug('Submitted participate txn %s to %s chain for bid %s', txid, chainparams[coin_to]['name'], bid_id.hex())
 | 
			
		||||
            bid.setPTxState(TxStates.TX_SENT)
 | 
			
		||||
        else:
 | 
			
		||||
            bid.participate_tx = SwapTx(
 | 
			
		||||
                bid_id=bid_id,
 | 
			
		||||
                tx_type=TxTypes.PTX,
 | 
			
		||||
                script=participate_script,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        # bid saved in checkBidState
 | 
			
		||||
 | 
			
		||||
@ -1506,16 +1510,21 @@ class BasicSwap():
 | 
			
		||||
        return tx_height
 | 
			
		||||
 | 
			
		||||
    def addParticipateTxn(self, bid_id, bid, coin_type, txid_hex, vout, tx_height):
 | 
			
		||||
        bid.participate_txid = bytes.fromhex(txid_hex)
 | 
			
		||||
        bid.participate_txn_n = vout
 | 
			
		||||
        # Start checking for spends of participate_txn before fully confirmed
 | 
			
		||||
 | 
			
		||||
        chain_name = chainparams[coin_type]['name']
 | 
			
		||||
        self.log.debug('Watching %s chain for spend of output %s %d', chain_name, txid_hex, vout)
 | 
			
		||||
 | 
			
		||||
        # TODO: Check connection type
 | 
			
		||||
        bid.participate_txn_height = self.setLastHeightChecked(coin_type, tx_height)
 | 
			
		||||
        participate_txn_height = self.setLastHeightChecked(coin_type, tx_height)
 | 
			
		||||
 | 
			
		||||
        if bid.participate_tx is None:
 | 
			
		||||
            bid.participate_tx = SwapTx(
 | 
			
		||||
                bid_id=bid_id,
 | 
			
		||||
                tx_type=TxTypes.PTX,
 | 
			
		||||
            )
 | 
			
		||||
        bid.participate_tx.txid = bytes.fromhex(txid_hex)
 | 
			
		||||
        bid.participate_tx.vout = vout
 | 
			
		||||
        bid.participate_tx.chain_height = participate_txn_height
 | 
			
		||||
 | 
			
		||||
        # Start checking for spends of participate_txn before fully confirmed
 | 
			
		||||
        self.log.debug('Watching %s chain for spend of output %s %d', chainparams[coin_type]['name'], txid_hex, vout)
 | 
			
		||||
        self.addWatchedOutput(coin_type, bid_id, txid_hex, vout, BidStates.SWAP_PARTICIPATING)
 | 
			
		||||
 | 
			
		||||
    def participateTxnConfirmed(self, bid_id, bid, offer):
 | 
			
		||||
@ -1642,25 +1651,25 @@ class BasicSwap():
 | 
			
		||||
        elif state == BidStates.SWAP_INITIATED:
 | 
			
		||||
            # Waiting for participate txn to be confirmed in 'to' chain
 | 
			
		||||
            if self.coin_clients[coin_to]['use_segwit']:
 | 
			
		||||
                addr = self.encodeSegwitP2WSH(coin_to, getP2WSH(bid.participate_script))
 | 
			
		||||
                addr = self.encodeSegwitP2WSH(coin_to, getP2WSH(bid.participate_tx.script))
 | 
			
		||||
            else:
 | 
			
		||||
                addr = self.getScriptAddress(coin_to, bid.participate_script)
 | 
			
		||||
                addr = self.getScriptAddress(coin_to, bid.participate_tx.script)
 | 
			
		||||
 | 
			
		||||
            found = self.lookupUnspentByAddress(coin_to, addr, assert_amount=bid.amount_to)
 | 
			
		||||
            if found:
 | 
			
		||||
                if bid.participate_txn_conf != found['n_conf']:
 | 
			
		||||
                if bid.participate_tx.conf != found['n_conf']:
 | 
			
		||||
                    save_bid = True
 | 
			
		||||
                bid.participate_txn_conf = found['n_conf']
 | 
			
		||||
                bid.participate_tx.conf = found['n_conf']
 | 
			
		||||
                index = found['index']
 | 
			
		||||
                if bid.participate_txid is None:
 | 
			
		||||
                if bid.participate_tx is None or bid.participate_tx.txid is None:
 | 
			
		||||
                    self.log.debug('Found bid %s participate txn %s in chain %s', bid_id.hex(), found['txid'], coin_to)
 | 
			
		||||
                    self.addParticipateTxn(bid_id, bid, coin_to, found['txid'], found['index'], found['height'])
 | 
			
		||||
                    bid.setPTxState(TxStates.TX_SENT)
 | 
			
		||||
                    save_bid = True
 | 
			
		||||
 | 
			
		||||
            if bid.participate_txn_conf is not None:
 | 
			
		||||
                self.log.debug('participate_txid %s confirms %d', bid.participate_txid.hex(), bid.participate_txn_conf)
 | 
			
		||||
                if bid.participate_txn_conf >= self.coin_clients[coin_to]['blocks_confirmed']:
 | 
			
		||||
            if bid.participate_tx.conf is not None:
 | 
			
		||||
                self.log.debug('participate txid %s confirms %d', bid.participate_tx.txid.hex(), bid.participate_tx.conf)
 | 
			
		||||
                if bid.participate_tx.conf >= self.coin_clients[coin_to]['blocks_confirmed']:
 | 
			
		||||
                    self.participateTxnConfirmed(bid_id, bid, offer)
 | 
			
		||||
                    save_bid = True
 | 
			
		||||
        elif state == BidStates.SWAP_PARTICIPATING:
 | 
			
		||||
@ -1672,14 +1681,14 @@ class BasicSwap():
 | 
			
		||||
        if state > BidStates.BID_ACCEPTED:
 | 
			
		||||
            # Wait for spend of all known swap txns
 | 
			
		||||
            if (bid.getITxState() is None or bid.getITxState() >= TxStates.TX_REDEEMED) \
 | 
			
		||||
               and (bid.participate_txn_state is None or bid.participate_txn_state >= TxStates.TX_REDEEMED):
 | 
			
		||||
               and (bid.getPTxState() is None or bid.getPTxState() >= TxStates.TX_REDEEMED):
 | 
			
		||||
                self.log.info('Swap completed for bid %s', bid_id.hex())
 | 
			
		||||
 | 
			
		||||
                if bid.getITxState() == TxStates.TX_REDEEMED:
 | 
			
		||||
                    self.returnAddressToPool(bid_id, TxTypes.ITX_REFUND)
 | 
			
		||||
                else:
 | 
			
		||||
                    self.returnAddressToPool(bid_id, TxTypes.ITX_REDEEM)
 | 
			
		||||
                if bid.participate_txn_state == TxStates.TX_REDEEMED:
 | 
			
		||||
                if bid.getPTxState() == TxStates.TX_REDEEMED:
 | 
			
		||||
                    self.returnAddressToPool(bid_id, TxTypes.PTX_REFUND)
 | 
			
		||||
                else:
 | 
			
		||||
                    self.returnAddressToPool(bid_id, TxTypes.PTX_REDEEM)
 | 
			
		||||
@ -1701,7 +1710,7 @@ class BasicSwap():
 | 
			
		||||
            except Exception as ex:
 | 
			
		||||
                if 'non-BIP68-final (code 64)' not in str(ex) and 'non-final' not in str(ex):
 | 
			
		||||
                    self.log.warning('Error trying to submit initiate refund txn: %s', str(ex))
 | 
			
		||||
        if (bid.participate_txn_state == TxStates.TX_SENT or bid.participate_txn_state == TxStates.TX_CONFIRMED) \
 | 
			
		||||
        if (bid.getPTxState() == TxStates.TX_SENT or bid.getPTxState() == TxStates.TX_CONFIRMED) \
 | 
			
		||||
           and bid.participate_txn_refund is not None:
 | 
			
		||||
            try:
 | 
			
		||||
                txid = self.submitTxn(coin_to, bid.participate_txn_refund.hex())
 | 
			
		||||
@ -1773,8 +1782,8 @@ class BasicSwap():
 | 
			
		||||
            bid = self.swaps_in_progress[bid_id][0]
 | 
			
		||||
            offer = self.swaps_in_progress[bid_id][1]
 | 
			
		||||
 | 
			
		||||
            bid.participate_spend_txid = bytes.fromhex(spend_txid)
 | 
			
		||||
            bid.participate_spend_n = spend_n
 | 
			
		||||
            bid.participate_tx.spend_txid = bytes.fromhex(spend_txid)
 | 
			
		||||
            bid.participate_tx.spend_n = spend_n
 | 
			
		||||
            spend_in = spend_txn['vin'][spend_n]
 | 
			
		||||
 | 
			
		||||
            coin_from = Coins(offer.coin_from)
 | 
			
		||||
@ -1801,7 +1810,7 @@ class BasicSwap():
 | 
			
		||||
 | 
			
		||||
                # TODO: Wait for depth? new state SWAP_TXI_REDEEM_SENT?
 | 
			
		||||
 | 
			
		||||
            self.removeWatchedOutput(coin_to, bid_id, bid.participate_txid.hex())
 | 
			
		||||
            self.removeWatchedOutput(coin_to, bid_id, bid.participate_tx.txid.hex())
 | 
			
		||||
            self.saveBid(bid_id, bid)
 | 
			
		||||
 | 
			
		||||
    def checkForSpends(self, coin_type, c):
 | 
			
		||||
@ -2075,8 +2084,6 @@ class BasicSwap():
 | 
			
		||||
        assert(bid.accept_msg_id is None), 'Bid already accepted'
 | 
			
		||||
 | 
			
		||||
        bid.accept_msg_id = bytes.fromhex(msg['msgid'])
 | 
			
		||||
        #bid.initiate_txid = bid_accept_data.initiate_txid
 | 
			
		||||
        #bid.initiate_script = bid_accept_data.contract_script
 | 
			
		||||
        bid.initiate_tx = SwapTx(
 | 
			
		||||
            bid_id=bid_id,
 | 
			
		||||
            tx_type=TxTypes.ITX,
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,6 @@
 | 
			
		||||
import struct
 | 
			
		||||
import time
 | 
			
		||||
import sqlalchemy as sa
 | 
			
		||||
from sqlalchemy.orm import sessionmaker, scoped_session
 | 
			
		||||
from sqlalchemy.ext.declarative import declarative_base
 | 
			
		||||
 | 
			
		||||
CURRENT_DB_VERSION = 1
 | 
			
		||||
@ -89,22 +88,12 @@ class Bid(Base):
 | 
			
		||||
    accept_msg_id = sa.Column(sa.LargeBinary)
 | 
			
		||||
    pkhash_seller = sa.Column(sa.LargeBinary)
 | 
			
		||||
 | 
			
		||||
    initiate_txn_redeem = sa.Column(sa.LargeBinary)
 | 
			
		||||
    initiate_txn_refund = sa.Column(sa.LargeBinary)
 | 
			
		||||
 | 
			
		||||
    participate_script = sa.Column(sa.LargeBinary)
 | 
			
		||||
    participate_txid = sa.Column(sa.LargeBinary)
 | 
			
		||||
    participate_txn_n = sa.Column(sa.Integer)
 | 
			
		||||
    participate_txn_conf = sa.Column(sa.Integer)
 | 
			
		||||
    participate_txn_redeem = sa.Column(sa.LargeBinary)
 | 
			
		||||
    participate_txn_refund = sa.Column(sa.LargeBinary)
 | 
			
		||||
 | 
			
		||||
    participate_spend_txid = sa.Column(sa.LargeBinary)
 | 
			
		||||
    participate_spend_n = sa.Column(sa.Integer)
 | 
			
		||||
 | 
			
		||||
    participate_txn_height = sa.Column(sa.Integer)
 | 
			
		||||
    participate_txn_state = sa.Column(sa.Integer)
 | 
			
		||||
    participate_txn_states = sa.Column(sa.LargeBinary)  # Packed states and times
 | 
			
		||||
 | 
			
		||||
    state = sa.Column(sa.Integer)
 | 
			
		||||
    state_time = sa.Column(sa.BigInteger)  # timestamp of last state change
 | 
			
		||||
    states = sa.Column(sa.LargeBinary)  # Packed states and times
 | 
			
		||||
@ -134,12 +123,6 @@ class Bid(Base):
 | 
			
		||||
            self.participate_tx.state = new_state
 | 
			
		||||
            self.participate_tx.states = (self.participate_tx.states if self.participate_tx.states is not None else bytes()) + struct.pack('<iq', new_state, int(time.time()))
 | 
			
		||||
 | 
			
		||||
        self.participate_txn_state = new_state
 | 
			
		||||
        if self.participate_txn_states is None:
 | 
			
		||||
            self.participate_txn_states = struct.pack('<iq', new_state, int(time.time()))
 | 
			
		||||
        else:
 | 
			
		||||
            self.participate_txn_states += struct.pack('<iq', new_state, int(time.time()))
 | 
			
		||||
 | 
			
		||||
    def setState(self, new_state):
 | 
			
		||||
        now = int(time.time())
 | 
			
		||||
        self.state = new_state
 | 
			
		||||
@ -190,4 +173,3 @@ class SentOffer(Base):
 | 
			
		||||
    __tablename__ = 'sentoffers'
 | 
			
		||||
 | 
			
		||||
    offer_id = sa.Column(sa.LargeBinary, primary_key=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -28,6 +28,7 @@ from .basicswap import (
 | 
			
		||||
    SwapTypes,
 | 
			
		||||
    BidStates,
 | 
			
		||||
    TxStates,
 | 
			
		||||
    TxTypes,
 | 
			
		||||
    strOfferState,
 | 
			
		||||
    strBidState,
 | 
			
		||||
    strTxState,
 | 
			
		||||
@ -49,6 +50,36 @@ def getCoinName(c):
 | 
			
		||||
    return chainparams[c]['name'].capitalize()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def getTxIdHex(bid, tx_type, prefix):
 | 
			
		||||
    if tx_type == TxTypes.ITX:
 | 
			
		||||
        obj = bid.initiate_tx
 | 
			
		||||
    elif tx_type == TxTypes.PTX:
 | 
			
		||||
        obj = bid.participate_tx
 | 
			
		||||
    else:
 | 
			
		||||
        return 'Unknown Type'
 | 
			
		||||
 | 
			
		||||
    if not obj:
 | 
			
		||||
        return None
 | 
			
		||||
    if not obj.txid:
 | 
			
		||||
        return None
 | 
			
		||||
    return obj.txid.hex() + prefix
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def getTxSpendHex(bid, tx_type):
 | 
			
		||||
    if tx_type == TxTypes.ITX:
 | 
			
		||||
        obj = bid.initiate_tx
 | 
			
		||||
    elif tx_type == TxTypes.PTX:
 | 
			
		||||
        obj = bid.participate_tx
 | 
			
		||||
    else:
 | 
			
		||||
        return 'Unknown Type'
 | 
			
		||||
 | 
			
		||||
    if not obj:
 | 
			
		||||
        return None
 | 
			
		||||
    if not obj.spend_txid:
 | 
			
		||||
        return None
 | 
			
		||||
    obj.spend_txid.hex() + ' {}'.format(obj.spend_n)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def html_content_start(title, h2=None, refresh=None):
 | 
			
		||||
    content = '<!DOCTYPE html><html lang="en">\n<head>' \
 | 
			
		||||
        + '<meta charset="UTF-8">' \
 | 
			
		||||
@ -275,7 +306,7 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
            sent_bid_id=sent_bid_id,
 | 
			
		||||
            messages=messages,
 | 
			
		||||
            data=data,
 | 
			
		||||
            bids=[(b.bid_id.hex(), format8(b.amount), strBidState(b.state), strTxState(b.getITxState()), strTxState(b.participate_txn_state)) for b in bids],
 | 
			
		||||
            bids=[(b.bid_id.hex(), format8(b.amount), strBidState(b.state), strTxState(b.getITxState()), strTxState(b.getPTxState())) for b in bids],
 | 
			
		||||
            form_id=os.urandom(8).hex(),
 | 
			
		||||
        ), 'UTF-8')
 | 
			
		||||
 | 
			
		||||
@ -364,10 +395,10 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
            state_description = 'Waiting for initiate txn to be spent in {} chain'.format(ticker_from)
 | 
			
		||||
        elif bid.state == BidStates.SWAP_COMPLETED:
 | 
			
		||||
            state_description = 'Swap completed'
 | 
			
		||||
            if bid.getITxState() == TxStates.TX_REDEEMED and bid.participate_txn_state == TxStates.TX_REDEEMED:
 | 
			
		||||
            if bid.getITxState() == TxStates.TX_REDEEMED and bid.getPTxState() == TxStates.TX_REDEEMED:
 | 
			
		||||
                state_description += ' successfully'
 | 
			
		||||
            else:
 | 
			
		||||
                state_description += ', ITX ' + strTxState(bid.getITxState() + ', PTX ' + strTxState(bid.participate_txn_state))
 | 
			
		||||
                state_description += ', ITX ' + strTxState(bid.getITxState() + ', PTX ' + strTxState(bid.getPTxState()))
 | 
			
		||||
        elif bid.state == BidStates.SWAP_TIMEDOUT:
 | 
			
		||||
            state_description = 'Timed out waiting for initiate txn'
 | 
			
		||||
        elif bid.state == BidStates.BID_ABANDONED:
 | 
			
		||||
@ -385,7 +416,7 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
            'bid_state': strBidState(bid.state),
 | 
			
		||||
            'state_description': state_description,
 | 
			
		||||
            'itx_state': strTxState(bid.getITxState()),
 | 
			
		||||
            'ptx_state': strTxState(bid.participate_txn_state),
 | 
			
		||||
            'ptx_state': strTxState(bid.getPTxState()),
 | 
			
		||||
            'offer_id': bid.offer_id.hex(),
 | 
			
		||||
            'addr_from': bid.bid_addr,
 | 
			
		||||
            'addr_fund_proof': bid.proof_address,
 | 
			
		||||
@ -393,18 +424,18 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
            'expired_at': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(bid.expire_at)),
 | 
			
		||||
            'was_sent': 'True' if bid.was_sent else 'False',
 | 
			
		||||
            'was_received': 'True' if bid.was_received else 'False',
 | 
			
		||||
            'initiate_tx': 'None' if not bid.initiate_tx else (bid.initiate_tx.txid.hex() + ' ' + ticker_from),
 | 
			
		||||
            'initiate_tx': getTxIdHex(bid, TxTypes.ITX, ' ' + ticker_from),
 | 
			
		||||
            'initiate_conf': 'None' if (not bid.initiate_tx or not bid.initiate_tx.conf) else bid.initiate_tx.conf,
 | 
			
		||||
            'participate_tx': 'None' if not bid.participate_tx else (bid.participate_tx.txid.hex() + ' ' + ticker_to),
 | 
			
		||||
            'participate_conf': 'None' if not bid.participate_txn_conf else bid.participate_txn_conf,
 | 
			
		||||
            'participate_tx': getTxIdHex(bid, TxTypes.PTX, ' ' + ticker_to),
 | 
			
		||||
            'participate_conf': 'None' if (not bid.participate_tx or not bid.participate_tx.conf) else bid.participate_tx.conf,
 | 
			
		||||
            'show_txns': show_txns,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if show_txns:
 | 
			
		||||
            data['initiate_tx_refund'] = 'None' if not bid.initiate_txn_refund else bid.initiate_txn_refund.hex()
 | 
			
		||||
            data['participate_tx_refund'] = 'None' if not bid.participate_txn_refund else bid.participate_txn_refund.hex()
 | 
			
		||||
            data['initiate_tx_spend'] = 'None' if not bid.initiate_spend_txid else (bid.initiate_spend_txid.hex() + ' {}'.format(bid.initiate_spend_n))
 | 
			
		||||
            data['participate_tx_spend'] = 'None' if not bid.participate_spend_txid else (bid.participate_spend_txid.hex() + ' {}'.format(bid.participate_spend_n))
 | 
			
		||||
            data['initiate_tx_spend'] = getTxSpendHex(bid, TxTypes.ITX),
 | 
			
		||||
            data['participate_tx_spend'] = getTxSpendHex(bid, TxTypes.PTX),
 | 
			
		||||
 | 
			
		||||
        old_states = []
 | 
			
		||||
        num_states = len(bid.states) // 12
 | 
			
		||||
@ -416,10 +447,10 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
            for i in range(num_states):
 | 
			
		||||
                up = struct.unpack_from('<iq', bid.initiate_tx.states[i * 12:(i + 1) * 12])
 | 
			
		||||
                old_states.append((up[1], 'ITX ' + strTxState(up[0])))
 | 
			
		||||
        if bid.participate_txn_states is not None:
 | 
			
		||||
            num_states = len(bid.participate_txn_states) // 12
 | 
			
		||||
        if bid.participate_tx and bid.participate_tx.states is not None:
 | 
			
		||||
            num_states = len(bid.participate_tx.states) // 12
 | 
			
		||||
            for i in range(num_states):
 | 
			
		||||
                up = struct.unpack_from('<iq', bid.participate_txn_states[i * 12:(i + 1) * 12])
 | 
			
		||||
                up = struct.unpack_from('<iq', bid.participate_tx.states[i * 12:(i + 1) * 12])
 | 
			
		||||
                old_states.append((up[1], 'PTX ' + strTxState(up[0])))
 | 
			
		||||
        if len(old_states) > 0:
 | 
			
		||||
            old_states.sort(key=lambda x: x[0])
 | 
			
		||||
@ -445,7 +476,7 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
            h2=self.server.title,
 | 
			
		||||
            page_type='Sent' if sent else 'Received',
 | 
			
		||||
            bids=[(time.strftime('%Y-%m-%d %H:%M', time.localtime(b.created_at)),
 | 
			
		||||
                   b.bid_id.hex(), b.offer_id.hex(), strBidState(b.state), strTxState(b.getITxState()), strTxState(b.participate_txn_state)) for b in bids],
 | 
			
		||||
                   b.bid_id.hex(), b.offer_id.hex(), strBidState(b.state), strTxState(b.getITxState()), strTxState(b.getPTxState())) for b in bids],
 | 
			
		||||
        ), 'UTF-8')
 | 
			
		||||
 | 
			
		||||
    def page_watched(self, url_split, post_string):
 | 
			
		||||
 | 
			
		||||
@ -371,7 +371,7 @@ class Test(unittest.TestCase):
 | 
			
		||||
            time.sleep(1)
 | 
			
		||||
            bid = swap_client.getBid(bid_id)
 | 
			
		||||
            if (initiate_state is None or bid.getITxState() == initiate_state) \
 | 
			
		||||
               and (participate_state is None or bid.participate_txn_state == participate_state):
 | 
			
		||||
               and (participate_state is None or bid.getPTxState() == participate_state):
 | 
			
		||||
                return
 | 
			
		||||
        raise ValueError('wait_for_bid_tx_state timed out.')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ class Test(unittest.TestCase):
 | 
			
		||||
            shutil.rmtree(test_path)
 | 
			
		||||
        except Exception as ex:
 | 
			
		||||
            logger.warning('tearDownClass %s', str(ex))
 | 
			
		||||
        super(Test, cls).tearDownClass()
 | 
			
		||||
        super(Test, self).tearDownClass()
 | 
			
		||||
 | 
			
		||||
    def test(self):
 | 
			
		||||
        testargs = ['basicswap-prepare', '-datadir=' + test_path]
 | 
			
		||||
 | 
			
		||||
@ -20,10 +20,8 @@ import sys
 | 
			
		||||
import time
 | 
			
		||||
import unittest
 | 
			
		||||
from unittest.mock import patch
 | 
			
		||||
from io import StringIO
 | 
			
		||||
import logging
 | 
			
		||||
import shutil
 | 
			
		||||
import json
 | 
			
		||||
import threading
 | 
			
		||||
 | 
			
		||||
import bin.basicswap_prepare as prepareSystem
 | 
			
		||||
 | 
			
		||||
@ -367,7 +367,7 @@ class Test(unittest.TestCase):
 | 
			
		||||
            time.sleep(1)
 | 
			
		||||
            bid = swap_client.getBid(bid_id)
 | 
			
		||||
            if (initiate_state is None or bid.getITxState() == initiate_state) \
 | 
			
		||||
               and (participate_state is None or bid.participate_txn_state == participate_state):
 | 
			
		||||
               and (participate_state is None or bid.getPTxState() == participate_state):
 | 
			
		||||
                return
 | 
			
		||||
        raise ValueError('wait_for_bid_tx_state timed out.')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user