add CPFP (child pays for parent) dialog to the Qt GUI

This commit is contained in:
ThomasV 2017-02-01 12:26:30 +01:00
parent 9e1931587d
commit 15b404b9de
3 changed files with 55 additions and 3 deletions

View File

@ -142,7 +142,7 @@ class HistoryList(MyTreeWidget):
height, conf, timestamp = self.wallet.get_tx_height(tx_hash)
tx = self.wallet.transactions.get(tx_hash)
is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx)
rbf = is_mine and height <=0 and tx and not tx.is_final()
is_unconfirmed = height <= 0
menu = QMenu()
menu.addAction(_("Copy %s")%column_title, lambda: self.parent.app.clipboard().setText(column_data))
@ -150,8 +150,14 @@ class HistoryList(MyTreeWidget):
menu.addAction(_("Edit %s")%column_title, lambda: self.editItem(item, column))
menu.addAction(_("Details"), lambda: self.parent.show_transaction(tx))
if rbf:
menu.addAction(_("Increase fee"), lambda: self.parent.bump_fee_dialog(tx))
if is_unconfirmed and tx:
rbf = is_mine and not tx.is_final()
if rbf:
menu.addAction(_("Increase fee"), lambda: self.parent.bump_fee_dialog(tx))
else:
child_tx = self.wallet.cpfp(tx, 0)
if child_tx:
menu.addAction(_("Child pays for parent"), lambda: self.parent.cpfp(tx, child_tx))
if tx_URL:
menu.addAction(_("View on block explorer"), lambda: webbrowser.open(tx_URL))
menu.exec_(self.viewport().mapToGlobal(position))

View File

@ -2767,6 +2767,33 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
vbox.addLayout(Buttons(CloseButton(d)))
d.exec_()
def cpfp(self, parent_tx, new_tx):
total_size = parent_tx.estimated_size() + new_tx.estimated_size()
d = WindowModalDialog(self, _('Child Pays for Parent'))
vbox = QVBoxLayout(d)
vbox.addWidget(QLabel(_('Total size') + ': %d bytes'% total_size))
max_fee = new_tx.output_value()
vbox.addWidget(QLabel(_('Max fee') + ': %s'% self.format_amount(max_fee) + ' ' + self.base_unit()))
vbox.addWidget(QLabel(_('Child fee' + ':')))
fee_e = BTCAmountEdit(self.get_decimal_point)
fee = self.config.fee_per_kb() * total_size / 1000
fee_e.setAmount(fee)
vbox.addWidget(fee_e)
def on_rate(dyn, pos, fee_rate):
fee = fee_rate * total_size / 1000
fee_e.setAmount(min(max_fee, fee))
fee_slider = FeeSlider(self, self.config, on_rate)
vbox.addWidget(fee_slider)
vbox.addLayout(Buttons(CancelButton(d), OkButton(d)))
if not d.exec_():
return
fee = fee_e.get_amount()
if fee > max_fee:
self.show_error(_('Max fee exceeded'))
return
new_tx = self.wallet.cpfp(parent_tx, fee)
new_tx.set_sequence(0)
self.show_transaction(new_tx)
def bump_fee_dialog(self, tx):
is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx)

View File

@ -1042,6 +1042,25 @@ class Abstract_Wallet(PrintError):
raise BaseException(_('Cannot bump fee: cound not find suitable outputs'))
return Transaction.from_io(inputs, outputs)
def cpfp(self, tx, fee):
txid = tx.txid()
for i, o in enumerate(tx.outputs()):
otype, address, value = o
if otype == TYPE_ADDRESS and self.is_mine(address):
break
else:
return
coins = self.get_addr_utxo(address)
for item in coins:
if item['prevout_hash'] == txid and item['prevout_n'] == i:
break
else:
return
self.add_input_info(item)
inputs = [item]
outputs = [(TYPE_ADDRESS, address, value - fee)]
return Transaction.from_io(inputs, outputs)
def add_input_info(self, txin):
# Add address for utxo that are in wallet
if txin.get('scriptSig') == '':