diff --git a/.gitignore b/.gitignore
index f3f2b590..07865821 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,7 @@ dist/
*.egg/
contrib/pyinstaller/
Electrum.egg-info/
-locale/
+electrum/locale/
.devlocaltmp/
*_trial_temp
packages
diff --git a/MANIFEST.in b/MANIFEST.in
index d09f4f5d..7caf98b0 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,5 @@
include LICENCE RELEASE-NOTES AUTHORS
include README.rst
-include electrum.conf.sample
include electrum.desktop
include *.py
include run_electrum
@@ -15,4 +14,6 @@ graft electrum
prune electrum/tests
global-exclude __pycache__
-global-exclude *.py[co]
+global-exclude *.py[co~]
+global-exclude *.py.orig
+global-exclude *.py.rej
diff --git a/README.rst b/README.rst
index 6dfb6994..ff3c18c1 100644
--- a/README.rst
+++ b/README.rst
@@ -91,25 +91,25 @@ Create translations (optional)::
Creating Binaries
=================
+Linux
+-----
-To create binaries, create the 'packages' directory::
+See :code:`contrib/build-linux/README.md`.
- ./contrib/make_packages
-
-This directory contains the python dependencies used by Electrum.
Mac OS X / macOS
---------
+----------------
+
+See :code:`contrib/osx/README.md`.
-See `contrib/osx/`.
Windows
-------
-See `contrib/build-wine/`.
+See :code:`contrib/build-wine/docker/README.md`.
Android
-------
-See `electrum/gui/kivy/Readme.md` file.
+See :code:`electrum/gui/kivy/Readme.md`.
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index ecf3ecb8..568fdecf 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,3 +1,14 @@
+# Release 3.3.3 - (January 25, 2019)
+
+ * Do not expose users to server error messages (#4968)
+ * Notify users of new releases. Release announcements must be signed,
+ and they are verified byElectrum using a hardcoded Bitcoin address.
+ * Hardware wallet fixes (#4991, #4993, #5006)
+ * Display only QR code in QRcode Window
+ * Fixed code signing on MacOS
+ * Randomise locktime of transactions
+
+
# Release 3.3.2 - (December 21, 2018)
* Fix Qt history export bug
diff --git a/contrib/build-linux/README.md b/contrib/build-linux/README.md
new file mode 100644
index 00000000..8d45038c
--- /dev/null
+++ b/contrib/build-linux/README.md
@@ -0,0 +1,20 @@
+Source tarballs
+===============
+
+1. Build locale files
+
+ ```
+ contrib/make_locale
+ ```
+
+2. Prepare python dependencies used by Electrum.
+
+ ```
+ contrib/make_packages
+ ```
+
+3. Create source tarball.
+
+ ```
+ contrib/make_tgz
+ ```
diff --git a/contrib/build-wine/prepare-wine.sh b/contrib/build-wine/prepare-wine.sh
index e80259f5..f9e6941f 100755
--- a/contrib/build-wine/prepare-wine.sh
+++ b/contrib/build-wine/prepare-wine.sh
@@ -116,7 +116,7 @@ $PYTHON -m pip install pip --upgrade
$PYTHON -m pip install -r $here/../deterministic-build/requirements-binaries.txt
# Install PyInstaller
-$PYTHON -m pip install pyinstaller==3.4
+$PYTHON -m pip install pyinstaller==3.4 --no-use-pep517
# Install ZBar
download_if_not_exist $ZBAR_FILENAME "$ZBAR_URL"
diff --git a/contrib/deterministic-build/electrum-icons b/contrib/deterministic-build/electrum-icons
index d586021b..201d45cd 160000
--- a/contrib/deterministic-build/electrum-icons
+++ b/contrib/deterministic-build/electrum-icons
@@ -1 +1 @@
-Subproject commit d586021ba0d4820d6587cff000756b3d035d4f08
+Subproject commit 201d45cd5d855c4f9de5680ab5c53621574dc6b6
diff --git a/contrib/deterministic-build/electrum-locale b/contrib/deterministic-build/electrum-locale
index caba5f30..e5b28e47 160000
--- a/contrib/deterministic-build/electrum-locale
+++ b/contrib/deterministic-build/electrum-locale
@@ -1 +1 @@
-Subproject commit caba5f30b134ec08d3e29150b33c87200597181a
+Subproject commit e5b28e4717d8c8a736d6d4e5398fa4fa67db80d0
diff --git a/contrib/deterministic-build/requirements-binaries.txt b/contrib/deterministic-build/requirements-binaries.txt
index e615ae3a..12fbcf06 100644
--- a/contrib/deterministic-build/requirements-binaries.txt
+++ b/contrib/deterministic-build/requirements-binaries.txt
@@ -1,34 +1,35 @@
-pip==18.1 \
- --hash=sha256:7909d0a0932e88ea53a7014dfd14522ffef91a464daaaf5c573343852ef98550 \
- --hash=sha256:c0a292bd977ef590379a3f05d7b7f65135487b67470f6281289a94e015650ea1
-pycryptodomex==3.7.2 \
- --hash=sha256:09f433a6ca4b96a4c89096af9eaa20c5d5e9029a03266f6a80062163d2042030 \
- --hash=sha256:0bb7686dd46d40cace053941638d2db4f9d86a50a62d6100f14157162e56e82f \
- --hash=sha256:13ef8e8a26a9ac7ae84616e9c500ca0cf721d3725d740124f68dda1b58e7d408 \
- --hash=sha256:195b6540f31cbe3dc7bf3877177bb4fe1a145ce02191efdd0cb6399bff275d4b \
- --hash=sha256:329ca5986c5e5f6a60edc3ff8b70c28d6cb259491e35e44870db6a8d92430e50 \
- --hash=sha256:42b2eccccb9da547e0ff140784037ea31c1a37012488706b51cbcadb885d2053 \
- --hash=sha256:4b2817bd02dd7dd36f223917f9bcc90d658bb66124bc596d7e3a0c250509acf7 \
- --hash=sha256:5b765870e17bf82a992f2ebb312207da76dbf8694ce865fee847005cce9244e4 \
- --hash=sha256:5d4e10ad9ff7940da534119ef92a500dcf7c28351d15e12d74ef0ce025e37d5b \
- --hash=sha256:75186284b593df724451869035bfab4a03b6b388ed6eea284ad7fe84c9b64ea0 \
- --hash=sha256:77928b02c28adb4d1d637c609aba380d890fb40ad63c58c826bef871c84cf488 \
- --hash=sha256:7cd21c1a4dd0879dc3b289afeb0033a9382da7d0a50cb9de8d0e59c1ab0977a7 \
- --hash=sha256:83b7fe71fb9d27ff12df9dd3f57ea84153a86f45a674ee2b4763aaaf8ca84988 \
- --hash=sha256:8a67f26365ddad6ae53c0b3800edce16d164e675ee773de31c110624e63736d8 \
- --hash=sha256:8e08238f8d146caabf9d80cca09dd31323a333f74f62323aabd075e7effbc45c \
- --hash=sha256:938af93204c93d1f576acdef970e95dfd0bbe40133f4bbf73c4b12b67f7bd4ed \
- --hash=sha256:b2f33943f91c764f2b27a1504cd3ec2c075deb7d1b8fcc3ab4d575bede7037a8 \
- --hash=sha256:b7efd0ac8b38dfdf8b2d387e84b007c843a66de9da437a950a86caa2d1437e1e \
- --hash=sha256:b95b14e5baaa4ca77ecb7a3d0f85fd13a8e31ada83c5a2bae5652d446414d63d \
- --hash=sha256:bad0c66c42d16e81eef2199b3c4fb78c873f54c7f9d156e69664e2138155747c \
- --hash=sha256:c384a85bede5396eed50f6c0374d8c51490fc10fdc65dffc8e613b57e5ab0ee0 \
- --hash=sha256:c58a324a8eb48f767abe8c906295d76e04330aa0a03d99dd58d9a42938ee0596 \
- --hash=sha256:d498731d66f9b9ad978c9a8018b0c6cfc4081e202a79c6e283ade7dcf2a72c18 \
- --hash=sha256:d516746fc25daff1c5e84d3f816d134d75a10e3551ffac92aa957a75b6b0208f \
- --hash=sha256:ec51ea9f11b11df2719a01ea1cacdcf80858542a93f530a25a3bc742d0fe2f4b \
- --hash=sha256:ef2792281138a29e54bdd7302fdab72be140192485dc622bb9e7e9a6f9cee4f9 \
- --hash=sha256:f79650ec8812b01f20aca503763b93b0b1b347423ecf9fd3a9ebb611bee84079
+pip==19.0.1 \
+ --hash=sha256:aae79c7afe895fb986ec751564f24d97df1331bb99cdfec6f70dada2f40c0044 \
+ --hash=sha256:e81ddd35e361b630e94abeda4a1eddd36d47a90e71eb00f38f46b57f787cd1a5
+pycryptodomex==3.7.3 \
+ --hash=sha256:0bda549e20db1eb8e29fb365d10acf84b224d813b1131c828fc830b2ce313dcd \
+ --hash=sha256:1210c0818e5334237b16d99b5785aa0cee815d9997ee258bd5e2936af8e8aa50 \
+ --hash=sha256:2090dc8cd7843eae75bd504b9be86792baa171fc5a758ea3f60188ab67ca95cf \
+ --hash=sha256:22e6784b65dfdd357bf9a8a842db445192b227103e2c3137a28c489c46742135 \
+ --hash=sha256:2edb8c3965a77e3092b5c5c1233ffd32de083f335202013f52d662404191ac79 \
+ --hash=sha256:310fe269ac870135ff610d272e88dcb594ee58f40ac237a688d7c972cbca43e8 \
+ --hash=sha256:456136b7d459f000794a67b23558351c72e21f0c2d4fcaa09fc99dae7844b0ef \
+ --hash=sha256:463e49a9c5f1fa7bd36aff8debae0b5c487868c1fb66704529f2ad7e92f0cc9f \
+ --hash=sha256:4a33b2828799ef8be789a462e6645ea6fe2c42b0df03e6763ccbfd1789c453e6 \
+ --hash=sha256:5ff02dff1b03929e6339226b318aa59bd0b5c362f96e3e0eb7f3401d30594ed3 \
+ --hash=sha256:6b1db8234b8ee2b30435d9e991389c2eeae4d45e09e471ffe757ba1dfae682bb \
+ --hash=sha256:6eb67ee02de143cd19e36a52bd3869a9dc53e9184cd6bed5c39ff71dee2f6a45 \
+ --hash=sha256:6f42eea5afc7eee29494fdfddc6bb7173953d4197d9200e4f67096c2a24bc21b \
+ --hash=sha256:87bc8082e2de2247df7d0b161234f8edb1384294362cc0c8db9324463097578b \
+ --hash=sha256:8df93d34bc0e3a28a27652070164683a07d8a50c628119d6e0f7710f4d01b42f \
+ --hash=sha256:989952c39e8fef1c959f0a0f85656e29c41c01162e33a3f5fd8ce71e47262ae9 \
+ --hash=sha256:a4a203077e2f312ec8677dde80a5c4e6fe5a82a46173a8edc8da668602a3e073 \
+ --hash=sha256:a793c1242dffd39f585ae356344e8935d30f01f6be7d4c62ffc87af376a2f5f9 \
+ --hash=sha256:b70fe991564e178af02ccf89435a8f9e8d052707a7c4b95bf6027cb785da3175 \
+ --hash=sha256:b83594196e3661cb78c97b80a62fbfbba2add459dfd532b58e7a7c62dd06aab4 \
+ --hash=sha256:ba27725237d0a3ea66ec2b6b387259471840908836711a3b215160808dffed0f \
+ --hash=sha256:d1ab8ad1113cdc553ca50c4d5f0142198c317497364c0c70443d69f7ad1c9288 \
+ --hash=sha256:dce039a8a8a318d7af83cae3fd08d58cefd2120075dfac0ae14d706974040f63 \
+ --hash=sha256:e3213037ea33c85ab705579268cbc8a4433357e9fb99ec7ce9fdcc4d4eec1d50 \
+ --hash=sha256:ec8d8023d31ef72026d46e9fb301ff8759eff5336bcf3d1510836375f53f96a9 \
+ --hash=sha256:ece65730d50aa57a1330d86d81582a2d1587b2ca51cb34f586da8551ddc68fee \
+ --hash=sha256:ed21fc515e224727793e4cc3fb3d00f33f59e3a167d3ad6ac1475ab3b05c2f9e \
+ --hash=sha256:eec1132d878153d61a05424f35f089f951bd6095a4f6c60bdd2ef8919d44425e
PyQt5==5.11.3 \
--hash=sha256:517e4339135c4874b799af0d484bc2e8c27b54850113a68eec40a0b56534f450 \
--hash=sha256:ac1eb5a114b6e7788e8be378be41c5e54b17d5158994504e85e43b5fca006a39 \
diff --git a/contrib/deterministic-build/requirements-hw.txt b/contrib/deterministic-build/requirements-hw.txt
index 60ff68b6..fad4e540 100644
--- a/contrib/deterministic-build/requirements-hw.txt
+++ b/contrib/deterministic-build/requirements-hw.txt
@@ -14,35 +14,35 @@ click==7.0 \
--hash=sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7
construct==2.9.45 \
--hash=sha256:2271a0efd0798679dea825ff47e22a4c550456a5db0ba8baa82f7eae0af0118c
-Cython==0.29.2 \
- --hash=sha256:004c181b75f926f48dc0570372ca2cfb06a1b3210cb647185977ce9fde98b66e \
- --hash=sha256:085d596c016130f5b1e2fe72446e3e63bfcf67535e7ff6772eaa05c5d2ad6fd5 \
- --hash=sha256:1014758344717844a05882c92ebd76d8fab15b0a8e9b42b378a99a6c5299ab3b \
- --hash=sha256:12c007d3704ca9840734748fd6c052960be67562ff15609c3b85d1ca638289d2 \
- --hash=sha256:1a20f575197e814453f2814829715fcb21436075e298d883a34c7ffe4d567a1d \
- --hash=sha256:1b6f201228368ec9b307261b46512f3605f84d4994bb6eb78cdab71455810424 \
- --hash=sha256:2ac187ff998a95abb7fae452b5178f91e1a713698c9ced89836c94e6b1d3f41e \
- --hash=sha256:3585fbe18d8666d91ecb3b3366ca6e9ea49001cd0a7c38a226cececb7852aa0d \
- --hash=sha256:3669dfe4117ee8825a48cf527cb4ac15a39a0142fcb72ecedfd75fe6545b2cda \
- --hash=sha256:382c1e0f8f8be36e9057264677fd60b669a41c5810113694cbbb4060ee0cefc0 \
- --hash=sha256:44bb606d8c60d8acaa7f72b3bbc2ebd9816785124c58d33c057ca326f1185dae \
- --hash=sha256:6f1a5344ff1f0f44023c41d4b0e52215b490658b42e017520cb89a56250ecbca \
- --hash=sha256:7a29f9d780ac497dcd76ce814a9d170575bedddeb89ecc25fe738abef4c87172 \
- --hash=sha256:8022a5b83ef442584f2efd941fe8678de1c67e28bf81e6671b20627ec8a79387 \
- --hash=sha256:998af90092cd1231990eb878e2c71ed92716d6a758aa03a2e6673e077a7dd072 \
- --hash=sha256:9e60b83afe8914ab6607f7150fd282d1cb0531a45cf98d2a40159f976ae4cd7a \
- --hash=sha256:a6581d3dda15adea19ac70b89211aadbf21f45c7f3ee3bc8e1536e5437c9faf9 \
- --hash=sha256:af515924b8aebb729f631590eb43300ce948fa67d3885fdae9238717c0a68821 \
- --hash=sha256:b49ea3bb357bc34eaa7b461633ce7c2d79186fe681297115ff9e2b8f5ceba2fd \
- --hash=sha256:bc524cc603f0aa23af00111ddd1aa0aad12d629f5a9a5207f425a1af66393094 \
- --hash=sha256:ca7daccffb14896767b20d69bfc8de9e41e9589b9377110292c3af8460ef9c2b \
- --hash=sha256:cdfb68eb11c6c4e90e34cf54ffd678a7813782fae980d648db6185e6b0c8a0ba \
- --hash=sha256:d21fb6e7a3831f1f8346275839d46ed1eb2abd350fc81bad2fdf208cc9e4f998 \
- --hash=sha256:e17104c6871e7c0eee4de12717892a1083bd3b8b1da0ec103fa464b1c6c80964 \
- --hash=sha256:e7f71b489959d478cff72d8dcab1531efd43299341e3f8b85ab980beec452ded \
- --hash=sha256:e8420326e4b40bcbb06f070efb218ca2ca21827891b7c69d4cc4802b3ce1afc9 \
- --hash=sha256:eec1b890cf5c16cb656a7062769ac276c0fccf898ce215ff8ef75eac740063f7 \
- --hash=sha256:f04e21ba7c117b20f57b0af2d4c8ed760495e5bb3f21b0352dbcfe5d2221678b
+Cython==0.29.3 \
+ --hash=sha256:1327655db47beb665961d3dc0365e20c9e8e80c234513ab2c7d06ec0dd9d63eb \
+ --hash=sha256:142400f13102403f43576bb92d808a668e29deda5625388cfa39fe0bcf37b3d1 \
+ --hash=sha256:1b4204715141281a631337378f0c15fe660b35e1b6888ca05f1f3f49df3b97d5 \
+ --hash=sha256:23aabaaf8887e6db99df2145de6742f8c92830134735778bf2ae26338f2b406f \
+ --hash=sha256:2a724c6f21fdf4e3c1e8c5c862ff87f5420fdaecf53a5a0417915e483d90217f \
+ --hash=sha256:2c9c8c1c6e8bd3587e5f5db6f865a42195ff2dedcaf5cdb63fdea10c98bd6246 \
+ --hash=sha256:3a1be38b774423605189d60652b3d8a324fc81d213f96569720c8093784245ab \
+ --hash=sha256:46be5297a76513e4d5d6e746737d4866a762cfe457e57d7c54baa7ef8fea7e9a \
+ --hash=sha256:48dc2ea4c4d3f34ddcad5bc71b1f1cf49830f868832d3e5df803c811e7395b6e \
+ --hash=sha256:53f33e04d2ed078ac02841741bcd536b546e1f416608084468ab30a87638a466 \
+ --hash=sha256:57b10588618ca19a4cc870f381aa8805bc5fe0c62d19d7f940232ff8a373887c \
+ --hash=sha256:6001038341b52301450bb9c62e5d5da825788944572679277e137ffb3596e718 \
+ --hash=sha256:70bef52e735607060f327d729be35c820d9018d260a875e4f98b20ba8c4fff96 \
+ --hash=sha256:7d0f76b251699be8f1f1064dcb12d4b3b2b676ce15ff30c104e0c2091a015142 \
+ --hash=sha256:9440b64c1569c26a184b7c778bb221cf9987c5c8486d32cda02302c66ea78980 \
+ --hash=sha256:956cc97eac6f9d3b16e3b2d2a94c5586af3403ba97945e9d88a4a0f029899646 \
+ --hash=sha256:ae430ad8cce937e07ea566d1d7899eef1fedc8ec512b4d5fa37ebf2c1f879936 \
+ --hash=sha256:bdb575149881978d62167dd8427402a5872a79bd83e9d51219680670e9f80b40 \
+ --hash=sha256:c0ffcddd3dbdf22aae3980931112cc8b2732315a6273988f3205cf5dacf36f45 \
+ --hash=sha256:c133e2efc57426974366ac74f2ef0f1171b860301ac27f72316deacff4ccdc17 \
+ --hash=sha256:c6e9521d0b77eb1da89e8264eb98c8f5cda7c49a49b8128acfd35f0ca50e56d0 \
+ --hash=sha256:c7cac0220ecb733024e8acfcfb6b593a007185690f2ea470d2392b72510b7187 \
+ --hash=sha256:d53483820ac28f2be2ff13eedd56c0f36a4c583727b551d3d468023556e2336a \
+ --hash=sha256:d60210784186d61e0ec808d5dbee5d661c7457a57f93cb5fdc456394607ce98c \
+ --hash=sha256:d687fb1cd9df28c1515666174c62e54bd894a6a6d0862f89705063cd47739f83 \
+ --hash=sha256:d926764d9c768a48b0a16a91696aaa25498057e060934f968fa4c5629b942d85 \
+ --hash=sha256:d94a2f4ad74732f58d1c771fc5d90a62c4fe4c98d0adfecbc76cd0d8d14bf044 \
+ --hash=sha256:def76a546eeec059666f5f4117dfdf9c78e50fa1f95bdd23b04618c7adf845cd
ecdsa==0.13 \
--hash=sha256:40d002cf360d0e035cf2cb985e1308d41aaa087cbfc135b2dc2d844296ea546c \
--hash=sha256:64cf1ee26d1cde3c73c6d7d107f835fed7c6a2904aef9eac223d57ad800c43fa
@@ -61,17 +61,19 @@ hidapi==0.7.99.post21 \
idna==2.8 \
--hash=sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407 \
--hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c
-keepkey==4.0.2 \
- --hash=sha256:cddee60ae405841cdff789cbc54168ceaeb2282633420f2be155554c25c69138
+keepkey==6.0.2 \
+ --hash=sha256:3236dd701bde74768c41a92e724e322ea5e01b90985e2e6215eb85b77f9a0ae1 \
+ --hash=sha256:677e07deacc2ff97bee313b8dd7ae55faebab02e7d17b9a8e49b889996a36010 \
+ --hash=sha256:af107f610fb0e2417fc7a9d87a2fa22aac9b80b79559370d178be424bb85489a
libusb1==1.7 \
--hash=sha256:9d4f66d2ed699986b06bc3082cd262101cb26af7a76a34bd15b7eb56cba37e0f
mnemonic==0.18 \
--hash=sha256:02a7306a792370f4a0c106c2cf1ce5a0c84b9dbd7e71c6792fdb9ad88a727f1d
pbkdf2==1.3 \
--hash=sha256:ac6397369f128212c43064a2b4878038dab78dab41875364554aaf2a684e6979
-pip==18.1 \
- --hash=sha256:7909d0a0932e88ea53a7014dfd14522ffef91a464daaaf5c573343852ef98550 \
- --hash=sha256:c0a292bd977ef590379a3f05d7b7f65135487b67470f6281289a94e015650ea1
+pip==19.0.1 \
+ --hash=sha256:aae79c7afe895fb986ec751564f24d97df1331bb99cdfec6f70dada2f40c0044 \
+ --hash=sha256:e81ddd35e361b630e94abeda4a1eddd36d47a90e71eb00f38f46b57f787cd1a5
protobuf==3.6.1 \
--hash=sha256:10394a4d03af7060fa8a6e1cbf38cea44be1467053b0aea5bbfcb4b13c4b88c4 \
--hash=sha256:1489b376b0f364bcc6f89519718c057eb191d7ad6f1b395ffd93d1aa45587811 \
@@ -114,13 +116,13 @@ setuptools==40.6.3 \
six==1.12.0 \
--hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \
--hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73
-trezor==0.11.0 \
- --hash=sha256:1132f6a97afb0979c5018b067494bc8917b881c02d965f991270a70543b5050c \
- --hash=sha256:ce8f6ff2502b530d0cd3c5aa4b59330a56abbc6046a34f22c7eb0b2713b4f09d
-typing-extensions==3.6.6 \
- --hash=sha256:2a6c6e78e291a4b6cbd0bbfd30edc0baaa366de962129506ec8fe06bdec66457 \
- --hash=sha256:51e7b7f3dcabf9ad22eed61490f3b8d23d9922af400fe6656cb08e66656b701f \
- --hash=sha256:55401f6ed58ade5638eb566615c150ba13624e2f0c1eedd080fc3c1b6cb76f1d
+trezor==0.11.1 \
+ --hash=sha256:6043f321d856e1b45b9df0c37810264f08d065bb56cd999f61a05fe2906e9e18 \
+ --hash=sha256:6119b30cf9a136667753935bd06c5f341e78950b35e8ccbadaecc65c12f1946d
+typing-extensions==3.7.2 \
+ --hash=sha256:07b2c978670896022a43c4b915df8958bec4a6b84add7f2c87b2b728bda3ba64 \
+ --hash=sha256:f3f0e67e1d42de47b5c67c32c9b26641642e9170fe7e292991793705cd5fef7c \
+ --hash=sha256:fb2cd053238d33a8ec939190f30cfd736c00653a85a2919415cecf7dc3d9da71
urllib3==1.24.1 \
--hash=sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39 \
--hash=sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22
diff --git a/contrib/deterministic-build/requirements.txt b/contrib/deterministic-build/requirements.txt
index 9c5faa02..68cabfd6 100644
--- a/contrib/deterministic-build/requirements.txt
+++ b/contrib/deterministic-build/requirements.txt
@@ -1,31 +1,32 @@
-aiohttp==3.4.4 \
- --hash=sha256:0419705a36b43c0ac6f15469f9c2a08cad5c939d78bd12a5c23ea167c8253b2b \
- --hash=sha256:1812fc4bc6ac1bde007daa05d2d0f61199324e0cc893b11523e646595047ca08 \
- --hash=sha256:2214b5c0153f45256d5d52d1e0cafe53f9905ed035a142191727a5fb620c03dd \
- --hash=sha256:275909137f0c92c61ba6bb1af856a522d5546f1de8ea01e4e726321c697754ac \
- --hash=sha256:3983611922b561868428ea1e7269e757803713f55b53502423decc509fef1650 \
- --hash=sha256:51afec6ffa50a9da4cdef188971a802beb1ca8e8edb40fa429e5e529db3475fa \
- --hash=sha256:589f2ec8a101a0f340453ee6945bdfea8e1cd84c8d88e5be08716c34c0799d95 \
- --hash=sha256:789820ddc65e1f5e71516adaca2e9022498fa5a837c79ba9c692a9f8f916c330 \
- --hash=sha256:7a968a0bdaaf9abacc260911775611c9a602214a23aeb846f2eb2eeaa350c4dc \
- --hash=sha256:7aeefbed253f59ea39e70c5848de42ed85cb941165357fc7e87ab5d8f1f9592b \
- --hash=sha256:7b2eb55c66512405103485bd7d285a839d53e7fdc261ab20e5bcc51d7aaff5de \
- --hash=sha256:87bc95d3d333bb689c8d755b4a9d7095a2356108002149523dfc8e607d5d32a4 \
- --hash=sha256:9d80e40db208e29168d3723d1440ecbb06054d349c5ece6a2c5a611490830dd7 \
- --hash=sha256:a1b442195c2a77d33e4dbee67c9877ccbdd3a1f686f91eb479a9577ed8cc326b \
- --hash=sha256:ab3d769413b322d6092f169f316f7b21cd261a7589f7e31db779d5731b0480d8 \
- --hash=sha256:b066d3dec5d0f5aee6e34e5765095dc3d6d78ef9839640141a2b20816a0642bd \
- --hash=sha256:b24e7845ae8de3e388ef4bcfcf7f96b05f52c8e633b33cf8003a6b1d726fc7c2 \
- --hash=sha256:c59a953c3f8524a7c86eaeaef5bf702555be12f5668f6384149fe4bb75c52698 \
- --hash=sha256:cf2cc6c2c10d242790412bea7ccf73726a9a44b4c4b073d2699ef3b48971fd95 \
- --hash=sha256:e0c9c8d4150ae904f308ff27b35446990d2b1dfc944702a21925937e937394c6 \
- --hash=sha256:f1839db4c2b08a9c8f9788112644f8a8557e8e0ecc77b07091afabb941dc55d0 \
- --hash=sha256:f3df52362be39908f9c028a65490fae0475e4898b43a03d8aa29d1e765b45e07
-aiohttp-socks==0.2.1 \
- --hash=sha256:8bcfde1bb0d394b0ff0d8c284de7459c38507bff1f7c144ac734a6de49f36a29
-aiorpcX==0.10.1 \
- --hash=sha256:0c0a3342a43d939f00af84684fd08c0c5e7de4fa3eb21740063bea98f6070798 \
- --hash=sha256:58fe42b3695bc4e761b61b9a61416b0c6d69b220630be222b9b129b96ac9c331
+aiohttp==3.5.4 \
+ --hash=sha256:00d198585474299c9c3b4f1d5de1a576cc230d562abc5e4a0e81d71a20a6ca55 \
+ --hash=sha256:0155af66de8c21b8dba4992aaeeabf55503caefae00067a3b1139f86d0ec50ed \
+ --hash=sha256:09654a9eca62d1bd6d64aa44db2498f60a5c1e0ac4750953fdd79d5c88955e10 \
+ --hash=sha256:199f1d106e2b44b6dacdf6f9245493c7d716b01d0b7fbe1959318ba4dc64d1f5 \
+ --hash=sha256:296f30dedc9f4b9e7a301e5cc963012264112d78a1d3094cd83ef148fdf33ca1 \
+ --hash=sha256:368ed312550bd663ce84dc4b032a962fcb3c7cae099dbbd48663afc305e3b939 \
+ --hash=sha256:40d7ea570b88db017c51392349cf99b7aefaaddd19d2c78368aeb0bddde9d390 \
+ --hash=sha256:629102a193162e37102c50713e2e31dc9a2fe7ac5e481da83e5bb3c0cee700aa \
+ --hash=sha256:6d5ec9b8948c3d957e75ea14d41e9330e1ac3fed24ec53766c780f82805140dc \
+ --hash=sha256:87331d1d6810214085a50749160196391a712a13336cd02ce1c3ea3d05bcf8d5 \
+ --hash=sha256:9a02a04bbe581c8605ac423ba3a74999ec9d8bce7ae37977a3d38680f5780b6d \
+ --hash=sha256:9c4c83f4fa1938377da32bc2d59379025ceeee8e24b89f72fcbccd8ca22dc9bf \
+ --hash=sha256:9cddaff94c0135ee627213ac6ca6d05724bfe6e7a356e5e09ec57bd3249510f6 \
+ --hash=sha256:a25237abf327530d9561ef751eef9511ab56fd9431023ca6f4803f1994104d72 \
+ --hash=sha256:a5cbd7157b0e383738b8e29d6e556fde8726823dae0e348952a61742b21aeb12 \
+ --hash=sha256:a97a516e02b726e089cffcde2eea0d3258450389bbac48cbe89e0f0b6e7b0366 \
+ --hash=sha256:acc89b29b5f4e2332d65cd1b7d10c609a75b88ef8925d487a611ca788432dfa4 \
+ --hash=sha256:b05bd85cc99b06740aad3629c2585bda7b83bd86e080b44ba47faf905fdf1300 \
+ --hash=sha256:c2bec436a2b5dafe5eaeb297c03711074d46b6eb236d002c13c42f25c4a8ce9d \
+ --hash=sha256:cc619d974c8c11fe84527e4b5e1c07238799a8c29ea1c1285149170524ba9303 \
+ --hash=sha256:d4392defd4648badaa42b3e101080ae3313e8f4787cb517efd3f5b8157eaefd6 \
+ --hash=sha256:e1c3c582ee11af7f63a34a46f0448fca58e59889396ffdae1f482085061a2889
+aiohttp-socks==0.2.2 \
+ --hash=sha256:e473ee222b001fe33798957b9ce3352b32c187cf41684f8e2259427925914993 \
+ --hash=sha256:eebd8939a7c3c1e3e7e1b2552c60039b4c65ef6b8b2351efcbdd98290538e310
+aiorpcX==0.10.2 \
+ --hash=sha256:23a59e625ca50cdf2866a2d8bd54256e648582a8d44d4495b34252f3dbc30e23 \
+ --hash=sha256:d2bf57fc46ae37d769ab3f5e58ebee4b44acab626e597b5150a201284b9808dd
async_timeout==3.0.1 \
--hash=sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f \
--hash=sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3
@@ -49,9 +50,9 @@ idna==2.8 \
--hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c
idna_ssl==1.1.0 \
--hash=sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c
-jsonrpclib-pelix==0.3.2 \
- --hash=sha256:14d288d1b3d3273cf96a729dd21a2470851c4962be8509f3dd62f0137ff90339 \
- --hash=sha256:27fcd919d3dbf6179bcce587f73e1bad006922ae23c83c308e01227b8533178c
+jsonrpclib-pelix==0.4.0 \
+ --hash=sha256:19c558e169a51480b39548783067ca55046b62b2409ab4559931255e12f635de \
+ --hash=sha256:a966d17f2f739ee89031cf5c807d85d92db6b2715fb2b2f8a88bbfc87f468b12
multidict==4.5.2 \
--hash=sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f \
--hash=sha256:041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3 \
@@ -82,9 +83,9 @@ multidict==4.5.2 \
--hash=sha256:d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9 \
--hash=sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7 \
--hash=sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b
-pip==18.1 \
- --hash=sha256:7909d0a0932e88ea53a7014dfd14522ffef91a464daaaf5c573343852ef98550 \
- --hash=sha256:c0a292bd977ef590379a3f05d7b7f65135487b67470f6281289a94e015650ea1
+pip==19.0.1 \
+ --hash=sha256:aae79c7afe895fb986ec751564f24d97df1331bb99cdfec6f70dada2f40c0044 \
+ --hash=sha256:e81ddd35e361b630e94abeda4a1eddd36d47a90e71eb00f38f46b57f787cd1a5
protobuf==3.6.1 \
--hash=sha256:10394a4d03af7060fa8a6e1cbf38cea44be1467053b0aea5bbfcb4b13c4b88c4 \
--hash=sha256:1489b376b0f364bcc6f89519718c057eb191d7ad6f1b395ffd93d1aa45587811 \
@@ -108,15 +109,19 @@ pyaes==1.6.1 \
QDarkStyle==2.5.4 \
--hash=sha256:3eb60922b8c4d9cedecb6897ca4c9f8a259d81bdefe5791976ccdf12432de1f0 \
--hash=sha256:51331fc6490b38c376e6ba8d8c814320c8d2d1c2663055bc396321a7c28fa8be
-qrcode==6.0 \
- --hash=sha256:037b0db4c93f44586e37f84c3da3f763874fcac85b2974a69a98e399ac78e1bf \
- --hash=sha256:de4ffc15065e6ff20a551ad32b6b41264f3c75275675406ddfa8e3530d154be3
+qrcode==6.1 \
+ --hash=sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5 \
+ --hash=sha256:505253854f607f2abf4d16092c61d4e9d511a3b4392e60bff957a68592b04369
setuptools==40.6.3 \
--hash=sha256:3b474dad69c49f0d2d86696b68105f3a6f195f7ab655af12ef9a9c326d2b08f8 \
--hash=sha256:e2c1ce9a832f34cf7a31ed010aabcab5008eb65ce8f2aadc04622232c14bdd0b
six==1.12.0 \
--hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \
--hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73
+typing-extensions==3.7.2 \
+ --hash=sha256:07b2c978670896022a43c4b915df8958bec4a6b84add7f2c87b2b728bda3ba64 \
+ --hash=sha256:f3f0e67e1d42de47b5c67c32c9b26641642e9170fe7e292991793705cd5fef7c \
+ --hash=sha256:fb2cd053238d33a8ec939190f30cfd736c00653a85a2919415cecf7dc3d9da71
wheel==0.32.3 \
--hash=sha256:029703bf514e16c8271c3821806a1c171220cc5bdd325cbf4e7da1e056a01db6 \
--hash=sha256:1e53cdb3f808d5ccd0df57f964263752aa74ea7359526d3da6c02114ec1e1d44
diff --git a/electrum.desktop b/electrum.desktop
index 481f3b93..e4010671 100644
--- a/electrum.desktop
+++ b/electrum.desktop
@@ -10,7 +10,8 @@ Icon=electrum
Name[en_US]=Electrum Bitcoin Wallet
Name=Electrum Bitcoin Wallet
Categories=Finance;Network;
-StartupNotify=false
+StartupNotify=true
+StartupWMClass=electrum
Terminal=false
Type=Application
MimeType=x-scheme-handler/bitcoin;
diff --git a/electrum/bitcoin.py b/electrum/bitcoin.py
index ee1b6c0f..08cbde22 100644
--- a/electrum/bitcoin.py
+++ b/electrum/bitcoin.py
@@ -235,28 +235,28 @@ def b58_address_to_hash160(addr: str) -> Tuple[int, bytes]:
def hash160_to_p2pkh(h160: bytes, *, net=None) -> str:
- if net is None:
- net = constants.net
+ if net is None: net = constants.net
return hash160_to_b58_address(h160, net.ADDRTYPE_P2PKH)
def hash160_to_p2sh(h160: bytes, *, net=None) -> str:
- if net is None:
- net = constants.net
+ if net is None: net = constants.net
return hash160_to_b58_address(h160, net.ADDRTYPE_P2SH)
-def public_key_to_p2pkh(public_key: bytes) -> str:
- return hash160_to_p2pkh(hash_160(public_key))
+def public_key_to_p2pkh(public_key: bytes, *, net=None) -> str:
+ if net is None: net = constants.net
+ return hash160_to_p2pkh(hash_160(public_key), net=net)
def hash_to_segwit_addr(h: bytes, witver: int, *, net=None) -> str:
- if net is None:
- net = constants.net
+ if net is None: net = constants.net
return segwit_addr.encode(net.SEGWIT_HRP, witver, h)
-def public_key_to_p2wpkh(public_key: bytes) -> str:
- return hash_to_segwit_addr(hash_160(public_key), witver=0)
+def public_key_to_p2wpkh(public_key: bytes, *, net=None) -> str:
+ if net is None: net = constants.net
+ return hash_to_segwit_addr(hash_160(public_key), witver=0, net=net)
-def script_to_p2wsh(script: str) -> str:
- return hash_to_segwit_addr(sha256(bfh(script)), witver=0)
+def script_to_p2wsh(script: str, *, net=None) -> str:
+ if net is None: net = constants.net
+ return hash_to_segwit_addr(sha256(bfh(script)), witver=0, net=net)
def p2wpkh_nested_script(pubkey: str) -> str:
pkh = bh2u(hash_160(bfh(pubkey)))
@@ -266,25 +266,27 @@ def p2wsh_nested_script(witness_script: str) -> str:
wsh = bh2u(sha256(bfh(witness_script)))
return '00' + push_script(wsh)
-def pubkey_to_address(txin_type: str, pubkey: str) -> str:
+def pubkey_to_address(txin_type: str, pubkey: str, *, net=None) -> str:
+ if net is None: net = constants.net
if txin_type == 'p2pkh':
- return public_key_to_p2pkh(bfh(pubkey))
+ return public_key_to_p2pkh(bfh(pubkey), net=net)
elif txin_type == 'p2wpkh':
- return public_key_to_p2wpkh(bfh(pubkey))
+ return public_key_to_p2wpkh(bfh(pubkey), net=net)
elif txin_type == 'p2wpkh-p2sh':
scriptSig = p2wpkh_nested_script(pubkey)
- return hash160_to_p2sh(hash_160(bfh(scriptSig)))
+ return hash160_to_p2sh(hash_160(bfh(scriptSig)), net=net)
else:
raise NotImplementedError(txin_type)
-def redeem_script_to_address(txin_type: str, redeem_script: str) -> str:
+def redeem_script_to_address(txin_type: str, redeem_script: str, *, net=None) -> str:
+ if net is None: net = constants.net
if txin_type == 'p2sh':
- return hash160_to_p2sh(hash_160(bfh(redeem_script)))
+ return hash160_to_p2sh(hash_160(bfh(redeem_script)), net=net)
elif txin_type == 'p2wsh':
- return script_to_p2wsh(redeem_script)
+ return script_to_p2wsh(redeem_script, net=net)
elif txin_type == 'p2wsh-p2sh':
scriptSig = p2wsh_nested_script(redeem_script)
- return hash160_to_p2sh(hash_160(bfh(scriptSig)))
+ return hash160_to_p2sh(hash_160(bfh(scriptSig)), net=net)
else:
raise NotImplementedError(txin_type)
@@ -296,8 +298,7 @@ def script_to_address(script: str, *, net=None) -> str:
return addr
def address_to_script(addr: str, *, net=None) -> str:
- if net is None:
- net = constants.net
+ if net is None: net = constants.net
if not is_address(addr, net=net):
raise BitcoinException(f"invalid bitcoin address: {addr}")
witver, witprog = segwit_addr.decode(net.SEGWIT_HRP, addr)
diff --git a/electrum/commands.py b/electrum/commands.py
index 773a83ca..07ec6a5f 100644
--- a/electrum/commands.py
+++ b/electrum/commands.py
@@ -220,6 +220,11 @@ class Commands:
self.wallet.storage.write()
return {'password':self.wallet.has_password()}
+ @command('w')
+ def get(self, key):
+ """Return item from wallet storage"""
+ return self.wallet.storage.get(key)
+
@command('')
def getconfig(self, key):
"""Return a configuration variable. """
diff --git a/electrum/daemon.py b/electrum/daemon.py
index 0db918c4..b4b021dd 100644
--- a/electrum/daemon.py
+++ b/electrum/daemon.py
@@ -294,7 +294,10 @@ class Daemon(DaemonThread):
kwargs[x] = (config_options.get(x) if x in ['password', 'new_password'] else config.get(x))
cmd_runner = Commands(config, wallet, self.network)
func = getattr(cmd_runner, cmd.name)
- result = func(*args, **kwargs)
+ try:
+ result = func(*args, **kwargs)
+ except TypeError as e:
+ raise Exception("Wrapping TypeError to prevent JSONRPC-Pelix from hiding traceback") from e
return result
def run(self):
diff --git a/electrum/ecc.py b/electrum/ecc.py
index feb56ce7..cf682c57 100644
--- a/electrum/ecc.py
+++ b/electrum/ecc.py
@@ -37,6 +37,7 @@ from .util import bfh, bh2u, assert_bytes, print_error, to_bytes, InvalidPasswor
from .crypto import (sha256d, aes_encrypt_with_iv, aes_decrypt_with_iv, hmac_oneshot)
from .ecc_fast import do_monkey_patching_of_python_ecdsa_internals_with_libsecp256k1
from . import msqr
+from . import constants
do_monkey_patching_of_python_ecdsa_internals_with_libsecp256k1()
@@ -309,16 +310,17 @@ def msg_magic(message: bytes) -> bytes:
return b"\x18Bitcoin Signed Message:\n" + length + message
-def verify_message_with_address(address: str, sig65: bytes, message: bytes):
+def verify_message_with_address(address: str, sig65: bytes, message: bytes, *, net=None):
from .bitcoin import pubkey_to_address
assert_bytes(sig65, message)
+ if net is None: net = constants.net
try:
h = sha256d(msg_magic(message))
public_key, compressed = ECPubkey.from_signature65(sig65, h)
# check public key using the address
pubkey_hex = public_key.get_public_key_hex(compressed)
for txin_type in ['p2pkh','p2wpkh','p2wpkh-p2sh']:
- addr = pubkey_to_address(txin_type, pubkey_hex)
+ addr = pubkey_to_address(txin_type, pubkey_hex, net=net)
if address == addr:
break
else:
diff --git a/electrum/gui/kivy/Readme.md b/electrum/gui/kivy/Readme.md
index b11ee9f0..edf6b9e2 100644
--- a/electrum/gui/kivy/Readme.md
+++ b/electrum/gui/kivy/Readme.md
@@ -74,3 +74,11 @@ $ sudo docker run -it --rm \
### How do I get more verbose logs?
See `log_level` in `buildozer.spec`
+
+
+### Kivy can be run directly on Linux Desktop. How?
+Install Kivy.
+
+Build atlas: `(cd electrum/gui/kivy/; make theming)`
+
+Run electrum with the `-g` switch: `electrum -g kivy`
diff --git a/electrum/gui/kivy/tools/Dockerfile b/electrum/gui/kivy/tools/Dockerfile
index 4e8f2b3b..67661da0 100644
--- a/electrum/gui/kivy/tools/Dockerfile
+++ b/electrum/gui/kivy/tools/Dockerfile
@@ -11,7 +11,7 @@ RUN apt -y update -qq \
ENV ANDROID_NDK_HOME="${ANDROID_HOME}/android-ndk"
-ENV ANDROID_NDK_VERSION="14b"
+ENV ANDROID_NDK_VERSION="17c"
ENV ANDROID_NDK_HOME_V="${ANDROID_NDK_HOME}-r${ANDROID_NDK_VERSION}"
# get the latest version from https://developer.android.com/ndk/downloads/index.html
@@ -122,6 +122,10 @@ USER ${USER}
RUN pip install --upgrade cython==0.29
RUN python3 -m pip install --upgrade cython==0.29
+# prepare git
+RUN git config --global user.name "John Doe" \
+ && git config --global user.email johndoe@example.com
+
# install buildozer
RUN cd /opt \
&& git clone https://github.com/kivy/buildozer \
@@ -134,7 +138,9 @@ RUN cd /opt \
&& cd python-for-android \
&& git remote add sombernight https://github.com/SomberNight/python-for-android \
&& git fetch --all \
- && git checkout 86eeec7c19679a5886d5e095ce0a43f1da138f87 \
+ && git checkout fad5dd2fdc9b116b7621470deac501e4a7c4cc11 \
+ # allowBackup="false":
+ && git cherry-pick 86eeec7c19679a5886d5e095ce0a43f1da138f87 \
&& python3 -m pip install -e .
# build env vars
diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py
index a0d41c9f..1ba1bd00 100644
--- a/electrum/gui/qt/main_window.py
+++ b/electrum/gui/qt/main_window.py
@@ -226,6 +226,28 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
gui_object.timer.timeout.connect(self.timer_actions)
self.fetch_alias()
+ # If the option hasn't been set yet
+ if config.get('check_updates') is None:
+ choice = QMessageBox.question(self,
+ "Electrum - " + _("Enable update check"),
+ _("For security reasons we advise that you always use the latest version of Electrum.") + " " +
+ _("Would you like to be notified when there is a newer version of Electrum available?"),
+ QMessageBox.Yes,
+ QMessageBox.No)
+ config.set_key('check_updates', choice == QMessageBox.Yes, save=True)
+
+ if config.get('check_updates', False):
+ # The references to both the thread and the window need to be stored somewhere
+ # to prevent GC from getting in our way.
+ def on_version_received(v):
+ if UpdateCheck.is_newer(v):
+ self.update_check_button.setText(_("Update to Electrum {} is available").format(v))
+ self.update_check_button.clicked.connect(lambda: self.show_update_check(v))
+ self.update_check_button.show()
+ self._update_check_thread = UpdateCheckThread(self)
+ self._update_check_thread.checked.connect(on_version_received)
+ self._update_check_thread.start()
+
def on_history(self, b):
self.wallet.clear_coin_price_cache()
self.new_fx_history_signal.emit()
@@ -577,6 +599,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
help_menu = menubar.addMenu(_("&Help"))
help_menu.addAction(_("&About"), self.show_about)
+ help_menu.addAction(_("&Check for updates"), self.show_update_check)
help_menu.addAction(_("&Official website"), lambda: webbrowser.open("https://electrum.org"))
help_menu.addSeparator()
help_menu.addAction(_("&Documentation"), lambda: webbrowser.open("http://docs.electrum.org/")).setShortcut(QKeySequence.HelpContents)
@@ -604,6 +627,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
"servers that handle the most complicated parts of the FLO system.") + "\n\n" +
_("Uses icons from the Icons8 icon pack (icons8.com).")))
+ def show_update_check(self, version=None):
+ self.gui_object._update_check = UpdateCheck(self, version)
+
def show_report_bug(self):
msg = ' '.join([
_("Please report any bugs as issues on github:
"),
@@ -2005,7 +2031,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
sb = QStatusBar()
sb.setFixedHeight(35)
- qtVersion = qVersion()
self.balance_label = QLabel("Loading wallet...")
self.balance_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
@@ -2017,6 +2042,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
self.search_box.hide()
sb.addPermanentWidget(self.search_box)
+ self.update_check_button = QPushButton("")
+ self.update_check_button.setFlat(True)
+ self.update_check_button.setCursor(QCursor(Qt.PointingHandCursor))
+ self.update_check_button.setIcon(QIcon(":icons/update.png"))
+ self.update_check_button.hide()
+ sb.addPermanentWidget(self.update_check_button)
+
self.lock_icon = QIcon()
self.password_button = StatusBarButton(self.lock_icon, _("Password"), self.change_password_dialog )
sb.addPermanentWidget(self.password_button)
@@ -2912,6 +2944,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
colortheme_combo.currentIndexChanged.connect(on_colortheme)
gui_widgets.append((colortheme_label, colortheme_combo))
+ updatecheck_cb = QCheckBox(_("Automatically check for software updates"))
+ updatecheck_cb.setChecked(self.config.get('check_updates', False))
+ def on_set_updatecheck(v):
+ self.config.set_key('check_updates', v == Qt.Checked, save=True)
+ updatecheck_cb.stateChanged.connect(on_set_updatecheck)
+ gui_widgets.append((updatecheck_cb, None))
+
usechange_cb = QCheckBox(_('Use change addresses'))
usechange_cb.setChecked(self.wallet.use_change)
if not self.config.is_modifiable('use_change'): usechange_cb.setEnabled(False)
@@ -3085,7 +3124,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
tabs_info = [
(fee_widgets, _('Fees')),
(tx_widgets, _('Transactions')),
- (gui_widgets, _('Appearance')),
+ (gui_widgets, _('General')),
(fiat_widgets, _('Fiat')),
(id_widgets, _('Identity')),
]
diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py
index a8358ba5..aee7bc1b 100644
--- a/electrum/gui/qt/util.py
+++ b/electrum/gui/qt/util.py
@@ -1,17 +1,24 @@
+import asyncio
import os.path
import time
import sys
import platform
import queue
+import traceback
+from distutils.version import StrictVersion
from functools import partial
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
+from electrum.util import FileImportFailed, FileExportFailed, make_aiohttp_session, PrintError
from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED
if TYPE_CHECKING:
@@ -819,6 +826,124 @@ class FromList(QTreeWidget):
self.header().setSectionResizeMode(0, sm)
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('