21
21
#include < interfaces/node.h>
22
22
#include < node/chainstatemanager_args.h>
23
23
#include < netbase.h>
24
+ #include < node/mempool_args.h> // for ParseDustDynamicOpt
24
25
#include < outputtype.h>
25
26
#include < primitives/transaction.h> // for WITNESS_SCALE_FACTOR
26
27
#include < txdb.h>
27
28
#include < txmempool.h> // for maxmempoolMinimum
28
29
#include < util/strencodings.h>
29
30
#include < chrono>
31
+ #include < utility>
30
32
31
33
#include < QApplication>
32
34
#include < QBoxLayout>
41
43
#include < QLabel>
42
44
#include < QLocale>
43
45
#include < QMessageBox>
46
+ #include < QRadioButton>
44
47
#include < QSpacerItem>
45
48
#include < QString>
46
49
#include < QStringList>
@@ -67,13 +70,15 @@ void OptionsDialog::CreateOptionUI(QBoxLayout * const layout, QWidget * const o,
67
70
68
71
if (!horizontalLayout) horizontalLayout = new QHBoxLayout ();
69
72
70
- QLabel * const labelBefore = new QLabel (parent);
71
- labelBefore->setText (text_parts[0 ]);
72
- labelBefore->setTextFormat (Qt::PlainText);
73
- labelBefore->setBuddy (o);
74
- labelBefore->setToolTip (o->toolTip ());
73
+ if (!text_parts[0 ].isEmpty ()) {
74
+ QLabel * const labelBefore = new QLabel (parent);
75
+ labelBefore->setText (text_parts[0 ]);
76
+ labelBefore->setTextFormat (Qt::PlainText);
77
+ labelBefore->setBuddy (o);
78
+ labelBefore->setToolTip (o->toolTip ());
79
+ horizontalLayout->addWidget (labelBefore);
80
+ }
75
81
76
- horizontalLayout->addWidget (labelBefore);
77
82
horizontalLayout->addWidget (o);
78
83
79
84
QLabel * const labelAfter = new QLabel (parent);
@@ -340,7 +345,67 @@ OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet)
340
345
});
341
346
342
347
dustrelayfee = new BitcoinAmountField (groupBox_Spamfiltering);
343
- CreateOptionUI (verticalLayout_Spamfiltering, dustrelayfee, tr (" Ignore transactions with values that would cost more to spend at a fee rate of %s per kvB." ));
348
+ CreateOptionUI (verticalLayout_Spamfiltering, dustrelayfee, tr (" Ignore transactions with values that would cost more to spend at a fee rate of %s per kvB (\" dust\" )." ));
349
+
350
+
351
+ auto hlayout = new QHBoxLayout ();
352
+ dustdynamic_enable = new QCheckBox (groupBox_Spamfiltering);
353
+ dustdynamic_enable->setText (tr (" Automatically adjust the dust limit upward to" ));
354
+ hlayout->addWidget (dustdynamic_enable);
355
+ dustdynamic_multiplier = new QDoubleSpinBox (groupBox_Spamfiltering);
356
+ dustdynamic_multiplier->setDecimals (3 );
357
+ dustdynamic_multiplier->setStepType (QAbstractSpinBox::DefaultStepType);
358
+ dustdynamic_multiplier->setSingleStep (1 );
359
+ dustdynamic_multiplier->setMinimum (0.001 );
360
+ dustdynamic_multiplier->setMaximum (65 );
361
+ dustdynamic_multiplier->setValue (DEFAULT_DUST_RELAY_MULTIPLIER / 1000.0 );
362
+ CreateOptionUI (verticalLayout_Spamfiltering, dustdynamic_multiplier, tr (" %s times:" ), hlayout);
363
+
364
+ QStyleOptionButton styleoptbtn;
365
+ const auto checkbox_indent = dustdynamic_enable->style ()->subElementRect (QStyle::SE_CheckBoxIndicator, &styleoptbtn, dustdynamic_enable).width ();
366
+
367
+ hlayout = new QHBoxLayout ();
368
+ hlayout->addSpacing (checkbox_indent);
369
+ dustdynamic_target = new QRadioButton (groupBox_Spamfiltering);
370
+ hlayout->addWidget (dustdynamic_target);
371
+ dustdynamic_target_blocks = new QSpinBox (groupBox_Spamfiltering);
372
+ dustdynamic_target_blocks->setMinimum (2 );
373
+ dustdynamic_target_blocks->setMaximum (1008 ); // FIXME: Get this from the fee estimator
374
+ dustdynamic_target_blocks->setValue (1008 );
375
+ CreateOptionUI (verticalLayout_Spamfiltering, dustdynamic_target_blocks, tr (" fee estimate for %s blocks." ), hlayout);
376
+ // FIXME: Make it possible to click labels to select + focus spinbox
377
+
378
+ hlayout = new QHBoxLayout ();
379
+ hlayout->addSpacing (checkbox_indent);
380
+ dustdynamic_mempool = new QRadioButton (groupBox_Spamfiltering);
381
+ hlayout->addWidget (dustdynamic_mempool);
382
+ dustdynamic_mempool_kvB = new QSpinBox (groupBox_Spamfiltering);
383
+ dustdynamic_mempool_kvB->setMinimum (1 );
384
+ dustdynamic_mempool_kvB->setMaximum (std::numeric_limits<int32_t >::max ());
385
+ dustdynamic_mempool_kvB->setValue (3024000 );
386
+ CreateOptionUI (verticalLayout_Spamfiltering, dustdynamic_mempool_kvB, tr (" the lowest fee of the best known %s kvB of unconfirmed transactions." ), hlayout);
387
+
388
+ connect (dustdynamic_enable, &QAbstractButton::toggled, [this ](const bool state){
389
+ dustdynamic_multiplier->setEnabled (state);
390
+ dustdynamic_target->setEnabled (state);
391
+ dustdynamic_mempool->setEnabled (state);
392
+ if (state) {
393
+ if (!dustdynamic_mempool->isChecked ()) dustdynamic_target->setChecked (true );
394
+ dustdynamic_target_blocks->setEnabled (dustdynamic_target->isChecked ());
395
+ dustdynamic_mempool_kvB->setEnabled (dustdynamic_mempool->isChecked ());
396
+ } else {
397
+ dustdynamic_target_blocks->setEnabled (false );
398
+ dustdynamic_mempool_kvB->setEnabled (false );
399
+ }
400
+ });
401
+ dustdynamic_enable->toggled (dustdynamic_enable->isChecked ());
402
+ connect (dustdynamic_target, &QAbstractButton::toggled, [this ](const bool state){
403
+ dustdynamic_target_blocks->setEnabled (state);
404
+ });
405
+ connect (dustdynamic_mempool, &QAbstractButton::toggled, [this ](const bool state){
406
+ dustdynamic_mempool_kvB->setEnabled (state);
407
+ });
408
+
344
409
345
410
verticalLayout_Mempool->addWidget (groupBox_Spamfiltering);
346
411
@@ -645,6 +710,24 @@ void OptionsDialog::setMapper()
645
710
mapper->addMapping (datacarriersize, OptionsModel::datacarriersize);
646
711
mapper->addMapping (dustrelayfee, OptionsModel::dustrelayfee);
647
712
713
+ QVariant current_dustdynamic = model->data (model->index (OptionsModel::dustdynamic, 0 ), Qt::EditRole);
714
+ const util::Result<std::pair<int32_t , int >> parsed_dustdynamic = ParseDustDynamicOpt (current_dustdynamic.toString ().toStdString (), std::numeric_limits<unsigned int >::max ());
715
+ if (parsed_dustdynamic) {
716
+ if (parsed_dustdynamic->first == 0 ) {
717
+ dustdynamic_enable->setChecked (false );
718
+ } else {
719
+ dustdynamic_multiplier->setValue (parsed_dustdynamic->second / 1000.0 );
720
+ if (parsed_dustdynamic->first < 0 ) {
721
+ dustdynamic_target->setChecked (true );
722
+ dustdynamic_target_blocks->setValue (-parsed_dustdynamic->first );
723
+ } else {
724
+ dustdynamic_mempool->setChecked (true );
725
+ dustdynamic_mempool_kvB->setValue (parsed_dustdynamic->first );
726
+ }
727
+ dustdynamic_enable->setChecked (true );
728
+ }
729
+ }
730
+
648
731
/* Mining tab */
649
732
650
733
mapper->addMapping (blockmintxfee, OptionsModel::blockmintxfee);
@@ -817,6 +900,16 @@ void OptionsDialog::on_okButton_clicked()
817
900
818
901
model->setData (model->index (OptionsModel::mempoolreplacement, 0 ), mempoolreplacement->itemData (mempoolreplacement->currentIndex ()));
819
902
903
+ if (dustdynamic_enable->isChecked ()) {
904
+ if (dustdynamic_target->isChecked ()) {
905
+ model->setData (model->index (OptionsModel::dustdynamic, 0 ), QStringLiteral (" %2*target:%1" ).arg (dustdynamic_target_blocks->value ()).arg (dustdynamic_multiplier->value ()));
906
+ } else if (dustdynamic_mempool->isChecked ()) {
907
+ model->setData (model->index (OptionsModel::dustdynamic, 0 ), QStringLiteral (" %2*mempool:%1" ).arg (dustdynamic_mempool_kvB->value ()).arg (dustdynamic_multiplier->value ()));
908
+ }
909
+ } else {
910
+ model->setData (model->index (OptionsModel::dustdynamic, 0 ), " off" );
911
+ }
912
+
820
913
mapper->submit ();
821
914
accept ();
822
915
updateDefaultProxyNets ();
0 commit comments