Browse Source

tx dialog: show various warnings if input amounts cannot be verified (#6217)

see #5749
bip39-recovery
ghost43 5 years ago
committed by GitHub
parent
commit
947af92126
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      electrum/gui/kivy/uix/dialogs/tx_dialog.py
  2. 16
      electrum/gui/qt/transaction_dialog.py
  3. 19
      electrum/transaction.py
  4. 34
      electrum/wallet.py

9
electrum/gui/kivy/uix/dialogs/tx_dialog.py

@ -132,9 +132,10 @@ class TxDialog(Factory.Popup):
self.tx = tx # type: Transaction
self._action_button_fn = lambda btn: None
# if the wallet can populate the inputs with more info, do it now.
# as a result, e.g. we might learn an imported address tx is segwit,
# or that a beyond-gap-limit address is is_mine
# If the wallet can populate the inputs with more info, do it now.
# As a result, e.g. we might learn an imported address tx is segwit,
# or that a beyond-gap-limit address is is_mine.
# note: this might fetch prev txs over the network.
tx.add_info_from_wallet(self.wallet)
def on_open(self):
@ -173,7 +174,7 @@ class TxDialog(Factory.Popup):
risk_of_burning_coins = (isinstance(self.tx, PartialTransaction)
and self.can_sign
and fee is not None
and self.tx.is_there_risk_of_burning_coins_as_fees())
and bool(self.wallet.get_warning_for_risk_of_burning_coins_as_fees(self.tx)))
if fee is not None and not risk_of_burning_coins:
self.fee_str = format_amount(fee)
fee_per_kb = fee / self.tx.estimated_size() * 1000

16
electrum/gui/qt/transaction_dialog.py

@ -211,9 +211,10 @@ class BaseTxDialog(QDialog, MessageBoxMixin):
self.tx.deserialize()
except BaseException as e:
raise SerializationError(e)
# if the wallet can populate the inputs with more info, do it now.
# as a result, e.g. we might learn an imported address tx is segwit,
# or that a beyond-gap-limit address is is_mine
# If the wallet can populate the inputs with more info, do it now.
# As a result, e.g. we might learn an imported address tx is segwit,
# or that a beyond-gap-limit address is is_mine.
# note: this might fetch prev txs over the network.
tx.add_info_from_wallet(self.wallet)
def do_broadcast(self):
@ -479,8 +480,9 @@ class BaseTxDialog(QDialog, MessageBoxMixin):
fee_str += ' - ' + _('Warning') + ': ' + _("high fee") + '!'
if isinstance(self.tx, PartialTransaction):
risk_of_burning_coins = (can_sign and fee is not None
and self.tx.is_there_risk_of_burning_coins_as_fees())
self.fee_warning_icon.setVisible(risk_of_burning_coins)
and self.wallet.get_warning_for_risk_of_burning_coins_as_fees(self.tx))
self.fee_warning_icon.setToolTip(str(risk_of_burning_coins))
self.fee_warning_icon.setVisible(bool(risk_of_burning_coins))
self.fee_label.setText(fee_str)
self.size_label.setText(size_str)
if ln_amount is None:
@ -596,10 +598,6 @@ class BaseTxDialog(QDialog, MessageBoxMixin):
pixmap_size = round(2 * char_width_in_lineedit())
pixmap = pixmap.scaled(pixmap_size, pixmap_size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
self.fee_warning_icon.setPixmap(pixmap)
self.fee_warning_icon.setToolTip(_("Warning") + ": "
+ _("The fee could not be verified. Signing non-segwit inputs is risky:\n"
"if this transaction was maliciously modified before you sign,\n"
"you might end up paying a higher mining fee than displayed."))
self.fee_warning_icon.setVisible(False)
fee_hbox.addWidget(self.fee_warning_icon)
fee_hbox.addStretch(1)

19
electrum/transaction.py

@ -1953,25 +1953,6 @@ class PartialTransaction(Transaction):
for txin in self.inputs():
txin.convert_utxo_to_witness_utxo()
def is_there_risk_of_burning_coins_as_fees(self) -> bool:
"""Returns whether there is risk of burning coins as fees if we sign.
Note:
- legacy sighash does not commit to any input amounts
- BIP-0143 sighash only commits to the *corresponding* input amount
- BIP-taproot sighash commits to *all* input amounts
"""
for txin in self.inputs():
# if we have full previous tx, we *know* the input amount
if txin.utxo:
continue
# if we have just the previous output, we only have guarantees if
# the sighash commits to this data
if txin.witness_utxo and Transaction.is_segwit_input(txin):
continue
return True
return False
def remove_signatures(self):
for txin in self.inputs():
txin.part_sigs = {}

34
electrum/wallet.py

@ -2023,6 +2023,40 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
self.sign_transaction(tx, password)
return tx
def get_warning_for_risk_of_burning_coins_as_fees(self, tx: 'PartialTransaction') -> Optional[str]:
"""Returns a warning message if there is risk of burning coins as fees if we sign.
Note that if not all inputs are ismine, e.g. coinjoin, the risk is not just about fees.
Note:
- legacy sighash does not commit to any input amounts
- BIP-0143 sighash only commits to the *corresponding* input amount
- BIP-taproot sighash commits to *all* input amounts
"""
assert isinstance(tx, PartialTransaction)
# if we have all full previous txs, we *know* all the input amounts -> fine
if all([txin.utxo for txin in tx.inputs()]):
return None
# a single segwit input -> fine
if len(tx.inputs()) == 1 and Transaction.is_segwit_input(tx.inputs()[0]) and tx.inputs()[0].witness_utxo:
return None
# coinjoin or similar
if any([not self.is_mine(txin.address) for txin in tx.inputs()]):
return (_("Warning") + ": "
+ _("The input amounts could not be verified as the previous transactions are missing.\n"
"The amount of money being spent CANNOT be verified."))
# some inputs are legacy
if any([not Transaction.is_segwit_input(txin) for txin in tx.inputs()]):
return (_("Warning") + ": "
+ _("The fee could not be verified. Signing non-segwit inputs is risky:\n"
"if this transaction was maliciously modified before you sign,\n"
"you might end up paying a higher mining fee than displayed."))
# all inputs are segwit
# https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-August/014843.html
return (_("Warning") + ": "
+ _("If you received this transaction from an untrusted device, "
"do not accept to sign it more than once,\n"
"otherwise you could end up paying a different fee."))
class Simple_Wallet(Abstract_Wallet):
# wallet with a single keystore

Loading…
Cancel
Save