URI: 
       tMerge pull request #3878 from SomberNight/coinchooser_output_rounding - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit cccf3807538639fb638424b06faf0563e7b7d80e
   DIR parent 95c5815fe3c922807af06547051339b082bcb926
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Fri,  9 Feb 2018 12:13:26 +0100
       
       Merge pull request #3878 from SomberNight/coinchooser_output_rounding
       
       coinchooser: make output value rounding configurable
       Diffstat:
         M gui/qt/main_window.py               |      15 ++++++++++++++-
         M lib/coinchooser.py                  |      20 ++++++++++++++++----
       
       2 files changed, 30 insertions(+), 5 deletions(-)
       ---
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -1136,7 +1136,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                def feerounding_onclick():
                    text = (self.feerounding_text + '\n\n' +
                            _('To somewhat protect your privacy, Electrum tries to create change with similar precision to other outputs.') + ' ' +
       -                    _('At most 100 satoshis might be lost due to this rounding.') + '\n' +
       +                    _('At most 100 satoshis might be lost due to this rounding.') + ' ' +
       +                    _("You can disable this setting in '{}'.").format(_('Preferences')) + '\n' +
                            _('Also, dust is not kept as change, but added to the fee.'))
                    QMessageBox.information(self, 'Fee rounding', text)
        
       t@@ -2893,6 +2894,18 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                unconf_cb.stateChanged.connect(on_unconf)
                tx_widgets.append((unconf_cb, None))
        
       +        def on_outrounding(x):
       +            self.config.set_key('coin_chooser_output_rounding', bool(x))
       +        enable_outrounding = self.config.get('coin_chooser_output_rounding', False)
       +        outrounding_cb = QCheckBox(_('Enable output value rounding'))
       +        outrounding_cb.setToolTip(
       +            _('Set the value of the change output so that it has similar precision to the other outputs.') + '\n' +
       +            _('This might improve your privacy somewhat.') + '\n' +
       +            _('If enabled, at most 100 satoshis might be lost due to this, per transaction.'))
       +        outrounding_cb.setChecked(enable_outrounding)
       +        outrounding_cb.stateChanged.connect(on_outrounding)
       +        tx_widgets.append((outrounding_cb, None))
       +
                # Fiat Currency
                hist_checkbox = QCheckBox()
                fiat_address_checkbox = QCheckBox()
   DIR diff --git a/lib/coinchooser.py b/lib/coinchooser.py
       t@@ -87,6 +87,8 @@ def strip_unneeded(bkts, sufficient_funds):
        
        class CoinChooserBase(PrintError):
        
       +    enable_output_value_rounding = False
       +
            def keys(self, coins):
                raise NotImplementedError
        
       t@@ -135,7 +137,13 @@ class CoinChooserBase(PrintError):
                zeroes = [trailing_zeroes(i) for i in output_amounts]
                min_zeroes = min(zeroes)
                max_zeroes = max(zeroes)
       -        zeroes = range(max(0, min_zeroes - 1), (max_zeroes + 1) + 1)
       +
       +        if n > 1:
       +            zeroes = range(max(0, min_zeroes - 1), (max_zeroes + 1) + 1)
       +        else:
       +            # if there is only one change output, this will ensure that we aim
       +            # to have one that is exactly as precise as the most precise output
       +            zeroes = [min_zeroes]
        
                # Calculate change; randomize it a bit if using more than 1 output
                remaining = change_amount
       t@@ -150,8 +158,10 @@ class CoinChooserBase(PrintError):
                    n -= 1
        
                # Last change output.  Round down to maximum precision but lose
       -        # no more than 100 satoshis to fees (2dp)
       -        N = pow(10, min(2, zeroes[0]))
       +        # no more than 10**max_dp_to_round_for_privacy
       +        # e.g. a max of 2 decimal places means losing 100 satoshis to fees
       +        max_dp_to_round_for_privacy = 2 if self.enable_output_value_rounding else 0
       +        N = pow(10, min(max_dp_to_round_for_privacy, zeroes[0]))
                amount = (remaining // N) * N
                amounts.append(amount)
        
       t@@ -370,4 +380,6 @@ def get_name(config):
        
        def get_coin_chooser(config):
            klass = COIN_CHOOSERS[get_name(config)]
       -    return klass()
       +    coinchooser = klass()
       +    coinchooser.enable_output_value_rounding = config.get('coin_chooser_output_rounding', False)
       +    return coinchooser