URI: 
       tMove change_amounts() to base class. - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 53fa9738983668970a86a5a96c4813cb80ceda57
   DIR parent 641f23229d42d05a9003d6e4be36040d890f64a7
  HTML Author: Neil Booth <kyuupichan@gmail.com>
       Date:   Fri, 15 Jan 2016 15:21:25 +0900
       
       Move change_amounts() to base class.
       
       Update tooltip of the preference.
       
       Diffstat:
         M gui/qt/main_window.py               |       2 +-
         M lib/coinchooser.py                  |      91 +++++++++++++++----------------
       
       2 files changed, 44 insertions(+), 49 deletions(-)
       ---
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -2756,7 +2756,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                multiple_change = self.wallet.multiple_change
                multiple_cb = QCheckBox(_('Multiple'))
                multiple_cb.setEnabled(self.wallet.use_change)
       -        multiple_cb.setToolTip(_('If appropriate, and the "privacy" coin chooser is selected, use up to 3 change addresses.'))
       +        multiple_cb.setToolTip(_('If appropriate use up to 3 change addresses.'))
                multiple_cb.setChecked(multiple_change)
                multiple_cb.stateChanged.connect(on_multiple)
                tx_widgets.append((usechange_cb, multiple_cb))
   DIR diff --git a/lib/coinchooser.py b/lib/coinchooser.py
       t@@ -60,8 +60,49 @@ class CoinChooserBase(PrintError):
                return penalty
        
            def change_amounts(self, tx, count, fee_estimator, dust_threshold):
       -        # The amount left after adding 1 change output
       -        return [max(0, tx.get_fee() - fee_estimator(1))]
       +        # Break change up if bigger than max_change
       +        output_amounts = [o[2] for o in tx.outputs]
       +        max_change = max(max(output_amounts) * 1.25, dust_threshold * 10)
       +
       +        # Use N change outputs
       +        for n in range(1, count + 1):
       +            # How much is left if we add this many change outputs?
       +            change_amount = max(0, tx.get_fee() - fee_estimator(n))
       +            if change_amount // n <= max_change:
       +                break
       +
       +        # Get a handle on the precision of the output amounts; round our
       +        # change to look similar
       +        def trailing_zeroes(val):
       +            s = str(val)
       +            return len(s) - len(s.rstrip('0'))
       +
       +        zeroes = map(trailing_zeroes, output_amounts)
       +        min_zeroes = min(zeroes)
       +        max_zeroes = max(zeroes)
       +        zeroes = range(max(0, min_zeroes - 1), (max_zeroes + 1) + 1)
       +
       +        # Calculate change; randomize it a bit if using more than 1 output
       +        remaining = change_amount
       +        amounts = []
       +        while n > 1:
       +            average = remaining // n
       +            amount = randint(int(average * 0.7), int(average * 1.3))
       +            precision = min(choice(zeroes), int(floor(log10(amount))))
       +            amount = int(round(amount, -precision))
       +            amounts.append(amount)
       +            remaining -= amount
       +            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]))
       +        amount = (remaining // N) * N
       +        amounts.append(amount)
       +
       +        assert sum(amounts) <= change_amount
       +
       +        return amounts
        
            def change_outputs(self, tx, change_addrs, fee_estimator, dust_threshold):
                amounts = self.change_amounts(tx, len(change_addrs), fee_estimator,
       t@@ -221,52 +262,6 @@ class CoinChooserPrivacy(CoinChooserRandom):
        
                return penalty
        
       -    def change_amounts(self, tx, count, fee_estimator, dust_threshold):
       -
       -        # Break change up if bigger than max_change
       -        output_amounts = [o[2] for o in tx.outputs]
       -        max_change = max(max(output_amounts) * 1.25, dust_threshold * 10)
       -
       -        # Use N change outputs
       -        for n in range(1, count + 1):
       -            # How much is left if we add this many change outputs?
       -            change_amount = max(0, tx.get_fee() - fee_estimator(n))
       -            if change_amount // n <= max_change:
       -                break
       -
       -        # Get a handle on the precision of the output amounts; round our
       -        # change to look similar
       -        def trailing_zeroes(val):
       -            s = str(val)
       -            return len(s) - len(s.rstrip('0'))
       -
       -        zeroes = map(trailing_zeroes, output_amounts)
       -        min_zeroes = min(zeroes)
       -        max_zeroes = max(zeroes)
       -        zeroes = range(max(0, min_zeroes - 1), (max_zeroes + 1) + 1)
       -
       -        # Calculate change; randomize it a bit if using more than 1 output
       -        remaining = change_amount
       -        amounts = []
       -        while n > 1:
       -            average = remaining // n
       -            amount = randint(int(average * 0.7), int(average * 1.3))
       -            precision = min(choice(zeroes), int(floor(log10(amount))))
       -            amount = int(round(amount, -precision))
       -            amounts.append(amount)
       -            remaining -= amount
       -            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]))
       -        amount = (remaining // N) * N
       -        amounts.append(amount)
       -
       -        assert sum(amounts) <= change_amount
       -
       -        return amounts
       -
        
        COIN_CHOOSERS = {'Oldest First': CoinChooserOldestFirst,
                         'Privacy': CoinChooserPrivacy}