electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 53fa9738983668970a86a5a96c4813cb80ceda57
parent 641f23229d42d05a9003d6e4be36040d890f64a7
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:
Mgui/qt/main_window.py | 2+-
Mlib/coinchooser.py | 91+++++++++++++++++++++++++++++++++++++------------------------------------------
2 files changed, 44 insertions(+), 49 deletions(-)

diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -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)) diff --git a/lib/coinchooser.py b/lib/coinchooser.py @@ -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, @@ -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}