From 4a07c891f6e7f9db1ae76c9c88858413531ec03e Mon Sep 17 00:00:00 2001 From: tecnovert Date: Sat, 27 Jul 2019 20:51:50 +0200 Subject: [PATCH] Refactor initiate_tx. --- .travis.yml | 3 ++ basicswap/basicswap.py | 52 +++++++++++++++++----------------- basicswap/db.py | 33 ++++++++++----------- basicswap/http_server.py | 36 +++++++++++------------ tests/basicswap/test_nmc.py | 16 +++++------ tests/basicswap/test_reload.py | 1 + tests/basicswap/test_run.py | 2 +- 7 files changed, 71 insertions(+), 72 deletions(-) diff --git a/.travis.yml b/.travis.yml index 431eb1f..547e3dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ stages: - lint env: global: + - TEST_DIR=/tmp/test_basicswap/ - PARTICL_BINDIR=/opt/binaries/particl-0.18.0.12/bin/ - BITCOIN_BINDIR=/opt/binaries/bitcoin-0.18.0/bin/ - LITECOIN_BINDIR=/opt/binaries/litecoin-0.17.1/bin/ @@ -19,6 +20,8 @@ script: - export PARTICL_BINDIR=/opt/binaries/particl-0.18.0.12/bin/ - export BITCOIN_BINDIR=/opt/binaries/bitcoin-0.18.0/bin/ - export LITECOIN_BINDIR=/opt/binaries/litecoin-0.17.1/bin/ + - mkdir -p ${TEST_DIR}/bin/{particl,bitcoin} + - cp /opt/binaries/bitcoin-0.18.0-x86_64-linux-gnu.tar.gz ${TEST_DIR}/bin/bitcoin - python setup.py test after_success: - echo "End test" diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 0a326f7..b4d8d7a 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -144,7 +144,7 @@ SEQUENCE_LOCKTIME_MASK = 0x0000ffff INITIATE_TX_TIMEOUT = 40 * 60 # TODO: make variable per coin -def getOfferState(state): +def strOfferState(state): if state == OfferStates.OFFER_SENT: return 'Sent' if state == OfferStates.OFFER_RECEIVED: @@ -154,7 +154,7 @@ def getOfferState(state): return 'Unknown' -def getBidState(state): +def strBidState(state): if state == BidStates.BID_SENT: return 'Sent' if state == BidStates.BID_RECEIVED: @@ -176,7 +176,7 @@ def getBidState(state): return 'Unknown' -def getTxState(state): +def strTxState(state): if state == TxStates.TX_NONE: return 'None' if state == TxStates.TX_SENT: @@ -517,7 +517,7 @@ class BasicSwap(): self.addWatchedOutput(coin_to, bid.bid_id, bid.participate_txid.hex(), bid.participate_txn_n, BidStates.SWAP_PARTICIPATING) if self.coin_clients[coin_from]['last_height_checked'] < 1: - self.coin_clients[coin_from]['last_height_checked'] = bid.initiate_txn_height + 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 @@ -1040,7 +1040,7 @@ class BasicSwap(): txid=bytes.fromhex(txid), script=script, ) - bid.setITXState(TxStates.TX_SENT) + bid.setITxState(TxStates.TX_SENT) # Check non-bip68 final try: @@ -1112,9 +1112,9 @@ class BasicSwap(): self.removeWatchedOutput(Coins(offer.coin_to), bid_id, None) # Return unused addrs to pool - if bid.initiate_txn_state != TxStates.TX_REDEEMED: + if bid.getITxState() != TxStates.TX_REDEEMED: self.returnAddressToPool(bid_id, TxTypes.ITX_REDEEM) - if bid.initiate_txn_state != TxStates.TX_REFUNDED: + if bid.getITxState() != TxStates.TX_REFUNDED: self.returnAddressToPool(bid_id, TxTypes.ITX_REFUND) if bid.participate_txn_state != TxStates.TX_REDEEMED: self.returnAddressToPool(bid_id, TxTypes.PTX_REDEEM) @@ -1180,7 +1180,7 @@ class BasicSwap(): else: # Lock from the height or time of the block containing the initiate txn coin_from = Coins(offer.coin_from) - initiate_tx_block_hash = self.callcoinrpc(coin_from, 'getblockhash', [bid.initiate_txn_height, ]) + initiate_tx_block_hash = self.callcoinrpc(coin_from, 'getblockhash', [bid.initiate_tx.chain_height, ]) initiate_tx_block_time = int(self.callcoinrpc(coin_from, 'getblock', [initiate_tx_block_hash, ])['time']) if offer.lock_type == ABS_LOCK_BLOCKS: # Walk the coin_to chain back until block time matches @@ -1475,7 +1475,7 @@ class BasicSwap(): def initiateTxnConfirmed(self, bid_id, bid, offer): self.log.debug('initiateTxnConfirmed for bid %s', bid_id.hex()) bid.setState(BidStates.SWAP_INITIATED) - bid.setITXState(TxStates.TX_CONFIRMED) + bid.setITxState(TxStates.TX_CONFIRMED) # Seller first mode, buyer participates self.deriveParticipateScript(bid_id, bid, offer) @@ -1486,7 +1486,7 @@ class BasicSwap(): txn = self.createParticipateTxn(bid_id, bid, offer) 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) + bid.setPTxState(TxStates.TX_SENT) # bid saved in checkBidState @@ -1521,7 +1521,7 @@ class BasicSwap(): def participateTxnConfirmed(self, bid_id, bid, offer): self.log.debug('participateTxnConfirmed for bid %s', bid_id.hex()) bid.setState(BidStates.SWAP_PARTICIPATING) - bid.setPTXState(TxStates.TX_CONFIRMED) + bid.setPTxState(TxStates.TX_CONFIRMED) # Seller redeems from participate txn if bid.was_received: @@ -1622,10 +1622,10 @@ class BasicSwap(): if bid.initiate_tx.vout is None: bid.initiate_tx.vout = index # Start checking for spends of initiate_txn before fully confirmed - bid.initiate_txn_height = self.setLastHeightChecked(coin_from, tx_height) + bid.initiate_tx.chain_height = self.setLastHeightChecked(coin_from, tx_height) self.addWatchedOutput(coin_from, bid_id, initiate_txnid_hex, bid.initiate_tx.vout, BidStates.SWAP_INITIATED) - if bid.initiate_txn_state is None or bid.initiate_txn_state < TxStates.TX_SENT: - bid.setITXState(TxStates.TX_SENT) + if bid.getITxState() is None or bid.getITxState() < TxStates.TX_SENT: + bid.setITxState(TxStates.TX_SENT) save_bid = True if bid.initiate_tx.conf >= self.coin_clients[coin_from]['blocks_confirmed']: @@ -1655,7 +1655,7 @@ class BasicSwap(): if bid.participate_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) + bid.setPTxState(TxStates.TX_SENT) save_bid = True if bid.participate_txn_conf is not None: @@ -1671,11 +1671,11 @@ class BasicSwap(): if state > BidStates.BID_ACCEPTED: # Wait for spend of all known swap txns - if (bid.initiate_txn_state is None or bid.initiate_txn_state >= TxStates.TX_REDEEMED) \ + 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): self.log.info('Swap completed for bid %s', bid_id.hex()) - if bid.initiate_txn_state == TxStates.TX_REDEEMED: + if bid.getITxState() == TxStates.TX_REDEEMED: self.returnAddressToPool(bid_id, TxTypes.ITX_REFUND) else: self.returnAddressToPool(bid_id, TxTypes.ITX_REDEEM) @@ -1692,7 +1692,7 @@ class BasicSwap(): self.saveBid(bid_id, bid) # Try refund, keep trying until sent tx is spent - if (bid.initiate_txn_state == TxStates.TX_SENT or bid.initiate_txn_state == TxStates.TX_CONFIRMED) \ + if (bid.getITxState() == TxStates.TX_SENT or bid.getITxState() == TxStates.TX_CONFIRMED) \ and bid.initiate_txn_refund is not None: try: txid = self.submitTxn(coin_from, bid.initiate_txn_refund.hex()) @@ -1745,8 +1745,8 @@ class BasicSwap(): bid = self.swaps_in_progress[bid_id][0] offer = self.swaps_in_progress[bid_id][1] - bid.initiate_spend_txid = bytes.fromhex(spend_txid) - bid.initiate_spend_n = spend_n + bid.initiate_tx.spend_txid = bytes.fromhex(spend_txid) + bid.initiate_tx.spend_n = spend_n spend_in = spend_txn['vin'][spend_n] coin_from = Coins(offer.coin_from) @@ -1756,11 +1756,11 @@ class BasicSwap(): if secret is None: self.log.info('Bid %s initiate txn refunded by %s %d', bid_id.hex(), spend_txid, spend_n) # TODO: Wait for depth? - bid.setITXState(TxStates.TX_REFUNDED) + bid.setITxState(TxStates.TX_REFUNDED) else: self.log.info('Bid %s initiate txn redeemed by %s %d', bid_id.hex(), spend_txid, spend_n) # TODO: Wait for depth? - bid.setITXState(TxStates.TX_REDEEMED) + bid.setITxState(TxStates.TX_REDEEMED) self.removeWatchedOutput(coin_from, bid_id, bid.initiate_tx.txid.hex()) self.saveBid(bid_id, bid) @@ -1784,18 +1784,18 @@ class BasicSwap(): if secret is None: self.log.info('Bid %s participate txn refunded by %s %d', bid_id.hex(), spend_txid, spend_n) # TODO: Wait for depth? - bid.setPTXState(TxStates.TX_REFUNDED) + bid.setPTxState(TxStates.TX_REFUNDED) else: self.log.debug('Secret %s extracted from participate spend %s %d', secret.hex(), spend_txid, spend_n) bid.recovered_secret = secret # TODO: Wait for depth? - bid.setPTXState(TxStates.TX_REDEEMED) + bid.setPTxState(TxStates.TX_REDEEMED) if bid.was_sent: txn = self.createRedeemTxn(coin_from, bid, for_txn_type='initiate') txid = self.submitTxn(coin_from, txn) - bid.initiate_spend_txid = bytes.fromhex(txid) + bid.initiate_tx.spend_txid = bytes.fromhex(txid) # bid.initiate_txn_redeem = bytes.fromhex(txn) # Worth keeping? self.log.debug('Submitted initiate redeem txn %s to %s chain for bid %s', txid, chainparams[coin_from]['name'], bid_id.hex()) @@ -2085,7 +2085,7 @@ class BasicSwap(): ) bid.pkhash_seller = bytes.fromhex(scriptvalues[3]) bid.setState(BidStates.BID_ACCEPTED) - bid.setITXState(TxStates.TX_NONE) + bid.setITxState(TxStates.TX_NONE) self.log.info('Received valid bid accept %s for bid %s', bid.accept_msg_id.hex(), bid_id.hex()) diff --git a/basicswap/db.py b/basicswap/db.py index 78782d4..97ff306 100644 --- a/basicswap/db.py +++ b/basicswap/db.py @@ -89,19 +89,8 @@ class Bid(Base): accept_msg_id = sa.Column(sa.LargeBinary) pkhash_seller = sa.Column(sa.LargeBinary) - #initiate_script = sa.Column(sa.LargeBinary) # contract_script - #initiate_txid = sa.Column(sa.LargeBinary) - #initiate_txn_n = sa.Column(sa.Integer) - #initiate_txn_conf = sa.Column(sa.Integer) initiate_txn_refund = sa.Column(sa.LargeBinary) - initiate_spend_txid = sa.Column(sa.LargeBinary) - initiate_spend_n = sa.Column(sa.Integer) - - initiate_txn_height = sa.Column(sa.Integer) - initiate_txn_state = sa.Column(sa.Integer) - initiate_txn_states = sa.Column(sa.LargeBinary) # Packed states and times - participate_script = sa.Column(sa.LargeBinary) participate_txid = sa.Column(sa.LargeBinary) participate_txn_n = sa.Column(sa.Integer) @@ -125,18 +114,22 @@ class Bid(Base): initiate_tx = None participate_tx = None - def setITXState(self, new_state): + def getITxState(self): + if self.initiate_tx is None: + return None + return self.initiate_tx.state + + def setITxState(self, new_state): if self.initiate_tx is not None: self.initiate_tx.state = new_state self.initiate_tx.states = (self.initiate_tx.states if self.initiate_tx.states is not None else bytes()) + struct.pack(' 0: old_states.sort(key=lambda x: x[0]) @@ -445,7 +445,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(), getBidState(b.state), getTxState(b.initiate_txn_state), getTxState(b.participate_txn_state)) for b in bids], + b.bid_id.hex(), b.offer_id.hex(), strBidState(b.state), strTxState(b.getITxState()), strTxState(b.participate_txn_state)) for b in bids], ), 'UTF-8') def page_watched(self, url_split, post_string): diff --git a/tests/basicswap/test_nmc.py b/tests/basicswap/test_nmc.py index c1e971b..89c9f27 100644 --- a/tests/basicswap/test_nmc.py +++ b/tests/basicswap/test_nmc.py @@ -370,15 +370,15 @@ class Test(unittest.TestCase): for i in range(seconds_for): time.sleep(1) bid = swap_client.getBid(bid_id) - if (initiate_state is None or bid.initiate_txn_state == initiate_state) \ + if (initiate_state is None or bid.getITxState() == initiate_state) \ and (participate_state is None or bid.participate_txn_state == participate_state): return raise ValueError('wait_for_bid_tx_state timed out.') def test_02_part_ltc(self): + logging.info('---------- Test PART to NMC') swap_clients = self.swap_clients - logging.info('---------- Test PART to NMC') offer_id = swap_clients[0].postOffer(Coins.PART, Coins.NMC, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST, ABS_LOCK_TIME) self.wait_for_offer(swap_clients[1], offer_id) @@ -403,9 +403,9 @@ class Test(unittest.TestCase): assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) def test_03_nmc_part(self): + logging.info('---------- Test NMC to PART') swap_clients = self.swap_clients - logging.info('---------- Test NMC to PART') offer_id = swap_clients[1].postOffer(Coins.NMC, Coins.PART, 10 * COIN, 9.0 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, ABS_LOCK_TIME) self.wait_for_offer(swap_clients[0], offer_id) @@ -428,9 +428,9 @@ class Test(unittest.TestCase): assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) def test_04_nmc_btc(self): + logging.info('---------- Test NMC to BTC') swap_clients = self.swap_clients - logging.info('---------- Test NMC to BTC') offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, ABS_LOCK_TIME) self.wait_for_offer(swap_clients[1], offer_id) @@ -457,9 +457,9 @@ class Test(unittest.TestCase): def test_05_refund(self): # Seller submits initiate txn, buyer doesn't respond + logging.info('---------- Test refund, NMC to BTC') swap_clients = self.swap_clients - logging.info('---------- Test refund, NMC to BTC') offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, ABS_LOCK_BLOCKS, 10) @@ -482,9 +482,8 @@ class Test(unittest.TestCase): assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) def test_06_self_bid(self): - swap_clients = self.swap_clients - logging.info('---------- Test same client, BTC to NMC') + swap_clients = self.swap_clients js_0_before = json.loads(urlopen('http://localhost:1800/json').read()) @@ -507,9 +506,8 @@ class Test(unittest.TestCase): assert(js_0['num_recv_bids'] == js_0_before['num_recv_bids'] + 1 and js_0['num_sent_bids'] == js_0_before['num_sent_bids'] + 1) def test_07_error(self): - swap_clients = self.swap_clients - logging.info('---------- Test error, BTC to NMC, set fee above bid value') + swap_clients = self.swap_clients js_0_before = json.loads(urlopen('http://localhost:1800/json').read()) diff --git a/tests/basicswap/test_reload.py b/tests/basicswap/test_reload.py index bf434da..a17256a 100644 --- a/tests/basicswap/test_reload.py +++ b/tests/basicswap/test_reload.py @@ -65,6 +65,7 @@ class Test(unittest.TestCase): thread = threading.Thread(target=self.run_thread) thread.start() + logger.log('TODO') time.sleep(5) runSystem.swap_client.stopRunning() diff --git a/tests/basicswap/test_run.py b/tests/basicswap/test_run.py index 9da8878..fdeb849 100644 --- a/tests/basicswap/test_run.py +++ b/tests/basicswap/test_run.py @@ -366,7 +366,7 @@ class Test(unittest.TestCase): for i in range(seconds_for): time.sleep(1) bid = swap_client.getBid(bid_id) - if (initiate_state is None or bid.initiate_txn_state == initiate_state) \ + if (initiate_state is None or bid.getITxState() == initiate_state) \ and (participate_state is None or bid.participate_txn_state == participate_state): return raise ValueError('wait_for_bid_tx_state timed out.')