Merge remote-tracking branch 'upstream/master' into upstreamMerge

This commit is contained in:
Vivek Teega 2019-01-31 00:41:06 +05:30
commit 0cd2f6e170
28 changed files with 402 additions and 168 deletions

2
.gitignore vendored
View File

@ -6,7 +6,7 @@ dist/
*.egg/ *.egg/
contrib/pyinstaller/ contrib/pyinstaller/
Electrum.egg-info/ Electrum.egg-info/
locale/ electrum/locale/
.devlocaltmp/ .devlocaltmp/
*_trial_temp *_trial_temp
packages packages

View File

@ -1,6 +1,5 @@
include LICENCE RELEASE-NOTES AUTHORS include LICENCE RELEASE-NOTES AUTHORS
include README.rst include README.rst
include electrum.conf.sample
include electrum.desktop include electrum.desktop
include *.py include *.py
include run_electrum include run_electrum
@ -15,4 +14,6 @@ graft electrum
prune electrum/tests prune electrum/tests
global-exclude __pycache__ global-exclude __pycache__
global-exclude *.py[co] global-exclude *.py[co~]
global-exclude *.py.orig
global-exclude *.py.rej

View File

@ -91,25 +91,25 @@ Create translations (optional)::
Creating Binaries 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 Mac OS X / macOS
-------- ----------------
See :code:`contrib/osx/README.md`.
See `contrib/osx/`.
Windows Windows
------- -------
See `contrib/build-wine/`. See :code:`contrib/build-wine/docker/README.md`.
Android Android
------- -------
See `electrum/gui/kivy/Readme.md` file. See :code:`electrum/gui/kivy/Readme.md`.

View File

@ -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) # Release 3.3.2 - (December 21, 2018)
* Fix Qt history export bug * Fix Qt history export bug

View File

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

View File

@ -116,7 +116,7 @@ $PYTHON -m pip install pip --upgrade
$PYTHON -m pip install -r $here/../deterministic-build/requirements-binaries.txt $PYTHON -m pip install -r $here/../deterministic-build/requirements-binaries.txt
# Install PyInstaller # Install PyInstaller
$PYTHON -m pip install pyinstaller==3.4 $PYTHON -m pip install pyinstaller==3.4 --no-use-pep517
# Install ZBar # Install ZBar
download_if_not_exist $ZBAR_FILENAME "$ZBAR_URL" download_if_not_exist $ZBAR_FILENAME "$ZBAR_URL"

@ -1 +1 @@
Subproject commit d586021ba0d4820d6587cff000756b3d035d4f08 Subproject commit 201d45cd5d855c4f9de5680ab5c53621574dc6b6

@ -1 +1 @@
Subproject commit caba5f30b134ec08d3e29150b33c87200597181a Subproject commit e5b28e4717d8c8a736d6d4e5398fa4fa67db80d0

View File

@ -1,34 +1,35 @@
pip==18.1 \ pip==19.0.1 \
--hash=sha256:7909d0a0932e88ea53a7014dfd14522ffef91a464daaaf5c573343852ef98550 \ --hash=sha256:aae79c7afe895fb986ec751564f24d97df1331bb99cdfec6f70dada2f40c0044 \
--hash=sha256:c0a292bd977ef590379a3f05d7b7f65135487b67470f6281289a94e015650ea1 --hash=sha256:e81ddd35e361b630e94abeda4a1eddd36d47a90e71eb00f38f46b57f787cd1a5
pycryptodomex==3.7.2 \ pycryptodomex==3.7.3 \
--hash=sha256:09f433a6ca4b96a4c89096af9eaa20c5d5e9029a03266f6a80062163d2042030 \ --hash=sha256:0bda549e20db1eb8e29fb365d10acf84b224d813b1131c828fc830b2ce313dcd \
--hash=sha256:0bb7686dd46d40cace053941638d2db4f9d86a50a62d6100f14157162e56e82f \ --hash=sha256:1210c0818e5334237b16d99b5785aa0cee815d9997ee258bd5e2936af8e8aa50 \
--hash=sha256:13ef8e8a26a9ac7ae84616e9c500ca0cf721d3725d740124f68dda1b58e7d408 \ --hash=sha256:2090dc8cd7843eae75bd504b9be86792baa171fc5a758ea3f60188ab67ca95cf \
--hash=sha256:195b6540f31cbe3dc7bf3877177bb4fe1a145ce02191efdd0cb6399bff275d4b \ --hash=sha256:22e6784b65dfdd357bf9a8a842db445192b227103e2c3137a28c489c46742135 \
--hash=sha256:329ca5986c5e5f6a60edc3ff8b70c28d6cb259491e35e44870db6a8d92430e50 \ --hash=sha256:2edb8c3965a77e3092b5c5c1233ffd32de083f335202013f52d662404191ac79 \
--hash=sha256:42b2eccccb9da547e0ff140784037ea31c1a37012488706b51cbcadb885d2053 \ --hash=sha256:310fe269ac870135ff610d272e88dcb594ee58f40ac237a688d7c972cbca43e8 \
--hash=sha256:4b2817bd02dd7dd36f223917f9bcc90d658bb66124bc596d7e3a0c250509acf7 \ --hash=sha256:456136b7d459f000794a67b23558351c72e21f0c2d4fcaa09fc99dae7844b0ef \
--hash=sha256:5b765870e17bf82a992f2ebb312207da76dbf8694ce865fee847005cce9244e4 \ --hash=sha256:463e49a9c5f1fa7bd36aff8debae0b5c487868c1fb66704529f2ad7e92f0cc9f \
--hash=sha256:5d4e10ad9ff7940da534119ef92a500dcf7c28351d15e12d74ef0ce025e37d5b \ --hash=sha256:4a33b2828799ef8be789a462e6645ea6fe2c42b0df03e6763ccbfd1789c453e6 \
--hash=sha256:75186284b593df724451869035bfab4a03b6b388ed6eea284ad7fe84c9b64ea0 \ --hash=sha256:5ff02dff1b03929e6339226b318aa59bd0b5c362f96e3e0eb7f3401d30594ed3 \
--hash=sha256:77928b02c28adb4d1d637c609aba380d890fb40ad63c58c826bef871c84cf488 \ --hash=sha256:6b1db8234b8ee2b30435d9e991389c2eeae4d45e09e471ffe757ba1dfae682bb \
--hash=sha256:7cd21c1a4dd0879dc3b289afeb0033a9382da7d0a50cb9de8d0e59c1ab0977a7 \ --hash=sha256:6eb67ee02de143cd19e36a52bd3869a9dc53e9184cd6bed5c39ff71dee2f6a45 \
--hash=sha256:83b7fe71fb9d27ff12df9dd3f57ea84153a86f45a674ee2b4763aaaf8ca84988 \ --hash=sha256:6f42eea5afc7eee29494fdfddc6bb7173953d4197d9200e4f67096c2a24bc21b \
--hash=sha256:8a67f26365ddad6ae53c0b3800edce16d164e675ee773de31c110624e63736d8 \ --hash=sha256:87bc8082e2de2247df7d0b161234f8edb1384294362cc0c8db9324463097578b \
--hash=sha256:8e08238f8d146caabf9d80cca09dd31323a333f74f62323aabd075e7effbc45c \ --hash=sha256:8df93d34bc0e3a28a27652070164683a07d8a50c628119d6e0f7710f4d01b42f \
--hash=sha256:938af93204c93d1f576acdef970e95dfd0bbe40133f4bbf73c4b12b67f7bd4ed \ --hash=sha256:989952c39e8fef1c959f0a0f85656e29c41c01162e33a3f5fd8ce71e47262ae9 \
--hash=sha256:b2f33943f91c764f2b27a1504cd3ec2c075deb7d1b8fcc3ab4d575bede7037a8 \ --hash=sha256:a4a203077e2f312ec8677dde80a5c4e6fe5a82a46173a8edc8da668602a3e073 \
--hash=sha256:b7efd0ac8b38dfdf8b2d387e84b007c843a66de9da437a950a86caa2d1437e1e \ --hash=sha256:a793c1242dffd39f585ae356344e8935d30f01f6be7d4c62ffc87af376a2f5f9 \
--hash=sha256:b95b14e5baaa4ca77ecb7a3d0f85fd13a8e31ada83c5a2bae5652d446414d63d \ --hash=sha256:b70fe991564e178af02ccf89435a8f9e8d052707a7c4b95bf6027cb785da3175 \
--hash=sha256:bad0c66c42d16e81eef2199b3c4fb78c873f54c7f9d156e69664e2138155747c \ --hash=sha256:b83594196e3661cb78c97b80a62fbfbba2add459dfd532b58e7a7c62dd06aab4 \
--hash=sha256:c384a85bede5396eed50f6c0374d8c51490fc10fdc65dffc8e613b57e5ab0ee0 \ --hash=sha256:ba27725237d0a3ea66ec2b6b387259471840908836711a3b215160808dffed0f \
--hash=sha256:c58a324a8eb48f767abe8c906295d76e04330aa0a03d99dd58d9a42938ee0596 \ --hash=sha256:d1ab8ad1113cdc553ca50c4d5f0142198c317497364c0c70443d69f7ad1c9288 \
--hash=sha256:d498731d66f9b9ad978c9a8018b0c6cfc4081e202a79c6e283ade7dcf2a72c18 \ --hash=sha256:dce039a8a8a318d7af83cae3fd08d58cefd2120075dfac0ae14d706974040f63 \
--hash=sha256:d516746fc25daff1c5e84d3f816d134d75a10e3551ffac92aa957a75b6b0208f \ --hash=sha256:e3213037ea33c85ab705579268cbc8a4433357e9fb99ec7ce9fdcc4d4eec1d50 \
--hash=sha256:ec51ea9f11b11df2719a01ea1cacdcf80858542a93f530a25a3bc742d0fe2f4b \ --hash=sha256:ec8d8023d31ef72026d46e9fb301ff8759eff5336bcf3d1510836375f53f96a9 \
--hash=sha256:ef2792281138a29e54bdd7302fdab72be140192485dc622bb9e7e9a6f9cee4f9 \ --hash=sha256:ece65730d50aa57a1330d86d81582a2d1587b2ca51cb34f586da8551ddc68fee \
--hash=sha256:f79650ec8812b01f20aca503763b93b0b1b347423ecf9fd3a9ebb611bee84079 --hash=sha256:ed21fc515e224727793e4cc3fb3d00f33f59e3a167d3ad6ac1475ab3b05c2f9e \
--hash=sha256:eec1132d878153d61a05424f35f089f951bd6095a4f6c60bdd2ef8919d44425e
PyQt5==5.11.3 \ PyQt5==5.11.3 \
--hash=sha256:517e4339135c4874b799af0d484bc2e8c27b54850113a68eec40a0b56534f450 \ --hash=sha256:517e4339135c4874b799af0d484bc2e8c27b54850113a68eec40a0b56534f450 \
--hash=sha256:ac1eb5a114b6e7788e8be378be41c5e54b17d5158994504e85e43b5fca006a39 \ --hash=sha256:ac1eb5a114b6e7788e8be378be41c5e54b17d5158994504e85e43b5fca006a39 \

View File

@ -14,35 +14,35 @@ click==7.0 \
--hash=sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7 --hash=sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7
construct==2.9.45 \ construct==2.9.45 \
--hash=sha256:2271a0efd0798679dea825ff47e22a4c550456a5db0ba8baa82f7eae0af0118c --hash=sha256:2271a0efd0798679dea825ff47e22a4c550456a5db0ba8baa82f7eae0af0118c
Cython==0.29.2 \ Cython==0.29.3 \
--hash=sha256:004c181b75f926f48dc0570372ca2cfb06a1b3210cb647185977ce9fde98b66e \ --hash=sha256:1327655db47beb665961d3dc0365e20c9e8e80c234513ab2c7d06ec0dd9d63eb \
--hash=sha256:085d596c016130f5b1e2fe72446e3e63bfcf67535e7ff6772eaa05c5d2ad6fd5 \ --hash=sha256:142400f13102403f43576bb92d808a668e29deda5625388cfa39fe0bcf37b3d1 \
--hash=sha256:1014758344717844a05882c92ebd76d8fab15b0a8e9b42b378a99a6c5299ab3b \ --hash=sha256:1b4204715141281a631337378f0c15fe660b35e1b6888ca05f1f3f49df3b97d5 \
--hash=sha256:12c007d3704ca9840734748fd6c052960be67562ff15609c3b85d1ca638289d2 \ --hash=sha256:23aabaaf8887e6db99df2145de6742f8c92830134735778bf2ae26338f2b406f \
--hash=sha256:1a20f575197e814453f2814829715fcb21436075e298d883a34c7ffe4d567a1d \ --hash=sha256:2a724c6f21fdf4e3c1e8c5c862ff87f5420fdaecf53a5a0417915e483d90217f \
--hash=sha256:1b6f201228368ec9b307261b46512f3605f84d4994bb6eb78cdab71455810424 \ --hash=sha256:2c9c8c1c6e8bd3587e5f5db6f865a42195ff2dedcaf5cdb63fdea10c98bd6246 \
--hash=sha256:2ac187ff998a95abb7fae452b5178f91e1a713698c9ced89836c94e6b1d3f41e \ --hash=sha256:3a1be38b774423605189d60652b3d8a324fc81d213f96569720c8093784245ab \
--hash=sha256:3585fbe18d8666d91ecb3b3366ca6e9ea49001cd0a7c38a226cececb7852aa0d \ --hash=sha256:46be5297a76513e4d5d6e746737d4866a762cfe457e57d7c54baa7ef8fea7e9a \
--hash=sha256:3669dfe4117ee8825a48cf527cb4ac15a39a0142fcb72ecedfd75fe6545b2cda \ --hash=sha256:48dc2ea4c4d3f34ddcad5bc71b1f1cf49830f868832d3e5df803c811e7395b6e \
--hash=sha256:382c1e0f8f8be36e9057264677fd60b669a41c5810113694cbbb4060ee0cefc0 \ --hash=sha256:53f33e04d2ed078ac02841741bcd536b546e1f416608084468ab30a87638a466 \
--hash=sha256:44bb606d8c60d8acaa7f72b3bbc2ebd9816785124c58d33c057ca326f1185dae \ --hash=sha256:57b10588618ca19a4cc870f381aa8805bc5fe0c62d19d7f940232ff8a373887c \
--hash=sha256:6f1a5344ff1f0f44023c41d4b0e52215b490658b42e017520cb89a56250ecbca \ --hash=sha256:6001038341b52301450bb9c62e5d5da825788944572679277e137ffb3596e718 \
--hash=sha256:7a29f9d780ac497dcd76ce814a9d170575bedddeb89ecc25fe738abef4c87172 \ --hash=sha256:70bef52e735607060f327d729be35c820d9018d260a875e4f98b20ba8c4fff96 \
--hash=sha256:8022a5b83ef442584f2efd941fe8678de1c67e28bf81e6671b20627ec8a79387 \ --hash=sha256:7d0f76b251699be8f1f1064dcb12d4b3b2b676ce15ff30c104e0c2091a015142 \
--hash=sha256:998af90092cd1231990eb878e2c71ed92716d6a758aa03a2e6673e077a7dd072 \ --hash=sha256:9440b64c1569c26a184b7c778bb221cf9987c5c8486d32cda02302c66ea78980 \
--hash=sha256:9e60b83afe8914ab6607f7150fd282d1cb0531a45cf98d2a40159f976ae4cd7a \ --hash=sha256:956cc97eac6f9d3b16e3b2d2a94c5586af3403ba97945e9d88a4a0f029899646 \
--hash=sha256:a6581d3dda15adea19ac70b89211aadbf21f45c7f3ee3bc8e1536e5437c9faf9 \ --hash=sha256:ae430ad8cce937e07ea566d1d7899eef1fedc8ec512b4d5fa37ebf2c1f879936 \
--hash=sha256:af515924b8aebb729f631590eb43300ce948fa67d3885fdae9238717c0a68821 \ --hash=sha256:bdb575149881978d62167dd8427402a5872a79bd83e9d51219680670e9f80b40 \
--hash=sha256:b49ea3bb357bc34eaa7b461633ce7c2d79186fe681297115ff9e2b8f5ceba2fd \ --hash=sha256:c0ffcddd3dbdf22aae3980931112cc8b2732315a6273988f3205cf5dacf36f45 \
--hash=sha256:bc524cc603f0aa23af00111ddd1aa0aad12d629f5a9a5207f425a1af66393094 \ --hash=sha256:c133e2efc57426974366ac74f2ef0f1171b860301ac27f72316deacff4ccdc17 \
--hash=sha256:ca7daccffb14896767b20d69bfc8de9e41e9589b9377110292c3af8460ef9c2b \ --hash=sha256:c6e9521d0b77eb1da89e8264eb98c8f5cda7c49a49b8128acfd35f0ca50e56d0 \
--hash=sha256:cdfb68eb11c6c4e90e34cf54ffd678a7813782fae980d648db6185e6b0c8a0ba \ --hash=sha256:c7cac0220ecb733024e8acfcfb6b593a007185690f2ea470d2392b72510b7187 \
--hash=sha256:d21fb6e7a3831f1f8346275839d46ed1eb2abd350fc81bad2fdf208cc9e4f998 \ --hash=sha256:d53483820ac28f2be2ff13eedd56c0f36a4c583727b551d3d468023556e2336a \
--hash=sha256:e17104c6871e7c0eee4de12717892a1083bd3b8b1da0ec103fa464b1c6c80964 \ --hash=sha256:d60210784186d61e0ec808d5dbee5d661c7457a57f93cb5fdc456394607ce98c \
--hash=sha256:e7f71b489959d478cff72d8dcab1531efd43299341e3f8b85ab980beec452ded \ --hash=sha256:d687fb1cd9df28c1515666174c62e54bd894a6a6d0862f89705063cd47739f83 \
--hash=sha256:e8420326e4b40bcbb06f070efb218ca2ca21827891b7c69d4cc4802b3ce1afc9 \ --hash=sha256:d926764d9c768a48b0a16a91696aaa25498057e060934f968fa4c5629b942d85 \
--hash=sha256:eec1b890cf5c16cb656a7062769ac276c0fccf898ce215ff8ef75eac740063f7 \ --hash=sha256:d94a2f4ad74732f58d1c771fc5d90a62c4fe4c98d0adfecbc76cd0d8d14bf044 \
--hash=sha256:f04e21ba7c117b20f57b0af2d4c8ed760495e5bb3f21b0352dbcfe5d2221678b --hash=sha256:def76a546eeec059666f5f4117dfdf9c78e50fa1f95bdd23b04618c7adf845cd
ecdsa==0.13 \ ecdsa==0.13 \
--hash=sha256:40d002cf360d0e035cf2cb985e1308d41aaa087cbfc135b2dc2d844296ea546c \ --hash=sha256:40d002cf360d0e035cf2cb985e1308d41aaa087cbfc135b2dc2d844296ea546c \
--hash=sha256:64cf1ee26d1cde3c73c6d7d107f835fed7c6a2904aef9eac223d57ad800c43fa --hash=sha256:64cf1ee26d1cde3c73c6d7d107f835fed7c6a2904aef9eac223d57ad800c43fa
@ -61,17 +61,19 @@ hidapi==0.7.99.post21 \
idna==2.8 \ idna==2.8 \
--hash=sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407 \ --hash=sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407 \
--hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c --hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c
keepkey==4.0.2 \ keepkey==6.0.2 \
--hash=sha256:cddee60ae405841cdff789cbc54168ceaeb2282633420f2be155554c25c69138 --hash=sha256:3236dd701bde74768c41a92e724e322ea5e01b90985e2e6215eb85b77f9a0ae1 \
--hash=sha256:677e07deacc2ff97bee313b8dd7ae55faebab02e7d17b9a8e49b889996a36010 \
--hash=sha256:af107f610fb0e2417fc7a9d87a2fa22aac9b80b79559370d178be424bb85489a
libusb1==1.7 \ libusb1==1.7 \
--hash=sha256:9d4f66d2ed699986b06bc3082cd262101cb26af7a76a34bd15b7eb56cba37e0f --hash=sha256:9d4f66d2ed699986b06bc3082cd262101cb26af7a76a34bd15b7eb56cba37e0f
mnemonic==0.18 \ mnemonic==0.18 \
--hash=sha256:02a7306a792370f4a0c106c2cf1ce5a0c84b9dbd7e71c6792fdb9ad88a727f1d --hash=sha256:02a7306a792370f4a0c106c2cf1ce5a0c84b9dbd7e71c6792fdb9ad88a727f1d
pbkdf2==1.3 \ pbkdf2==1.3 \
--hash=sha256:ac6397369f128212c43064a2b4878038dab78dab41875364554aaf2a684e6979 --hash=sha256:ac6397369f128212c43064a2b4878038dab78dab41875364554aaf2a684e6979
pip==18.1 \ pip==19.0.1 \
--hash=sha256:7909d0a0932e88ea53a7014dfd14522ffef91a464daaaf5c573343852ef98550 \ --hash=sha256:aae79c7afe895fb986ec751564f24d97df1331bb99cdfec6f70dada2f40c0044 \
--hash=sha256:c0a292bd977ef590379a3f05d7b7f65135487b67470f6281289a94e015650ea1 --hash=sha256:e81ddd35e361b630e94abeda4a1eddd36d47a90e71eb00f38f46b57f787cd1a5
protobuf==3.6.1 \ protobuf==3.6.1 \
--hash=sha256:10394a4d03af7060fa8a6e1cbf38cea44be1467053b0aea5bbfcb4b13c4b88c4 \ --hash=sha256:10394a4d03af7060fa8a6e1cbf38cea44be1467053b0aea5bbfcb4b13c4b88c4 \
--hash=sha256:1489b376b0f364bcc6f89519718c057eb191d7ad6f1b395ffd93d1aa45587811 \ --hash=sha256:1489b376b0f364bcc6f89519718c057eb191d7ad6f1b395ffd93d1aa45587811 \
@ -114,13 +116,13 @@ setuptools==40.6.3 \
six==1.12.0 \ six==1.12.0 \
--hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \ --hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \
--hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73 --hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73
trezor==0.11.0 \ trezor==0.11.1 \
--hash=sha256:1132f6a97afb0979c5018b067494bc8917b881c02d965f991270a70543b5050c \ --hash=sha256:6043f321d856e1b45b9df0c37810264f08d065bb56cd999f61a05fe2906e9e18 \
--hash=sha256:ce8f6ff2502b530d0cd3c5aa4b59330a56abbc6046a34f22c7eb0b2713b4f09d --hash=sha256:6119b30cf9a136667753935bd06c5f341e78950b35e8ccbadaecc65c12f1946d
typing-extensions==3.6.6 \ typing-extensions==3.7.2 \
--hash=sha256:2a6c6e78e291a4b6cbd0bbfd30edc0baaa366de962129506ec8fe06bdec66457 \ --hash=sha256:07b2c978670896022a43c4b915df8958bec4a6b84add7f2c87b2b728bda3ba64 \
--hash=sha256:51e7b7f3dcabf9ad22eed61490f3b8d23d9922af400fe6656cb08e66656b701f \ --hash=sha256:f3f0e67e1d42de47b5c67c32c9b26641642e9170fe7e292991793705cd5fef7c \
--hash=sha256:55401f6ed58ade5638eb566615c150ba13624e2f0c1eedd080fc3c1b6cb76f1d --hash=sha256:fb2cd053238d33a8ec939190f30cfd736c00653a85a2919415cecf7dc3d9da71
urllib3==1.24.1 \ urllib3==1.24.1 \
--hash=sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39 \ --hash=sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39 \
--hash=sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22 --hash=sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22

View File

@ -1,31 +1,32 @@
aiohttp==3.4.4 \ aiohttp==3.5.4 \
--hash=sha256:0419705a36b43c0ac6f15469f9c2a08cad5c939d78bd12a5c23ea167c8253b2b \ --hash=sha256:00d198585474299c9c3b4f1d5de1a576cc230d562abc5e4a0e81d71a20a6ca55 \
--hash=sha256:1812fc4bc6ac1bde007daa05d2d0f61199324e0cc893b11523e646595047ca08 \ --hash=sha256:0155af66de8c21b8dba4992aaeeabf55503caefae00067a3b1139f86d0ec50ed \
--hash=sha256:2214b5c0153f45256d5d52d1e0cafe53f9905ed035a142191727a5fb620c03dd \ --hash=sha256:09654a9eca62d1bd6d64aa44db2498f60a5c1e0ac4750953fdd79d5c88955e10 \
--hash=sha256:275909137f0c92c61ba6bb1af856a522d5546f1de8ea01e4e726321c697754ac \ --hash=sha256:199f1d106e2b44b6dacdf6f9245493c7d716b01d0b7fbe1959318ba4dc64d1f5 \
--hash=sha256:3983611922b561868428ea1e7269e757803713f55b53502423decc509fef1650 \ --hash=sha256:296f30dedc9f4b9e7a301e5cc963012264112d78a1d3094cd83ef148fdf33ca1 \
--hash=sha256:51afec6ffa50a9da4cdef188971a802beb1ca8e8edb40fa429e5e529db3475fa \ --hash=sha256:368ed312550bd663ce84dc4b032a962fcb3c7cae099dbbd48663afc305e3b939 \
--hash=sha256:589f2ec8a101a0f340453ee6945bdfea8e1cd84c8d88e5be08716c34c0799d95 \ --hash=sha256:40d7ea570b88db017c51392349cf99b7aefaaddd19d2c78368aeb0bddde9d390 \
--hash=sha256:789820ddc65e1f5e71516adaca2e9022498fa5a837c79ba9c692a9f8f916c330 \ --hash=sha256:629102a193162e37102c50713e2e31dc9a2fe7ac5e481da83e5bb3c0cee700aa \
--hash=sha256:7a968a0bdaaf9abacc260911775611c9a602214a23aeb846f2eb2eeaa350c4dc \ --hash=sha256:6d5ec9b8948c3d957e75ea14d41e9330e1ac3fed24ec53766c780f82805140dc \
--hash=sha256:7aeefbed253f59ea39e70c5848de42ed85cb941165357fc7e87ab5d8f1f9592b \ --hash=sha256:87331d1d6810214085a50749160196391a712a13336cd02ce1c3ea3d05bcf8d5 \
--hash=sha256:7b2eb55c66512405103485bd7d285a839d53e7fdc261ab20e5bcc51d7aaff5de \ --hash=sha256:9a02a04bbe581c8605ac423ba3a74999ec9d8bce7ae37977a3d38680f5780b6d \
--hash=sha256:87bc95d3d333bb689c8d755b4a9d7095a2356108002149523dfc8e607d5d32a4 \ --hash=sha256:9c4c83f4fa1938377da32bc2d59379025ceeee8e24b89f72fcbccd8ca22dc9bf \
--hash=sha256:9d80e40db208e29168d3723d1440ecbb06054d349c5ece6a2c5a611490830dd7 \ --hash=sha256:9cddaff94c0135ee627213ac6ca6d05724bfe6e7a356e5e09ec57bd3249510f6 \
--hash=sha256:a1b442195c2a77d33e4dbee67c9877ccbdd3a1f686f91eb479a9577ed8cc326b \ --hash=sha256:a25237abf327530d9561ef751eef9511ab56fd9431023ca6f4803f1994104d72 \
--hash=sha256:ab3d769413b322d6092f169f316f7b21cd261a7589f7e31db779d5731b0480d8 \ --hash=sha256:a5cbd7157b0e383738b8e29d6e556fde8726823dae0e348952a61742b21aeb12 \
--hash=sha256:b066d3dec5d0f5aee6e34e5765095dc3d6d78ef9839640141a2b20816a0642bd \ --hash=sha256:a97a516e02b726e089cffcde2eea0d3258450389bbac48cbe89e0f0b6e7b0366 \
--hash=sha256:b24e7845ae8de3e388ef4bcfcf7f96b05f52c8e633b33cf8003a6b1d726fc7c2 \ --hash=sha256:acc89b29b5f4e2332d65cd1b7d10c609a75b88ef8925d487a611ca788432dfa4 \
--hash=sha256:c59a953c3f8524a7c86eaeaef5bf702555be12f5668f6384149fe4bb75c52698 \ --hash=sha256:b05bd85cc99b06740aad3629c2585bda7b83bd86e080b44ba47faf905fdf1300 \
--hash=sha256:cf2cc6c2c10d242790412bea7ccf73726a9a44b4c4b073d2699ef3b48971fd95 \ --hash=sha256:c2bec436a2b5dafe5eaeb297c03711074d46b6eb236d002c13c42f25c4a8ce9d \
--hash=sha256:e0c9c8d4150ae904f308ff27b35446990d2b1dfc944702a21925937e937394c6 \ --hash=sha256:cc619d974c8c11fe84527e4b5e1c07238799a8c29ea1c1285149170524ba9303 \
--hash=sha256:f1839db4c2b08a9c8f9788112644f8a8557e8e0ecc77b07091afabb941dc55d0 \ --hash=sha256:d4392defd4648badaa42b3e101080ae3313e8f4787cb517efd3f5b8157eaefd6 \
--hash=sha256:f3df52362be39908f9c028a65490fae0475e4898b43a03d8aa29d1e765b45e07 --hash=sha256:e1c3c582ee11af7f63a34a46f0448fca58e59889396ffdae1f482085061a2889
aiohttp-socks==0.2.1 \ aiohttp-socks==0.2.2 \
--hash=sha256:8bcfde1bb0d394b0ff0d8c284de7459c38507bff1f7c144ac734a6de49f36a29 --hash=sha256:e473ee222b001fe33798957b9ce3352b32c187cf41684f8e2259427925914993 \
aiorpcX==0.10.1 \ --hash=sha256:eebd8939a7c3c1e3e7e1b2552c60039b4c65ef6b8b2351efcbdd98290538e310
--hash=sha256:0c0a3342a43d939f00af84684fd08c0c5e7de4fa3eb21740063bea98f6070798 \ aiorpcX==0.10.2 \
--hash=sha256:58fe42b3695bc4e761b61b9a61416b0c6d69b220630be222b9b129b96ac9c331 --hash=sha256:23a59e625ca50cdf2866a2d8bd54256e648582a8d44d4495b34252f3dbc30e23 \
--hash=sha256:d2bf57fc46ae37d769ab3f5e58ebee4b44acab626e597b5150a201284b9808dd
async_timeout==3.0.1 \ async_timeout==3.0.1 \
--hash=sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f \ --hash=sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f \
--hash=sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3 --hash=sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3
@ -49,9 +50,9 @@ idna==2.8 \
--hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c --hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c
idna_ssl==1.1.0 \ idna_ssl==1.1.0 \
--hash=sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c --hash=sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c
jsonrpclib-pelix==0.3.2 \ jsonrpclib-pelix==0.4.0 \
--hash=sha256:14d288d1b3d3273cf96a729dd21a2470851c4962be8509f3dd62f0137ff90339 \ --hash=sha256:19c558e169a51480b39548783067ca55046b62b2409ab4559931255e12f635de \
--hash=sha256:27fcd919d3dbf6179bcce587f73e1bad006922ae23c83c308e01227b8533178c --hash=sha256:a966d17f2f739ee89031cf5c807d85d92db6b2715fb2b2f8a88bbfc87f468b12
multidict==4.5.2 \ multidict==4.5.2 \
--hash=sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f \ --hash=sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f \
--hash=sha256:041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3 \ --hash=sha256:041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3 \
@ -82,9 +83,9 @@ multidict==4.5.2 \
--hash=sha256:d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9 \ --hash=sha256:d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9 \
--hash=sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7 \ --hash=sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7 \
--hash=sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b --hash=sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b
pip==18.1 \ pip==19.0.1 \
--hash=sha256:7909d0a0932e88ea53a7014dfd14522ffef91a464daaaf5c573343852ef98550 \ --hash=sha256:aae79c7afe895fb986ec751564f24d97df1331bb99cdfec6f70dada2f40c0044 \
--hash=sha256:c0a292bd977ef590379a3f05d7b7f65135487b67470f6281289a94e015650ea1 --hash=sha256:e81ddd35e361b630e94abeda4a1eddd36d47a90e71eb00f38f46b57f787cd1a5
protobuf==3.6.1 \ protobuf==3.6.1 \
--hash=sha256:10394a4d03af7060fa8a6e1cbf38cea44be1467053b0aea5bbfcb4b13c4b88c4 \ --hash=sha256:10394a4d03af7060fa8a6e1cbf38cea44be1467053b0aea5bbfcb4b13c4b88c4 \
--hash=sha256:1489b376b0f364bcc6f89519718c057eb191d7ad6f1b395ffd93d1aa45587811 \ --hash=sha256:1489b376b0f364bcc6f89519718c057eb191d7ad6f1b395ffd93d1aa45587811 \
@ -108,15 +109,19 @@ pyaes==1.6.1 \
QDarkStyle==2.5.4 \ QDarkStyle==2.5.4 \
--hash=sha256:3eb60922b8c4d9cedecb6897ca4c9f8a259d81bdefe5791976ccdf12432de1f0 \ --hash=sha256:3eb60922b8c4d9cedecb6897ca4c9f8a259d81bdefe5791976ccdf12432de1f0 \
--hash=sha256:51331fc6490b38c376e6ba8d8c814320c8d2d1c2663055bc396321a7c28fa8be --hash=sha256:51331fc6490b38c376e6ba8d8c814320c8d2d1c2663055bc396321a7c28fa8be
qrcode==6.0 \ qrcode==6.1 \
--hash=sha256:037b0db4c93f44586e37f84c3da3f763874fcac85b2974a69a98e399ac78e1bf \ --hash=sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5 \
--hash=sha256:de4ffc15065e6ff20a551ad32b6b41264f3c75275675406ddfa8e3530d154be3 --hash=sha256:505253854f607f2abf4d16092c61d4e9d511a3b4392e60bff957a68592b04369
setuptools==40.6.3 \ setuptools==40.6.3 \
--hash=sha256:3b474dad69c49f0d2d86696b68105f3a6f195f7ab655af12ef9a9c326d2b08f8 \ --hash=sha256:3b474dad69c49f0d2d86696b68105f3a6f195f7ab655af12ef9a9c326d2b08f8 \
--hash=sha256:e2c1ce9a832f34cf7a31ed010aabcab5008eb65ce8f2aadc04622232c14bdd0b --hash=sha256:e2c1ce9a832f34cf7a31ed010aabcab5008eb65ce8f2aadc04622232c14bdd0b
six==1.12.0 \ six==1.12.0 \
--hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \ --hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \
--hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73 --hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73
typing-extensions==3.7.2 \
--hash=sha256:07b2c978670896022a43c4b915df8958bec4a6b84add7f2c87b2b728bda3ba64 \
--hash=sha256:f3f0e67e1d42de47b5c67c32c9b26641642e9170fe7e292991793705cd5fef7c \
--hash=sha256:fb2cd053238d33a8ec939190f30cfd736c00653a85a2919415cecf7dc3d9da71
wheel==0.32.3 \ wheel==0.32.3 \
--hash=sha256:029703bf514e16c8271c3821806a1c171220cc5bdd325cbf4e7da1e056a01db6 \ --hash=sha256:029703bf514e16c8271c3821806a1c171220cc5bdd325cbf4e7da1e056a01db6 \
--hash=sha256:1e53cdb3f808d5ccd0df57f964263752aa74ea7359526d3da6c02114ec1e1d44 --hash=sha256:1e53cdb3f808d5ccd0df57f964263752aa74ea7359526d3da6c02114ec1e1d44

View File

@ -10,7 +10,8 @@ Icon=electrum
Name[en_US]=Electrum Bitcoin Wallet Name[en_US]=Electrum Bitcoin Wallet
Name=Electrum Bitcoin Wallet Name=Electrum Bitcoin Wallet
Categories=Finance;Network; Categories=Finance;Network;
StartupNotify=false StartupNotify=true
StartupWMClass=electrum
Terminal=false Terminal=false
Type=Application Type=Application
MimeType=x-scheme-handler/bitcoin; MimeType=x-scheme-handler/bitcoin;

View File

@ -235,28 +235,28 @@ def b58_address_to_hash160(addr: str) -> Tuple[int, bytes]:
def hash160_to_p2pkh(h160: bytes, *, net=None) -> str: def hash160_to_p2pkh(h160: bytes, *, net=None) -> str:
if net is None: if net is None: net = constants.net
net = constants.net
return hash160_to_b58_address(h160, net.ADDRTYPE_P2PKH) return hash160_to_b58_address(h160, net.ADDRTYPE_P2PKH)
def hash160_to_p2sh(h160: bytes, *, net=None) -> str: def hash160_to_p2sh(h160: bytes, *, net=None) -> str:
if net is None: if net is None: net = constants.net
net = constants.net
return hash160_to_b58_address(h160, net.ADDRTYPE_P2SH) return hash160_to_b58_address(h160, net.ADDRTYPE_P2SH)
def public_key_to_p2pkh(public_key: bytes) -> str: def public_key_to_p2pkh(public_key: bytes, *, net=None) -> str:
return hash160_to_p2pkh(hash_160(public_key)) 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: def hash_to_segwit_addr(h: bytes, witver: int, *, net=None) -> str:
if net is None: if net is None: net = constants.net
net = constants.net
return segwit_addr.encode(net.SEGWIT_HRP, witver, h) return segwit_addr.encode(net.SEGWIT_HRP, witver, h)
def public_key_to_p2wpkh(public_key: bytes) -> str: def public_key_to_p2wpkh(public_key: bytes, *, net=None) -> str:
return hash_to_segwit_addr(hash_160(public_key), witver=0) 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: def script_to_p2wsh(script: str, *, net=None) -> str:
return hash_to_segwit_addr(sha256(bfh(script)), witver=0) 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: def p2wpkh_nested_script(pubkey: str) -> str:
pkh = bh2u(hash_160(bfh(pubkey))) pkh = bh2u(hash_160(bfh(pubkey)))
@ -266,25 +266,27 @@ def p2wsh_nested_script(witness_script: str) -> str:
wsh = bh2u(sha256(bfh(witness_script))) wsh = bh2u(sha256(bfh(witness_script)))
return '00' + push_script(wsh) 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': if txin_type == 'p2pkh':
return public_key_to_p2pkh(bfh(pubkey)) return public_key_to_p2pkh(bfh(pubkey), net=net)
elif txin_type == 'p2wpkh': 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': elif txin_type == 'p2wpkh-p2sh':
scriptSig = p2wpkh_nested_script(pubkey) scriptSig = p2wpkh_nested_script(pubkey)
return hash160_to_p2sh(hash_160(bfh(scriptSig))) return hash160_to_p2sh(hash_160(bfh(scriptSig)), net=net)
else: else:
raise NotImplementedError(txin_type) 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': 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': elif txin_type == 'p2wsh':
return script_to_p2wsh(redeem_script) return script_to_p2wsh(redeem_script, net=net)
elif txin_type == 'p2wsh-p2sh': elif txin_type == 'p2wsh-p2sh':
scriptSig = p2wsh_nested_script(redeem_script) 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: else:
raise NotImplementedError(txin_type) raise NotImplementedError(txin_type)
@ -296,8 +298,7 @@ def script_to_address(script: str, *, net=None) -> str:
return addr return addr
def address_to_script(addr: str, *, net=None) -> str: def address_to_script(addr: str, *, net=None) -> str:
if net is None: if net is None: net = constants.net
net = constants.net
if not is_address(addr, net=net): if not is_address(addr, net=net):
raise BitcoinException(f"invalid bitcoin address: {addr}") raise BitcoinException(f"invalid bitcoin address: {addr}")
witver, witprog = segwit_addr.decode(net.SEGWIT_HRP, addr) witver, witprog = segwit_addr.decode(net.SEGWIT_HRP, addr)

View File

@ -220,6 +220,11 @@ class Commands:
self.wallet.storage.write() self.wallet.storage.write()
return {'password':self.wallet.has_password()} return {'password':self.wallet.has_password()}
@command('w')
def get(self, key):
"""Return item from wallet storage"""
return self.wallet.storage.get(key)
@command('') @command('')
def getconfig(self, key): def getconfig(self, key):
"""Return a configuration variable. """ """Return a configuration variable. """

View File

@ -294,7 +294,10 @@ class Daemon(DaemonThread):
kwargs[x] = (config_options.get(x) if x in ['password', 'new_password'] else config.get(x)) kwargs[x] = (config_options.get(x) if x in ['password', 'new_password'] else config.get(x))
cmd_runner = Commands(config, wallet, self.network) cmd_runner = Commands(config, wallet, self.network)
func = getattr(cmd_runner, cmd.name) 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 return result
def run(self): def run(self):

View File

@ -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 .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 .ecc_fast import do_monkey_patching_of_python_ecdsa_internals_with_libsecp256k1
from . import msqr from . import msqr
from . import constants
do_monkey_patching_of_python_ecdsa_internals_with_libsecp256k1() 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 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 from .bitcoin import pubkey_to_address
assert_bytes(sig65, message) assert_bytes(sig65, message)
if net is None: net = constants.net
try: try:
h = sha256d(msg_magic(message)) h = sha256d(msg_magic(message))
public_key, compressed = ECPubkey.from_signature65(sig65, h) public_key, compressed = ECPubkey.from_signature65(sig65, h)
# check public key using the address # check public key using the address
pubkey_hex = public_key.get_public_key_hex(compressed) pubkey_hex = public_key.get_public_key_hex(compressed)
for txin_type in ['p2pkh','p2wpkh','p2wpkh-p2sh']: 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: if address == addr:
break break
else: else:

View File

@ -74,3 +74,11 @@ $ sudo docker run -it --rm \
### How do I get more verbose logs? ### How do I get more verbose logs?
See `log_level` in `buildozer.spec` 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`

View File

@ -11,7 +11,7 @@ RUN apt -y update -qq \
ENV ANDROID_NDK_HOME="${ANDROID_HOME}/android-ndk" 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}" 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 # 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 pip install --upgrade cython==0.29
RUN python3 -m 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 # install buildozer
RUN cd /opt \ RUN cd /opt \
&& git clone https://github.com/kivy/buildozer \ && git clone https://github.com/kivy/buildozer \
@ -134,7 +138,9 @@ RUN cd /opt \
&& cd python-for-android \ && cd python-for-android \
&& git remote add sombernight https://github.com/SomberNight/python-for-android \ && git remote add sombernight https://github.com/SomberNight/python-for-android \
&& git fetch --all \ && git fetch --all \
&& git checkout 86eeec7c19679a5886d5e095ce0a43f1da138f87 \ && git checkout fad5dd2fdc9b116b7621470deac501e4a7c4cc11 \
# allowBackup="false":
&& git cherry-pick 86eeec7c19679a5886d5e095ce0a43f1da138f87 \
&& python3 -m pip install -e . && python3 -m pip install -e .
# build env vars # build env vars

View File

@ -226,6 +226,28 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
gui_object.timer.timeout.connect(self.timer_actions) gui_object.timer.timeout.connect(self.timer_actions)
self.fetch_alias() 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): def on_history(self, b):
self.wallet.clear_coin_price_cache() self.wallet.clear_coin_price_cache()
self.new_fx_history_signal.emit() self.new_fx_history_signal.emit()
@ -577,6 +599,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
help_menu = menubar.addMenu(_("&Help")) help_menu = menubar.addMenu(_("&Help"))
help_menu.addAction(_("&About"), self.show_about) 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.addAction(_("&Official website"), lambda: webbrowser.open("https://electrum.org"))
help_menu.addSeparator() help_menu.addSeparator()
help_menu.addAction(_("&Documentation"), lambda: webbrowser.open("http://docs.electrum.org/")).setShortcut(QKeySequence.HelpContents) 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" + "servers that handle the most complicated parts of the FLO system.") + "\n\n" +
_("Uses icons from the Icons8 icon pack (icons8.com)."))) _("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): def show_report_bug(self):
msg = ' '.join([ msg = ' '.join([
_("Please report any bugs as issues on github:<br/>"), _("Please report any bugs as issues on github:<br/>"),
@ -2005,7 +2031,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
sb = QStatusBar() sb = QStatusBar()
sb.setFixedHeight(35) sb.setFixedHeight(35)
qtVersion = qVersion()
self.balance_label = QLabel("Loading wallet...") self.balance_label = QLabel("Loading wallet...")
self.balance_label.setTextInteractionFlags(Qt.TextSelectableByMouse) self.balance_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
@ -2017,6 +2042,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
self.search_box.hide() self.search_box.hide()
sb.addPermanentWidget(self.search_box) 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.lock_icon = QIcon()
self.password_button = StatusBarButton(self.lock_icon, _("Password"), self.change_password_dialog ) self.password_button = StatusBarButton(self.lock_icon, _("Password"), self.change_password_dialog )
sb.addPermanentWidget(self.password_button) sb.addPermanentWidget(self.password_button)
@ -2912,6 +2944,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
colortheme_combo.currentIndexChanged.connect(on_colortheme) colortheme_combo.currentIndexChanged.connect(on_colortheme)
gui_widgets.append((colortheme_label, colortheme_combo)) 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 = QCheckBox(_('Use change addresses'))
usechange_cb.setChecked(self.wallet.use_change) usechange_cb.setChecked(self.wallet.use_change)
if not self.config.is_modifiable('use_change'): usechange_cb.setEnabled(False) if not self.config.is_modifiable('use_change'): usechange_cb.setEnabled(False)
@ -3085,7 +3124,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
tabs_info = [ tabs_info = [
(fee_widgets, _('Fees')), (fee_widgets, _('Fees')),
(tx_widgets, _('Transactions')), (tx_widgets, _('Transactions')),
(gui_widgets, _('Appearance')), (gui_widgets, _('General')),
(fiat_widgets, _('Fiat')), (fiat_widgets, _('Fiat')),
(id_widgets, _('Identity')), (id_widgets, _('Identity')),
] ]

View File

@ -1,17 +1,24 @@
import asyncio
import os.path import os.path
import time import time
import sys import sys
import platform import platform
import queue import queue
import traceback
from distutils.version import StrictVersion
from functools import partial from functools import partial
from typing import NamedTuple, Callable, Optional, TYPE_CHECKING from typing import NamedTuple, Callable, Optional, TYPE_CHECKING
import base64
from PyQt5.QtGui import * from PyQt5.QtGui import *
from PyQt5.QtCore import * from PyQt5.QtCore import *
from PyQt5.QtWidgets import * from PyQt5.QtWidgets import *
from electrum import version
from electrum import ecc
from electrum import constants
from electrum.i18n import _, languages 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 from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED
if TYPE_CHECKING: if TYPE_CHECKING:
@ -819,6 +826,124 @@ class FromList(QTreeWidget):
self.header().setSectionResizeMode(0, sm) self.header().setSectionResizeMode(0, sm)
self.header().setSectionResizeMode(1, 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('<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):
try:
self.checked.emit(asyncio.run_coroutine_threadsafe(self.get_update_info(), self.main_window.network.asyncio_loop).result())
except Exception:
self.print_error(traceback.format_exc())
self.failed.emit()
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication([]) app = QApplication([])
t = WaitingDialog(None, 'testing ...', lambda: [time.sleep(1)], lambda x: QMessageBox.information(None, 'done', "done")) t = WaitingDialog(None, 'testing ...', lambda: [time.sleep(1)], lambda x: QMessageBox.information(None, 'done', "done"))

View File

@ -30,6 +30,7 @@ from electrum.i18n import _
from .util import * from .util import *
class UTXOList(MyTreeView): class UTXOList(MyTreeView):
headers = [ _('Address'), _('Label'), _('Amount'), _('Height'), _('Output point')]
filter_columns = [0, 1] # Address, Label filter_columns = [0, 1] # Address, Label
def __init__(self, parent=None): def __init__(self, parent=None):
@ -44,7 +45,7 @@ class UTXOList(MyTreeView):
utxos = self.wallet.get_utxos() utxos = self.wallet.get_utxos()
self.utxo_dict = {} self.utxo_dict = {}
self.model().clear() self.model().clear()
self.update_headers([ _('Address'), _('Label'), _('Amount'), _('Height'), _('Output point')]) self.update_headers(self.__class__.headers)
for idx, x in enumerate(utxos): for idx, x in enumerate(utxos):
address = x.get('address') address = x.get('address')
height = x.get('height') height = x.get('height')

View File

@ -1,17 +1,17 @@
from electrum.util import print_msg, print_error, raw_input from electrum.util import print_error, print_stderr, raw_input
class CmdLineHandler: class CmdLineHandler:
def get_passphrase(self, msg, confirm): def get_passphrase(self, msg, confirm):
import getpass import getpass
print_msg(msg) print_stderr(msg)
return getpass.getpass('') return getpass.getpass('')
def get_pin(self, msg): def get_pin(self, msg):
t = { 'a':'7', 'b':'8', 'c':'9', 'd':'4', 'e':'5', 'f':'6', 'g':'1', 'h':'2', 'i':'3'} t = { 'a':'7', 'b':'8', 'c':'9', 'd':'4', 'e':'5', 'f':'6', 'g':'1', 'h':'2', 'i':'3'}
print_msg(msg) print_stderr(msg)
print_msg("a b c\nd e f\ng h i\n-----") print_stderr("a b c\nd e f\ng h i\n-----")
o = raw_input() o = raw_input()
try: try:
return ''.join(map(lambda x: t[x], o)) return ''.join(map(lambda x: t[x], o))
@ -20,24 +20,24 @@ class CmdLineHandler:
def prompt_auth(self, msg): def prompt_auth(self, msg):
import getpass import getpass
print_msg(msg) print_stderr(msg)
response = getpass.getpass('') response = getpass.getpass('')
if len(response) == 0: if len(response) == 0:
return None return None
return response return response
def yes_no_question(self, msg): def yes_no_question(self, msg):
print_msg(msg) print_stderr(msg)
return raw_input() in 'yY' return raw_input() in 'yY'
def stop(self): def stop(self):
pass pass
def show_message(self, msg, on_cancel=None): def show_message(self, msg, on_cancel=None):
print_msg(msg) print_stderr(msg)
def show_error(self, msg, blocking=False): def show_error(self, msg, blocking=False):
print_msg(msg) print_stderr(msg)
def update_status(self, b): def update_status(self, b):
print_error('hw device status', b) print_error('hw device status', b)

View File

@ -289,7 +289,8 @@ class KeepKeyPlugin(HW_PluginBase):
client = self.get_client(keystore) client = self.get_client(keystore)
inputs = self.tx_inputs(tx, True) inputs = self.tx_inputs(tx, True)
outputs = self.tx_outputs(keystore.get_derivation(), tx) outputs = self.tx_outputs(keystore.get_derivation(), tx)
signatures = client.sign_tx(self.get_coin_name(), inputs, outputs, lock_time=tx.locktime)[0] signatures = client.sign_tx(self.get_coin_name(), inputs, outputs,
lock_time=tx.locktime, version=tx.version)[0]
signatures = [(bh2u(x) + '01') for x in signatures] signatures = [(bh2u(x) + '01') for x in signatures]
tx.update_signatures(signatures) tx.update_signatures(signatures)

View File

@ -306,7 +306,8 @@ class SafeTPlugin(HW_PluginBase):
client = self.get_client(keystore) client = self.get_client(keystore)
inputs = self.tx_inputs(tx, True) inputs = self.tx_inputs(tx, True)
outputs = self.tx_outputs(keystore.get_derivation(), tx) outputs = self.tx_outputs(keystore.get_derivation(), tx)
signatures = client.sign_tx(self.get_coin_name(), inputs, outputs, lock_time=tx.locktime)[0] signatures = client.sign_tx(self.get_coin_name(), inputs, outputs,
lock_time=tx.locktime, version=tx.version)[0]
signatures = [(bh2u(x) + '01') for x in signatures] signatures = [(bh2u(x) + '01') for x in signatures]
tx.update_signatures(signatures) tx.update_signatures(signatures)

View File

@ -310,7 +310,7 @@ class TrezorPlugin(HW_PluginBase):
client = self.get_client(keystore) client = self.get_client(keystore)
inputs = self.tx_inputs(tx, xpub_path, True) inputs = self.tx_inputs(tx, xpub_path, True)
outputs = self.tx_outputs(keystore.get_derivation(), tx) outputs = self.tx_outputs(keystore.get_derivation(), tx)
details = SignTx(lock_time=tx.locktime) details = SignTx(lock_time=tx.locktime, version=tx.version)
signatures, _ = client.sign_tx(self.get_coin_name(), inputs, outputs, details=details, prev_txes=prev_tx) signatures, _ = client.sign_tx(self.get_coin_name(), inputs, outputs, details=details, prev_txes=prev_tx)
signatures = [(bh2u(x) + '01') for x in signatures] signatures = [(bh2u(x) + '01') for x in signatures]
tx.update_signatures(signatures) tx.update_signatures(signatures)

View File

@ -1,5 +1,5 @@
ELECTRUM_VERSION = '3.3.2' # version of the client package ELECTRUM_VERSION = '3.3.3' # version of the client package
APK_VERSION = '3.3.2.0' # read by buildozer.spec APK_VERSION = '3.3.3.0' # read by buildozer.spec
PROTOCOL_VERSION = '1.4' # protocol version requested PROTOCOL_VERSION = '1.4' # protocol version requested

View File

@ -63,6 +63,7 @@
<file>icons/unconfirmed.png</file> <file>icons/unconfirmed.png</file>
<file>icons/unpaid.png</file> <file>icons/unpaid.png</file>
<file>icons/unlock.png</file> <file>icons/unlock.png</file>
<file>icons/update.png</file>
<file>icons/warning.png</file> <file>icons/warning.png</file>
<file>icons/zoom.png</file> <file>icons/zoom.png</file>
</qresource> </qresource>

BIN
icons/update.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB