1
0

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:
Sander van Grieken
2023-11-20 15:23:49 +01:00
committed by accumulator
parent 6467db0b7d
commit 7b96a83350
9 changed files with 167 additions and 22 deletions

View File

@@ -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: