Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
gruve-p committed Oct 26, 2024
2 parents 6c6e87c + 5c81f77 commit 8779c15
Show file tree
Hide file tree
Showing 22 changed files with 202 additions and 94 deletions.
11 changes: 11 additions & 0 deletions contrib/android/buildozer_qml.spec
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,18 @@ source.exclude_dirs =
electrum_grs/scripts,
electrum_grs/utils,
electrum_grs/gui/qt,
electrum_grs/plugins/audio_modem,
electrum_grs/plugins/bitbox02,
electrum_grs/plugins/coldcard,
electrum_grs/plugins/digitalbitbox,
electrum_grs/plugins/hw_wallet,
electrum_grs/plugins/jade,
electrum_grs/plugins/keepkey,
electrum_grs/plugins/ledger,
electrum_grs/plugins/trezor,
electrum_grs/plugins/payserver,
electrum_grs/plugins/revealer,
electrum_grs/plugins/safe_t,
packages/qdarkstyle,
packages/qtpy,
packages/bin,
Expand Down
2 changes: 1 addition & 1 deletion electrum_grs/gui/qml/components/ConfirmTxDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ ElDialog {
Layout.fillWidth: true
text: (Daemon.currentWallet.isWatchOnly || !Daemon.currentWallet.canSignWithoutCosigner)
? qsTr('Finalize')
: qsTr('Pay')
: qsTr('Pay...')
icon.source: '../../icons/confirmed.png'
enabled: finalizer.valid
onClicked: doAccept()
Expand Down
2 changes: 1 addition & 1 deletion electrum_grs/gui/qml/components/InvoiceDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ ElDialog {
FlatButton {
Layout.fillWidth: true
Layout.preferredWidth: 1
text: qsTr('Pay')
text: qsTr('Pay...')
icon.source: '../../icons/confirmed.png'
enabled: invoice.invoiceType != Invoice.Invalid && invoice.canPay
onClicked: {
Expand Down
2 changes: 1 addition & 1 deletion electrum_grs/gui/qml/components/LnurlPayRequestDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ ElDialog {
FlatButton {
Layout.topMargin: constants.paddingLarge
Layout.fillWidth: true
text: qsTr('Pay')
text: qsTr('Pay...')
icon.source: '../../icons/confirmed.png'
enabled: valid
onClicked: {
Expand Down
24 changes: 21 additions & 3 deletions electrum_grs/gui/qml/components/OpenChannelDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ ElDialog {
font.family: FixedFont
wrapMode: Text.Wrap
placeholderText: qsTr('Paste or scan node uri/pubkey')
inputMethodHints: Qt.ImhSensitiveData | Qt.ImhNoPredictiveText | Qt.ImhNoAutoUppercase
onTextChanged: {
if (activeFocus)
channelopener.connectStr = text
}
onActiveFocusChanged: {
if (!activeFocus)
channelopener.connectStr = text
Expand All @@ -96,9 +101,17 @@ ElDialog {
icon.height: constants.iconSizeMedium
icon.width: constants.iconSizeMedium
onClicked: {
if (channelopener.validateConnectString(AppController.clipboardToText())) {
channelopener.connectStr = AppController.clipboardToText()
var cliptext = AppController.clipboardToText()
if (!cliptext)
return
if (channelopener.validateConnectString(cliptext)) {
channelopener.connectStr = cliptext
node.text = channelopener.connectStr
} else {
var dialog = app.messageDialog.createObject(app, {
text: qsTr('Invalid node-id or connect string')
})
dialog.open()
}
}
}
Expand All @@ -109,12 +122,17 @@ ElDialog {
scale: 1.2
onClicked: {
var dialog = app.scanDialog.createObject(app, {
hint: qsTr('Scan a channel connect string')
hint: qsTr('Scan a node-id or a connect string')
})
dialog.onFound.connect(function() {
if (channelopener.validateConnectString(dialog.scanData)) {
channelopener.connectStr = dialog.scanData
node.text = channelopener.connectStr
} else {
var errdialog = app.messageDialog.createObject(app, {
text: qsTr('Invalid node-id or connect string')
})
errdialog.open()
}
dialog.close()
})
Expand Down
2 changes: 1 addition & 1 deletion electrum_grs/gui/qml/components/OtpDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ElDialog {
id: dialog

title: qsTr('Trustedcoin')
iconSource: '../../../icons/trustedcoin-status.png'
iconSource: Qt.resolvedUrl('../../../plugins/trustedcoin/trustedcoin-status.png')

property string otpauth

Expand Down
2 changes: 1 addition & 1 deletion electrum_grs/gui/qml/components/controls/SeedTextArea.qml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Pane {
font.pixelSize: constants.fontSizeLarge
font.family: FixedFont
inputMethodHints: Qt.ImhSensitiveData | Qt.ImhLowercaseOnly | Qt.ImhNoPredictiveText
readOnly: true
readOnly: AppController.isAndroid()

background: Rectangle {
color: constants.darkerBackground
Expand Down
4 changes: 2 additions & 2 deletions electrum_grs/gui/qml/components/wizard/WCHaveSeed.qml
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ WizardComponent {
if (seed_variant_cb.currentValue == 'electrum') {
apply()
if (wiz.hasDuplicateMasterKeys(wizard_data)) {
validationtext.text = qsTr('Error: duplicate master public key')
_validationMessage = qsTr('Error: duplicate master public key')
return
} else if (wiz.hasHeterogeneousMasterKeys(wizard_data)) {
validationtext.text = qsTr('Error: master public key types do not match')
_validationMessage = qsTr('Error: master public key types do not match')
return
} else {
_seedValid = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ WizardComponent {
var p = isMultisig ? getMultisigScriptTypePurposeDict() : getScriptTypePurposeDict()
if (!scripttypegroup.checkedButton.scripttype in p)
return
if (!bitcoin.verifyDerivationPath(derivationpathtext.text))
if (!bitcoin.verifyDerivationPath(derivationpathtext.text)) {
validationtext.text = qsTr('Invalid derivation path')
return
}

if (isMultisig && cosigner) {
apply()
Expand Down
3 changes: 2 additions & 1 deletion electrum_grs/gui/qml/qeapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ def textToClipboard(self, text):

@pyqtSlot(result='QString')
def clipboardToText(self):
return QGuiApplication.clipboard().text()
clip = QGuiApplication.clipboard()
return clip.text() if clip.mimeData().hasText() else ''

@pyqtSlot(str, result=QObject)
def plugin(self, plugin_name):
Expand Down
42 changes: 17 additions & 25 deletions electrum_grs/gui/qml/qetxfinalizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,19 @@ def update_outputs_from_tx(self, tx):
})
self.outputs = outputs

def update_fee_warning_from_tx(self, *, tx: PartialTransaction, invoice_amt: Optional[int]):
if invoice_amt is None:
invoice_amt = sum([txo.value for txo in tx.outputs() if not txo.is_mine])
if invoice_amt == 0:
invoice_amt = tx.output_value()
fee_warning_tuple = self._wallet.wallet.get_tx_fee_warning(
invoice_amt=invoice_amt, tx_size=tx.estimated_size(), fee=tx.get_fee())
if fee_warning_tuple:
allow_send, long_warning, short_warning = fee_warning_tuple
self.warning = _('Warning') + ': ' + long_warning
else:
self.warning = ''


class QETxFinalizer(TxFeeSlider):
_logger = get_logger(__name__)
Expand Down Expand Up @@ -385,13 +398,7 @@ def update(self):
x_fee_address, x_fee_amount = x_fee
self.extraFee = QEAmount(amount_sat=x_fee_amount)

fee_warning_tuple = self._wallet.wallet.get_tx_fee_warning(
invoice_amt=amount, tx_size=tx.estimated_size(), fee=tx.get_fee())
if fee_warning_tuple:
allow_send, long_warning, short_warning = fee_warning_tuple
self.warning = _('Warning') + ': ' + long_warning
else:
self.warning = ''
self.update_fee_warning_from_tx(tx=tx, invoice_amt=amount)

self._valid = True
self.validChanged.emit()
Expand Down Expand Up @@ -603,16 +610,7 @@ def update(self):
self._tx.set_rbf(self.rbf)

self.update_from_tx(self._tx)

# TODO: deduce amount sent?
# TODO: we don't handle send-max txs correctly yet
# fee_warning_tuple = self._wallet.wallet.get_tx_fee_warning(
# invoice_amt=amount, tx_size=tx.estimated_size(), fee=tx.get_fee())
# if fee_warning_tuple:
# allow_send, long_warning, short_warning = fee_warning_tuple
# self.warning = long_warning
# else:
# self.warning = ''
self.update_fee_warning_from_tx(tx=self._tx, invoice_amt=None)

self._valid = True
self.validChanged.emit()
Expand Down Expand Up @@ -709,6 +707,7 @@ def update(self):
self._tx.set_rbf(self.rbf)

self.update_from_tx(self._tx)
self.update_fee_warning_from_tx(tx=self._tx, invoice_amt=None)

self._valid = True
self.validChanged.emit()
Expand Down Expand Up @@ -952,14 +951,7 @@ def update(self):
self.effectiveAmountChanged.emit()

self.update_from_tx(tx)

fee_warning_tuple = self._wallet.wallet.get_tx_fee_warning(
invoice_amt=amount, tx_size=tx.estimated_size(), fee=tx.get_fee())
if fee_warning_tuple:
allow_send, long_warning, short_warning = fee_warning_tuple
self.warning = _('Warning') + ': ' + long_warning
else:
self.warning = ''
self.update_fee_warning_from_tx(tx=self._tx, invoice_amt=amount)

self._valid = True
self.validChanged.emit()
Expand Down
12 changes: 8 additions & 4 deletions electrum_grs/gui/qt/seed_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def __init__(

self.options = options
self.config = config
self.msg = msg

if options:
self.seed_types = [
Expand Down Expand Up @@ -222,24 +223,27 @@ def on_selected(idx):
self.updated.emit()

def update_seed_warning(self):
if self.msg:
return

if self.seed_type == 'bip39':
msg = ' '.join([
message = ' '.join([
'<b>' + _('Warning') + ':</b> ',
_('BIP39 seeds can be imported in Electrum, so that users can access funds locked in other wallets.'),
_('However, we do not generate BIP39 seeds, because they do not meet our safety standard.'),
_('BIP39 seeds do not include a version number, which compromises compatibility with future software.'),
_('We do not guarantee that BIP39 imports will always be supported in Electrum.'),
])
elif self.seed_type == 'slip39':
msg = ' '.join([
message = ' '.join([
'<b>' + _('Warning') + ':</b> ',
_('SLIP39 seeds can be imported in Electrum, so that users can access funds locked in other wallets.'),
_('However, we do not generate SLIP39 seeds.'),
])
else:
msg = ''
message = ''

self.seed_warning.setText(msg)
self.seed_warning.setText(message)

def initialize_completer(self):
if self.seed_type != 'slip39':
Expand Down
14 changes: 10 additions & 4 deletions electrum_grs/gui/qt/wizard/wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ def __init__(self, config: 'SimpleConfig', app: 'QElectrumApplication', *, start
outer_vbox.addLayout(hbox)
outer_vbox.addLayout(Buttons(self.back_button, self.next_button))

self.setTabOrder(self.back_button, self.next_button)

self.icon_filename = None
self.set_icon('electrum.png')

Expand All @@ -127,6 +129,7 @@ def strt(self):
else:
viewstate = self.start_wizard()
self.load_next_component(viewstate.view, viewstate.wizard_data, viewstate.params)
self.next_button.setFocus()
# TODO: re-test if needed on macOS
self.refresh_gui() # Need for QT on MacOSX. Lame.

Expand All @@ -143,6 +146,7 @@ def load_next_component(self, view, wdata=None, params=None):

comp = self.view_to_component(view)
try:
self._logger.debug(f'load_next_component: {comp!r}')
page = comp(self.main_widget, self)
except Exception as e:
self._logger.error(f'not a class: {comp!r}')
Expand All @@ -151,13 +155,11 @@ def load_next_component(self, view, wdata=None, params=None):
page.params = params
page.on_ready() # call before component emits any signals

self._logger.debug(f'load_next_component: {page=!r}')

page.updated.connect(self.on_page_updated)

# add to stack and update wizard
self.main_widget.setCurrentIndex(self.main_widget.addWidget(page))
page.apply()
self.main_widget.setCurrentIndex(self.main_widget.addWidget(page))
self.update()

@pyqtSlot(object)
Expand Down Expand Up @@ -218,7 +220,11 @@ def on_next_button_clicked(self):
self.prev() # rollback the submit above
else:
view = self.submit(wd)
self.load_next_component(view.view, view.wizard_data, view.params)
try:
self.load_next_component(view.view, view.wizard_data, view.params)
except Exception as e:
self.prev() # rollback the submit above
raise e

def start_wizard(self) -> 'WizardViewState':
self.start()
Expand Down
18 changes: 16 additions & 2 deletions electrum_grs/lnpeer.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from . import constants
from .util import (bfh, log_exceptions, ignore_exceptions, chunks, OldTaskGroup,
UnrelatedTransactionException, error_text_bytes_to_safe_str, AsyncHangDetector)
from .util import event_listener, EventListener
from . import transaction
from .bitcoin import make_op_return, DummyAddress
from .transaction import PartialTxOutput, match_script_against_template, Sighash
Expand Down Expand Up @@ -64,7 +65,7 @@
LN_P2P_NETWORK_TIMEOUT = 20


class Peer(Logger):
class Peer(Logger, EventListener):
# note: in general this class is NOT thread-safe. Most methods are assumed to be running on asyncio thread.

LOGGING_SHORTCUT = 'P'
Expand Down Expand Up @@ -122,6 +123,7 @@ def __init__(
self._received_revack_event = asyncio.Event()
self.received_commitsig_event = asyncio.Event()
self.downstream_htlc_resolved_event = asyncio.Event()
self.register_callbacks()

def send_message(self, message_name: str, **kwargs):
assert util.get_running_loop() == util.get_asyncio_loop(), f"this must be run on the asyncio thread!"
Expand Down Expand Up @@ -633,6 +635,7 @@ def close_and_cleanup(self):
# note: This method might get called multiple times!
# E.g. if you call close_and_cleanup() to cause a disconnection from the peer,
# it will get called a second time in handle_disconnect().
self.unregister_callbacks()
try:
if self.transport:
self.transport.close()
Expand Down Expand Up @@ -2251,6 +2254,13 @@ def on_revoke_and_ack(self, chan: Channel, payload):
self._received_revack_event.set()
self._received_revack_event.clear()

@event_listener
async def on_event_fee(self, *args):
async def async_wrapper():
for chan in self.channels.values():
self.maybe_update_fee(chan)
await self.taskgroup.spawn(async_wrapper)

def on_update_fee(self, chan: Channel, payload):
if chan.peer_state != PeerState.GOOD: # should never happen
raise Exception(f"received update_fee in unexpected {chan.peer_state=!r}")
Expand Down Expand Up @@ -2750,6 +2760,7 @@ async def wrapped_callback():
# return payment_key so this branch will not be executed again
return None, payment_key, None
elif preimage:
self.lnworker.maybe_cleanup_mpp(chan.get_scid_or_local_alias(), htlc)
return preimage, None, None
else:
# we are waiting for mpp consolidation or preimage
Expand All @@ -2761,7 +2772,10 @@ async def wrapped_callback():
preimage = self.lnworker.get_preimage(payment_hash)
error_bytes, error_reason = self.lnworker.get_forwarding_failure(payment_key)
if error_bytes or error_reason or preimage:
self.lnworker.maybe_cleanup_forwarding(payment_key, chan.get_scid_or_local_alias(), htlc)
cleanup_keys = self.lnworker.maybe_cleanup_mpp(chan.get_scid_or_local_alias(), htlc)
is_htlc_key = ':' in payment_key
if is_htlc_key or payment_key in cleanup_keys:
self.lnworker.maybe_cleanup_forwarding(payment_key)
if error_bytes:
return None, None, error_bytes
if error_reason:
Expand Down
Loading

0 comments on commit 8779c15

Please sign in to comment.