From 1e49bf4ec3dfb4156838d603e664b96eece6911b Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Sat, 25 Feb 2017 22:54:53 +0200 Subject: [PATCH] persist ignored_makers in Qt app; rationalize cleanUp() Modify tooltip for Start button to explain Abort Retrieve nonresponsive makers in daemon and pass to client Taker receives ignored_makers in init and client adds --- jmclient/jmclient/client_protocol.py | 4 +- jmclient/jmclient/taker.py | 10 ++-- jmdaemon/jmdaemon/daemon_protocol.py | 7 ++- scripts/joinmarket-qt.py | 71 +++++++++++----------------- 4 files changed, 43 insertions(+), 49 deletions(-) diff --git a/jmclient/jmclient/client_protocol.py b/jmclient/jmclient/client_protocol.py index 920aaa3..80d4a65 100644 --- a/jmclient/jmclient/client_protocol.py +++ b/jmclient/jmclient/client_protocol.py @@ -180,7 +180,9 @@ class JMTakerClientProtocol(amp.AMP): """ ioauth_data = json.loads(ioauth_data) if not success: - jlog.info("Makers didnt respond") + nonresponders = ioauth_data + jlog.info("Makers didnt respond: " + str(nonresponders)) + self.taker.add_ignored_makers(nonresponders) return {'accepted': True} else: jlog.info("Makers responded with: " + json.dumps(ioauth_data)) diff --git a/jmclient/jmclient/taker.py b/jmclient/jmclient/taker.py index 04091fb..196b9e5 100644 --- a/jmclient/jmclient/taker.py +++ b/jmclient/jmclient/taker.py @@ -30,7 +30,8 @@ class Taker(object): order_chooser=weighted_order_choose, sign_method=None, callbacks=None, - tdestaddrs=[]): + tdestaddrs=None, + ignored_makers=None): """Schedule must be a list of tuples: (see sample_schedule_for_testnet for explanation of syntax, also schedule.py module in this directory), which will be a sequence of joins to do. @@ -76,11 +77,11 @@ class Taker(object): self.wallet = wallet self.schedule = schedule self.order_chooser = order_chooser - self.ignored_makers = None + self.ignored_makers = [] if not ignored_makers else ignored_makers self.waiting_for_conf = False self.txid = None self.schedule_index = -1 - self.tdestaddrs = tdestaddrs + self.tdestaddrs = [] if not tdestaddrs else tdestaddrs #allow custom wallet-based clients to use their own signing code; #currently only setting "wallet" is allowed, calls wallet.sign_tx(tx) self.sign_method = sign_method @@ -93,6 +94,9 @@ class Taker(object): def default_taker_info_callback(self, infotype, msg): jlog.debug(infotype + ":" + msg) + def add_ignored_makers(self, makers): + self.ignored_makers.extend(makers) + def initialize(self, orderbook): """Once the daemon is active and has returned the current orderbook, select offers, re-initialize variables and prepare a commitment, diff --git a/jmdaemon/jmdaemon/daemon_protocol.py b/jmdaemon/jmdaemon/daemon_protocol.py index 6504fa4..140cde9 100644 --- a/jmdaemon/jmdaemon/daemon_protocol.py +++ b/jmdaemon/jmdaemon/daemon_protocol.py @@ -224,9 +224,14 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch): #do nothing return self.jm_state = 3 + if not accepted: + #use ioauth data field to return the list of non-responsive makers + nonresponders = [x for x in self.active_orders.keys() if x not + in self.ioauth_data.keys()] + ioauth_data = self.ioauth_data if accepted else nonresponders d = self.callRemote(JMFillResponse, success=accepted, - ioauth_data = json.dumps(self.ioauth_data)) + ioauth_data = json.dumps(ioauth_data)) if not accepted: #Client simply accepts failure TODO self.defaultCallbacks(d) diff --git a/scripts/joinmarket-qt.py b/scripts/joinmarket-qt.py index ae8dd53..0b2a3f3 100644 --- a/scripts/joinmarket-qt.py +++ b/scripts/joinmarket-qt.py @@ -466,9 +466,11 @@ class SpendTab(QWidget): lambda: checkAddress(self, self.widgets[0][1].text())) self.startButton = QPushButton('Start') self.startButton.setToolTip( - 'You will be prompted to decide whether to accept\n' + - 'the transaction after connecting, and shown the\n' + - 'fees to pay; you can cancel at that point if you wish.') + 'If "checktx" is selected in the Settings, you will be \n' + 'prompted to decide whether to accept\n' + 'the transaction after connecting, and shown the\n' + 'fees to pay; you can cancel at that point, or by \n' + 'pressing "Abort".') self.startButton.clicked.connect(self.startSingle) self.abortButton = QPushButton('Abort') self.abortButton.setEnabled(False) @@ -587,7 +589,7 @@ class SpendTab(QWidget): self.spendstate.updateRun('running') self.startJoin() - def startJoin(self, ignored_makers=None): + def startJoin(self): if not w.wallet: JMQtMessageBox(self, "Cannot start without a loaded wallet.", mbtype="crit", title="Error") @@ -624,20 +626,21 @@ class SpendTab(QWidget): callbacks=[check_offers_callback, self.callback_takerInfo, self.callback_takerFinished], - tdestaddrs=destaddrs) - if ignored_makers: - self.taker.ignored_makers.extend(ignored_makers) + tdestaddrs=destaddrs, + ignored_makers=ignored_makers) if not self.clientfactory: #First run means we need to start: create clientfactory #and start reactor Thread self.clientfactory = JMTakerClientProtocolFactory(self.taker) thread = TaskThread(self) + daemon = jm_single().config.getint("DAEMON", "no_daemon") + daemon = True if daemon == 1 else False thread.add(partial(start_reactor, "localhost", jm_single().config.getint("GUI", "daemon_port"), self.clientfactory, ish=False, - daemon=True)) + daemon=daemon)) else: #This will re-use IRC connections in background (daemon), no restart self.clientfactory.getClient().taker = self.taker @@ -830,7 +833,9 @@ class SpendTab(QWidget): else: msg = "All transactions have been confirmed." JMQtMessageBox(self, msg, title="Success") - self.cleanUp() + self.cleanUp() + else: + self.giveUp() def persistTxToHistory(self, addr, amt, txid): #persist the transaction to history @@ -874,44 +879,21 @@ class SpendTab(QWidget): self.giveUp() def giveUp(self): + """Inform the user that the transaction failed, then reset state. + """ log.debug("Transaction aborted.") - self.qtw.setTabEnabled(0, True) - self.qtw.setTabEnabled(1, True) - self.spendstate.reset() - self.tumbler_options = None - self.tumbler_destaddrs = None w.statusBar().showMessage("Transaction aborted.") + if len(self.taker.ignored_makers) > 0: + JMQtMessageBox(self, "These Makers did not respond, and will be \n" + "ignored in future: \n" + str( + ','.join(self.taker.ignored_makers)), + title="Transaction aborted") + ignored_makers.extend(self.taker.ignored_makers) + self.cleanUp() def cleanUp(self): - if not self.taker.txid: - if not self.taker.aborted: - if not self.taker.ignored_makers: - w.statusBar().showMessage("Transaction failed.") - JMQtMessageBox(self, - "Transaction was not completed.", - mbtype='warn', - title="Failed") - else: - reply = JMQtMessageBox( - self, - '\n'.join([ - "The following counterparties did not respond: ", - ','.join(self.taker.ignored_makers), - "This sometimes happens due to bad network connections.", - "", - "If you would like to try again, ignoring those", - "counterparties, click Yes." - ]), - mbtype='question', - title="Transaction not completed.") - if reply == QMessageBox.Yes: - self.startJoin( - ignored_makers=self.taker.ignored_makers) - else: - self.giveUp() - return - self.qtw.setTabEnabled(0, True) - self.qtw.setTabEnabled(1, True) + """Reset state to 'ready' + """ self.spendstate.reset() self.tumbler_options = None self.tumbler_destaddrs = None @@ -1590,7 +1572,8 @@ for dname in ['logs', 'wallets', 'cmtdata']: logsdir = os.path.join(os.path.dirname(jm_single().config_location), "logs") #tumble log will not always be used, but is made available anyway: tumble_log = get_tumble_log(logsdir) - +#ignored makers list persisted across entire app run +ignored_makers = [] appWindowTitle = 'JoinMarketQt' w = JMMainWindow() tabWidget = QTabWidget(w)