From a2afd3f00f5fe062a1773c4d71a6cd54e47a2107 Mon Sep 17 00:00:00 2001 From: tecnovert Date: Fri, 1 Jul 2022 16:37:10 +0200 Subject: [PATCH] refactor: Separate MSG4F and lock txn sending --- Dockerfile | 7 +- basicswap/__init__.py | 2 +- basicswap/basicswap.py | 147 ++++--- basicswap/basicswap_util.py | 11 + basicswap/db.py | 7 +- basicswap/db_upgrades.py | 14 +- .../xmr.bidder.alt.xu.min.svg | 408 +++++++++++++++++- .../xmr.offerer.alt.xu.min.svg | 389 ++++++++++++++++- doc/protocols/sequence_diagrams/.gitignore | 1 + .../sequence_diagrams/xmr.bidder.alt.xu | 80 ++++ .../sequence_diagrams/xmr.offerer.alt.xu | 7 +- .../sequence_diagrams/xmr.offerer.simple.xu | 55 --- docker/production/swapclient/Dockerfile | 7 +- tests/basicswap/common_xmr.py | 2 + tests/basicswap/extended/test_network.py | 2 + .../basicswap/extended/test_xmr_persistent.py | 2 + tests/basicswap/test_xmr.py | 2 + 17 files changed, 1003 insertions(+), 140 deletions(-) create mode 100644 doc/protocols/sequence_diagrams/.gitignore create mode 100644 doc/protocols/sequence_diagrams/xmr.bidder.alt.xu delete mode 100644 doc/protocols/sequence_diagrams/xmr.offerer.simple.xu diff --git a/Dockerfile b/Dockerfile index d51f42f..c121e92 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,9 +15,10 @@ RUN wget -O protobuf_src.tar.gz https://github.com/protocolbuffers/protobuf/rele make install && \ ldconfig -RUN wget -O coincurve-anonswap.zip https://github.com/tecnovert/coincurve/archive/refs/tags/anonswap_v0.1.zip && \ - unzip -d coincurve-anonswap coincurve-anonswap.zip && \ - mv ./coincurve-anonswap/*/{.,}* ./coincurve-anonswap || true && \ +ARG COINCURVE_VERSION=v0.1 +RUN wget -O coincurve-anonswap.zip https://github.com/tecnovert/coincurve/archive/refs/tags/anonswap_$COINCURVE_VERSION.zip && \ + unzip coincurve-anonswap.zip && \ + mv ./coincurve-anonswap_$COINCURVE_VERSION ./coincurve-anonswap && \ cd coincurve-anonswap && \ python3 setup.py install --force diff --git a/basicswap/__init__.py b/basicswap/__init__.py index 7b60633..440097b 100644 --- a/basicswap/__init__.py +++ b/basicswap/__init__.py @@ -1,3 +1,3 @@ name = "basicswap" -__version__ = "0.0.33" +__version__ = "0.0.34" diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 341fdfb..8a71404 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -225,6 +225,8 @@ class BasicSwap(BaseApp): # TODO: Adjust ranges self.min_delay_event = self.settings.get('min_delay_event', 10) self.max_delay_event = self.settings.get('max_delay_event', 60) + self.min_delay_event_short = self.settings.get('min_delay_event_short', 2) + self.max_delay_event_short = self.settings.get('max_delay_event_short', 30) self.min_delay_retry = self.settings.get('min_delay_retry', 60) self.max_delay_retry = self.settings.get('max_delay_retry', 5 * 60) @@ -893,6 +895,21 @@ class BasicSwap(BaseApp): nm += 1 self.log.info('Scanned %d unread messages.', nm) + def getActiveBidMsgValidTime(self): + return self.SMSG_SECONDS_IN_HOUR * 48 + + def getAcceptBidMsgValidTime(self, bid): + now = int(time.time()) + smsg_max_valid = self.SMSG_SECONDS_IN_HOUR * 48 + smsg_min_valid = self.SMSG_SECONDS_IN_HOUR * 1 + bid_valid = (bid.expire_at - now) + 10 * 60 # Add 10 minute buffer + return max(smsg_min_valid, min(smsg_max_valid, bid_valid)) + + def sendSmsg(self, addr_from, addr_to, payload_hex, msg_valid): + options = {'decodehex': True, 'ttl_is_seconds': True} + ro = self.callrpc('smsgsend', [addr_from, addr_to, payload_hex, False, msg_valid, False, options]) + return bytes.fromhex(ro['msgid']) + def validateSwapType(self, coin_from, coin_to, swap_type): if coin_from == Coins.XMR: raise ValueError('TODO: XMR coin_from') @@ -1054,13 +1071,8 @@ class BasicSwap(BaseApp): offer_bytes = msg_buf.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.OFFER) + offer_bytes.hex() - - options = {'decodehex': True, 'ttl_is_seconds': True} msg_valid = max(self.SMSG_SECONDS_IN_HOUR * 1, valid_for_seconds) - ro = self.callrpc('smsgsend', [offer_addr, offer_addr_to, payload_hex, False, msg_valid, False, options]) - msg_id = ro['msgid'] - - offer_id = bytes.fromhex(msg_id) + offer_id = self.sendSmsg(offer_addr, offer_addr_to, payload_hex, msg_valid) security_token = extra_options.get('security_token', None) if security_token is not None and len(security_token) != 20: @@ -1145,10 +1157,8 @@ class BasicSwap(BaseApp): msg_bytes = msg_buf.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.OFFER_REVOKE) + msg_bytes.hex() - - options = {'decodehex': True, 'ttl_is_seconds': True} - ro = self.callrpc('smsgsend', [offer.addr_from, self.network_addr, payload_hex, False, offer.time_valid, False, options]) - msg_id = ro['msgid'] + msg_id = self.sendSmsg(offer.addr_from, self.network_addr, payload_hex, offer.time_valid) + self.log.debug('Revoked offer %s in msg %s', offer_id.hex(), msg_id.hex()) finally: if session: session.close() @@ -1680,10 +1690,8 @@ class BasicSwap(BaseApp): bid_addr = self.newSMSGAddress(use_type=AddressTypes.BID)[0] if addr_send_from is None else addr_send_from options = {'decodehex': True, 'ttl_is_seconds': True} msg_valid = max(self.SMSG_SECONDS_IN_HOUR * 1, valid_for_seconds) - ro = self.callrpc('smsgsend', [bid_addr, offer.addr_from, payload_hex, False, msg_valid, False, options]) - msg_id = ro['msgid'] - bid_id = bytes.fromhex(msg_id) + bid_id = self.sendSmsg(bid_addr, offer.addr_from, payload_hex, msg_valid) bid = Bid( protocol_version=msg_buf.protocol_version, active_ind=1, @@ -1962,19 +1970,13 @@ class BasicSwap(BaseApp): bid_bytes = msg_buf.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.BID_ACCEPT) + bid_bytes.hex() - options = {'decodehex': True, 'ttl_is_seconds': True} - # TODO: set msg_valid based on bid / offer parameters - msg_valid = self.SMSG_SECONDS_IN_HOUR * 48 - ro = self.callrpc('smsgsend', [offer.addr_from, bid.bid_addr, payload_hex, False, msg_valid, False, options]) - msg_id = ro['msgid'] - accept_msg_id = bytes.fromhex(msg_id) + msg_valid = self.getAcceptBidMsgValidTime(bid) + bid.accept_msg_id = self.sendSmsg(offer.addr_from, bid.bid_addr, payload_hex, msg_valid) - bid.accept_msg_id = accept_msg_id + self.log.info('Sent BID_ACCEPT %s', bid.accept_msg_id.hex()) bid.setState(BidStates.BID_ACCEPTED) - self.log.info('Sent BID_ACCEPT %s', accept_msg_id.hex()) - self.saveBid(bid_id, bid) self.swaps_in_progress[bid_id] = (bid, offer) @@ -2064,8 +2066,7 @@ class BasicSwap(BaseApp): bid_addr = self.newSMSGAddress(use_type=AddressTypes.BID)[0] if addr_send_from is None else addr_send_from options = {'decodehex': True, 'ttl_is_seconds': True} msg_valid = max(self.SMSG_SECONDS_IN_HOUR * 1, valid_for_seconds) - ro = self.callrpc('smsgsend', [bid_addr, offer.addr_from, payload_hex, False, msg_valid, False, options]) - xmr_swap.bid_id = bytes.fromhex(ro['msgid']) + xmr_swap.bid_id = self.sendSmsg(bid_addr, offer.addr_from, payload_hex, msg_valid) if coin_to == Coins.XMR: msg_buf2 = XmrSplitMessage( @@ -2076,8 +2077,7 @@ class BasicSwap(BaseApp): ) msg_bytes = msg_buf2.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_SPLIT) + msg_bytes.hex() - ro = self.callrpc('smsgsend', [bid_addr, offer.addr_from, payload_hex, False, msg_valid, False, options]) - xmr_swap.bid_msg_id2 = bytes.fromhex(ro['msgid']) + xmr_swap.bid_msg_id2 = self.sendSmsg(bid_addr, offer.addr_from, payload_hex, msg_valid) msg_buf3 = XmrSplitMessage( msg_id=xmr_swap.bid_id, @@ -2087,8 +2087,7 @@ class BasicSwap(BaseApp): ) msg_bytes = msg_buf3.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_SPLIT) + msg_bytes.hex() - ro = self.callrpc('smsgsend', [bid_addr, offer.addr_from, payload_hex, False, msg_valid, False, options]) - xmr_swap.bid_msg_id3 = bytes.fromhex(ro['msgid']) + xmr_swap.bid_msg_id3 = self.sendSmsg(bid_addr, offer.addr_from, payload_hex, msg_valid) bid = Bid( protocol_version=msg_buf.protocol_version, @@ -2266,11 +2265,9 @@ class BasicSwap(BaseApp): msg_bytes = msg_buf.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_ACCEPT_LF) + msg_bytes.hex() - options = {'decodehex': True, 'ttl_is_seconds': True} - msg_valid = self.SMSG_SECONDS_IN_HOUR * 48 - ro = self.callrpc('smsgsend', [offer.addr_from, bid.bid_addr, payload_hex, False, msg_valid, False, options]) - msg_id = ro['msgid'] - bid.accept_msg_id = bytes.fromhex(msg_id) + + msg_valid = self.getAcceptBidMsgValidTime(bid) + bid.accept_msg_id = self.sendSmsg(offer.addr_from, bid.bid_addr, payload_hex, msg_valid) xmr_swap.bid_accept_msg_id = bid.accept_msg_id if coin_to == Coins.XMR: @@ -2282,8 +2279,7 @@ class BasicSwap(BaseApp): ) msg_bytes = msg_buf2.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_SPLIT) + msg_bytes.hex() - ro = self.callrpc('smsgsend', [offer.addr_from, bid.bid_addr, payload_hex, False, msg_valid, False, options]) - xmr_swap.bid_accept_msg_id2 = bytes.fromhex(ro['msgid']) + xmr_swap.bid_accept_msg_id2 = self.sendSmsg(offer.addr_from, bid.bid_addr, payload_hex, msg_valid) msg_buf3 = XmrSplitMessage( msg_id=bid_id, @@ -2293,8 +2289,7 @@ class BasicSwap(BaseApp): ) msg_bytes = msg_buf3.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_SPLIT) + msg_bytes.hex() - ro = self.callrpc('smsgsend', [offer.addr_from, bid.bid_addr, payload_hex, False, msg_valid, False, options]) - xmr_swap.bid_accept_msg_id3 = bytes.fromhex(ro['msgid']) + xmr_swap.bid_accept_msg_id3 = self.sendSmsg(offer.addr_from, bid.bid_addr, payload_hex, msg_valid) bid.setState(BidStates.BID_ACCEPTED) @@ -2946,7 +2941,7 @@ class BasicSwap(BaseApp): rv = True # Remove from swaps_in_progress elif state == BidStates.XMR_SWAP_FAILED_SWIPED: rv = True # Remove from swaps_in_progress - elif state == BidStates.XMR_SWAP_HAVE_SCRIPT_COIN_SPEND_TX: + elif state in (BidStates.XMR_SWAP_HAVE_SCRIPT_COIN_SPEND_TX, BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX): if bid.xmr_a_lock_tx is None: return rv @@ -3585,6 +3580,8 @@ class BasicSwap(BaseApp): self.redeemXmrBidCoinBLockTx(row.linked_id, session) elif row.action_type == ActionTypes.RECOVER_XMR_SWAP_LOCK_TX_B: self.recoverXmrBidCoinBLockTx(row.linked_id, session) + elif row.action_type == ActionTypes.SEND_XMR_SWAP_LOCK_SPEND_MSG: + self.sendXmrBidCoinALockSpendTxMsg(row.linked_id, session) else: self.log.warning('Unknown event type: %d', row.event_type) except Exception as ex: @@ -4165,7 +4162,7 @@ class BasicSwap(BaseApp): if xmr_swap.pkal == xmr_swap.pkaf: raise ValueError('Duplicate script spend pubkey.') - bid.setState(BidStates.SWAP_DELAYING) + bid.setState(BidStates.BID_ACCEPTED) # XMR self.saveBidInSession(bid.bid_id, bid, session, xmr_swap) delay = random.randrange(self.min_delay_event, self.max_delay_event) @@ -4387,11 +4384,8 @@ class BasicSwap(BaseApp): msg_bytes = msg_buf.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_TXN_SIGS_FL) + msg_bytes.hex() - options = {'decodehex': True, 'ttl_is_seconds': True} - # TODO: set msg_valid based on bid / offer parameters - msg_valid = self.SMSG_SECONDS_IN_HOUR * 48 - ro = self.callrpc('smsgsend', [bid.bid_addr, offer.addr_from, payload_hex, False, msg_valid, False, options]) - xmr_swap.coin_a_lock_tx_sigs_l_msg_id = bytes.fromhex(ro['msgid']) + msg_valid = self.getActiveBidMsgValidTime() + xmr_swap.coin_a_lock_tx_sigs_l_msg_id = self.sendSmsg(bid.bid_addr, offer.addr_from, payload_hex, msg_valid) self.log.info('Sent XMR_BID_TXN_SIGS_FL %s', xmr_swap.coin_a_lock_tx_sigs_l_msg_id.hex()) @@ -4406,7 +4400,7 @@ class BasicSwap(BaseApp): ) bid.xmr_a_lock_tx.setState(TxStates.TX_NONE) - bid.setState(BidStates.BID_ACCEPTED) # XMR + bid.setState(BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS) self.watchXmrSwap(bid, offer, xmr_swap) self.saveBidInSession(bid_id, bid, session, xmr_swap) except Exception as ex: @@ -4414,7 +4408,7 @@ class BasicSwap(BaseApp): self.log.error(traceback.format_exc()) def sendXmrBidCoinALockTx(self, bid_id, session): - # Send coin A lock tx and MSG4F L -> F + # Offerer/Leader. Send coin A lock tx self.log.debug('Sending coin A lock tx for xmr bid %s', bid_id.hex()) bid, xmr_swap = self.getXmrBidFromSession(session, bid_id) @@ -4431,6 +4425,10 @@ class BasicSwap(BaseApp): kal = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, KeyTypes.KAL) + # Prove leader can sign for kal, sent in MSG4F + xmr_swap.kal_sig = ci_from.signCompact(kal, 'proof key owned for swap') + + # Create Script lock spend tx xmr_swap.a_lock_spend_tx = ci_from.createScriptLockSpendTx( xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script, xmr_swap.dest_af, @@ -4440,24 +4438,9 @@ class BasicSwap(BaseApp): prevout_amount = ci_from.getLockTxSwapOutputValue(bid, xmr_swap) xmr_swap.al_lock_spend_tx_esig = ci_from.signTxOtVES(kal, xmr_swap.pkasf, xmr_swap.a_lock_spend_tx, 0, xmr_swap.a_lock_tx_script, prevout_amount) - # Prove leader can sign for kal - xmr_swap.kal_sig = ci_from.signCompact(kal, 'proof key owned for swap') - - msg_buf = XmrBidLockSpendTxMessage( - bid_msg_id=bid_id, - a_lock_spend_tx=xmr_swap.a_lock_spend_tx, - kal_sig=xmr_swap.kal_sig) - - msg_bytes = msg_buf.SerializeToString() - payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_LOCK_SPEND_TX_LF) + msg_bytes.hex() - - options = {'decodehex': True, 'ttl_is_seconds': True} - # TODO: set msg_valid based on bid / offer parameters - msg_valid = self.SMSG_SECONDS_IN_HOUR * 48 - ro = self.callrpc('smsgsend', [offer.addr_from, bid.bid_addr, payload_hex, False, msg_valid, False, options]) - xmr_swap.coin_a_lock_refund_spend_tx_msg_id = bytes.fromhex(ro['msgid']) - - # TODO: Separate MSG4F and txn sending + delay = random.randrange(self.min_delay_event_short, self.max_delay_event_short) + self.log.info('Sending lock spend tx message for bid %s in %d seconds', bid_id.hex(), delay) + self.createActionInSession(delay, ActionTypes.SEND_XMR_SWAP_LOCK_SPEND_MSG, bid_id, session) # publishalocktx lock_tx_signed = ci_from.signTxWithWallet(xmr_swap.a_lock_tx) @@ -4560,11 +4543,8 @@ class BasicSwap(BaseApp): msg_bytes = msg_buf.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_LOCK_RELEASE_LF) + msg_bytes.hex() - options = {'decodehex': True, 'ttl_is_seconds': True} - # TODO: set msg_valid based on bid / offer parameters - msg_valid = self.SMSG_SECONDS_IN_HOUR * 48 - ro = self.callrpc('smsgsend', [offer.addr_from, bid.bid_addr, payload_hex, False, msg_valid, False, options]) - xmr_swap.coin_a_lock_refund_spend_tx_msg_id = bytes.fromhex(ro['msgid']) + msg_valid = self.getActiveBidMsgValidTime() + xmr_swap.coin_a_lock_release_msg_id = self.sendSmsg(offer.addr_from, bid.bid_addr, payload_hex, msg_valid) bid.setState(BidStates.XMR_SWAP_LOCK_RELEASED) self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer) @@ -4740,6 +4720,33 @@ class BasicSwap(BaseApp): bid.setState(BidStates.XMR_SWAP_NOSCRIPT_TX_RECOVERED) self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer) + def sendXmrBidCoinALockSpendTxMsg(self, bid_id, session): + # Send MSG4F L -> F + self.log.debug('Sending coin A lock spend tx msg for xmr bid %s', bid_id.hex()) + + bid, xmr_swap = self.getXmrBidFromSession(session, bid_id) + ensure(bid, 'Bid not found: {}.'.format(bid_id.hex())) + ensure(xmr_swap, 'XMR swap not found: {}.'.format(bid_id.hex())) + + offer, xmr_offer = self.getXmrOfferFromSession(session, bid.offer_id, sent=False) + ensure(offer, 'Offer not found: {}.'.format(bid.offer_id.hex())) + ensure(xmr_offer, 'XMR offer not found: {}.'.format(bid.offer_id.hex())) + ci_from = self.ci(offer.coin_from) + + msg_buf = XmrBidLockSpendTxMessage( + bid_msg_id=bid_id, + a_lock_spend_tx=xmr_swap.a_lock_spend_tx, + kal_sig=xmr_swap.kal_sig) + + msg_bytes = msg_buf.SerializeToString() + payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_LOCK_SPEND_TX_LF) + msg_bytes.hex() + + msg_valid = self.getActiveBidMsgValidTime() + xmr_swap.coin_a_lock_refund_spend_tx_msg_id = self.sendSmsg(offer.addr_from, bid.bid_addr, payload_hex, msg_valid) + + bid.setState(BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX) + self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer) + def processXmrBidCoinALockSigs(self, msg): # Leader processing MSG3L self.log.debug('Processing xmr coin a follower lock sigs msg %s', msg['msgid']) @@ -4795,7 +4802,7 @@ class BasicSwap(BaseApp): self.log.info('Sending coin A lock tx for xmr bid %s in %d seconds', bid_id.hex(), delay) self.createAction(delay, ActionTypes.SEND_XMR_SWAP_LOCK_TX_A, bid_id) - bid.setState(BidStates.SWAP_DELAYING) + bid.setState(BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS) self.saveBid(bid_id, bid, xmr_swap=xmr_swap) except Exception as ex: if self.debug: diff --git a/basicswap/basicswap_util.py b/basicswap/basicswap_util.py index 3ce9935..7854e8c 100644 --- a/basicswap/basicswap_util.py +++ b/basicswap/basicswap_util.py @@ -96,6 +96,8 @@ class BidStates(IntEnum): BID_STALLED_FOR_TEST = 24 BID_REJECTED = 25 BID_STATE_UNKNOWN = 26 + XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS = 27 # XmrBidLockTxSigsMessage + XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX = 28 # XmrBidLockSpendTxMessage class TxStates(IntEnum): @@ -132,6 +134,7 @@ class ActionTypes(IntEnum): REDEEM_XMR_SWAP_LOCK_TX_A = auto() # Follower REDEEM_XMR_SWAP_LOCK_TX_B = auto() # Leader RECOVER_XMR_SWAP_LOCK_TX_B = auto() + SEND_XMR_SWAP_LOCK_SPEND_MSG = auto() class EventLogTypes(IntEnum): @@ -235,6 +238,10 @@ def strBidState(state): return 'Failed' if state == BidStates.SWAP_DELAYING: return 'Delaying' + if state == BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS: + return 'Exchanged script lock tx sigs msg' + if state == BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX: + return 'Exchanged script lock spend tx msg' return 'Unknown' + ' ' + str(state) @@ -408,4 +415,8 @@ def isActiveBidState(state): return True if state == BidStates.XMR_SWAP_SCRIPT_TX_PREREFUND: return True + if state == BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS: + return True + if state == BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX: + return True return False diff --git a/basicswap/db.py b/basicswap/db.py index 75b036c..e5bf6f7 100644 --- a/basicswap/db.py +++ b/basicswap/db.py @@ -12,8 +12,8 @@ from enum import IntEnum, auto from sqlalchemy.ext.declarative import declarative_base -CURRENT_DB_VERSION = 14 -CURRENT_DB_DATA_VERSION = 1 +CURRENT_DB_VERSION = 15 +CURRENT_DB_DATA_VERSION = 2 Base = declarative_base() @@ -301,7 +301,8 @@ class XmrSwap(Base): bid_accept_msg_id3 = sa.Column(sa.LargeBinary) coin_a_lock_tx_sigs_l_msg_id = sa.Column(sa.LargeBinary) # MSG3L F -> L - coin_a_lock_refund_spend_tx_msg_id = sa.Column(sa.LargeBinary) # MSG4F L -> F + coin_a_lock_spend_tx_msg_id = sa.Column(sa.LargeBinary) # MSG4F L -> F + coin_a_lock_release_msg_id = sa.Column(sa.LargeBinary) # MSG5F L -> F contract_count = sa.Column(sa.Integer) diff --git a/basicswap/db_upgrades.py b/basicswap/db_upgrades.py index 08f79c1..6e1784f 100644 --- a/basicswap/db_upgrades.py +++ b/basicswap/db_upgrades.py @@ -59,6 +59,15 @@ def upgradeDatabaseData(self, data_version): label=strBidState(state), created_at=now)) + if data_version < 2: + for state in (BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS, BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX): + session.add(BidState( + active_ind=1, + state_id=int(state), + in_progress=isActiveBidState(state), + label=strBidState(state), + created_at=now)) + self.db_data_version = CURRENT_DB_DATA_VERSION self.setIntKVInSession('db_data_version', self.db_data_version, session) session.commit() @@ -203,7 +212,10 @@ def upgradeDatabase(self, db_version): session.execute('ALTER TABLE actions RENAME COLUMN event_id TO action_id') session.execute('ALTER TABLE actions RENAME COLUMN event_type TO action_type') session.execute('ALTER TABLE actions RENAME COLUMN event_data TO action_data') - + elif current_version == 14: + db_version += 1 + session.execute('ALTER TABLE xmr_swaps ADD COLUMN coin_a_lock_release_msg_id BLOB') + session.execute('ALTER TABLE xmr_swaps RENAME COLUMN coin_a_lock_refund_spend_tx_msg_id TO coin_a_lock_spend_tx_msg_id') if current_version != db_version: self.db_version = db_version self.setIntKVInSession('db_version', db_version, session) diff --git a/basicswap/static/sequence_diagrams/xmr.bidder.alt.xu.min.svg b/basicswap/static/sequence_diagrams/xmr.bidder.alt.xu.min.svg index c4b0e55..ae54aed 100644 --- a/basicswap/static/sequence_diagrams/xmr.bidder.alt.xu.min.svg +++ b/basicswap/static/sequence_diagrams/xmr.bidder.alt.xu.min.svg @@ -1 +1,407 @@ - NetworkOffererBidder Sends OfferDetects OfferSends BidSends BidAccept messageSends XmrBidLockTxSigsMessageSends XmrBidLockSpendTxMessageSends script-coin-lock-txWait forscript-coin-lock-tx toconfirmSends noscript-coin-lock-txWait fornoscript-coin-lock-tx toconfirmWait fornoscript-coin-lock-tx toconfirmSends script-coin-lock-txrelease messageSends script-coin-lock-spend-txfail pathWait forscript-coin-lock-tx lock toexpireSendsscript-coin-lock-pre-refund-txscript-coin-lock-pre-refund-txWait forpre-refund tx to confirmSendsscript-coin-lock-pre-refund-spend-txDetects script-coin-lock-pre-refund-spend-txSends scriptless-coin-lock-recover-txbidder swipes script coin lock txWait forpre-refund tx lock to expireSends script-coin-lock-pre-refund-swipe-txBid SentUser accepts bidThe BidAccept message contains the pubkeys the offerer will use anda DLEAG proof one key will work across both chains of the swappingcoinsBid Receiving acceptBid AcceptedThe XmrBidLockTxSigsMessage contains the bidder's signatures for thescript-coin-lock-refund and script-coin-lock-refund-spend txns.The XmrBidLockSpendTxMessage contains the script-coin-lock-tx andthe offerer's signature for it.Bid Script coin spend tx validBid Script coin lockedalt: success pathBid Scriptless coin lockedThe XmrBidLockReleaseMessage contains the offerer's OTVES for it. The bidder decodes the offerer's signaturefrom the OTVES. When the offerer has theplaintext signature, they can decode the bidder's noscript-coin-lock-txsignature.Script coin lock releasedScript tx redeemedBid Completedtx can be sent by either party.Bid Script pre-refund tx inchainalt: offerer refunds script coin lock txRefunds the script lock tx, with the offerer's cleartext signaturethe bidder can refund the noscript lock tx. Once the lock expires the pre-refund tx can be spent by the bidder.Bid Failed, refundedBidder recovers the offerer's scriptless chain key-shard.Bid Scriptless tx recoveredBid Failed, refundedBid Failed, swiped \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Network + + Offerer + + Bidder + + + + + + + Sends Offer + + + Detects Offer + + + Sends Bid + + + Sends BidAccept message + + + Sends XmrBidLockTxSigsMessage + + + Sends XmrBidLockSpendTxMessage + + + Sends script-coin-lock-tx + + + Wait for + + script-coin-lock-tx to + + confirm + + + Sends noscript-coin-lock-tx + + + Wait for + + noscript-coin-lock-tx to + + confirm + + + Wait for + + noscript-coin-lock-tx to + + confirm + + + Sends script-coin-lock-tx + + release message + + + Sends script-coin-lock-spend-tx + + + fail path + + + Wait for + + script-coin-lock-tx lock to + + expire + + + Sends + + script-coin-lock-pre-refund-tx + + + script-coin-lock-pre-refund-tx + + + Wait for + + pre-refund tx to confirm + + + Sends + + script-coin-lock-pre-refund-spend-tx + + + Detects script-coin-lock-pre-refund-spend-tx + + + Sends scriptless-coin-lock-recover-tx + + + bidder swipes script coin lock tx + + + Wait for + + pre-refund tx lock to expire + + + Sends script-coin-lock-pre-refund-swipe-tx + + + + Bid Sent + + User accepts bid + + The BidAccept message contains the pubkeys the offerer will use and + a DLEAG proof one key will work across both chains of the swapping + coins + + Bid Receiving accept + + Bid Accepted + + The XmrBidLockTxSigsMessage contains the bidder's signatures for the + script-coin-lock-refund and script-coin-lock-refund-spend txns. + + Exchanged script lock tx sigs + msg + + The XmrBidLockSpendTxMessage contains the script-coin-lock-tx and + the offerer's signature for it. + + Bid Script coin spend tx valid + + Bid Script coin locked + + alt: success path + + Bid Scriptless coin locked + + The XmrBidLockReleaseMessage contains the offerer's OTVES for it. + The bidder decodes the offerer's signature + from the OTVES. When the offerer has the + plaintext signature, they can decode the bidder's noscript-coin-lock-tx + signature. + + Script coin lock released + + Script tx redeemed + + Bid Completed + + tx can be sent by either party. + + Bid Script pre-refund tx in + chain + + alt: offerer refunds script coin lock tx + + Refunds the script lock tx, with the offerer's cleartext signature + the bidder can refund the noscript lock tx. + Once the lock expires the pre-refund tx can be spent by the bidder. + + Bid Failed, refunded + + Bidder recovers the offerer's scriptless chain key-shard. + + Bid Scriptless tx recovered + + Bid Failed, refunded + + Bid Failed, swiped + + + diff --git a/basicswap/static/sequence_diagrams/xmr.offerer.alt.xu.min.svg b/basicswap/static/sequence_diagrams/xmr.offerer.alt.xu.min.svg index 2b53bc2..7c9a847 100644 --- a/basicswap/static/sequence_diagrams/xmr.offerer.alt.xu.min.svg +++ b/basicswap/static/sequence_diagrams/xmr.offerer.alt.xu.min.svg @@ -1 +1,388 @@ - NetworkOffererBidder Sends OfferDetects OfferSends BidSends BidAccept messageSends XmrBidLockTxSigsMessageSends XmrBidLockSpendTxMessageSends script-coin-lock-txWait forscript-coin-lock-tx toconfirmWait forscript-coin-lock-tx toconfirmSends noscript-coin-lock-txWait fornoscript-coin-lock-tx toconfirmSends script-coin-lock-txrelease messageSends script-coin-lock-spend-txDetects script-coin-lock-spend-txSends noscript-coin-lock-spend-txWait fornoscript-coin-lock-spend-txto confirmfail pathWait forscript-coin-lock-txlocktime to expireSendsscript-coin-lock-pre-refund-txscript-coin-lock-pre-refund-txWait forpre-refund tx to confirmSendsscript-coin-lock-pre-refund-spend-txBid ReceivingBid ReceivedUser accepts bidThe BidAccept message contains the pubkeys the offerer will use and aDLEAG proof one key will work across both chains of the swapping coinsBid AcceptedThe XmrBidLockTxSigsMessage contains the bidder's signatures for thescript-coin-lock-refund and script-coin-lock-refund-spend txns.The XmrBidLockSpendTxMessage contains the script-coin-lock-tx and theofferer's signature for it.Bid Script coin spend tx validBid Script coin lockedalt: success pathBid Scriptless coin lockedThe XmrBidLockReleaseMessage contains the offerer's OTVES for thescript-coin-lock-tx. The bidder decodes theofferer's signature from the OTVES. When theofferer has the plaintext signature, they can decode the bidder's keyfor the noscript-lock-tx.Bid Script coin lock releasedBid Script tx redeemedThe offerer extracts the bidder's plaintext signature and derives thebidder's noscript-lock-tx keyhalf.Bid Scriptless tx redeemedBid Completedtx can be sent by either party.Bid Script pre-refund tx inchainRefunds the script lock tx, with the offerer's cleartext signaturethe bidder can refund the noscript lock tx.Bid Failed, refunded \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Network + + Offerer + + Bidder + + + + + + + Sends Offer + + + Detects Offer + + + Sends Bid + + + Sends BidAccept message + + + Sends XmrBidLockTxSigsMessage + + + Sends script-coin-lock-tx + + + Sends XmrBidLockSpendTxMessage + + + Wait for + + script-coin-lock-tx to + + confirm + + + Wait for + + script-coin-lock-tx to + + confirm + + + Sends noscript-coin-lock-tx + + + Wait for + + noscript-coin-lock-tx to + + confirm + + + Sends script-coin-lock-tx + + release message + + + Sends script-coin-lock-spend-tx + + + Detects script-coin-lock-spend-tx + + + Sends noscript-coin-lock-spend-tx + + + Wait for + + noscript-coin-lock-spend-tx + + to confirm + + + fail path + + + Wait for + + script-coin-lock-tx + + locktime to expire + + + Sends + + script-coin-lock-pre-refund-tx + + + script-coin-lock-pre-refund-tx + + + Wait for + + pre-refund tx to confirm + + + Sends + + script-coin-lock-pre-refund-spend-tx + + + + Bid Receiving + + Bid Received + + User accepts bid + + The BidAccept message contains the pubkeys the offerer will use and a + DLEAG proof one key will work across both chains of the swapping coins + + Bid Accepted + + The XmrBidLockTxSigsMessage contains the bidder's signatures for the + script-coin-lock-refund and script-coin-lock-refund-spend txns. + + Exchanged script lock tx sigs + msg + + Bid Script coin spend tx valid + + The XmrBidLockSpendTxMessage contains the script-coin-lock-tx and the + offerer's signature for it. + + Exchanged script lock spend tx + msg + + Bid Script coin locked + + alt: success path + + Bid Scriptless coin locked + + The XmrBidLockReleaseMessage contains the offerer's OTVES for the + script-coin-lock-tx. The bidder decodes the + offerer's signature from the OTVES. When the + offerer has the plaintext signature, they can decode the bidder's key + for the noscript-lock-tx. + + Bid Script coin lock released + + Bid Script tx redeemed + + The offerer extracts the bidder's plaintext signature and derives the + bidder's noscript-lock-tx keyhalf. + + Bid Scriptless tx redeemed + + Bid Completed + + tx can be sent by either party. + + Bid Script pre-refund tx in + chain + + Refunds the script lock tx, with the offerer's cleartext signature + the bidder can refund the noscript lock tx. + + Bid Failed, refunded + + + diff --git a/doc/protocols/sequence_diagrams/.gitignore b/doc/protocols/sequence_diagrams/.gitignore new file mode 100644 index 0000000..756b22f --- /dev/null +++ b/doc/protocols/sequence_diagrams/.gitignore @@ -0,0 +1 @@ +*.svg diff --git a/doc/protocols/sequence_diagrams/xmr.bidder.alt.xu b/doc/protocols/sequence_diagrams/xmr.bidder.alt.xu new file mode 100644 index 0000000..f001172 --- /dev/null +++ b/doc/protocols/sequence_diagrams/xmr.bidder.alt.xu @@ -0,0 +1,80 @@ +xu { + hscale="1.3", wordwraparcs=on; + + CB [label=" ", linecolor="transparent"], + N [label="Network", linecolor="#008800", textbgcolor="#CCFFCC", arclinecolor="#008800"], + O [label="Offerer", linecolor="#FF0000", textbgcolor="#FFCCCC", arclinecolor="#FF0000"], + B [label="Bidder", linecolor="#0000FF", textbgcolor="#CCCCFF", arclinecolor="#0000FF"], + C [label=" ", linecolor="transparent"], C2 [label=" ", linecolor="transparent"]; + O =>> N [label="Sends Offer"]; + N >> B [label="Detects Offer"]; + B =>> O [label="Sends Bid"]; + B abox B [label="Bid Sent"]; + O box O [label="User accepts bid"]; + O =>> B [label="Sends BidAccept message"], + C note C2 + [label="The BidAccept message contains the pubkeys the offerer will use and a DLEAG proof one key will work across both chains of the swapping coins", + textbgcolor="#FFFFCC"]; + B abox B [label="Bid Receiving accept"]; + B abox B [label="Bid Accepted"]; + B =>> O [label="Sends XmrBidLockTxSigsMessage"], + C note C2 + [label="The XmrBidLockTxSigsMessage contains the bidder's signatures for the script-coin-lock-refund and script-coin-lock-refund-spend txns.", + textbgcolor="#FFFFCC"]; + B abox B [label="Exchanged script lock tx sigs msg"]; + O =>> B [label="Sends XmrBidLockSpendTxMessage"], + C note C2 + [label="The XmrBidLockSpendTxMessage contains the script-coin-lock-tx and the offerer's signature for it.", + textbgcolor="#FFFFCC"]; + O =>> N [label="Sends script-coin-lock-tx"], + B abox B [label="Bid Script coin spend tx valid"]; + B => B [label="Wait for script-coin-lock-tx to confirm"]; + B abox B [label="Bid Script coin locked"]; + CB alt C [label="success path"] { + B =>> N [label="Sends noscript-coin-lock-tx"]; + B => B [label="Wait for noscript-coin-lock-tx to confirm"], O => O [label="Wait for noscript-coin-lock-tx to confirm"]; + B abox B [label="Bid Scriptless coin locked"]; + O => B [label="Sends script-coin-lock-tx release message"], + C note C2 + [label="The XmrBidLockReleaseMessage contains the offerer's OTVES for it. + The bidder decodes the offerer's signature from the OTVES. + When the offerer has the plaintext signature, they can decode the bidder's noscript-coin-lock-tx signature.", + textbgcolor="#FFFFCC"]; + B abox B [label="Script coin lock released"]; + B =>> N [label="Sends script-coin-lock-spend-tx"]; + B abox B [label="Script tx redeemed"]; + B abox B [label="Bid Completed"]; + --- [label="fail path"]; + |||; + B => B [label="Wait for script-coin-lock-tx lock to expire"]; + O =>> N [label="Sends script-coin-lock-pre-refund-tx"], + C note C2 + [label="tx can be sent by either party.", + textbgcolor="#FFFFCC"]; + N >> O [label="script-coin-lock-pre-refund-tx"]; + B abox B [label="Bid Script pre-refund tx in chain"]; + CB alt C [label="offerer refunds script coin lock tx"] { + |||; + O => O [label="Wait for pre-refund tx to confirm"]; + O =>> N [label="Sends script-coin-lock-pre-refund-spend-tx"], + C note C2 + [label="Refunds the script lock tx, with the offerer's cleartext signature the bidder can refund the noscript lock tx. + Once the lock expires the pre-refund tx can be spent by the bidder.", + textbgcolor="#FFFFCC"]; + O abox O [label="Bid Failed, refunded"]; + N >> B [label="Detects script-coin-lock-pre-refund-spend-tx"], + C note C2 + [label="Bidder recovers the offerer's scriptless chain key-shard.", + textbgcolor="#FFFFCC"]; + B =>> N [label="Sends scriptless-coin-lock-recover-tx"]; + B abox B [label="Bid Scriptless tx recovered"]; + B abox B [label="Bid Failed, refunded"]; + --- [label="bidder swipes script coin lock tx"]; + |||; + B => B [label="Wait for pre-refund tx lock to expire"]; + B =>> N [label="Sends script-coin-lock-pre-refund-swipe-tx"]; + B abox B [label="Bid Failed, swiped"]; + }; + }; +} + diff --git a/doc/protocols/sequence_diagrams/xmr.offerer.alt.xu b/doc/protocols/sequence_diagrams/xmr.offerer.alt.xu index 7b789d7..c48c53b 100644 --- a/doc/protocols/sequence_diagrams/xmr.offerer.alt.xu +++ b/doc/protocols/sequence_diagrams/xmr.offerer.alt.xu @@ -21,12 +21,15 @@ xu { C note C2 [label="The XmrBidLockTxSigsMessage contains the bidder's signatures for the script-coin-lock-refund and script-coin-lock-refund-spend txns.", textbgcolor="#FFFFCC"]; + O abox O [label="Exchanged script lock tx sigs msg"]; + O =>> N [label="Sends script-coin-lock-tx"]; + O abox O [label="Bid Script coin spend tx valid"]; O =>> B [label="Sends XmrBidLockSpendTxMessage"], C note C2 [label="The XmrBidLockSpendTxMessage contains the script-coin-lock-tx and the offerer's signature for it.", textbgcolor="#FFFFCC"]; - O =>> N [label="Sends script-coin-lock-tx"], - O abox O [label="Bid Script coin spend tx valid"]; + O abox O [label="Exchanged script lock spend tx msg"]; + |||; B => B [label="Wait for script-coin-lock-tx to confirm"], O => O [label="Wait for script-coin-lock-tx to confirm"]; O abox O [label="Bid Script coin locked"]; diff --git a/doc/protocols/sequence_diagrams/xmr.offerer.simple.xu b/doc/protocols/sequence_diagrams/xmr.offerer.simple.xu deleted file mode 100644 index dcce045..0000000 --- a/doc/protocols/sequence_diagrams/xmr.offerer.simple.xu +++ /dev/null @@ -1,55 +0,0 @@ -xu { - hscale="1.3", wordwraparcs=on; - - CB [label=" ", linecolor="transparent"], - N [label="Network", linecolor="#008800", textbgcolor="#CCFFCC", arclinecolor="#008800"], - O [label="Offerer", linecolor="#FF0000", textbgcolor="#FFCCCC", arclinecolor="#FF0000"], - B [label="Bidder", linecolor="#0000FF", textbgcolor="#CCCCFF", arclinecolor="#0000FF"], - C [label=" ", linecolor="transparent"], C2 [label=" ", linecolor="transparent"]; - O =>> N [label="Sends Offer"]; - N >> B [label="Detects Offer"]; - B =>> O [label="Sends Bid"]; - O abox O [label="Bid Receiving"]; - O abox O [label="Bid Received"]; - O box O [label="Input: Accepts bid"]; - O =>> B [label="Sends BidAccept message"], - C note C2 - [label="The BidAccept message contains the pubkeys the offerer will use and a DLEAG proof one key will work across both chains of the swapping coins", - textbgcolor="#FFFFCC"]; - O abox O [label="Bid Accepted"]; - B =>> O [label="Sends XmrBidLockTxSigsMessage"], - C note C2 - [label="The XmrBidLockTxSigsMessage contains the bidder's signatures for the script-coin-lock-refund and script-coin-lock-refund-spend txns.", - textbgcolor="#FFFFCC"]; - O =>> B [label="Sends XmrBidLockSpendTxMessage"], - C note C2 - [label="The XmrBidLockSpendTxMessage contains the script-coin-lock-tx and the offerer's signature for it.", - textbgcolor="#FFFFCC"]; - O =>> N [label="Sends script-coin-lock-tx"], - O abox O [label="Bid Script coin spend tx valid"]; - |||; - B => B [label="Wait for script-coin-lock-tx to confirm"], O => O [label="Wait for script-coin-lock-tx to confirm"]; - O abox O [label="Bid Script coin locked"]; - B =>> N [label="Sends noscript-coin-lock-tx"]; - |||; - O => O [label="Wait for noscript-coin-lock-tx to confirm"]; - O abox O [label="Bid Scriptless coin locked"]; - O => B [label="Sends script-coin-lock-tx release message"], - C note C2 - [label="The XmrBidLockReleaseMessage contains the offerer's OTVES for the script-coin-lock-tx. - The bidder decodes the offerer's signature from the OTVES. - When the offerer has the plaintext signature, they can decode the bidder's key for the noscript-lock-tx.", - textbgcolor="#FFFFCC"]; - O abox O [label="Bid Script coin lock released"]; - B =>> N [label="Sends script-coin-lock-spend-tx"]; - N >> O [label="Detects script-coin-lock-spend-tx"]; - O abox O [label="Bid Script tx redeemed"], - C note C2 - [label="The offerer extracts the bidder's plaintext signature and derives the bidder's noscript-lock-tx keyhalf.", - textbgcolor="#FFFFCC"]; - O =>> N [label="Sends noscript-coin-lock-spend-tx"]; - O abox O [label="Bid Scriptless tx redeemed"]; - |||; - O => O [label="Wait for noscript-coin-lock-spend-tx to confirm"]; - O abox O [label="Bid Completed"]; -} diff --git a/docker/production/swapclient/Dockerfile b/docker/production/swapclient/Dockerfile index 51a42ba..110e5a3 100644 --- a/docker/production/swapclient/Dockerfile +++ b/docker/production/swapclient/Dockerfile @@ -15,9 +15,10 @@ RUN wget -O protobuf_src.tar.gz https://github.com/protocolbuffers/protobuf/rele make install && \ ldconfig -RUN wget -O coincurve-anonswap.zip https://github.com/tecnovert/coincurve/archive/refs/tags/anonswap_v0.1.zip && \ - unzip -d coincurve-anonswap coincurve-anonswap.zip && \ - mv ./coincurve-anonswap/*/{.,}* ./coincurve-anonswap || true && \ +ARG COINCURVE_VERSION=v0.1 +RUN wget -O coincurve-anonswap.zip https://github.com/tecnovert/coincurve/archive/refs/tags/anonswap_$COINCURVE_VERSION.zip && \ + unzip coincurve-anonswap.zip && \ + mv ./coincurve-anonswap_$COINCURVE_VERSION ./coincurve-anonswap && \ cd coincurve-anonswap && \ python3 setup.py install --force diff --git a/tests/basicswap/common_xmr.py b/tests/basicswap/common_xmr.py index 1d4b5c0..52287b1 100644 --- a/tests/basicswap/common_xmr.py +++ b/tests/basicswap/common_xmr.py @@ -116,6 +116,8 @@ class XmrTestBase(unittest.TestCase): settings['min_delay_event'] = 1 settings['max_delay_event'] = 4 + settings['min_delay_event_short'] = 1 + settings['max_delay_event_short'] = 4 settings['min_delay_retry'] = 10 settings['max_delay_retry'] = 20 diff --git a/tests/basicswap/extended/test_network.py b/tests/basicswap/extended/test_network.py index e5cc14b..25f4ddf 100644 --- a/tests/basicswap/extended/test_network.py +++ b/tests/basicswap/extended/test_network.py @@ -115,6 +115,8 @@ def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey): 'check_xmr_swaps_seconds': 1, 'min_delay_event': 1, 'max_delay_event': 5, + 'min_delay_event_short': 1, + 'max_delay_event_short': 5, 'min_delay_retry': 2, 'max_delay_retry': 10 } diff --git a/tests/basicswap/extended/test_xmr_persistent.py b/tests/basicswap/extended/test_xmr_persistent.py index b40b95d..a22de8c 100644 --- a/tests/basicswap/extended/test_xmr_persistent.py +++ b/tests/basicswap/extended/test_xmr_persistent.py @@ -222,6 +222,8 @@ class Test(unittest.TestCase): settings['min_delay_event'] = 1 settings['max_delay_event'] = 4 + settings['min_delay_event_short'] = 1 + settings['max_delay_event_short'] = 4 settings['min_delay_retry'] = 15 settings['max_delay_retry'] = 30 settings['min_sequence_lock_seconds'] = 60 diff --git a/tests/basicswap/test_xmr.py b/tests/basicswap/test_xmr.py index be073d7..57d2d4d 100644 --- a/tests/basicswap/test_xmr.py +++ b/tests/basicswap/test_xmr.py @@ -192,6 +192,8 @@ def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey, with_l 'check_xmr_swaps_seconds': 1, 'min_delay_event': 1, 'max_delay_event': 5, + 'min_delay_event_short': 1, + 'max_delay_event_short': 5, 'min_delay_retry': 2, 'max_delay_retry': 10, 'debug_ui': True,