wallet: add sighash check to class Abstract_Wallet
qml: use backend sighash check and add user confirmation path qt: use backend sighash check and add user confirmation path qml: include get_warning_for_risk_of_burning_coins_as_fees test in txdetails qt: add warning icon to sighash warning add sighash and fee checks to wallet.sign_transaction, making all warnings fatal unless ignore_warnings is set to True tests: test sign_transaction on both code paths with ignore_warnings True and False, raise specific exceptions TransactionPotentiallyDangerousException and TransactionDangerousException
This commit is contained in:
committed by
accumulator
parent
6467db0b7d
commit
7b96a83350
@@ -50,8 +50,7 @@ from electrum.bitcoin import base_encode, NLOCKTIME_BLOCKHEIGHT_MAX, DummyAddres
|
||||
from electrum.i18n import _
|
||||
from electrum.plugin import run_hook
|
||||
from electrum import simple_config
|
||||
from electrum.transaction import SerializationError, Transaction, PartialTransaction, PartialTxInput, TxOutpoint
|
||||
from electrum.transaction import TxinDataFetchProgress
|
||||
from electrum.transaction import SerializationError, Transaction, PartialTransaction, TxOutpoint, TxinDataFetchProgress
|
||||
from electrum.logging import get_logger
|
||||
from electrum.util import ShortID, get_asyncio_loop
|
||||
from electrum.network import Network
|
||||
@@ -77,15 +76,16 @@ _logger = get_logger(__name__)
|
||||
dialogs = [] # Otherwise python randomly garbage collects the dialogs...
|
||||
|
||||
|
||||
|
||||
class TxSizeLabel(QLabel):
|
||||
def setAmount(self, byte_size):
|
||||
self.setText(('x %s bytes =' % byte_size) if byte_size else '')
|
||||
|
||||
|
||||
class TxFiatLabel(QLabel):
|
||||
def setAmount(self, fiat_fee):
|
||||
self.setText(('≈ %s' % fiat_fee) if fiat_fee else '')
|
||||
|
||||
|
||||
class QTextBrowserWithDefaultSize(QTextBrowser):
|
||||
def __init__(self, width: int = 0, height: int = 0):
|
||||
self._width = width
|
||||
@@ -96,8 +96,8 @@ class QTextBrowserWithDefaultSize(QTextBrowser):
|
||||
def sizeHint(self):
|
||||
return QSize(self._width, self._height)
|
||||
|
||||
class TxInOutWidget(QWidget):
|
||||
|
||||
class TxInOutWidget(QWidget):
|
||||
def __init__(self, main_window: 'ElectrumWindow', wallet: 'Abstract_Wallet'):
|
||||
QWidget.__init__(self)
|
||||
|
||||
@@ -113,9 +113,24 @@ class TxInOutWidget(QWidget):
|
||||
self.inputs_textedit.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
self.inputs_textedit.customContextMenuRequested.connect(self.on_context_menu_for_inputs)
|
||||
|
||||
self.sighash_label = QLabel()
|
||||
self.sighash_label.setStyleSheet('font-weight: bold')
|
||||
self.sighash_confirm = False
|
||||
self.sighash_reject = False
|
||||
self.sighash_message = ''
|
||||
self.inputs_warning_icon = QLabel()
|
||||
pixmap = QPixmap(icon_path("warning"))
|
||||
pixmap_size = round(2 * char_width_in_lineedit())
|
||||
pixmap = pixmap.scaled(pixmap_size, pixmap_size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
self.inputs_warning_icon.setPixmap(pixmap)
|
||||
self.inputs_warning_icon.setVisible(False)
|
||||
|
||||
self.inheader_hbox = QHBoxLayout()
|
||||
self.inheader_hbox.setContentsMargins(0, 0, 0, 0)
|
||||
self.inheader_hbox.addWidget(self.inputs_header)
|
||||
self.inheader_hbox.addStretch(2)
|
||||
self.inheader_hbox.addWidget(self.sighash_label)
|
||||
self.inheader_hbox.addWidget(self.inputs_warning_icon)
|
||||
|
||||
self.txo_color_recv = TxOutputColoring(
|
||||
legend=_("Wallet Address"), color=ColorScheme.GREEN, tooltip=_("Wallet receiving address"))
|
||||
@@ -246,6 +261,13 @@ class TxInOutWidget(QWidget):
|
||||
short_id=str(txin.short_id), addr=addr, value=txin_value,
|
||||
)
|
||||
|
||||
if isinstance(self.tx, PartialTransaction):
|
||||
self.sighash_confirm, self.sighash_reject, self.sighash_message = self.wallet.check_sighash(self.tx)
|
||||
if self.sighash_message:
|
||||
self.sighash_label.setText(_('Danger! This transaction is non-standard!'))
|
||||
self.inputs_warning_icon.setVisible(True)
|
||||
self.inputs_warning_icon.setToolTip(self.sighash_message)
|
||||
|
||||
self.outputs_header.setText(_("Outputs") + ' (%d)'%len(self.tx.outputs()))
|
||||
o_text = self.outputs_textedit
|
||||
o_text.clear()
|
||||
@@ -645,6 +667,14 @@ class TxDialog(QDialog, MessageBoxMixin):
|
||||
self.update()
|
||||
self.main_window.pop_top_level_window(self)
|
||||
|
||||
if self.io_widget.sighash_confirm:
|
||||
if not self.question('\n'.join([
|
||||
_('Danger! This transaction is non-standard!'),
|
||||
self.io_widget.sighash_message,
|
||||
'',
|
||||
_('Are you sure you want to sign this transaction?')
|
||||
])):
|
||||
return
|
||||
self.sign_button.setDisabled(True)
|
||||
self.main_window.push_top_level_window(self)
|
||||
self.main_window.sign_tx(self.tx, callback=sign_done, external_keypairs=self.external_keypairs)
|
||||
@@ -771,7 +801,8 @@ class TxDialog(QDialog, MessageBoxMixin):
|
||||
self.broadcast_button.setEnabled(tx_details.can_broadcast)
|
||||
can_sign = not self.tx.is_complete() and \
|
||||
(self.wallet.can_sign(self.tx) or bool(self.external_keypairs))
|
||||
self.sign_button.setEnabled(can_sign)
|
||||
self.sign_button.setEnabled(can_sign and not self.io_widget.sighash_reject)
|
||||
self.sign_button.setToolTip(self.io_widget.sighash_message)
|
||||
if tx_details.txid:
|
||||
self.tx_hash_e.setText(tx_details.txid)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user