diff --git a/.travis.yml b/.travis.yml index bada43a..f29268b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,7 @@ before_script: - python3 setup.py install --force script: - cd $TRAVIS_BUILD_DIR + - python3 setup.py install - basicswap-prepare --bindir=${BIN_DIRS} --preparebinonly --withcoins=particl,bitcoin,litecoin,monero - export DATADIRS="${TEST_DIR}" - mkdir -p "${DATADIRS}/bin" diff --git a/basicswap/__init__.py b/basicswap/__init__.py index a72af3f..3b1b41e 100644 --- a/basicswap/__init__.py +++ b/basicswap/__init__.py @@ -1,3 +1,3 @@ name = "basicswap" -__version__ = "0.0.9" +__version__ = "0.0.10" diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 61b6b36..658346e 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -440,12 +440,7 @@ class BasicSwap(BaseApp): self.swaps_in_progress = dict() - if self.chain == 'regtest': - self.SMSG_SECONDS_IN_DAY = 600 - self.SMSG_SECONDS_IN_HOUR = 60 * 2 - else: - self.SMSG_SECONDS_IN_DAY = 86400 - self.SMSG_SECONDS_IN_HOUR = 60 * 60 + self.SMSG_SECONDS_IN_HOUR = 60 * 2 if self.chain == 'regtest' else 60 * 60 # Encode key to match network wif_prefix = chainparams[Coins.PART][self.chain]['key_prefix'] @@ -579,7 +574,7 @@ class BasicSwap(BaseApp): if self.coin_clients[coin]['connection_type'] == 'rpc': if coin == Coins.XMR: - self.coin_clients[coin]['walletrpchost'] = chain_client_settings.get('walletrpchost', 'localhost') + self.coin_clients[coin]['walletrpchost'] = chain_client_settings.get('walletrpchost', '127.0.0.1') self.coin_clients[coin]['walletrpcport'] = chain_client_settings.get('walletrpcport', chainparams[coin][self.chain]['walletrpcport']) if 'walletrpcpassword' in chain_client_settings: self.coin_clients[coin]['walletrpcauth'] = (chain_client_settings['walletrpcuser'], chain_client_settings['walletrpcpassword']) @@ -803,9 +798,9 @@ class BasicSwap(BaseApp): kv.value = int_val session.add(kv) session.commit() + finally: session.close() session.remove() - finally: self.mxDB.release() def setStringKV(self, str_key, str_val): @@ -819,9 +814,9 @@ class BasicSwap(BaseApp): kv.value = str_val session.add(kv) session.commit() + finally: session.close() session.remove() - finally: self.mxDB.release() def getStringKV(self, str_key): @@ -963,12 +958,15 @@ class BasicSwap(BaseApp): self.loadFromDB() # Scan inbox - options = {'encoding': 'hex'} + # TODO: Redundant? small window for zmq messages to go unnoticed during startup? + # options = {'encoding': 'hex'} + options = {'encoding': 'none'} ro = self.callrpc('smsginbox', ['unread', '', options]) nm = 0 for msg in ro['messages']: - msg['hex'] += '00' # Add nullbtye to match output from 'smsg' cmd - TODO: make consistent - self.processMsg(msg) + # TODO: Remove workaround for smsginbox bug + get_msg = self.callrpc('smsg', [msg['msgid'], {'encoding': 'hex', 'setread': True}]) + self.processMsg(get_msg) nm += 1 self.log.info('Scanned %d unread messages.', nm) @@ -1024,6 +1022,7 @@ class BasicSwap(BaseApp): self.validateOfferLockValue(coin_from_t, coin_to_t, lock_type, lock_value) self.mxDB.acquire() + session = None try: self.checkSynced(coin_from_t, coin_to_t) # TODO: require proof of funds on offers? @@ -1123,9 +1122,11 @@ class BasicSwap(BaseApp): if addr_send_from is None: session.add(SmsgAddress(addr=offer_addr, use_type=MessageTypes.OFFER)) session.commit() - session.close() - session.remove() + finally: + if session: + session.close() + session.remove() self.mxDB.release() self.log.info('Sent OFFER %s', offer_id.hex()) return offer_id @@ -1262,9 +1263,9 @@ class BasicSwap(BaseApp): addr = record.addr session.add(record) session.commit() + finally: session.close() session.remove() - finally: self.mxDB.release() return addr @@ -1280,9 +1281,9 @@ class BasicSwap(BaseApp): session.commit() except Exception as ex: pass + finally: session.close() session.remove() - finally: self.mxDB.release() def getReceiveAddressForCoin(self, coin_type): @@ -1380,9 +1381,9 @@ class BasicSwap(BaseApp): value=addr )) session.commit() + finally: session.close() session.remove() - finally: self.mxDB.release() return addr @@ -1391,11 +1392,11 @@ class BasicSwap(BaseApp): try: self._contract_count += 1 session = scoped_session(self.session_factory) - self.engine.execute('UPDATE kv_int SET value = {} WHERE KEY="contract_count"'.format(self._contract_count)) + session.execute('UPDATE kv_int SET value = {} WHERE KEY="contract_count"'.format(self._contract_count)) session.commit() + finally: session.close() session.remove() - finally: self.mxDB.release() return self._contract_count @@ -1458,9 +1459,9 @@ class BasicSwap(BaseApp): session = scoped_session(self.session_factory) self.saveBidInSession(bid_id, bid, session, xmr_swap) session.commit() + finally: session.close() session.remove() - finally: self.mxDB.release() def saveToDB(self, db_record): @@ -1469,9 +1470,9 @@ class BasicSwap(BaseApp): session = scoped_session(self.session_factory) session.add(db_record) session.commit() + finally: session.close() session.remove() - finally: self.mxDB.release() def createEventInSession(self, delay, event_type, linked_id, session): @@ -1492,9 +1493,9 @@ class BasicSwap(BaseApp): session = scoped_session(self.session_factory) self.createEventInSession(delay, event_type, linked_id, session) session.commit() + finally: session.close() session.remove() - finally: self.mxDB.release() def logBidEvent(self, bid, event_type, event_msg, session): @@ -1577,13 +1578,15 @@ class BasicSwap(BaseApp): ) bid.setState(BidStates.BID_SENT) - session = scoped_session(self.session_factory) - self.saveBidInSession(bid_id, bid, session) - if addr_send_from is None: - session.add(SmsgAddress(addr=bid_addr, use_type=MessageTypes.BID)) - session.commit() - session.close() - session.remove() + try: + session = scoped_session(self.session_factory) + self.saveBidInSession(bid_id, bid, session) + if addr_send_from is None: + session.add(SmsgAddress(addr=bid_addr, use_type=MessageTypes.BID)) + session.commit() + finally: + session.close() + session.remove() self.log.info('Sent BID %s', bid_id.hex()) return bid_id @@ -1712,17 +1715,16 @@ class BasicSwap(BaseApp): self.mxDB.release() def list_bid_events(self, bid_id, session): - session = scoped_session(self.session_factory) query_str = 'SELECT created_at, event_type, event_msg FROM eventlog ' + \ 'WHERE active_ind = 1 AND linked_type = {} AND linked_id = x\'{}\' '.format(TableTypes.BID, bid_id.hex()) - q = self.engine.execute(query_str) + q = session.execute(query_str) events = [] for row in q: events.append({'at': row[0], 'desc': describeEventEntry(row[1], row[2])}) query_str = 'SELECT created_at, trigger_at FROM eventqueue ' + \ 'WHERE active_ind = 1 AND linked_id = x\'{}\' '.format(bid_id.hex()) - q = self.engine.execute(query_str) + q = session.execute(query_str) events = [] for row in q: events.append({'at': row[0], 'desc': 'Delaying until: {}'.format(format_timestamp(row[1]))}) @@ -1736,13 +1738,13 @@ class BasicSwap(BaseApp): assert(bid), 'Bid not found' assert(offer), 'Offer not found' - if offer.swap_type == SwapTypes.XMR_SWAP: - return self.acceptXmrBid(bid_id) - # Ensure bid is still valid now = int(time.time()) assert(bid.expire_at > now), 'Bid expired' - assert(bid.state == BidStates.BID_RECEIVED), 'Wrong bid state: {}'.format(BidStates(bid.state)) + assert(bid.state == BidStates.BID_RECEIVED), 'Wrong bid state: {}'.format(str(BidStates(bid.state))) + + if offer.swap_type == SwapTypes.XMR_SWAP: + return self.acceptXmrBid(bid_id) if bid.contract_count is None: bid.contract_count = self.getNewContractId() @@ -1934,13 +1936,15 @@ class BasicSwap(BaseApp): ) bid.setState(BidStates.BID_SENT) - session = scoped_session(self.session_factory) - self.saveBidInSession(xmr_swap.bid_id, bid, session, xmr_swap) - if addr_send_from is None: - session.add(SmsgAddress(addr=bid_addr, use_type=MessageTypes.BID)) - session.commit() - session.close() - session.remove() + try: + session = scoped_session(self.session_factory) + self.saveBidInSession(xmr_swap.bid_id, bid, session, xmr_swap) + if addr_send_from is None: + session.add(SmsgAddress(addr=bid_addr, use_type=MessageTypes.BID)) + session.commit() + finally: + session.close() + session.remove() self.log.info('Sent XMR_BID_FL %s', xmr_swap.bid_id.hex()) return xmr_swap.bid_id @@ -1957,7 +1961,8 @@ class BasicSwap(BaseApp): bid, xmr_swap = self.getXmrBid(bid_id) assert(bid), 'Bid not found: {}.'.format(bid_id.hex()) assert(xmr_swap), 'XMR swap not found: {}.'.format(bid_id.hex()) - assert(bid.expire_at > now), 'Offer has expired' + assert(bid.expire_at > now), 'Bid expired' + assert(bid.state == BidStates.BID_RECEIVED), 'Wrong bid state: {}'.format(str(BidStates(bid.state))) offer, xmr_offer = self.getXmrOffer(bid.offer_id) assert(offer), 'Offer not found: {}.'.format(bid.offer_id.hex()) @@ -2066,11 +2071,7 @@ class BasicSwap(BaseApp): bid.setState(BidStates.BID_ACCEPTED) - session = scoped_session(self.session_factory) - self.saveBidInSession(bid_id, bid, session, xmr_swap) - session.commit() - session.close() - session.remove() + self.saveBid(bid_id, bid, xmr_swap=xmr_swap) # Add to swaps_in_progress only when waiting on txns self.log.info('Sent XMR_BID_ACCEPT_LF %s', bid_id.hex()) @@ -3182,7 +3183,7 @@ class BasicSwap(BaseApp): self.initiateTxnSpent(watched_output.bid_id, spend_txid_hex, spend_n, spend_txn) 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) if coin_type == Coins.PART and self.coin_clients[coin_type]['have_spent_index']: @@ -3236,11 +3237,18 @@ class BasicSwap(BaseApp): now = int(time.time()) options = {'encoding': 'none'} ro = self.callrpc('smsginbox', ['all', '', options]) + num_messages = 0 + num_removed = 0 for msg in ro['messages']: - expire_at = msg['sent'] + msg['daysretention'] * self.SMSG_SECONDS_IN_DAY + num_messages += 1 + expire_at = msg['sent'] + msg['ttl'] if expire_at < now: options = {'encoding': 'none', 'delete': True} del_msg = self.callrpc('smsg', [msg['msgid'], options]) + num_removed += 1 + + if num_messages + num_removed > 0: + logging.info('Expired {} / {} messages.'.format(num_removed, num_messages)) logging.debug('TODO: Expire records from db') @@ -3303,7 +3311,7 @@ class BasicSwap(BaseApp): session = scoped_session(self.session_factory) q = session.query(Bid).filter(Bid.state == BidStates.BID_RECEIVING) for bid in q: - q = self.engine.execute('SELECT COUNT(*) FROM xmr_split_data WHERE bid_id = x\'{}\' AND msg_type = {}'.format(bid.bid_id.hex(), XmrSplitMsgTypes.BID)).first() + q = session.execute('SELECT COUNT(*) FROM xmr_split_data WHERE bid_id = x\'{}\' AND msg_type = {}'.format(bid.bid_id.hex(), XmrSplitMsgTypes.BID)).first() num_segments = q[0] if num_segments > 1: try: @@ -3321,7 +3329,7 @@ class BasicSwap(BaseApp): q = session.query(Bid).filter(Bid.state == BidStates.BID_RECEIVING_ACC) for bid in q: - q = self.engine.execute('SELECT COUNT(*) FROM xmr_split_data WHERE bid_id = x\'{}\' AND msg_type = {}'.format(bid.bid_id.hex(), XmrSplitMsgTypes.BID_ACCEPT)).first() + q = session.execute('SELECT COUNT(*) FROM xmr_split_data WHERE bid_id = x\'{}\' AND msg_type = {}'.format(bid.bid_id.hex(), XmrSplitMsgTypes.BID_ACCEPT)).first() num_segments = q[0] if num_segments > 1: try: @@ -3330,6 +3338,7 @@ class BasicSwap(BaseApp): self.log.info('Verify xmr bid accept {} failed: {}'.format(bid.bid_id.hex(), str(ex))) bid.setState(BidStates.BID_ERROR, 'Failed accept validation: ' + str(ex)) session.add(bid) + self.updateBidInProgress(bid) continue if bid.created_at + ttl_xmr_split_messages < now: self.log.debug('Expiring partially received bid accept: {}'.format(bid.bid_id.hex())) @@ -3388,49 +3397,51 @@ class BasicSwap(BaseApp): raise ValueError('Offer has been revoked {}.'.format(offer_id.hex())) session = scoped_session(self.session_factory) - # Check for sent - existing_offer = self.getOffer(offer_id) - if existing_offer is None: - offer = Offer( - offer_id=offer_id, - active_ind=1, + try: + # Check for sent + existing_offer = self.getOffer(offer_id) + if existing_offer is None: + offer = Offer( + offer_id=offer_id, + active_ind=1, - coin_from=offer_data.coin_from, - coin_to=offer_data.coin_to, - amount_from=offer_data.amount_from, - rate=offer_data.rate, - min_bid_amount=offer_data.min_bid_amount, - time_valid=offer_data.time_valid, - lock_type=int(offer_data.lock_type), - lock_value=offer_data.lock_value, - swap_type=offer_data.swap_type, + coin_from=offer_data.coin_from, + coin_to=offer_data.coin_to, + amount_from=offer_data.amount_from, + rate=offer_data.rate, + min_bid_amount=offer_data.min_bid_amount, + time_valid=offer_data.time_valid, + lock_type=int(offer_data.lock_type), + lock_value=offer_data.lock_value, + swap_type=offer_data.swap_type, - addr_from=msg['from'], - created_at=msg['sent'], - expire_at=msg['sent'] + offer_data.time_valid, - was_sent=False) - offer.setState(OfferStates.OFFER_RECEIVED) - session.add(offer) + addr_from=msg['from'], + created_at=msg['sent'], + expire_at=msg['sent'] + offer_data.time_valid, + was_sent=False) + offer.setState(OfferStates.OFFER_RECEIVED) + session.add(offer) - if offer.swap_type == SwapTypes.XMR_SWAP: - xmr_offer = XmrOffer() + if offer.swap_type == SwapTypes.XMR_SWAP: + xmr_offer = XmrOffer() - xmr_offer.offer_id = offer_id - xmr_offer.lock_time_1 = getExpectedSequence(offer_data.lock_type, offer_data.lock_value, coin_from) - xmr_offer.lock_time_2 = getExpectedSequence(offer_data.lock_type, offer_data.lock_value, coin_from) + xmr_offer.offer_id = offer_id + xmr_offer.lock_time_1 = getExpectedSequence(offer_data.lock_type, offer_data.lock_value, coin_from) + xmr_offer.lock_time_2 = getExpectedSequence(offer_data.lock_type, offer_data.lock_value, coin_from) - xmr_offer.a_fee_rate = offer_data.fee_rate_from - xmr_offer.b_fee_rate = offer_data.fee_rate_to + xmr_offer.a_fee_rate = offer_data.fee_rate_from + xmr_offer.b_fee_rate = offer_data.fee_rate_to - session.add(xmr_offer) + session.add(xmr_offer) - self.log.debug('Received new offer %s', offer_id.hex()) - else: - existing_offer.setState(OfferStates.OFFER_RECEIVED) - session.add(existing_offer) - session.commit() - session.close() - session.remove() + self.log.debug('Received new offer %s', offer_id.hex()) + else: + existing_offer.setState(OfferStates.OFFER_RECEIVED) + session.add(existing_offer) + session.commit() + finally: + session.close() + session.remove() def processOfferRevoke(self, msg): assert(msg['to'] == self.network_addr), 'Message received on wrong address' @@ -3540,6 +3551,7 @@ class BasicSwap(BaseApp): was_received=True, ) else: + assert(bid.state == BidStates.BID_SENT), 'Wrong bid state: {}'.format(str(BidStates(bid.state))) bid.created_at = msg['sent'] bid.expire_at = msg['sent'] + bid_data.time_valid bid.was_received = True @@ -3585,7 +3597,7 @@ class BasicSwap(BaseApp): if bid.was_received: # Sent to self self.log.info('Received valid bid accept %s for bid %s sent to self', bid.accept_msg_id.hex(), bid_id.hex()) return - raise ValueError('Wrong bid state: {}'.format(str(BidStates(bid.state)))) + raise ValueError('Wrong bid state: {}'.format(str(BidStates(str(BidStates(bid.state)))))) use_csv = True if offer.lock_type < ABS_LOCK_BLOCKS else False @@ -3784,6 +3796,7 @@ class BasicSwap(BaseApp): xmr_swap.b_restore_height = ci_to._restore_height self.log.warning('XMR swap restore height clamped to {}'.format(ci_to._restore_height)) else: + assert(bid.state == BidStates.BID_SENT), 'Wrong bid state: {}'.format(str(BidStates(bid.state))) bid.created_at = msg['sent'] bid.expire_at = msg['sent'] + bid_data.time_valid bid.was_received = True @@ -4336,13 +4349,25 @@ class BasicSwap(BaseApp): assert(len(msg_data.msg_id) == 28), 'Bad msg_id length' if msg_data.msg_type == XmrSplitMsgTypes.BID or msg_data.msg_type == XmrSplitMsgTypes.BID_ACCEPT: - dbr = XmrSplitData() - dbr.bid_id = msg_data.msg_id - dbr.msg_type = msg_data.msg_type - dbr.msg_sequence = msg_data.sequence - dbr.dleag = msg_data.dleag - dbr.created_at = now - self.saveToDB(dbr) + try: + session = scoped_session(self.session_factory) + q = session.execute('SELECT COUNT(*) FROM xmr_split_data WHERE bid_id = x\'{}\' AND msg_type = {} AND msg_sequence = {}'.format(msg_data.msg_id.hex(), msg_data.msg_type, msg_data.sequence)).first() + num_exists = q[0] + if num_exists > 0: + self.log.warning('Ignoring duplicate xmr_split_data entry: ({}, {}, {})'.format(msg_data.msg_id.hex(), msg_data.msg_type, msg_data.sequence)) + return + + dbr = XmrSplitData() + dbr.bid_id = msg_data.msg_id + dbr.msg_type = msg_data.msg_type + dbr.msg_sequence = msg_data.sequence + dbr.dleag = msg_data.dleag + dbr.created_at = now + session.add(dbr) + session.commit() + finally: + session.close() + session.remove() def processXmrLockReleaseMessage(self, msg): self.log.debug('Processing xmr secret msg %s', msg['msgid']) @@ -4640,9 +4665,9 @@ class BasicSwap(BaseApp): try: session = scoped_session(self.session_factory) if offer_id: - q = self.engine.execute('SELECT COUNT(*) FROM bids WHERE state >= {} AND offer_id = x\'{}\''.format(BidStates.BID_ACCEPTED, offer_id.hex())).first() + q = session.execute('SELECT COUNT(*) FROM bids WHERE state >= {} AND offer_id = x\'{}\''.format(BidStates.BID_ACCEPTED, offer_id.hex())).first() else: - q = self.engine.execute('SELECT COUNT(*) FROM bids WHERE state >= {}'.format(BidStates.BID_ACCEPTED)).first() + q = session.execute('SELECT COUNT(*) FROM bids WHERE state >= {}'.format(BidStates.BID_ACCEPTED)).first() return q[0] finally: session.close() @@ -4712,7 +4737,7 @@ class BasicSwap(BaseApp): query_str += 'WHERE bids.was_received = 1 ' query_str += 'ORDER BY bids.created_at DESC' - q = self.engine.execute(query_str) + q = session.execute(query_str) for row in q: rv.append(row) return rv @@ -4751,7 +4776,7 @@ class BasicSwap(BaseApp): try: session = scoped_session(self.session_factory) rv = [] - q = self.engine.execute('SELECT addr FROM smsgaddresses WHERE use_type = {} ORDER BY addr_id DESC'.format(use_type)) + q = session.execute('SELECT addr FROM smsgaddresses WHERE use_type = {} ORDER BY addr_id DESC'.format(use_type)) for row in q: rv.append(row[0]) return rv diff --git a/basicswap/db.py b/basicswap/db.py index f9b00b8..f84e73d 100644 --- a/basicswap/db.py +++ b/basicswap/db.py @@ -330,6 +330,8 @@ class XmrSplitData(Base): dleag = sa.Column(sa.LargeBinary) created_at = sa.Column(sa.BigInteger) + __table_args__ = (sa.UniqueConstraint('bid_id', 'msg_type', 'msg_sequence', name='uc_1'),) + class RevokedMessage(Base): __tablename__ = 'revoked_messages' diff --git a/basicswap/http_server.py b/basicswap/http_server.py index 7e80de7..1168f0f 100644 --- a/basicswap/http_server.py +++ b/basicswap/http_server.py @@ -39,6 +39,7 @@ from .js_server import ( js_bids, js_sentbids, js_network, + js_revokeoffer, js_index, ) from .ui import ( @@ -821,6 +822,7 @@ class HttpHandler(BaseHTTPRequestHandler): 'bids': js_bids, 'sentbids': js_sentbids, 'network': js_network, + 'revokeoffer': js_revokeoffer, }.get(url_split[2], js_index) return func(self, url_split, post_string) except Exception as ex: diff --git a/basicswap/interface_btc.py b/basicswap/interface_btc.py index 033868e..da64f03 100644 --- a/basicswap/interface_btc.py +++ b/basicswap/interface_btc.py @@ -117,7 +117,7 @@ class BTCInterface(CoinInterface): def __init__(self, coin_settings, network): super().__init__() - rpc_host = coin_settings.get('rpchost', 'localhost') + rpc_host = coin_settings.get('rpchost', '127.0.0.1') self.rpc_callback = make_rpc_func(coin_settings['rpcport'], coin_settings['rpcauth'], host=rpc_host) self.txoType = CTxOut self._network = network diff --git a/basicswap/interface_part.py b/basicswap/interface_part.py index 9f375b3..4d34496 100644 --- a/basicswap/interface_part.py +++ b/basicswap/interface_part.py @@ -36,7 +36,7 @@ class PARTInterface(BTCInterface): return 213 def __init__(self, coin_settings, network): - rpc_host = coin_settings.get('rpchost', 'localhost') + rpc_host = coin_settings.get('rpchost', '127.0.0.1') self.rpc_callback = make_rpc_func(coin_settings['rpcport'], coin_settings['rpcauth'], host=rpc_host) self.txoType = CTxOutPart self._network = network diff --git a/basicswap/interface_xmr.py b/basicswap/interface_xmr.py index be1e4fb..618f2ef 100644 --- a/basicswap/interface_xmr.py +++ b/basicswap/interface_xmr.py @@ -57,8 +57,8 @@ class XMRInterface(CoinInterface): def __init__(self, coin_settings, network): super().__init__() - self.rpc_cb = make_xmr_rpc_func(coin_settings['rpcport'], host=coin_settings.get('rpchost', 'localhost')) - self.rpc_cb2 = make_xmr_rpc2_func(coin_settings['rpcport'], host=coin_settings.get('rpchost', 'localhost')) # non-json endpoint + self.rpc_cb = make_xmr_rpc_func(coin_settings['rpcport'], host=coin_settings.get('rpchost', '127.0.0.1')) + self.rpc_cb2 = make_xmr_rpc2_func(coin_settings['rpcport'], host=coin_settings.get('rpchost', '127.0.0.1')) # non-json endpoint self.rpc_wallet_cb = make_xmr_wallet_rpc_func(coin_settings['walletrpcport'], coin_settings['walletrpcauth']) self._network = network diff --git a/basicswap/js_server.py b/basicswap/js_server.py index 65d3f9c..3698b61 100644 --- a/basicswap/js_server.py +++ b/basicswap/js_server.py @@ -34,6 +34,7 @@ def js_wallets(self, url_split, post_string): def js_offers(self, url_split, post_string, sent=False): + offer_id = None if len(url_split) > 3: if url_split[3] == 'new': if post_string == '': @@ -52,6 +53,10 @@ def js_offers(self, url_split, post_string, sent=False): 'sort_by': 'created_at', 'sort_dir': 'desc', } + + if offer_id: + filters['offer_id'] = offer_id + if post_string != '': post_data = urllib.parse.parse_qs(post_string) filters['coin_from'] = setCoinFilter(form_data, b'coin_from') @@ -160,5 +165,12 @@ def js_network(self, url_split, post_string): return bytes(json.dumps(self.server.swap_client.get_network_info()), 'UTF-8') +def js_revokeoffer(self, url_split, post_string): + offer_id = bytes.fromhex(url_split[3]) + assert(len(offer_id) == 28) + self.server.swap_client.revokeOffer(offer_id) + return bytes(json.dumps({'revoked_offer': offer_id.hex()}), 'UTF-8') + + def js_index(self, url_split, post_string): return bytes(json.dumps(self.server.swap_client.getSummary()), 'UTF-8') diff --git a/bin/basicswap_prepare.py b/bin/basicswap_prepare.py index ea2c4be..194dc30 100755 --- a/bin/basicswap_prepare.py +++ b/bin/basicswap_prepare.py @@ -53,11 +53,11 @@ logger.level = logging.DEBUG if not len(logger.handlers): logger.addHandler(logging.StreamHandler(sys.stdout)) -XMR_RPC_HOST = os.getenv('XMR_RPC_HOST', 'localhost') +XMR_RPC_HOST = os.getenv('XMR_RPC_HOST', '127.0.0.1') BASE_XMR_RPC_PORT = int(os.getenv('BASE_XMR_RPC_PORT', 29798)) BASE_XMR_ZMQ_PORT = int(os.getenv('BASE_XMR_ZMQ_PORT', 30898)) BASE_XMR_WALLET_PORT = int(os.getenv('BASE_XMR_WALLET_PORT', 29998)) -XMR_WALLET_RPC_HOST = os.getenv('XMR_WALLET_RPC_HOST', 'localhost') +XMR_WALLET_RPC_HOST = os.getenv('XMR_WALLET_RPC_HOST', '127.0.0.1') XMR_WALLET_RPC_USER = os.getenv('XMR_WALLET_RPC_USER', 'xmr_wallet_user') XMR_WALLET_RPC_PWD = os.getenv('XMR_WALLET_RPC_PWD', 'xmr_wallet_pwd') XMR_SITE_COMMIT = 'd27c1eee9fe0e8daa011d07baae8b67dd2b62a04' # Lock hashes.txt to monero version @@ -65,10 +65,10 @@ XMR_SITE_COMMIT = 'd27c1eee9fe0e8daa011d07baae8b67dd2b62a04' # Lock hashes.txt DEFAULT_XMR_RESTORE_HEIGHT = 2245107 -PART_RPC_HOST = os.getenv('PART_RPC_HOST', 'localhost') -LTC_RPC_HOST = os.getenv('LTC_RPC_HOST', 'localhost') -BTC_RPC_HOST = os.getenv('BTC_RPC_HOST', 'localhost') -NMC_RPC_HOST = os.getenv('NMC_RPC_HOST', 'localhost') +PART_RPC_HOST = os.getenv('PART_RPC_HOST', '127.0.0.1') +LTC_RPC_HOST = os.getenv('LTC_RPC_HOST', '127.0.0.1') +BTC_RPC_HOST = os.getenv('BTC_RPC_HOST', '127.0.0.1') +NMC_RPC_HOST = os.getenv('NMC_RPC_HOST', '127.0.0.1') extract_core_overwrite = True @@ -82,7 +82,7 @@ def make_reporthook(): nonlocal last_percent_str read += blocksize if totalsize > 0: - percent_str = '%5.1f%%' % (read * 1e2 / totalsize) + percent_str = '%5.0f%%' % (read * 1e2 / totalsize) if percent_str != last_percent_str: logger.info(percent_str) last_percent_str = percent_str @@ -393,7 +393,7 @@ def printHelp(): logger.info('--preparebinonly Don\'t prepare settings or datadirs.') logger.info('--nocores Don\'t download and extract any coin clients.') logger.info('--portoffset=n Raise all ports by n.') - logger.info('--htmlhost= Interface to host on, default:localhost.') + logger.info('--htmlhost= Interface to host on, default:127.0.0.1.') logger.info('--xmrrestoreheight=n Block height to restore Monero wallet from, default:{}.'.format(DEFAULT_XMR_RESTORE_HEIGHT)) logger.info('--noextractover Prevent extracting cores if files exist. Speeds up tests') @@ -431,7 +431,7 @@ def main(): with_coins = {'particl'} add_coin = '' disable_coin = '' - htmlhost = 'localhost' + htmlhost = '127.0.0.1' xmr_restore_height = DEFAULT_XMR_RESTORE_HEIGHT for v in sys.argv[1:]: @@ -535,7 +535,7 @@ def main(): chainclients = { 'particl': { 'connection_type': 'rpc', - 'manage_daemon': True if ('particl' in with_coins and PART_RPC_HOST == 'localhost') else False, + 'manage_daemon': True if ('particl' in with_coins and PART_RPC_HOST == '127.0.0.1') else False, 'rpchost': PART_RPC_HOST, 'rpcport': 19792 + port_offset, 'datadir': os.getenv('PART_DATA_DIR', os.path.join(data_dir, 'particl')), @@ -548,7 +548,7 @@ def main(): }, 'litecoin': { 'connection_type': 'rpc' if 'litecoin' in with_coins else 'none', - 'manage_daemon': True if ('litecoin' in with_coins and LTC_RPC_HOST == 'localhost') else False, + 'manage_daemon': True if ('litecoin' in with_coins and LTC_RPC_HOST == '127.0.0.1') else False, 'rpchost': LTC_RPC_HOST, 'rpcport': 19795 + port_offset, 'datadir': os.getenv('LTC_DATA_DIR', os.path.join(data_dir, 'litecoin')), @@ -561,7 +561,7 @@ def main(): }, 'bitcoin': { 'connection_type': 'rpc' if 'bitcoin' in with_coins else 'none', - 'manage_daemon': True if ('bitcoin' in with_coins and BTC_RPC_HOST == 'localhost') else False, + 'manage_daemon': True if ('bitcoin' in with_coins and BTC_RPC_HOST == '127.0.0.1') else False, 'rpchost': BTC_RPC_HOST, 'rpcport': 19796 + port_offset, 'datadir': os.getenv('BTC_DATA_DIR', os.path.join(data_dir, 'bitcoin')), @@ -574,7 +574,7 @@ def main(): }, 'namecoin': { 'connection_type': 'rpc' if 'namecoin' in with_coins else 'none', - 'manage_daemon': True if ('namecoin' in with_coins and NMC_RPC_HOST == 'localhost') else False, + 'manage_daemon': True if ('namecoin' in with_coins and NMC_RPC_HOST == '127.0.0.1') else False, 'rpchost': NMC_RPC_HOST, 'rpcport': 19798 + port_offset, 'datadir': os.getenv('NMC_DATA_DIR', os.path.join(data_dir, 'namecoin')), @@ -588,8 +588,8 @@ def main(): }, 'monero': { 'connection_type': 'rpc' if 'monero' in with_coins else 'none', - 'manage_daemon': True if ('monero' in with_coins and XMR_RPC_HOST == 'localhost') else False, - 'manage_wallet_daemon': True if ('monero' in with_coins and XMR_WALLET_RPC_HOST == 'localhost') else False, + 'manage_daemon': True if ('monero' in with_coins and XMR_RPC_HOST == '127.0.0.1') else False, + 'manage_wallet_daemon': True if ('monero' in with_coins and XMR_WALLET_RPC_HOST == '127.0.0.1') else False, 'rpcport': BASE_XMR_RPC_PORT + port_offset, 'zmqport': BASE_XMR_ZMQ_PORT + port_offset, 'walletrpcport': BASE_XMR_WALLET_PORT + port_offset, diff --git a/tests/basicswap/common.py b/tests/basicswap/common.py index 891e2f4..d5ff95f 100644 --- a/tests/basicswap/common.py +++ b/tests/basicswap/common.py @@ -162,7 +162,7 @@ def wait_for_none_active(delay_event, port, wait_for=30): if delay_event.is_set(): raise ValueError('Test stopped.') delay_event.wait(1) - js = json.loads(urlopen('http://localhost:{}/json'.format(port)).read()) + js = json.loads(urlopen('http://127.0.0.1:{}/json'.format(port)).read()) if js['num_swapping'] == 0 and js['num_watched_outputs'] == 0: return raise ValueError('wait_for_none_active timed out.') diff --git a/tests/basicswap/extended/test_network.py b/tests/basicswap/extended/test_network.py index b834bc1..d398cc5 100644 --- a/tests/basicswap/extended/test_network.py +++ b/tests/basicswap/extended/test_network.py @@ -79,7 +79,7 @@ def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey): 'p2p_port': BASE_P2P_PORT + node_id, 'zmqhost': 'tcp://127.0.0.1', 'zmqport': BASE_ZMQ_PORT + node_id, - 'htmlhost': 'localhost', + 'htmlhost': '127.0.0.1', 'htmlport': TEST_HTTP_PORT + node_id, 'network_key': network_key, 'network_pubkey': network_pubkey, @@ -298,7 +298,7 @@ class Test(unittest.TestCase): for i in range(wait_for): if delay_event.is_set(): raise ValueError('Test stopped.') - js = json.loads(urlopen('http://localhost:{}/json/network'.format(port)).read()) + js = json.loads(urlopen('http://127.0.0.1:{}/json/network'.format(port)).read()) num_nodes = 0 for p in js['peers']: if p['ready'] is True: @@ -313,7 +313,7 @@ class Test(unittest.TestCase): logging.info('---------- Test Network') swap_clients = self.swap_clients - js_1 = json.loads(urlopen('http://localhost:1801/json/wallets').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json/wallets').read()) offer_id = swap_clients[0].postOffer(Coins.PART, Coins.BTC, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST) @@ -322,7 +322,7 @@ class Test(unittest.TestCase): self.wait_for_num_nodes(1800, 2) - js_n0 = json.loads(urlopen('http://localhost:1800/json/network').read()) + js_n0 = json.loads(urlopen('http://127.0.0.1:1800/json/network').read()) print(dumpj(js_n0)) path = [swap_clients[0]._network._network_pubkey, swap_clients[2]._network._network_pubkey] diff --git a/tests/basicswap/extended/test_nmc.py b/tests/basicswap/extended/test_nmc.py index f4a5b8f..b59c621 100644 --- a/tests/basicswap/extended/test_nmc.py +++ b/tests/basicswap/extended/test_nmc.py @@ -146,7 +146,7 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey): 'debug': True, 'zmqhost': 'tcp://127.0.0.1', 'zmqport': BASE_ZMQ_PORT + nodeId, - 'htmlhost': 'localhost', + 'htmlhost': '127.0.0.1', 'htmlport': 12700 + nodeId, 'network_key': network_key, 'network_pubkey': network_pubkey, @@ -380,8 +380,8 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) - js_1 = json.loads(urlopen('http://localhost:1801/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) @@ -405,8 +405,8 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) - js_1 = json.loads(urlopen('http://localhost:1801/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) @@ -430,10 +430,10 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - js_0bid = json.loads(urlopen('http://localhost:1800/json/bids/{}'.format(bid_id.hex())).read()) + js_0bid = json.loads(urlopen('http://127.0.0.1:1800/json/bids/{}'.format(bid_id.hex())).read()) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) - js_1 = json.loads(urlopen('http://localhost:1801/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) @@ -459,8 +459,8 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.BID_ABANDONED, sent=True, wait_for=60) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) - js_1 = json.loads(urlopen('http://localhost:1801/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) @@ -468,7 +468,7 @@ class Test(unittest.TestCase): logging.info('---------- Test same client, BTC to NMC') swap_clients = self.swap_clients - js_0_before = json.loads(urlopen('http://localhost:1800/json').read()) + js_0_before = json.loads(urlopen('http://127.0.0.1:1800/json').read()) offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 10 * COIN, 10 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, ABS_LOCK_TIME) @@ -484,7 +484,7 @@ class Test(unittest.TestCase): wait_for_bid_tx_state(delay_event, swap_clients[0], bid_id, TxStates.TX_REDEEMED, TxStates.TX_REDEEMED, wait_for=60) wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) 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) @@ -492,7 +492,7 @@ class Test(unittest.TestCase): 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()) + js_0_before = json.loads(urlopen('http://127.0.0.1:1800/json').read()) offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 0.001 * COIN, 1.0 * COIN, 0.001 * COIN, SwapTypes.SELLER_FIRST, ABS_LOCK_TIME) diff --git a/tests/basicswap/test_prepare.py b/tests/basicswap/extended/test_prepare.py similarity index 100% rename from tests/basicswap/test_prepare.py rename to tests/basicswap/extended/test_prepare.py diff --git a/tests/basicswap/extended/test_wallet_init.py b/tests/basicswap/extended/test_wallet_init.py index 1414c2a..70aa00b 100644 --- a/tests/basicswap/extended/test_wallet_init.py +++ b/tests/basicswap/extended/test_wallet_init.py @@ -55,10 +55,10 @@ def waitForServer(port): for i in range(20): try: time.sleep(1) - summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read()) + summary = json.loads(urlopen('http://127.0.0.1:{}/json'.format(port)).read()) break - except Exception: - traceback.print_exc() + except Exception as e: + print('waitForServer, error:', str(e)) class Test(unittest.TestCase): @@ -98,7 +98,7 @@ class Test(unittest.TestCase): fp.write('minstakeinterval=5\n') for ip in range(3): if ip != i: - fp.write('connect=localhost:{}\n'.format(PARTICL_PORT_BASE + ip)) + fp.write('connect=127.0.0.1:{}\n'.format(PARTICL_PORT_BASE + ip)) # Pruned nodes don't provide blocks with open(os.path.join(client_path, 'bitcoin', 'bitcoin.conf'), 'r') as fp: @@ -115,7 +115,7 @@ class Test(unittest.TestCase): fp.write('bind=127.0.0.1\n') for ip in range(3): if ip != i: - fp.write('connect=localhost:{}\n'.format(BITCOIN_PORT_BASE + ip)) + fp.write('connect=127.0.0.1:{}\n'.format(BITCOIN_PORT_BASE + ip)) with open(os.path.join(client_path, 'monero', 'monerod.conf'), 'a') as fp: fp.write('p2p-bind-ip=127.0.0.1\n') @@ -145,12 +145,12 @@ class Test(unittest.TestCase): try: waitForServer(12700) - wallets_0 = json.loads(urlopen('http://localhost:12700/json/wallets').read()) + wallets_0 = json.loads(urlopen('http://127.0.0.1:12700/json/wallets').read()) assert(wallets_0['1']['expected_seed'] is True) assert(wallets_0['6']['expected_seed'] is True) waitForServer(12701) - wallets_1 = json.loads(urlopen('http://localhost:12701/json/wallets').read()) + wallets_1 = json.loads(urlopen('http://127.0.0.1:12701/json/wallets').read()) assert(wallets_0['1']['expected_seed'] is True) assert(wallets_1['6']['expected_seed'] is True) diff --git a/tests/basicswap/test_reload.py b/tests/basicswap/test_reload.py index 4e391b1..342ded7 100644 --- a/tests/basicswap/test_reload.py +++ b/tests/basicswap/test_reload.py @@ -59,16 +59,16 @@ def waitForServer(port): for i in range(20): try: time.sleep(1) - summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read()) + summary = json.loads(urlopen('http://127.0.0.1:{}/json'.format(port)).read()) return - except Exception: - traceback.print_exc() + except Exception as e: + print('waitForServer, error:', str(e)) raise ValueError('waitForServer failed') def waitForNumOffers(port, offers): for i in range(20): - summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read()) + summary = json.loads(urlopen('http://127.0.0.1:{}/json'.format(port)).read()) if summary['num_network_offers'] >= offers: return time.sleep(1) @@ -77,7 +77,7 @@ def waitForNumOffers(port, offers): def waitForNumBids(port, bids): for i in range(20): - summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read()) + summary = json.loads(urlopen('http://127.0.0.1:{}/json'.format(port)).read()) if summary['num_recv_bids'] >= bids: return time.sleep(1) @@ -86,7 +86,7 @@ def waitForNumBids(port, bids): def waitForNumSwapping(port, bids): for i in range(20): - summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read()) + summary = json.loads(urlopen('http://127.0.0.1:{}/json'.format(port)).read()) if summary['num_swapping'] >= bids: return time.sleep(1) @@ -135,7 +135,7 @@ class Test(unittest.TestCase): fp.write('minstakeinterval=5\n') for ip in range(3): if ip != i: - fp.write('connect=localhost:{}\n'.format(PARTICL_PORT_BASE + ip)) + fp.write('connect=127.0.0.1:{}\n'.format(PARTICL_PORT_BASE + ip)) # Pruned nodes don't provide blocks with open(os.path.join(client_path, 'bitcoin', 'bitcoin.conf'), 'r') as fp: @@ -152,7 +152,7 @@ class Test(unittest.TestCase): fp.write('bind=127.0.0.1\n') for ip in range(3): if ip != i: - fp.write('connect=localhost:{}\n'.format(BITCOIN_PORT_BASE + ip)) + fp.write('connect=127.0.0.1:{}\n'.format(BITCOIN_PORT_BASE + ip)) assert(os.path.exists(config_path)) @@ -180,9 +180,10 @@ class Test(unittest.TestCase): for i in range(20): blocks = btcRpc(0, 'getblockchaininfo')['blocks'] - if blocks >= 500: + if blocks >= num_blocks: break - assert(blocks >= 500) + time.sleep(2) + assert(blocks >= num_blocks) data = parse.urlencode({ 'addr_from': '-1', @@ -192,8 +193,8 @@ class Test(unittest.TestCase): 'amt_to': '1', 'lockhrs': '24'}).encode() - offer_id = json.loads(urlopen('http://localhost:12700/json/offers/new', data=data).read()) - summary = json.loads(urlopen('http://localhost:12700/json').read()) + offer_id = json.loads(urlopen('http://127.0.0.1:12700/json/offers/new', data=data).read()) + summary = json.loads(urlopen('http://127.0.0.1:12700/json').read()) assert(summary['num_sent_offers'] == 1) except Exception: traceback.print_exc() @@ -201,24 +202,24 @@ class Test(unittest.TestCase): logger.info('Waiting for offer:') waitForNumOffers(12701, 1) - offers = json.loads(urlopen('http://localhost:12701/json/offers').read()) + offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers').read()) offer = offers[0] data = parse.urlencode({ 'offer_id': offer['offer_id'], 'amount_from': offer['amount_from']}).encode() - bid_id = json.loads(urlopen('http://localhost:12701/json/bids/new', data=data).read()) + bid_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=data).read()) waitForNumBids(12700, 1) - bids = json.loads(urlopen('http://localhost:12700/json/bids').read()) + bids = json.loads(urlopen('http://127.0.0.1:12700/json/bids').read()) bid = bids[0] data = parse.urlencode({ 'accept': True }).encode() - rv = json.loads(urlopen('http://localhost:12700/json/bids/{}'.format(bid['bid_id']), data=data).read()) + rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid['bid_id']), data=data).read()) assert(rv['bid_state'] == 'Accepted') waitForNumSwapping(12701, 1) @@ -231,7 +232,7 @@ class Test(unittest.TestCase): processes[1].start() waitForServer(12701) - rv = json.loads(urlopen('http://localhost:12701/json').read()) + rv = json.loads(urlopen('http://127.0.0.1:12701/json').read()) assert(rv['num_swapping'] == 1) update_thread = threading.Thread(target=updateThread) @@ -241,7 +242,7 @@ class Test(unittest.TestCase): for i in range(240): time.sleep(5) - rv = json.loads(urlopen('http://localhost:12700/json/bids/{}'.format(bid['bid_id'])).read()) + rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid['bid_id'])).read()) print(rv) if rv['bid_state'] == 'Completed': break diff --git a/tests/basicswap/test_reload_xmr.py b/tests/basicswap/test_reload_xmr.py index bd3329e..3eefe0f 100644 --- a/tests/basicswap/test_reload_xmr.py +++ b/tests/basicswap/test_reload_xmr.py @@ -60,10 +60,10 @@ def waitForServer(port, wait_for=20): raise ValueError('Test stopped.') try: delay_event.wait(1) - summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read()) + summary = json.loads(urlopen('http://127.0.0.1:{}/json'.format(port)).read()) return - except Exception: - traceback.print_exc() + except Exception as e: + print('waitForServer, error:', str(e)) raise ValueError('waitForServer failed') @@ -71,7 +71,7 @@ def waitForNumOffers(port, offers, wait_for=20): for i in range(wait_for): if delay_event.is_set(): raise ValueError('Test stopped.') - summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read()) + summary = json.loads(urlopen('http://127.0.0.1:{}/json'.format(port)).read()) if summary['num_network_offers'] >= offers: return delay_event.wait(1) @@ -82,7 +82,7 @@ def waitForNumBids(port, bids, wait_for=20): for i in range(wait_for): if delay_event.is_set(): raise ValueError('Test stopped.') - summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read()) + summary = json.loads(urlopen('http://127.0.0.1:{}/json'.format(port)).read()) if summary['num_recv_bids'] >= bids: return delay_event.wait(1) @@ -93,13 +93,25 @@ def waitForNumSwapping(port, bids, wait_for=60): for i in range(wait_for): if delay_event.is_set(): raise ValueError('Test stopped.') - summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read()) + summary = json.loads(urlopen('http://127.0.0.1:{}/json'.format(port)).read()) if summary['num_swapping'] >= bids: return delay_event.wait(1) raise ValueError('waitForNumSwapping failed') +def waitForBidState(port, bid_id, state_str, wait_for=60): + for i in range(wait_for): + if delay_event.is_set(): + raise ValueError('Test stopped.') + bid = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid_id)).read()) + print('[rm] bid', bid) + if bid['bid_state'] == state_str: + return + delay_event.wait(1) + raise ValueError('waitForBidState failed') + + def updateThread(xmr_addr): while not delay_event.is_set(): try: @@ -154,7 +166,7 @@ class Test(unittest.TestCase): fp.write('minstakeinterval=5\n') for ip in range(3): if ip != i: - fp.write('connect=localhost:{}\n'.format(PARTICL_PORT_BASE + ip)) + fp.write('connect=127.0.0.1:{}\n'.format(PARTICL_PORT_BASE + ip)) with open(os.path.join(client_path, 'monero', 'monerod.conf'), 'a') as fp: fp.write('p2p-bind-ip=127.0.0.1\n') @@ -196,7 +208,7 @@ class Test(unittest.TestCase): try: waitForServer(12701) - wallets = json.loads(urlopen('http://localhost:12701/json/wallets').read()) + wallets = json.loads(urlopen('http://127.0.0.1:12701/json/wallets').read()) xmr_addr1 = wallets['6']['deposit_address'] num_blocks = 100 @@ -229,7 +241,7 @@ class Test(unittest.TestCase): try: waitForServer(12700) waitForServer(12701) - wallets1 = json.loads(urlopen('http://localhost:12701/json/wallets').read()) + wallets1 = json.loads(urlopen('http://127.0.0.1:12701/json/wallets').read()) assert(float(wallets1['6']['balance']) > 0.0) data = parse.urlencode({ @@ -240,26 +252,26 @@ class Test(unittest.TestCase): 'amt_to': '1', 'lockhrs': '24'}).encode() - offer_id = json.loads(urlopen('http://localhost:12700/json/offers/new', data=data).read()) - summary = json.loads(urlopen('http://localhost:12700/json').read()) + offer_id = json.loads(urlopen('http://127.0.0.1:12700/json/offers/new', data=data).read())['offer_id'] + summary = json.loads(urlopen('http://127.0.0.1:12700/json').read()) assert(summary['num_sent_offers'] == 1) logger.info('Waiting for offer') waitForNumOffers(12701, 1) - offers = json.loads(urlopen('http://localhost:12701/json/offers').read()) + offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers').read()) offer = offers[0] data = parse.urlencode({ 'offer_id': offer['offer_id'], 'amount_from': offer['amount_from']}).encode() - bid_id = json.loads(urlopen('http://localhost:12701/json/bids/new', data=data).read()) + bid_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=data).read()) waitForNumBids(12700, 1) for i in range(10): - bids = json.loads(urlopen('http://localhost:12700/json/bids').read()) + bids = json.loads(urlopen('http://127.0.0.1:12700/json/bids').read()) bid = bids[0] if bid['bid_state'] == 'Received': break @@ -268,7 +280,7 @@ class Test(unittest.TestCase): data = parse.urlencode({ 'accept': True }).encode() - rv = json.loads(urlopen('http://localhost:12700/json/bids/{}'.format(bid['bid_id']), data=data).read()) + rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid['bid_id']), data=data).read()) assert(rv['bid_state'] == 'Accepted') waitForNumSwapping(12701, 1) @@ -281,19 +293,27 @@ class Test(unittest.TestCase): self.processes[1].start() waitForServer(12701) - rv = json.loads(urlopen('http://localhost:12701/json').read()) + rv = json.loads(urlopen('http://127.0.0.1:12701/json').read()) assert(rv['num_swapping'] == 1) + rv = json.loads(urlopen('http://127.0.0.1:12700/json/revokeoffer/{}'.format(offer_id)).read()) + assert(rv['revoked_offer'] == offer_id) + logger.info('Completing swap') for i in range(240): if delay_event.is_set(): raise ValueError('Test stopped.') delay_event.wait(4) - rv = json.loads(urlopen('http://localhost:12700/json/bids/{}'.format(bid['bid_id'])).read()) + rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid['bid_id'])).read()) if rv['bid_state'] == 'Completed': break assert(rv['bid_state'] == 'Completed') + + # Ensure offer was revoked + summary = json.loads(urlopen('http://127.0.0.1:12700/json').read()) + assert(summary['num_network_offers'] == 0) + except Exception as e: traceback.print_exc() raise(e) @@ -307,10 +327,89 @@ class Test(unittest.TestCase): try: waitForServer(12700) waitForServer(12701) - wallets1 = json.loads(urlopen('http://localhost:12701/json/wallets').read()) - print('wallets 1', json.dumps(wallets1, indent=4)) + wallets1 = json.loads(urlopen('http://127.0.0.1:12701/json/wallets').read()) assert(float(wallets1['6']['balance']) > 0.0) + offer_data = { + 'addr_from': '-1', + 'coin_from': '1', + 'coin_to': '6', + 'amt_from': '1', + 'amt_to': '1', + 'lockhrs': '24', + 'autoaccept': True} + rv = json.loads(urlopen('http://127.0.0.1:12700/json/offers/new', data=parse.urlencode(offer_data).encode()).read()) + offer0_id = rv['offer_id'] + + offer_data['amt_from'] = '2' + rv = json.loads(urlopen('http://127.0.0.1:12700/json/offers/new', data=parse.urlencode(offer_data).encode()).read()) + offer1_id = rv['offer_id'] + + summary = json.loads(urlopen('http://127.0.0.1:12700/json').read()) + assert(summary['num_sent_offers'] > 1) + + logger.info('Waiting for offer') + waitForNumOffers(12701, 2) + + logger.info('Stopping node 0') + c0 = self.processes[0] + c0.terminate() + c0.join() + + offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers/{}'.format(offer0_id)).read()) + assert(len(offers) == 1) + offer0 = offers[0] + + bid_data = { + 'offer_id': offer0_id, + 'amount_from': offer0['amount_from']} + + bid0_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(bid_data).encode()).read())['bid_id'] + + offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers/{}'.format(offer1_id)).read()) + assert(len(offers) == 1) + offer1 = offers[0] + + bid_data = { + 'offer_id': offer1_id, + 'amount_from': offer1['amount_from']} + + bid1_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(bid_data).encode()).read())['bid_id'] + + delay_event.wait(5) + + logger.info('Starting node 0') + self.processes[0] = multiprocessing.Process(target=self.run_thread, args=(0,)) + self.processes[0].start() + + waitForServer(12700) + waitForNumBids(12700, 2) + + waitForBidState(12700, bid0_id, 'Received') + waitForBidState(12700, bid1_id, 'Received') + + # Manually accept on top of auto-accept for extra chaos + data = parse.urlencode({ + 'accept': True + }).encode() + rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid0_id), data=data).read()) + assert(rv['bid_state'] == 'Accepted') + rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid1_id), data=data).read()) + assert(rv['bid_state'] == 'Accepted') + + logger.info('Completing swap') + for i in range(240): + if delay_event.is_set(): + raise ValueError('Test stopped.') + delay_event.wait(4) + + rv0 = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid0_id)).read()) + rv1 = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid1_id)).read()) + if rv0['bid_state'] == 'Completed' and rv1['bid_state'] == 'Completed': + break + assert(rv0['bid_state'] == 'Completed') + assert(rv1['bid_state'] == 'Completed') + except Exception as e: traceback.print_exc() raise(e) diff --git a/tests/basicswap/test_run.py b/tests/basicswap/test_run.py index 01e80a9..b78167e 100644 --- a/tests/basicswap/test_run.py +++ b/tests/basicswap/test_run.py @@ -152,7 +152,7 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey): 'debug': True, 'zmqhost': 'tcp://127.0.0.1', 'zmqport': BASE_ZMQ_PORT + nodeId, - 'htmlhost': 'localhost', + 'htmlhost': '127.0.0.1', 'htmlport': 12700 + nodeId, 'network_key': network_key, 'network_pubkey': network_pubkey, @@ -423,8 +423,8 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) - js_1 = json.loads(urlopen('http://localhost:1801/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) @@ -448,8 +448,8 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) - js_1 = json.loads(urlopen('http://localhost:1801/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) @@ -473,10 +473,10 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - js_0bid = json.loads(urlopen('http://localhost:1800/json/bids/{}'.format(bid_id.hex())).read()) + js_0bid = json.loads(urlopen('http://127.0.0.1:1800/json/bids/{}'.format(bid_id.hex())).read()) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) - js_1 = json.loads(urlopen('http://localhost:1801/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) @@ -502,8 +502,8 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.BID_ABANDONED, sent=True, wait_for=60) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) - js_1 = json.loads(urlopen('http://localhost:1801/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) @@ -511,7 +511,7 @@ class Test(unittest.TestCase): logging.info('---------- Test same client, BTC to LTC') swap_clients = self.swap_clients - js_0_before = json.loads(urlopen('http://localhost:1800/json').read()) + js_0_before = json.loads(urlopen('http://127.0.0.1:1800/json').read()) offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.LTC, 10 * COIN, 10 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST) @@ -527,7 +527,7 @@ class Test(unittest.TestCase): wait_for_bid_tx_state(delay_event, swap_clients[0], bid_id, TxStates.TX_REDEEMED, TxStates.TX_REDEEMED, wait_for=60) wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) 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) @@ -535,7 +535,7 @@ class Test(unittest.TestCase): logging.info('---------- Test error, BTC to LTC, set fee above bid value') swap_clients = self.swap_clients - js_0_before = json.loads(urlopen('http://localhost:1800/json').read()) + js_0_before = json.loads(urlopen('http://127.0.0.1:1800/json').read()) offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.LTC, 0.001 * COIN, 1.0 * COIN, 0.001 * COIN, SwapTypes.SELLER_FIRST) @@ -580,8 +580,8 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - js_0 = json.loads(urlopen('http://localhost:1800/json').read()) - js_1 = json.loads(urlopen('http://localhost:1801/json').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json').read()) assert(js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) assert(js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) diff --git a/tests/basicswap/test_xmr.py b/tests/basicswap/test_xmr.py index ddd67d8..298a492 100644 --- a/tests/basicswap/test_xmr.py +++ b/tests/basicswap/test_xmr.py @@ -119,7 +119,7 @@ def startXmrWalletRPC(node_dir, bin_dir, wallet_bin, node_id, opts=[]): data_dir = os.path.expanduser(node_dir) args = [daemon_bin] args += ['--non-interactive'] - args += ['--daemon-address=localhost:{}'.format(XMR_BASE_RPC_PORT + node_id)] + args += ['--daemon-address=127.0.0.1:{}'.format(XMR_BASE_RPC_PORT + node_id)] args += ['--no-dns'] args += ['--rpc-bind-port={}'.format(XMR_BASE_WALLET_RPC_PORT + node_id)] args += ['--wallet-dir={}'.format(os.path.join(data_dir, 'wallets'))] @@ -145,7 +145,7 @@ def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey): 'debug': True, 'zmqhost': 'tcp://127.0.0.1', 'zmqport': BASE_ZMQ_PORT + node_id, - 'htmlhost': 'localhost', + 'htmlhost': '127.0.0.1', 'htmlport': TEST_HTTP_PORT + node_id, 'network_key': network_key, 'network_pubkey': network_pubkey, @@ -431,7 +431,7 @@ class Test(unittest.TestCase): logging.info('---------- Test PART to XMR') swap_clients = self.swap_clients - js_1 = json.loads(urlopen('http://localhost:1801/json/wallets').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json/wallets').read()) assert(make_int(js_1[str(int(Coins.XMR))]['balance'], scale=12) > 0) assert(make_int(js_1[str(int(Coins.XMR))]['unconfirmed'], scale=12) > 0) @@ -453,7 +453,7 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) - js_0_end = json.loads(urlopen('http://localhost:1800/json/wallets').read()) + js_0_end = json.loads(urlopen('http://127.0.0.1:1800/json/wallets').read()) end_xmr = float(js_0_end['6']['balance']) + float(js_0_end['6']['unconfirmed']) assert(end_xmr > 10.9 and end_xmr < 11.0) @@ -461,7 +461,7 @@ class Test(unittest.TestCase): logging.info('---------- Test PART to XMR leader recovers coin a lock tx') swap_clients = self.swap_clients - js_w0_before = json.loads(urlopen('http://localhost:1800/json/wallets').read()) + js_w0_before = json.loads(urlopen('http://127.0.0.1:1800/json/wallets').read()) offer_id = swap_clients[0].postOffer( Coins.PART, Coins.XMR, 101 * COIN, 0.12 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP, @@ -483,7 +483,7 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True) - js_w0_after = json.loads(urlopen('http://localhost:1800/json/wallets').read()) + js_w0_after = json.loads(urlopen('http://127.0.0.1:1800/json/wallets').read()) print('[rm] js_w0_before', json.dumps(js_w0_before)) print('[rm] js_w0_after', json.dumps(js_w0_after)) @@ -491,7 +491,7 @@ class Test(unittest.TestCase): logging.info('---------- Test PART to XMR follower recovers coin a lock tx') swap_clients = self.swap_clients - js_w0_before = json.loads(urlopen('http://localhost:1800/json/wallets').read()) + js_w0_before = json.loads(urlopen('http://127.0.0.1:1800/json/wallets').read()) offer_id = swap_clients[0].postOffer( Coins.PART, Coins.XMR, 101 * COIN, 0.13 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP, @@ -514,7 +514,7 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_ABANDONED, wait_for=180) wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=80, sent=True) - js_w0_after = json.loads(urlopen('http://localhost:1800/json/wallets').read()) + js_w0_after = json.loads(urlopen('http://127.0.0.1:1800/json/wallets').read()) wait_for_none_active(delay_event, 1800) wait_for_none_active(delay_event, 1801) @@ -629,11 +629,11 @@ class Test(unittest.TestCase): def test_08_withdraw(self): logging.info('---------- Test xmr withdrawals') swap_clients = self.swap_clients - js_0 = json.loads(urlopen('http://localhost:1800/json/wallets').read()) + js_0 = json.loads(urlopen('http://127.0.0.1:1800/json/wallets').read()) print('js_0 debug', js_0) address_to = js_0[str(int(Coins.XMR))]['deposit_address'] - js_1 = json.loads(urlopen('http://localhost:1801/json/wallets').read()) + js_1 = json.loads(urlopen('http://127.0.0.1:1801/json/wallets').read()) assert(float(js_1[str(int(Coins.XMR))]['balance']) > 0.0) swap_clients[1].withdrawCoin(Coins.XMR, 1.1, address_to, False) diff --git a/tox.ini b/tox.ini index 1d73a60..08070b7 100644 --- a/tox.ini +++ b/tox.ini @@ -9,6 +9,8 @@ passenv = BITCOIN_BINDIR LITECOIN_BINDIR XMR_BINDIR + TEST_PREPARE_PATH + TEST_RELOAD_PATH deps = pytest -rrequirements.txt