From d56a15353b590f86fbf10a115fe4da3bb958b93a Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Mon, 27 Feb 2017 16:28:50 +0200 Subject: [PATCH] Fix Qt tumble restart to prompt for options --- scripts/joinmarket-qt.py | 30 +++++++++---------- scripts/qtsupport.py | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/scripts/joinmarket-qt.py b/scripts/joinmarket-qt.py index a898090..1575529 100644 --- a/scripts/joinmarket-qt.py +++ b/scripts/joinmarket-qt.py @@ -55,12 +55,13 @@ from jmclient import (load_program_config, get_network, Wallet, human_readable_schedule_entry, tumbler_taker_finished_update, get_tumble_log, restart_wait, tumbler_filter_orders_callback) -from qtsupport import (ScheduleWizard, warnings, config_tips, config_types, - TaskThread, QtHandler, XStream, Buttons, CloseButton, - CopyButton, CopyCloseButton, OkButton, CancelButton, - check_password_strength, update_password_strength, - make_password_dialog, PasswordDialog, MyTreeWidget, - JMQtMessageBox, BLUE_FG, donation_more_message) +from qtsupport import (ScheduleWizard, TumbleRestartWizard, warnings, config_tips, + config_types, TaskThread, QtHandler, XStream, Buttons, + CloseButton, CopyButton, CopyCloseButton, OkButton, + CancelButton, check_password_strength, + update_password_strength, make_password_dialog, + PasswordDialog, MyTreeWidget, JMQtMessageBox, BLUE_FG, + donation_more_message) def satoshis_to_amt_str(x): return str(Decimal(x)/Decimal('1e8')) + " BTC" @@ -542,16 +543,15 @@ class SpendTab(QWidget): self.spendstate.updateRun('running') if self.tumbler_options: - #TODO: mincjamount is the only tumbler setting, except maxcjfee, - #that is not part of sched-generation, so request from user - if not hasattr(jm_single(), 'mincjamount'): - mincjamount, ok = QInputDialog.getInt(self, - "Set min coinjoin amount", - "Enter minimum allowable coinjoin amount in satoshis") - if not ok: - self.giveUp() + #Uses the flag 'True' value from selectSchedule to recognize a restart, + #which needs new dynamic option values. The rationale for using input + #is in case the user can increase success probability by changing them. + if self.tumbler_options == True: + wizard = TumbleRestartWizard() + wizard_return = wizard.exec_() + if wizard_return == QDialog.Rejected: return - jm_single().mincjamount = mincjamount + self.tumbler_options = wizard.getOptions() #check for a partially-complete schedule; if so, #follow restart logic #1. filter out complete: diff --git a/scripts/qtsupport.py b/scripts/qtsupport.py index a6b6d59..d5eb53d 100644 --- a/scripts/qtsupport.py +++ b/scripts/qtsupport.py @@ -722,3 +722,66 @@ class ScheduleWizard(QWizard): #needed for Taker to check: jm_single().mincjamount = self.opts['mincjamount'] return get_tumble_schedule(self.opts, self.destaddrs) + +class TumbleRestartWizard(QWizard): + def __init__(self): + super(TumbleRestartWizard, self).__init__() + self.setWindowTitle("Restart tumbler schedule") + self.setPage(0, RestartSettingsPage(self)) + + def getOptions(self): + self.opts = {} + self.opts['amountpower'] = float(self.field("amountpower").toString()) + self.opts['mincjamount'] = int(self.field("mincjamount").toString()) + relfeeval = float(self.field("maxrelfee").toString()) + absfeeval = int(self.field("maxabsfee").toString()) + self.opts['maxcjfee'] = (relfeeval, absfeeval) + #needed for Taker to check: + jm_single().mincjamount = self.opts['mincjamount'] + return self.opts + +class RestartSettingsPage(QWizardPage): + + def __init__(self, parent): + super(RestartSettingsPage, self).__init__(parent) + self.setTitle("Tumbler options") + self.setSubTitle("Options settings that can be varied on restart") + layout = QGridLayout() + layout.setSpacing(4) + + results = [] + sN = ['Amount power', + 'Min coinjoin amount', + 'Max relative fee per counterparty (e.g. 0.005)', + 'Max fee per counterparty, satoshis (e.g. 10000)'] + #Tooltips + sH = ["A parameter to control the random coinjoin sizes.", + "The lowest allowed size of any coinjoin, in satoshis.", + "A decimal fraction (e.g. 0.001 = 0.1%) (this AND next must be violated to reject", + "Integer number of satoshis (this AND previous must be violated to reject)"] + #types + sT = [float, int, float, int] + #constraints + sMM = [(1.0, 10000.0, 1), (100000, 100000000), (0.000001, 0.25, 6), + (0, 10000000)] + sD = ['100.0', '1000000', '0.0005', '10000'] + for x in zip(sN, sH, sT, sD, sMM): + ql = QLabel(x[0]) + ql.setToolTip(x[1]) + qle = QLineEdit(x[3]) + if x[2] == int: + qle.setValidator(QIntValidator(*x[4])) + if x[2] == float: + qle.setValidator(QDoubleValidator(*x[4])) + results.append((ql, qle)) + layout = QGridLayout() + layout.setSpacing(4) + for i, x in enumerate(results): + layout.addWidget(x[0], i + 1, 0) + layout.addWidget(x[1], i + 1, 1, 1, 2) + self.setLayout(layout) + #fields not considered 'mandatory' as defaults are accepted + self.registerField("amountpower", results[0][1]) + self.registerField("mincjamount", results[1][1]) + self.registerField("maxrelfee", results[2][1]) + self.registerField("maxabsfee", results[3][1])