commit 67d080b34a244f6e13c43052a0f4ba3d7c6eb346
parent 6926b8b2d4fdfa02ab67ad021cd6cce2764bb2fc
Author: SomberNight <somber.night@protonmail.com>
Date: Mon, 4 Feb 2019 18:45:42 +0100
mv qt update checker to its own file
Diffstat:
3 files changed, 145 insertions(+), 131 deletions(-)
diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py
@@ -75,6 +75,7 @@ from .fee_slider import FeeSlider
from .util import *
from .installwizard import WIF_HELP_TEXT
from .history_list import HistoryList, HistoryModel
+from .update_checker import UpdateCheck, UpdateCheckThread
class StatusBarButton(QPushButton):
diff --git a/electrum/gui/qt/update_checker.py b/electrum/gui/qt/update_checker.py
@@ -0,0 +1,141 @@
+# Copyright (C) 2019 The Electrum developers
+# Distributed under the MIT software license, see the accompanying
+# file LICENCE or http://www.opensource.org/licenses/mit-license.php
+
+import asyncio
+import base64
+from distutils.version import StrictVersion
+
+from PyQt5.QtCore import Qt, QThread, pyqtSignal
+from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QLabel, QProgressBar,
+ QHBoxLayout, QPushButton)
+
+from electrum import version
+from electrum import constants
+from electrum import ecc
+from electrum.i18n import _
+from electrum.util import PrintError, make_aiohttp_session
+
+
+class UpdateCheck(QWidget, PrintError):
+ url = "https://electrum.org/version"
+ download_url = "https://electrum.org/#download"
+
+ VERSION_ANNOUNCEMENT_SIGNING_KEYS = (
+ "13xjmVAB1EATPP8RshTE8S8sNwwSUM9p1P",
+ )
+
+ def __init__(self, main_window, latest_version=None):
+ self.main_window = main_window
+ QWidget.__init__(self)
+ self.setWindowTitle('Electrum - ' + _('Update Check'))
+ self.content = QVBoxLayout()
+ self.content.setContentsMargins(*[10]*4)
+
+ self.heading_label = QLabel()
+ self.content.addWidget(self.heading_label)
+
+ self.detail_label = QLabel()
+ self.detail_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
+ self.detail_label.setOpenExternalLinks(True)
+ self.content.addWidget(self.detail_label)
+
+ self.pb = QProgressBar()
+ self.pb.setMaximum(0)
+ self.pb.setMinimum(0)
+ self.content.addWidget(self.pb)
+
+ versions = QHBoxLayout()
+ versions.addWidget(QLabel(_("Current version: {}".format(version.ELECTRUM_VERSION))))
+ self.latest_version_label = QLabel(_("Latest version: {}".format(" ")))
+ versions.addWidget(self.latest_version_label)
+ self.content.addLayout(versions)
+
+ self.update_view(latest_version)
+
+ self.update_check_thread = UpdateCheckThread(self.main_window)
+ self.update_check_thread.checked.connect(self.on_version_retrieved)
+ self.update_check_thread.failed.connect(self.on_retrieval_failed)
+ self.update_check_thread.start()
+
+ close_button = QPushButton(_("Close"))
+ close_button.clicked.connect(self.close)
+ self.content.addWidget(close_button)
+ self.setLayout(self.content)
+ self.show()
+
+ def on_version_retrieved(self, version):
+ self.update_view(version)
+
+ def on_retrieval_failed(self):
+ self.heading_label.setText('<h2>' + _("Update check failed") + '</h2>')
+ self.detail_label.setText(_("Sorry, but we were unable to check for updates. Please try again later."))
+ self.pb.hide()
+
+ @staticmethod
+ def is_newer(latest_version):
+ return latest_version > StrictVersion(version.ELECTRUM_VERSION)
+
+ def update_view(self, latest_version=None):
+ if latest_version:
+ self.pb.hide()
+ self.latest_version_label.setText(_("Latest version: {}".format(latest_version)))
+ if self.is_newer(latest_version):
+ self.heading_label.setText('<h2>' + _("There is a new update available") + '</h2>')
+ url = "<a href='{u}'>{u}</a>".format(u=UpdateCheck.download_url)
+ self.detail_label.setText(_("You can download the new version from {}.").format(url))
+ else:
+ self.heading_label.setText('<h2>' + _("Already up to date") + '</h2>')
+ self.detail_label.setText(_("You are already on the latest version of Electrum."))
+ else:
+ self.heading_label.setText('<h2>' + _("Checking for updates...") + '</h2>')
+ self.detail_label.setText(_("Please wait while Electrum checks for available updates."))
+
+
+class UpdateCheckThread(QThread, PrintError):
+ checked = pyqtSignal(object)
+ failed = pyqtSignal()
+
+ def __init__(self, main_window):
+ super().__init__()
+ self.main_window = main_window
+
+ async def get_update_info(self):
+ async with make_aiohttp_session(proxy=self.main_window.network.proxy) as session:
+ async with session.get(UpdateCheck.url) as result:
+ signed_version_dict = await result.json(content_type=None)
+ # example signed_version_dict:
+ # {
+ # "version": "3.9.9",
+ # "signatures": {
+ # "1Lqm1HphuhxKZQEawzPse8gJtgjm9kUKT4": "IA+2QG3xPRn4HAIFdpu9eeaCYC7S5wS/sDxn54LJx6BdUTBpse3ibtfq8C43M7M1VfpGkD5tsdwl5C6IfpZD/gQ="
+ # }
+ # }
+ version_num = signed_version_dict['version']
+ sigs = signed_version_dict['signatures']
+ for address, sig in sigs.items():
+ if address not in UpdateCheck.VERSION_ANNOUNCEMENT_SIGNING_KEYS:
+ continue
+ sig = base64.b64decode(sig)
+ msg = version_num.encode('utf-8')
+ if ecc.verify_message_with_address(address=address, sig65=sig, message=msg,
+ net=constants.BitcoinMainnet):
+ self.print_error(f"valid sig for version announcement '{version_num}' from address '{address}'")
+ break
+ else:
+ raise Exception('no valid signature for version announcement')
+ return StrictVersion(version_num.strip())
+
+ def run(self):
+ network = self.main_window.network
+ if not network:
+ self.failed.emit()
+ return
+ try:
+ update_info = asyncio.run_coroutine_threadsafe(self.get_update_info(), network.asyncio_loop).result()
+ except Exception as e:
+ #self.print_error(traceback.format_exc())
+ self.print_error(f"got exception: '{repr(e)}'")
+ self.failed.emit()
+ else:
+ self.checked.emit(update_info)
diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py
@@ -5,21 +5,17 @@ import sys
import platform
import queue
import traceback
-from distutils.version import StrictVersion
+
from functools import partial, lru_cache
from typing import NamedTuple, Callable, Optional, TYPE_CHECKING
-import base64
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
-from electrum import version
-from electrum import ecc
-from electrum import constants
from electrum.i18n import _, languages
-from electrum.util import (FileImportFailed, FileExportFailed, make_aiohttp_session,
- PrintError, resource_path)
+from electrum.util import (FileImportFailed, FileExportFailed,
+ resource_path)
from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED
if TYPE_CHECKING:
@@ -826,130 +822,6 @@ class FromList(QTreeWidget):
self.header().setSectionResizeMode(1, sm)
-class UpdateCheck(QWidget, PrintError):
- url = "https://electrum.org/version"
- download_url = "https://electrum.org/#download"
-
- VERSION_ANNOUNCEMENT_SIGNING_KEYS = (
- "13xjmVAB1EATPP8RshTE8S8sNwwSUM9p1P",
- )
-
- def __init__(self, main_window, latest_version=None):
- self.main_window = main_window
- QWidget.__init__(self)
- self.setWindowTitle('Electrum - ' + _('Update Check'))
- self.content = QVBoxLayout()
- self.content.setContentsMargins(*[10]*4)
-
- self.heading_label = QLabel()
- self.content.addWidget(self.heading_label)
-
- self.detail_label = QLabel()
- self.detail_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
- self.detail_label.setOpenExternalLinks(True)
- self.content.addWidget(self.detail_label)
-
- self.pb = QProgressBar()
- self.pb.setMaximum(0)
- self.pb.setMinimum(0)
- self.content.addWidget(self.pb)
-
- versions = QHBoxLayout()
- versions.addWidget(QLabel(_("Current version: {}".format(version.ELECTRUM_VERSION))))
- self.latest_version_label = QLabel(_("Latest version: {}".format(" ")))
- versions.addWidget(self.latest_version_label)
- self.content.addLayout(versions)
-
- self.update_view(latest_version)
-
- self.update_check_thread = UpdateCheckThread(self.main_window)
- self.update_check_thread.checked.connect(self.on_version_retrieved)
- self.update_check_thread.failed.connect(self.on_retrieval_failed)
- self.update_check_thread.start()
-
- close_button = QPushButton(_("Close"))
- close_button.clicked.connect(self.close)
- self.content.addWidget(close_button)
- self.setLayout(self.content)
- self.show()
-
- def on_version_retrieved(self, version):
- self.update_view(version)
-
- def on_retrieval_failed(self):
- self.heading_label.setText('<h2>' + _("Update check failed") + '</h2>')
- self.detail_label.setText(_("Sorry, but we were unable to check for updates. Please try again later."))
- self.pb.hide()
-
- @staticmethod
- def is_newer(latest_version):
- return latest_version > StrictVersion(version.ELECTRUM_VERSION)
-
- def update_view(self, latest_version=None):
- if latest_version:
- self.pb.hide()
- self.latest_version_label.setText(_("Latest version: {}".format(latest_version)))
- if self.is_newer(latest_version):
- self.heading_label.setText('<h2>' + _("There is a new update available") + '</h2>')
- url = "<a href='{u}'>{u}</a>".format(u=UpdateCheck.download_url)
- self.detail_label.setText(_("You can download the new version from {}.").format(url))
- else:
- self.heading_label.setText('<h2>' + _("Already up to date") + '</h2>')
- self.detail_label.setText(_("You are already on the latest version of Electrum."))
- else:
- self.heading_label.setText('<h2>' + _("Checking for updates...") + '</h2>')
- self.detail_label.setText(_("Please wait while Electrum checks for available updates."))
-
-
-class UpdateCheckThread(QThread, PrintError):
- checked = pyqtSignal(object)
- failed = pyqtSignal()
-
- def __init__(self, main_window):
- super().__init__()
- self.main_window = main_window
-
- async def get_update_info(self):
- async with make_aiohttp_session(proxy=self.main_window.network.proxy) as session:
- async with session.get(UpdateCheck.url) as result:
- signed_version_dict = await result.json(content_type=None)
- # example signed_version_dict:
- # {
- # "version": "3.9.9",
- # "signatures": {
- # "1Lqm1HphuhxKZQEawzPse8gJtgjm9kUKT4": "IA+2QG3xPRn4HAIFdpu9eeaCYC7S5wS/sDxn54LJx6BdUTBpse3ibtfq8C43M7M1VfpGkD5tsdwl5C6IfpZD/gQ="
- # }
- # }
- version_num = signed_version_dict['version']
- sigs = signed_version_dict['signatures']
- for address, sig in sigs.items():
- if address not in UpdateCheck.VERSION_ANNOUNCEMENT_SIGNING_KEYS:
- continue
- sig = base64.b64decode(sig)
- msg = version_num.encode('utf-8')
- if ecc.verify_message_with_address(address=address, sig65=sig, message=msg,
- net=constants.BitcoinMainnet):
- self.print_error(f"valid sig for version announcement '{version_num}' from address '{address}'")
- break
- else:
- raise Exception('no valid signature for version announcement')
- return StrictVersion(version_num.strip())
-
- def run(self):
- network = self.main_window.network
- if not network:
- self.failed.emit()
- return
- try:
- update_info = asyncio.run_coroutine_threadsafe(self.get_update_info(), network.asyncio_loop).result()
- except Exception as e:
- #self.print_error(traceback.format_exc())
- self.print_error(f"got exception: '{repr(e)}'")
- self.failed.emit()
- else:
- self.checked.emit(update_info)
-
-
if __name__ == "__main__":
app = QApplication([])
t = WaitingDialog(None, 'testing ...', lambda: [time.sleep(1)], lambda x: QMessageBox.information(None, 'done', "done"))