From c7622d757bd4abeee72593f45169c8a716cdb242 Mon Sep 17 00:00:00 2001 From: zebra-lucky Date: Thu, 28 Jun 2018 19:05:18 +0300 Subject: [PATCH] changes to contrib, .travis.yml --- .travis.yml | 85 +- contrib/build-wine/README.md | 38 - contrib/build-wine/build-electrum-git.sh | 86 --- contrib/build-wine/build.sh | 23 - contrib/build-wine/deterministic.spec | 122 --- contrib/build-wine/prepare-hw.sh | 28 - contrib/build-wine/prepare-pyinstaller.sh | 24 - contrib/build-wine/prepare-wine.sh | 113 --- .../find_restricted_dependencies.py | 38 + .../requirements-binaries.txt | 61 ++ .../deterministic-build/requirements-hw.txt | 119 +++ contrib/deterministic-build/requirements.txt | 69 ++ contrib/freeze_packages.sh | 22 - contrib/make_download | 51 -- contrib/make_osx | 6 - contrib/osx.spec | 82 -- contrib/requirements/requirements-hw.txt | 4 + contrib/requirements/requirements.txt | 9 + contrib/sign-releases.py | 725 ++++++++++++++++++ contrib/sign_packages | 18 - contrib/zcash/deterministic.spec | 161 ++++ .../electrum.nsi => zcash/electrum-zcash.nsi} | 50 +- contrib/zcash/osx.spec | 158 ++++ contrib/zcash/pyi_runtimehook.py | 88 +++ contrib/zcash/pyi_tctl_runtimehook.py | 3 + contrib/{ => zcash}/requirements.txt | 1 + contrib/zcash/travis/Dockerfile-kivy | 119 +++ contrib/zcash/travis/Dockerfile-linux | 7 + contrib/zcash/travis/Dockerfile-wine | 87 +++ .../zcash/travis/before_install-linux-apk.sh | 10 + contrib/zcash/travis/before_install-linux.sh | 10 + contrib/zcash/travis/before_install-osx.sh | 27 + contrib/zcash/travis/build_linux.sh | 7 + contrib/zcash/travis/build_wine.sh | 49 ++ .../travis/electrum_zcash_version_env.sh | 14 + .../zcash/travis/travis-build-linux-apk.sh | 28 + contrib/zcash/travis/travis-build-linux.sh | 53 ++ contrib/zcash/travis/travis-build-osx.sh | 49 ++ 38 files changed, 2001 insertions(+), 643 deletions(-) delete mode 100644 contrib/build-wine/README.md delete mode 100755 contrib/build-wine/build-electrum-git.sh delete mode 100755 contrib/build-wine/build.sh delete mode 100644 contrib/build-wine/deterministic.spec delete mode 100755 contrib/build-wine/prepare-hw.sh delete mode 100755 contrib/build-wine/prepare-pyinstaller.sh delete mode 100755 contrib/build-wine/prepare-wine.sh create mode 100755 contrib/deterministic-build/find_restricted_dependencies.py create mode 100644 contrib/deterministic-build/requirements-binaries.txt create mode 100644 contrib/deterministic-build/requirements-hw.txt create mode 100644 contrib/deterministic-build/requirements.txt delete mode 100755 contrib/freeze_packages.sh delete mode 100755 contrib/make_download delete mode 100755 contrib/make_osx delete mode 100644 contrib/osx.spec create mode 100644 contrib/requirements/requirements-hw.txt create mode 100644 contrib/requirements/requirements.txt create mode 100755 contrib/sign-releases.py delete mode 100755 contrib/sign_packages create mode 100644 contrib/zcash/deterministic.spec rename contrib/{build-wine/electrum.nsi => zcash/electrum-zcash.nsi} (79%) create mode 100644 contrib/zcash/osx.spec create mode 100644 contrib/zcash/pyi_runtimehook.py create mode 100644 contrib/zcash/pyi_tctl_runtimehook.py rename contrib/{ => zcash}/requirements.txt (93%) create mode 100644 contrib/zcash/travis/Dockerfile-kivy create mode 100644 contrib/zcash/travis/Dockerfile-linux create mode 100644 contrib/zcash/travis/Dockerfile-wine create mode 100755 contrib/zcash/travis/before_install-linux-apk.sh create mode 100755 contrib/zcash/travis/before_install-linux.sh create mode 100755 contrib/zcash/travis/before_install-osx.sh create mode 100755 contrib/zcash/travis/build_linux.sh create mode 100755 contrib/zcash/travis/build_wine.sh create mode 100755 contrib/zcash/travis/electrum_zcash_version_env.sh create mode 100755 contrib/zcash/travis/travis-build-linux-apk.sh create mode 100755 contrib/zcash/travis/travis-build-linux.sh create mode 100755 contrib/zcash/travis/travis-build-osx.sh diff --git a/.travis.yml b/.travis.yml index 1a86f4f4..560aaa4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,77 @@ -sudo: false +sudo: required language: python -python: - - "3.5" - - "3.6" +services: +- docker +addons: + apt: + packages: + - libusb-1.0-0-dev + - libudev-dev +matrix: + include: + - if: tag =~ .+ + os: osx + language: ruby + osx_image: xcode7.3 + - os: linux + python: "3.4" + - os: linux + python: "3.5" + - if: NOT tag =~ .+ + os: linux + python: "3.6" +before_install: +- source contrib/zcash/travis/electrum_zcash_version_env.sh +- echo electrum-zcash version is $ELECTRUM_ZCASH_VERSION +- mkdir -p build && cp contrib/zcash/travis/* ./build/ +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'osx' ]]; then + ./build/before_install-osx.sh; + fi +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then + ./build/before_install-linux.sh; + fi +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then + ./build/before_install-linux-apk.sh; + fi install: - - pip install tox - - pip install tox-travis - - pip install python-coveralls +- if [[ -z $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]]; then + pip install tox; pip install tox-travis; + fi script: - - tox -after_success: - - if [ "$TRAVIS_BRANCH" = "master" ]; then pip install pycurl requests && contrib/make_locale; fi - - coveralls +- if [[ -z $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]];then + tox; + fi +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'osx' ]]; then + ./build/travis-build-osx.sh ; + fi +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then + ./build/travis-build-linux.sh; + fi +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then + ./build/travis-build-linux-apk.sh; + fi +deploy: +- provider: releases + api_key: + secure: ipcWAaqrPrgXX+L86AEq/VkfJ81j3RvDF1b+BUcPCmU/HB0UE6Eg8TTtGZ/LPZXUfcsmhLCS9zinwSh8HTYjJ1fd+yVv7V7xFrp1vRuxTE06JNwPETOOZRAk/sMlOfKU2T0rw8iyW4qhfCHO0r6Dqmb6/0psARrq0bxihKWfI+eemVLdMJPzCJABSwKOrPWK01j6FCehvlPyFnRy/Ti0sAy8JYSJ/r+ICN08qHZTVrskquEE/Bds9E3Js3Jc/tZSCPhw+/u6t34zVnFAGvEnhcgHZFDuooCl2BR02jBNpkgjHSjGUEDjom85J+FKRAg+9mDU+wH9X0s+uf4O+AIVQH4COhWjbcqviX+PyHzG8kT6uVnIj39yLmgIAhDXVfjVgy8lfb8M6pS1ajhZB1C4fwHU6ef98xk4BhTlWbex6nvko5cy8lituezfD8U8JQhbv4KSz+xRpOIspUXj1KnHTaJhBEizxFi60MX+mlKRXeKIpSqveEPZnKuqkpnOb3K8BTM8Ca2UjYagasrV7ix4w+SCAmAjF+Tdtqf8LMht1mSn+zeB32ZsnyWnL74HPWqw6/StdlS5HSxlvmfl2UnxH77e5EPGNI0KGUPG6vQcUxBg9B1tv7iruNgYJThT54sE3zWy+6eFJy5XCGkZuiS2ETiL31h+9CEwGWRsR6L6+tA= + file: + - build/electrum-zcash/dist/electrum-zcash-$ELECTRUM_ZCASH_VERSION-macosx.dmg + on: + repo: zebra-lucky/electrum-zcash + tags: true + condition: "$TRAVIS_OS_NAME = osx" +- provider: releases + api_key: + secure: ipcWAaqrPrgXX+L86AEq/VkfJ81j3RvDF1b+BUcPCmU/HB0UE6Eg8TTtGZ/LPZXUfcsmhLCS9zinwSh8HTYjJ1fd+yVv7V7xFrp1vRuxTE06JNwPETOOZRAk/sMlOfKU2T0rw8iyW4qhfCHO0r6Dqmb6/0psARrq0bxihKWfI+eemVLdMJPzCJABSwKOrPWK01j6FCehvlPyFnRy/Ti0sAy8JYSJ/r+ICN08qHZTVrskquEE/Bds9E3Js3Jc/tZSCPhw+/u6t34zVnFAGvEnhcgHZFDuooCl2BR02jBNpkgjHSjGUEDjom85J+FKRAg+9mDU+wH9X0s+uf4O+AIVQH4COhWjbcqviX+PyHzG8kT6uVnIj39yLmgIAhDXVfjVgy8lfb8M6pS1ajhZB1C4fwHU6ef98xk4BhTlWbex6nvko5cy8lituezfD8U8JQhbv4KSz+xRpOIspUXj1KnHTaJhBEizxFi60MX+mlKRXeKIpSqveEPZnKuqkpnOb3K8BTM8Ca2UjYagasrV7ix4w+SCAmAjF+Tdtqf8LMht1mSn+zeB32ZsnyWnL74HPWqw6/StdlS5HSxlvmfl2UnxH77e5EPGNI0KGUPG6vQcUxBg9B1tv7iruNgYJThT54sE3zWy+6eFJy5XCGkZuiS2ETiL31h+9CEwGWRsR6L6+tA= + file: + - build/electrum-zcash/dist/Electrum-Zcash-$ELECTRUM_ZCASH_VERSION.tar.gz + - build/electrum-zcash/dist/electrum-zcash-$ELECTRUM_ZCASH_VERSION-setup-win32.exe + - build/electrum-zcash/dist/electrum-zcash-$ELECTRUM_ZCASH_VERSION-setup-win64.exe + - build/electrum-zcash/bin/Electrum_Zcash-$ELECTRUM_ZCASH_APK_VERSION-release-unsigned.apk + on: + repo: zebra-lucky/electrum-zcash + tags: true + condition: "$TRAVIS_OS_NAME = linux" +notifications: + slack: + secure: g2tFyXklhL4WOD/jQ8nxiOBqVv2F26iE4aVgvpclQ/9Fnh6jXEk3jCXyMqt39fcbB4Hka2wPr4n5uWH3tRaChFpwK5LQS5vuymllloqdxAShgIXXciZ1k/Ka1K+mxMEPJriQm4MT5AvzcLVSkJ0i5LYW8nWgG7+fTEullWS4hlPLC77C36iK2CWDaxfFqqe8oPTdsCVbik8HQ62ZWDM6Sh6TZbQD7F9eUBmiwwQhRB2BMxPkWghwQ//FRJ+PIpg7PtWRru/JjNg3adOsHnwlltqUVAolacZCbpxDKFR+GLpYmLkMrwdnVA7apZ2In/yo25ByAkxshCgw45lmGB0dtC1zeAe3Get9eGP5w3o9Zedj5T5esX0BNArDK70C+kTXcPeJaRRQJPrs5OYXRPKjD+uiJqe1fIFSmhdM6vvuMPdyA1z0Fd0/9G2O/Qi8tFxcFmM8n6JQGfD9ojOQF8fPYcHM9gsOgNU9J2PfV3RnRtv3VZogxs4azKG2M8JhD/lwqZBNi4FgdllW6NE7+5TB2KX07xy/zx0m81u8k6J228sAuiRsUBcpmW7pqlqLIENMzwV8pDcA93Ps0EWJKWbzRi+hIEkBnaFE9WHY0GcKuW0TCrnonZ4FOnJNO/G9HzxvQ97bcJDvhUloJ2pBBsH0P4IZ1RlDXFpc5DqTT2qxZSo= diff --git a/contrib/build-wine/README.md b/contrib/build-wine/README.md deleted file mode 100644 index b63485e8..00000000 --- a/contrib/build-wine/README.md +++ /dev/null @@ -1,38 +0,0 @@ -Windows Binary Builds -===================== - -These scripts can be used for cross-compilation of Windows Electrum executables from Linux/Wine. -Produced binaries are deterministic so you should be able to generate binaries that match the official releases. - - -Usage: - - -1. Install the following dependencies: - - - dirmngr - - gpg - - Wine (>= v2) - - -For example: - - -``` -$ sudo apt-get install wine-development dirmngr gnupg2 -$ sudo ln -sf /usr/bin/wine-development /usr/local/bin/wine -$ wine --version - wine-2.0 (Debian 2.0-3+b2) -``` - -or - -``` -$ pacman -S wine gnupg -$ wine --version - wine-2.21 -``` - -2. Make sure `/opt` is writable by the current user. -3. Run `build.sh`. -4. The generated binaries are in `./dist`. diff --git a/contrib/build-wine/build-electrum-git.sh b/contrib/build-wine/build-electrum-git.sh deleted file mode 100755 index f1a7a022..00000000 --- a/contrib/build-wine/build-electrum-git.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash - -NAME_ROOT=electrum -PYTHON_VERSION=3.5.4 - -if [ "$#" -gt 0 ]; then - BRANCH="$1" -fi - -# These settings probably don't need any change -export WINEPREFIX=/opt/wine64 -export PYTHONDONTWRITEBYTECODE=1 -export PYTHONHASHSEED=22 - -PYHOME=c:/python$PYTHON_VERSION -PYTHON="wine $PYHOME/python.exe -OO -B" - - -# Let's begin! -cd `dirname $0` -set -e - -cd tmp - -for repo in electrum electrum-locale electrum-icons; do - if [ -d $repo ]; then - cd $repo - git pull - git checkout master - cd .. - else - URL=https://github.com/spesmilo/$repo.git - git clone -b master $URL $repo - fi -done - -pushd electrum-locale -for i in ./locale/*; do - dir=$i/LC_MESSAGES - mkdir -p $dir - msgfmt --output-file=$dir/electrum.mo $i/electrum.po || true -done -popd - -pushd electrum -git checkout $BRANCH -VERSION=`git describe --tags` -echo "Last commit: $VERSION" -find -exec touch -d '2000-11-11T11:11:11+00:00' {} + -popd - -rm -rf $WINEPREFIX/drive_c/electrum -cp -r electrum $WINEPREFIX/drive_c/electrum -cp electrum/LICENCE . -cp -r electrum-locale/locale $WINEPREFIX/drive_c/electrum/lib/ -cp electrum-icons/icons_rc.py $WINEPREFIX/drive_c/electrum/gui/qt/ - -# Install frozen dependencies -$PYTHON -m pip install -r ../../requirements.txt - -pushd $WINEPREFIX/drive_c/electrum -$PYTHON setup.py install -popd - -cd .. - -rm -rf dist/ - -# build standalone and portable versions -wine "C:/python$PYTHON_VERSION/scripts/pyinstaller.exe" --noconfirm --ascii --name $NAME_ROOT-$VERSION -w deterministic.spec - -# set timestamps in dist, in order to make the installer reproducible -pushd dist -find -exec touch -d '2000-11-11T11:11:11+00:00' {} + -popd - -# build NSIS installer -# $VERSION could be passed to the electrum.nsi script, but this would require some rewriting in the script iself. -wine "$WINEPREFIX/drive_c/Program Files (x86)/NSIS/makensis.exe" /DPRODUCT_VERSION=$VERSION electrum.nsi - -cd dist -mv electrum-setup.exe $NAME_ROOT-$VERSION-setup.exe -cd .. - -echo "Done." -md5sum dist/electrum*exe diff --git a/contrib/build-wine/build.sh b/contrib/build-wine/build.sh deleted file mode 100755 index 6c578578..00000000 --- a/contrib/build-wine/build.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# Lucky number -export PYTHONHASHSEED=22 - -here=$(dirname "$0") - -echo "Clearing $here/build and $here/dist..." -rm $here/build/* -rf -rm $here/dist/* -rf - -$here/prepare-wine.sh && \ -$here/prepare-pyinstaller.sh && \ -$here/prepare-hw.sh || exit 1 - -echo "Resetting modification time in C:\Python..." -# (Because of some bugs in pyinstaller) -pushd /opt/wine64/drive_c/python* -find -exec touch -d '2000-11-11T11:11:11+00:00' {} + -popd -ls -l /opt/wine64/drive_c/python* - -$here/build-electrum-git.sh && \ -echo "Done." diff --git a/contrib/build-wine/deterministic.spec b/contrib/build-wine/deterministic.spec deleted file mode 100644 index bbd6c210..00000000 --- a/contrib/build-wine/deterministic.spec +++ /dev/null @@ -1,122 +0,0 @@ -# -*- mode: python -*- - -from PyInstaller.utils.hooks import collect_data_files, collect_submodules - -import sys -for i, x in enumerate(sys.argv): - if x == '--name': - cmdline_name = sys.argv[i+1] - break -else: - raise BaseException('no name') - - -home = 'C:\\electrum\\' - -# see https://github.com/pyinstaller/pyinstaller/issues/2005 -hiddenimports = [] -hiddenimports += collect_submodules('trezorlib') -hiddenimports += collect_submodules('btchip') -hiddenimports += collect_submodules('keepkeylib') - -datas = [ - (home+'lib/currencies.json', 'electrum'), - (home+'lib/servers.json', 'electrum'), - (home+'lib/servers_testnet.json', 'electrum'), - (home+'lib/wordlist/english.txt', 'electrum/wordlist'), - (home+'lib/locale', 'electrum/locale'), - (home+'plugins', 'electrum_plugins'), -] -datas += collect_data_files('trezorlib') -datas += collect_data_files('btchip') -datas += collect_data_files('keepkeylib') - -# We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports -a = Analysis([home+'electrum', - home+'gui/qt/main_window.py', - home+'gui/text.py', - home+'lib/util.py', - home+'lib/wallet.py', - home+'lib/simple_config.py', - home+'lib/bitcoin.py', - home+'lib/dnssec.py', - home+'lib/commands.py', - home+'plugins/cosigner_pool/qt.py', - home+'plugins/email_requests/qt.py', - home+'plugins/trezor/client.py', - home+'plugins/trezor/qt.py', - home+'plugins/keepkey/qt.py', - home+'plugins/ledger/qt.py', - #home+'packages/requests/utils.py' - ], - datas=datas, - #pathex=[home+'lib', home+'gui', home+'plugins'], - hiddenimports=hiddenimports, - hookspath=[]) - - -# http://stackoverflow.com/questions/19055089/pyinstaller-onefile-warning-pyconfig-h-when-importing-scipy-or-scipy-signal -for d in a.datas: - if 'pyconfig' in d[0]: - a.datas.remove(d) - break - -# hotfix for #3171 (pre-Win10 binaries) -a.binaries = [x for x in a.binaries if not x[1].lower().startswith(r'c:\windows')] - -pyz = PYZ(a.pure) - - -##### -# "standalone" exe with all dependencies packed into it - -exe_standalone = EXE( - pyz, - a.scripts, - a.binaries, - a.datas, - name=os.path.join('build\\pyi.win32\\electrum', cmdline_name + ".exe"), - debug=False, - strip=None, - upx=False, - icon=home+'icons/electrum.ico', - console=False) - # console=True makes an annoying black box pop up, but it does make Electrum output command line commands, with this turned off no output will be given but commands can still be used - -exe_portable = EXE( - pyz, - a.scripts, - a.binaries, - a.datas + [ ('is_portable', 'README.md', 'DATA' ) ], - name=os.path.join('build\\pyi.win32\\electrum', cmdline_name + "-portable.exe"), - debug=False, - strip=None, - upx=False, - icon=home+'icons/electrum.ico', - console=False) - -##### -# exe and separate files that NSIS uses to build installer "setup" exe - -exe_dependent = EXE( - pyz, - a.scripts, - exclude_binaries=True, - name=os.path.join('build\\pyi.win32\\electrum', cmdline_name), - debug=False, - strip=None, - upx=False, - icon=home+'icons/electrum.ico', - console=False) - -coll = COLLECT( - exe_dependent, - a.binaries, - a.zipfiles, - a.datas, - strip=None, - upx=True, - debug=False, - icon=home+'icons/electrum.ico', - console=False, - name=os.path.join('dist', 'electrum')) diff --git a/contrib/build-wine/prepare-hw.sh b/contrib/build-wine/prepare-hw.sh deleted file mode 100755 index c73e13fc..00000000 --- a/contrib/build-wine/prepare-hw.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -TREZOR_GIT_URL=https://github.com/trezor/python-trezor.git -KEEPKEY_GIT_URL=https://github.com/keepkey/python-keepkey.git -BTCHIP_GIT_URL=https://github.com/LedgerHQ/btchip-python.git - -BRANCH=master - -PYTHON_VERSION=3.5.4 - -# These settings probably don't need any change -export WINEPREFIX=/opt/wine64 - -PYHOME=c:/python$PYTHON_VERSION -PYTHON="wine $PYHOME/python.exe -OO -B" - -# Let's begin! -cd `dirname $0` -set -e - -cd tmp - -$PYTHON -m pip install setuptools --upgrade -$PYTHON -m pip install cython --upgrade -$PYTHON -m pip install trezor==0.7.16 --upgrade -$PYTHON -m pip install keepkey==4.0.2 --upgrade -$PYTHON -m pip install btchip-python==0.1.24 --upgrade - diff --git a/contrib/build-wine/prepare-pyinstaller.sh b/contrib/build-wine/prepare-pyinstaller.sh deleted file mode 100755 index cf8a326c..00000000 --- a/contrib/build-wine/prepare-pyinstaller.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -PYTHON_VERSION=3.5.4 - -PYINSTALLER_GIT_URL=https://github.com/ecdsa/pyinstaller.git -BRANCH=fix_2952 - -export WINEPREFIX=/opt/wine64 -PYHOME=c:/python$PYTHON_VERSION -PYTHON="wine $PYHOME/python.exe -OO -B" - -cd `dirname $0` -set -e -cd tmp -if [ ! -d "pyinstaller" ]; then - git clone -b $BRANCH $PYINSTALLER_GIT_URL pyinstaller -fi - -cd pyinstaller -git pull -git checkout $BRANCH -$PYTHON setup.py install -cd .. - -wine "C:/python$PYTHON_VERSION/scripts/pyinstaller.exe" -v diff --git a/contrib/build-wine/prepare-wine.sh b/contrib/build-wine/prepare-wine.sh deleted file mode 100755 index 542a2085..00000000 --- a/contrib/build-wine/prepare-wine.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/bash - -# Please update these carefully, some versions won't work under Wine -NSIS_URL=https://prdownloads.sourceforge.net/nsis/nsis-3.02.1-setup.exe?download -NSIS_SHA256=736c9062a02e297e335f82252e648a883171c98e0d5120439f538c81d429552e -PYTHON_VERSION=3.5.4 - -## These settings probably don't need change -export WINEPREFIX=/opt/wine64 -#export WINEARCH='win32' - -PYHOME=c:/python$PYTHON_VERSION -PYTHON="wine $PYHOME/python.exe -OO -B" - - -# based on https://superuser.com/questions/497940/script-to-verify-a-signature-with-gpg -verify_signature() { - local file=$1 keyring=$2 out= - if out=$(gpg --no-default-keyring --keyring "$keyring" --status-fd 1 --verify "$file" 2>/dev/null) && - echo "$out" | grep -qs "^\[GNUPG:\] VALIDSIG "; then - return 0 - else - echo "$out" >&2 - exit 0 - fi -} - -verify_hash() { - local file=$1 expected_hash=$2 out= - actual_hash=$(sha256sum $file | awk '{print $1}') - if [ "$actual_hash" == "$expected_hash" ]; then - return 0 - else - echo "$file $actual_hash (unexpected hash)" >&2 - exit 0 - fi -} - -# Let's begin! -cd `dirname $0` -set -e - -# Clean up Wine environment -echo "Cleaning $WINEPREFIX" -rm -rf $WINEPREFIX -echo "done" - -wine 'wineboot' - -echo "Cleaning tmp" -rm -rf tmp -mkdir -p tmp -echo "done" - -cd tmp - -# Install Python -# note: you might need "sudo apt-get install dirmngr" for the following -# keys from https://www.python.org/downloads/#pubkeys -KEYRING_PYTHON_DEV=keyring-electrum-build-python-dev.gpg -gpg --no-default-keyring --keyring $KEYRING_PYTHON_DEV --recv-keys 531F072D39700991925FED0C0EDDC5F26A45C816 26DEA9D4613391EF3E25C9FF0A5B101836580288 CBC547978A3964D14B9AB36A6AF053F07D9DC8D2 C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF 12EF3DC38047DA382D18A5B999CDEA9DA4135B38 8417157EDBE73D9EAC1E539B126EB563A74B06BF DBBF2EEBF925FAADCF1F3FFFD9866941EA5BBD71 2BA0DB82515BBB9EFFAC71C5C9BE28DEE6DF025C 0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D C9B104B3DD3AA72D7CCB1066FB9921286F5E1540 97FC712E4C024BBEA48A61ED3A5CA953F73C700D 7ED10B6531D7C8E1BC296021FC624643487034E5 -for msifile in core dev exe lib pip tools; do - echo "Installing $msifile..." - wget "https://www.python.org/ftp/python/$PYTHON_VERSION/win32/${msifile}.msi" - wget "https://www.python.org/ftp/python/$PYTHON_VERSION/win32/${msifile}.msi.asc" - verify_signature "${msifile}.msi.asc" $KEYRING_PYTHON_DEV - wine msiexec /i "${msifile}.msi" /qb TARGETDIR=C:/python$PYTHON_VERSION -done - -# upgrade pip -$PYTHON -m pip install pip --upgrade - -# Install PyWin32 -$PYTHON -m pip install pypiwin32 - -# Install PyQt -$PYTHON -m pip install PyQt5 - -## Install pyinstaller -#$PYTHON -m pip install pyinstaller==3.3 - - -# Install ZBar -#wget -q -O zbar.exe "https://sourceforge.net/projects/zbar/files/zbar/0.10/zbar-0.10-setup.exe/download" -#wine zbar.exe - -# install Cryptodome -$PYTHON -m pip install pycryptodomex - -# install PySocks -$PYTHON -m pip install win_inet_pton - -# install websocket (python2) -$PYTHON -m pip install websocket-client - -# Upgrade setuptools (so Electrum can be installed later) -$PYTHON -m pip install setuptools --upgrade - -# Install NSIS installer -wget -q -O nsis.exe "$NSIS_URL" -verify_hash nsis.exe $NSIS_SHA256 -wine nsis.exe /S - -# Install UPX -#wget -O upx.zip "https://downloads.sourceforge.net/project/upx/upx/3.08/upx308w.zip" -#unzip -o upx.zip -#cp upx*/upx.exe . - -# add dlls needed for pyinstaller: -cp $WINEPREFIX/drive_c/python$PYTHON_VERSION/Lib/site-packages/PyQt5/Qt/bin/* $WINEPREFIX/drive_c/python$PYTHON_VERSION/ - - -echo "Wine is configured. Please run prepare-pyinstaller.sh" diff --git a/contrib/deterministic-build/find_restricted_dependencies.py b/contrib/deterministic-build/find_restricted_dependencies.py new file mode 100755 index 00000000..1734d575 --- /dev/null +++ b/contrib/deterministic-build/find_restricted_dependencies.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import sys + +import requests + + +def check_restriction(p, r): + # See: https://www.python.org/dev/peps/pep-0496/ + # Hopefully we don't need to parse the whole microlanguage + if "extra" in r and "[" not in p: + return False + for marker in ["os_name", "platform_release", "sys_platform", "platform_system"]: + if marker in r: + return True + + +for p in sys.stdin.read().split(): + p = p.strip() + if not p: + continue + assert "==" in p, "This script expects a list of packages with pinned version, e.g. package==1.2.3, not {}".format(p) + p, v = p.rsplit("==", 1) + try: + data = requests.get("https://pypi.org/pypi/{}/{}/json".format(p, v)).json()["info"] + except ValueError: + raise Exception("Package could not be found: {}=={}".format(p, v)) + try: + for r in data["requires_dist"]: + if ";" not in r: + continue + d, restricted = r.split(";", 1) + if check_restriction(d, restricted): + print(d, sep=" ") + print("Installing {} from {} although it is only needed for {}".format(d, p, restricted), file=sys.stderr) + except TypeError: + # Has no dependencies at all + continue + diff --git a/contrib/deterministic-build/requirements-binaries.txt b/contrib/deterministic-build/requirements-binaries.txt new file mode 100644 index 00000000..da4af58c --- /dev/null +++ b/contrib/deterministic-build/requirements-binaries.txt @@ -0,0 +1,61 @@ +pip==9.0.3 \ + --hash=sha256:7bf48f9a693be1d58f49f7af7e0ae9fe29fd671cde8a55e6edca3581c4ef5796 \ + --hash=sha256:c3ede34530e0e0b2381e7363aded78e0c33291654937e7373032fda04e8803e5 +pycryptodomex==3.6.0 \ + --hash=sha256:023432d6938c17bd8ff5c4a3efcac7923e3724a42655e011580a84db0be0903b \ + --hash=sha256:11756a831e0cc2549fb67be50aca040495d7e20a47b2ab1cf77f0db6eaae75e0 \ + --hash=sha256:18837dbf05ed97bcb169b1f5465ec2569985f25c787cc91d89b363217f31f63b \ + --hash=sha256:1d815ac94211ae6b15a92dc8242eb81369214e4c6805d4ff663a14f7707f0212 \ + --hash=sha256:27533f616df0da5964c1a1b9506b0d6c09f90dd5d22e44773871a1cba9fddede \ + --hash=sha256:2c2894facf93b6a99a8c2c34b9d998bbd79db32dedb06d89dc8ab0c198fad687 \ + --hash=sha256:38feac59199ce6146a77550671c2db66ec48ce100688489640485dd658d7cf65 \ + --hash=sha256:398d7631c286572b0edf2a8fea00ce5ec2c140d0159e16096296ecbb2b62192b \ + --hash=sha256:3d0b011a1514db2bee5db6dd02cc2672f2cb490df57652d3e506069e1129ed01 \ + --hash=sha256:41a5bd025c4d93d7ef8147709da5ec0ef9101b963ca52851a67befea8c94f9ec \ + --hash=sha256:5a854546fe8d6081cae9a1c1980862e2f0477f81117c123a82468aefc3d4db5c \ + --hash=sha256:73ae29574d19e76a3033e93e88d4bfe7decce11da45f5e3fc695dfb7899dae53 \ + --hash=sha256:7433a59ce37d376d593424e8d3587dfd4d4bf294b5e787f4b22be875af1b82a1 \ + --hash=sha256:7597afd495ece825cd0de04e237d45d32554443f32cb332e2de0e0adc08d76e1 \ + --hash=sha256:87630254a6ca33c98dcd590e02c70edf3af3b755c06d7a991421955c00f4e8c2 \ + --hash=sha256:8e59e995a417e86b11ddb66d95e975bc012290989d8f8b1696a7956b990c29ee \ + --hash=sha256:9a56672ae636de779563fe793cb6a473296f4f06e86c5e065e7a1378c4eb498f \ + --hash=sha256:adce464e726d2742275fcedf58cd2c099bc8d6daab49331fec9f59e4d6160cab \ + --hash=sha256:b28998827c363ebb445a3b5b98946a3df68ef9059ed0cd6d13c3d9b4b4b6c944 \ + --hash=sha256:bb2c76cabe94335247c562d58a54eb62088b1ae93f0417785738508d2319dd48 \ + --hash=sha256:c63a12f6c3b17305ace17529b6a2afe60808e01beb5e0b8414532f28cfdbea4c \ + --hash=sha256:cd7fc58c11afc299e2aeb11827b940fb3715ba2e5ab5a6a5693af095742e9b4c \ + --hash=sha256:ce93300534b1c282e6c8971252f8e5887d20d8669e0af3d2a06cef1d47a03e97 \ + --hash=sha256:d893c16f187c6f175cc5b84e1743cab1bc45f48b4fd52e8815e5e632eb55bb9d \ + --hash=sha256:e185783b0461ae62cf7143117e8603363dfe66820436ed29ca18c8a4010d3252 \ + --hash=sha256:f934e15b59c3073e8957ab5b027bb32b38b04bc03aa5180610b2bb6164c43b3b \ + --hash=sha256:ffc2b73e58bb44515cce14faa395c427c8e0bbdc6bac9a4e7674c7135d6ffad5 +PyQt5==5.10.1 \ + --hash=sha256:1e652910bd1ffd23a3a48c510ecad23a57a853ed26b782cd54b16658e6f271ac \ + --hash=sha256:4db7113f464c733a99fcb66c4c093a47cf7204ad3f8b3bda502efcc0839ac14b \ + --hash=sha256:9c17ab3974c1fc7bbb04cc1c9dae780522c0ebc158613f3025fccae82227b5f7 \ + --hash=sha256:f6035baa009acf45e5f460cf88f73580ad5dc0e72330029acd99e477f20a5d61 +setuptools==39.0.1 \ + --hash=sha256:8010754433e3211b9cdbbf784b50f30e80bf40fc6b05eb5f865fab83300599b8 \ + --hash=sha256:bec7badf0f60e7fc8153fac47836edc41b74e5d541d7692e614e635720d6a7c7 +SIP==4.19.8 \ + --hash=sha256:09f9a4e6c28afd0bafedb26ffba43375b97fe7207bd1a0d3513f79b7d168b331 \ + --hash=sha256:105edaaa1c8aa486662226360bd3999b4b89dd56de3e314d82b83ed0587d8783 \ + --hash=sha256:1bb10aac55bd5ab0e2ee74b3047aa2016cfa7932077c73f602a6f6541af8cd51 \ + --hash=sha256:265ddf69235dd70571b7d4da20849303b436192e875ce7226be7144ca702a45c \ + --hash=sha256:52074f7cb5488e8b75b52f34ec2230bc75d22986c7fe5cd3f2d266c23f3349a7 \ + --hash=sha256:5ff887a33839de8fc77d7f69aed0259b67a384dc91a1dc7588e328b0b980bde2 \ + --hash=sha256:74da4ddd20c5b35c19cda753ce1e8e1f71616931391caeac2de7a1715945c679 \ + --hash=sha256:7d69e9cf4f8253a3c0dfc5ba6bb9ac8087b8239851f22998e98cb35cfe497b68 \ + --hash=sha256:97bb93ee0ef01ba90f57be2b606e08002660affd5bc380776dd8b0fcaa9e093a \ + --hash=sha256:cf98150a99e43fda7ae22abe655b6f202e491d6291486548daa56cb15a2fcf85 \ + --hash=sha256:d9023422127b94d11c1a84bfa94933e959c484f2c79553c1ef23c69fe00d25f8 \ + --hash=sha256:e72955e12f4fccf27aa421be383453d697b8a44bde2cc26b08d876fd492d0174 +six==1.11.0 \ + --hash=sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9 \ + --hash=sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb +websocket-client==0.47.0 \ + --hash=sha256:188b68b14fdb2d8eb1a111f21b9ffd2dbf1dbc4e4c1d28cf2c37cdbf1dd1cae6 \ + --hash=sha256:a453dc4dfa6e0db3d8fd7738a308a88effe6240c59f3226eb93e8f020c216149 +wheel==0.31.0 \ + --hash=sha256:1ae8153bed701cb062913b72429bcf854ba824f973735427681882a688cb55ce \ + --hash=sha256:9cdc8ab2cc9c3c2e2727a4b67c22881dbb0e1c503d592992594c5e131c867107 diff --git a/contrib/deterministic-build/requirements-hw.txt b/contrib/deterministic-build/requirements-hw.txt new file mode 100644 index 00000000..88cd12e7 --- /dev/null +++ b/contrib/deterministic-build/requirements-hw.txt @@ -0,0 +1,119 @@ +btchip-python==0.1.26 \ + --hash=sha256:427d67c5b4f4709605c51dd91d5d44a2ad8f541693673817765271e4b3a1461e +certifi==2018.1.18 \ + --hash=sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296 \ + --hash=sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d +chardet==3.0.4 \ + --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \ + --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 +click==6.7 \ + --hash=sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d \ + --hash=sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b +Cython==0.28.1 \ + --hash=sha256:0a44c3645a84724d4f7f7c1126f3807cad14271f210bb1a9a15bfd330c8d20b9 \ + --hash=sha256:152ee5f345012ca3bb7cc71da2d3736ee20f52cd8476e4d49e5e25c5a4102b12 \ + --hash=sha256:15cbde95cdf6a346c63c0b38b895aa3186d0a49adcaf42b9e19c4cb0473cb921 \ + --hash=sha256:175273eb6a90af364b9b2aea74e3c3eebcde9caec02d617cd8886c0933ec3304 \ + --hash=sha256:1a434e7621ca6671ce949893fef94b13a580853ba976e729f68dda5ab270ee8a \ + --hash=sha256:1da199a5be7c486ee89b4a8bda7f00f9fd98b800d9af3a1fe3fc63e68dadea85 \ + --hash=sha256:26196ff8fe00e7c4c5815a310c368edfc1a1c8a3c90ac9220435d1b01e795cf7 \ + --hash=sha256:2b73b062658511167dde37a51acb80ae6ddea1ffa284ebdbc47a900f21e63c70 \ + --hash=sha256:2b9aa64473fefbe988e36a30915732a0e2a75ffe0f3e81a70e3f8d367c2e4119 \ + --hash=sha256:32638aefc164404ac70e5f86558cd3aece34df17db16da905abf5e664073bae4 \ + --hash=sha256:330c95c03e39835976d1410f5fa877b75fcc5c50dc146d4c02377fc719b1f8c9 \ + --hash=sha256:38b499fa317cf6939e46317457240553b13e974f08ed387523f10af26e269f6c \ + --hash=sha256:3c60caa0075aa1f1c5e10b5352d2e8bb9a18361ce9fca50fa7d4baea67804ade \ + --hash=sha256:3fc9b945541cadb5a10316e48b5e73f4b6f635b7d30156f502b66f3766545b23 \ + --hash=sha256:427299c47cfe04d97f9f09ea55570c05898a87b64caf6ddebb529b6f64e5d228 \ + --hash=sha256:4e07e619af85e7c1ec2344ecab558929bb4acbca25f8f170d07dc677e8ee413f \ + --hash=sha256:5010e048fb9791522fe626bd40137b8a847ba77a6e656bb64d6d7acdc45ece32 \ + --hash=sha256:70bc2806fc9e5affcf74c0d4fa12cba57ffb94cdfc28b975692c8df56ea86402 \ + --hash=sha256:7cdd5303121024269610236876d9f4beb6a909a1ea5d7bc48e7bbf5d8774a3f2 \ + --hash=sha256:80856aa45004514a3ff5e102bd18fbd5230d234311de1f83d4e5b97ef42f6c93 \ + --hash=sha256:996ae959ab2600b8ad4c80981afc32e89b42d0abe3234c48e960e40180459cb2 \ + --hash=sha256:b5c2e31be55bc61d3c758889d06b16d84f4fda944832fbed63c113ec2dbc5f97 \ + --hash=sha256:c39b3a042bf5ded7c8336c82b1fa817e1f46a7ef16d41d66b3d3340e7a3b60ed \ + --hash=sha256:d08f5dd2fbf7d1506c9d986a8352b2423170002ddb635b184d2a916d2b5df0d6 \ + --hash=sha256:d2b636c16931663aeb8ffb91cf871a912e66e7200755ce68aa8c502c16eb366f \ + --hash=sha256:e27e12834ac315c7d67ca697a325d42ff8395e9b82fb62c8665bb583eb0df589 \ + --hash=sha256:e312dd688b97e9f97199a8e4ba18b65db2747157630761d27193a18761b23fed \ + --hash=sha256:e47bbe74d6c87fab2e22f1580aa3e4a8e7482b4265b1fc76685fc49f90e18f99 \ + --hash=sha256:ea113ff58e96152738e646b8ee77b41d3994735df77bee0a26cd413a67e03c0f \ + --hash=sha256:ea22d79133583b5b0f856dbfda097363228ae0a3d77431deaba90634e5d4853a +ecdsa==0.13 \ + --hash=sha256:40d002cf360d0e035cf2cb985e1308d41aaa087cbfc135b2dc2d844296ea546c \ + --hash=sha256:64cf1ee26d1cde3c73c6d7d107f835fed7c6a2904aef9eac223d57ad800c43fa +hidapi==0.7.99.post21 \ + --hash=sha256:1ac170f4d601c340f2cd52fd06e85c5e77bad7ceac811a7bb54b529f7dc28c24 \ + --hash=sha256:8d3be666f464347022e2b47caf9132287885d9eacc7895314fc8fefcb4e42946 \ + --hash=sha256:b4b1f6aff0192e9be153fe07c1b7576cb7a1ff52e78e3f76d867be95301a8e87 \ + --hash=sha256:bf03f06f586ce7d8aeb697a94b7dba12dc9271aae92d7a8d4486360ff711a660 \ + --hash=sha256:c76de162937326fcd57aa399f94939ce726242323e65c15c67e183da1f6c26f7 \ + --hash=sha256:d4ad1e46aef98783a9e6274d523b8b1e766acfc3d72828cd44a337564d984cfa \ + --hash=sha256:d4b5787a04613503357606bb10e59c3e2c1114fa00ee328b838dd257f41cbd7b \ + --hash=sha256:e0be1aa6566979266a8fc845ab0e18613f4918cf2c977fe67050f5dc7e2a9a97 \ + --hash=sha256:edfb16b16a298717cf05b8c8a9ad1828b6ff3de5e93048ceccd74e6ae4ff0922 +idna==2.6 \ + --hash=sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f \ + --hash=sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4 +keepkey==4.0.2 \ + --hash=sha256:cddee60ae405841cdff789cbc54168ceaeb2282633420f2be155554c25c69138 +libusb1==1.6.4 \ + --hash=sha256:8c930d9c1d037d9c83924c82608aa6a1adcaa01ca0e4a23ee0e8e18d7eee670d +mnemonic==0.18 \ + --hash=sha256:02a7306a792370f4a0c106c2cf1ce5a0c84b9dbd7e71c6792fdb9ad88a727f1d +pbkdf2==1.3 \ + --hash=sha256:ac6397369f128212c43064a2b4878038dab78dab41875364554aaf2a684e6979 +pip==9.0.3 \ + --hash=sha256:7bf48f9a693be1d58f49f7af7e0ae9fe29fd671cde8a55e6edca3581c4ef5796 \ + --hash=sha256:c3ede34530e0e0b2381e7363aded78e0c33291654937e7373032fda04e8803e5 +protobuf==3.5.2.post1 \ + --hash=sha256:01ccd6d03449ae75b779fb5bf4ed62177d61afe3c5e6465ccf3f8b2e1a84afbe \ + --hash=sha256:1d92cc30b0b46cced33adde5853d920179eb5ea8eecdee9552502a7f29cc3f21 \ + --hash=sha256:242e4c7ae565267a8bc8b92d707177f915607ea4bd73244bec6cbf4a49b96661 \ + --hash=sha256:3b60685732bd0cbdc802dfcb6071efbcf5d927ce3127c13c33ea1a8efae3aa76 \ + --hash=sha256:3f655e1f99c3e14d56ca900af1b9a4715b691319a295cc38939d7f77eabd5e7c \ + --hash=sha256:560a38e692a69957a70ba0e5839aa67430efd63072bf91b0539dac19055694cd \ + --hash=sha256:5c1c8f6a0a68a874e3beff89255959dd80fad45870e96c88944a1b81a22dd5f5 \ + --hash=sha256:628a3bf0794a8b3cabb18db11eb67cc10e0cc6e5525d557ae7b682bb73fa2018 \ + --hash=sha256:7222d6616108b33ad6cbeff8117062a73c43cdc8fa8f64f6a322ebeb663e710e \ + --hash=sha256:76ef6ca3c50e4cfd044861586d5f1b352e0fe7f17f883df6c165bad5b4d0e10a \ + --hash=sha256:7c193e6964e752bd056735594826c5b03274ceb8f07349d3ae47d9766250ba96 \ + --hash=sha256:869e12bcfb5759e683f53ec1dd6155b7be034065431da289f0cb4510040a0799 \ + --hash=sha256:905414e5ea6cdb78d8730f66335755152b46685fcb9fc2f2134024e3ea9e8dcc \ + --hash=sha256:ac0067e3c60737865ed72bb7416e02297d229d960902802d874c0e167128c809 \ + --hash=sha256:adf716a89c9cc1891ead79a861c427071ef59172f0e11967b00565a9547b3bd0 \ + --hash=sha256:bcfa99f5a82f5eaaf6e5cee5bfdca5a1670f5740aec1d93dae170645ed1a16b0 \ + --hash=sha256:cc94079ae6cbcea5ae194464a30f3223f075e06a0446f52bca9ddbeb6e9f412a \ + --hash=sha256:d5d9edfdc5a3a01d06062d677b121081629782edf0e05ca1be14f15bb947eeee \ + --hash=sha256:e269ab7a50bf0fa6fe6a88ea7dcc7a1079ae9450d9ab9b7730ac32916d55508b \ + --hash=sha256:e7fd33a3474cbe18fd5b5620784a0fa21fcae3e402b1806e29c6b450c7f61706 +pyblake2==1.1.1 \ + --hash=sha256:11c1d9d94cbaf5a4834aadf7f57bcb29eae1d174721269f242ca891f62cd6502 \ + --hash=sha256:427e7e91d644c3b9952e84145e211e4e3197fc4a3a0dbbd87b6da6b6cfa0a0df \ + --hash=sha256:4903d64e1a24f0cf2f8b8a1e0aaab12898951112b370ab9600651a4be4387c99 \ + --hash=sha256:6886b050521aed0293b2f67a3e1da74ea6080e4be19b57d9e1ae3d6ff10e223a \ + --hash=sha256:8cc4198ce61dddd33c9e66a216fc70be04fab66d02baa79e6bdebd83f16af57e \ + --hash=sha256:8ec8e9087d13c99b354ab6d8b4cadb1758633db5946ff95a6bc7ac538b6d7b3d \ + --hash=sha256:a785faf939810dca4aef525b6f59890fdcabdef09228cb30f4d77c3021707846 \ + --hash=sha256:e51b86e685045e2f8896d581b230effb1cc69f1134e11318f3607d98fa5ba95c \ + --hash=sha256:f51051de4eb27dc63c525a562daf9ead14e3e3583f096b9b90d3a360b5ca4995 +requests==2.18.4 \ + --hash=sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b \ + --hash=sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e +rlp==0.6.0 \ + --hash=sha256:87879a0ba1479b760cee98af165de2eee95258b261faa293199f60742be96f34 +setuptools==39.0.1 \ + --hash=sha256:8010754433e3211b9cdbbf784b50f30e80bf40fc6b05eb5f865fab83300599b8 \ + --hash=sha256:bec7badf0f60e7fc8153fac47836edc41b74e5d541d7692e614e635720d6a7c7 +six==1.11.0 \ + --hash=sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9 \ + --hash=sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb +trezor==0.9.1 \ + --hash=sha256:a481191011bade98f1e9f1201e7c72a83945050657bbc90dc4ac32dc8b8b46a4 +urllib3==1.22 \ + --hash=sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b \ + --hash=sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f +wheel==0.31.0 \ + --hash=sha256:1ae8153bed701cb062913b72429bcf854ba824f973735427681882a688cb55ce \ + --hash=sha256:9cdc8ab2cc9c3c2e2727a4b67c22881dbb0e1c503d592992594c5e131c867107 diff --git a/contrib/deterministic-build/requirements.txt b/contrib/deterministic-build/requirements.txt new file mode 100644 index 00000000..8ec2501c --- /dev/null +++ b/contrib/deterministic-build/requirements.txt @@ -0,0 +1,69 @@ +certifi==2018.1.18 \ + --hash=sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296 \ + --hash=sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d +chardet==3.0.4 \ + --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \ + --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 +dnspython==1.15.0 \ + --hash=sha256:40f563e1f7a7b80dc5a4e76ad75c23da53d62f1e15e6e517293b04e1f84ead7c \ + --hash=sha256:861e6e58faa730f9845aaaa9c6c832851fbf89382ac52915a51f89c71accdd31 +ecdsa==0.13 \ + --hash=sha256:40d002cf360d0e035cf2cb985e1308d41aaa087cbfc135b2dc2d844296ea546c \ + --hash=sha256:64cf1ee26d1cde3c73c6d7d107f835fed7c6a2904aef9eac223d57ad800c43fa +idna==2.6 \ + --hash=sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f \ + --hash=sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4 +jsonrpclib-pelix==0.3.1 \ + --hash=sha256:5417b1508d5a50ec64f6e5b88907f111155d52607b218ff3ba9a777afb2e49e3 \ + --hash=sha256:bd89a6093bc4d47dc8a096197aacb827359944a4533be5193f3845f57b9f91b4 +pbkdf2==1.3 \ + --hash=sha256:ac6397369f128212c43064a2b4878038dab78dab41875364554aaf2a684e6979 +pip==9.0.3 \ + --hash=sha256:7bf48f9a693be1d58f49f7af7e0ae9fe29fd671cde8a55e6edca3581c4ef5796 \ + --hash=sha256:c3ede34530e0e0b2381e7363aded78e0c33291654937e7373032fda04e8803e5 +protobuf==3.5.2.post1 \ + --hash=sha256:01ccd6d03449ae75b779fb5bf4ed62177d61afe3c5e6465ccf3f8b2e1a84afbe \ + --hash=sha256:1d92cc30b0b46cced33adde5853d920179eb5ea8eecdee9552502a7f29cc3f21 \ + --hash=sha256:242e4c7ae565267a8bc8b92d707177f915607ea4bd73244bec6cbf4a49b96661 \ + --hash=sha256:3b60685732bd0cbdc802dfcb6071efbcf5d927ce3127c13c33ea1a8efae3aa76 \ + --hash=sha256:3f655e1f99c3e14d56ca900af1b9a4715b691319a295cc38939d7f77eabd5e7c \ + --hash=sha256:560a38e692a69957a70ba0e5839aa67430efd63072bf91b0539dac19055694cd \ + --hash=sha256:5c1c8f6a0a68a874e3beff89255959dd80fad45870e96c88944a1b81a22dd5f5 \ + --hash=sha256:628a3bf0794a8b3cabb18db11eb67cc10e0cc6e5525d557ae7b682bb73fa2018 \ + --hash=sha256:7222d6616108b33ad6cbeff8117062a73c43cdc8fa8f64f6a322ebeb663e710e \ + --hash=sha256:76ef6ca3c50e4cfd044861586d5f1b352e0fe7f17f883df6c165bad5b4d0e10a \ + --hash=sha256:7c193e6964e752bd056735594826c5b03274ceb8f07349d3ae47d9766250ba96 \ + --hash=sha256:869e12bcfb5759e683f53ec1dd6155b7be034065431da289f0cb4510040a0799 \ + --hash=sha256:905414e5ea6cdb78d8730f66335755152b46685fcb9fc2f2134024e3ea9e8dcc \ + --hash=sha256:ac0067e3c60737865ed72bb7416e02297d229d960902802d874c0e167128c809 \ + --hash=sha256:adf716a89c9cc1891ead79a861c427071ef59172f0e11967b00565a9547b3bd0 \ + --hash=sha256:bcfa99f5a82f5eaaf6e5cee5bfdca5a1670f5740aec1d93dae170645ed1a16b0 \ + --hash=sha256:cc94079ae6cbcea5ae194464a30f3223f075e06a0446f52bca9ddbeb6e9f412a \ + --hash=sha256:d5d9edfdc5a3a01d06062d677b121081629782edf0e05ca1be14f15bb947eeee \ + --hash=sha256:e269ab7a50bf0fa6fe6a88ea7dcc7a1079ae9450d9ab9b7730ac32916d55508b \ + --hash=sha256:e7fd33a3474cbe18fd5b5620784a0fa21fcae3e402b1806e29c6b450c7f61706 +pyaes==1.6.1 \ + --hash=sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f +PySocks==1.6.8 \ + --hash=sha256:3fe52c55890a248676fd69dc9e3c4e811718b777834bcaab7a8125cf9deac672 +qrcode==6.0 \ + --hash=sha256:037b0db4c93f44586e37f84c3da3f763874fcac85b2974a69a98e399ac78e1bf \ + --hash=sha256:de4ffc15065e6ff20a551ad32b6b41264f3c75275675406ddfa8e3530d154be3 +requests==2.18.4 \ + --hash=sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b \ + --hash=sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e +setuptools==39.0.1 \ + --hash=sha256:8010754433e3211b9cdbbf784b50f30e80bf40fc6b05eb5f865fab83300599b8 \ + --hash=sha256:bec7badf0f60e7fc8153fac47836edc41b74e5d541d7692e614e635720d6a7c7 +six==1.11.0 \ + --hash=sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9 \ + --hash=sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb +urllib3==1.22 \ + --hash=sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b \ + --hash=sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f +wheel==0.31.0 \ + --hash=sha256:1ae8153bed701cb062913b72429bcf854ba824f973735427681882a688cb55ce \ + --hash=sha256:9cdc8ab2cc9c3c2e2727a4b67c22881dbb0e1c503d592992594c5e131c867107 +colorama==0.3.9 \ + --hash=sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda \ + --hash=sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1 diff --git a/contrib/freeze_packages.sh b/contrib/freeze_packages.sh deleted file mode 100755 index 139fb6ee..00000000 --- a/contrib/freeze_packages.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# Run this after a new release to update dependencies - -venv_dir=~/.electrum-venv -contrib=$(dirname "$0") - -which virtualenv > /dev/null 2>&1 || { echo "Please install virtualenv" && exit 1; } - -rm $venv_dir -rf -virtualenv $venv_dir - -source $venv_dir/bin/activate - -echo "Installing dependencies" - -pushd $contrib/.. -python setup.py install -popd - -pip freeze | sed '/^Electrum/ d' > $contrib/requirements.txt - -echo "Updated requirements" diff --git a/contrib/make_download b/contrib/make_download deleted file mode 100755 index 84e4ff21..00000000 --- a/contrib/make_download +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/python2 -import re -import os - -from versions import version, version_win, version_mac, version_android, version_apk -from versions import download_template, download_page - -with open(download_template) as f: - string = f.read() - -string = string.replace("##VERSION##", version) -string = string.replace("##VERSION_WIN##", version_win) -string = string.replace("##VERSION_MAC##", version_mac) -string = string.replace("##VERSION_ANDROID##", version_android) -string = string.replace("##VERSION_APK##", version_apk) - -files = { - 'tgz': "Electrum-%s.tar.gz" % version, - 'zip': "Electrum-%s.zip" % version, - 'mac': "electrum-%s.dmg" % version_mac, - 'win': "electrum-%s.exe" % version_win, - 'win_setup': "electrum-%s-setup.exe" % version_win, - 'win_portable': "electrum-%s-portable.exe" % version_win, -} - -for k, n in files.items(): - path = "dist/%s"%n - link = "https://download.electrum.org/%s/%s"%(version,n) - if not os.path.exists(path): - os.system("wget -q %s -O %s" % (link, path)) - if not os.path.getsize(path): - os.unlink(path) - string = re.sub("
(.*?)
"%k, '', string, flags=re.DOTALL + re.MULTILINE) - continue - sigpath = path + '.asc' - siglink = link + '.asc' - if not os.path.exists(sigpath): - os.system("wget -q %s -O %s" % (siglink, sigpath)) - if not os.path.getsize(sigpath): - os.unlink(sigpath) - string = re.sub("
(.*?)
"%k, '', string, flags=re.DOTALL + re.MULTILINE) - continue - if os.system("gpg --verify %s"%sigpath) != 0: - raise BaseException(sigpath) - string = string.replace("##link_%s##"%k, link) - - -with open(download_page,'w') as f: - f.write(string) - - diff --git a/contrib/make_osx b/contrib/make_osx deleted file mode 100755 index f354e331..00000000 --- a/contrib/make_osx +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -rm -rf dist -export PYTHONHASHSEED=22 -VERSION=`git describe --tags` -pyinstaller --noconfirm --ascii --name $VERSION contrib/osx.spec -hdiutil create -fs HFS+ -volname "Electrum" -srcfolder dist/Electrum.app dist/electrum-$VERSION.dmg diff --git a/contrib/osx.spec b/contrib/osx.spec deleted file mode 100644 index 81f98bb7..00000000 --- a/contrib/osx.spec +++ /dev/null @@ -1,82 +0,0 @@ -# -*- mode: python -*- - -from PyInstaller.utils.hooks import collect_data_files, collect_submodules - -import sys -for i, x in enumerate(sys.argv): - if x == '--name': - VERSION = sys.argv[i+1] - break -else: - raise BaseException('no version') - -home = '/Users/voegtlin/electrum/' -block_cipher=None - -# see https://github.com/pyinstaller/pyinstaller/issues/2005 -hiddenimports = [] -hiddenimports += collect_submodules('trezorlib') -hiddenimports += collect_submodules('btchip') -hiddenimports += collect_submodules('keepkeylib') - -datas = [ - (home+'lib/currencies.json', 'electrum'), - (home+'lib/servers.json', 'electrum'), - (home+'lib/wordlist/english.txt', 'electrum/wordlist'), - (home+'lib/locale', 'electrum/locale'), - (home+'plugins', 'electrum_plugins'), -] -datas += collect_data_files('trezorlib') -datas += collect_data_files('btchip') -datas += collect_data_files('keepkeylib') - -# We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports -a = Analysis([home+'electrum', - home+'gui/qt/main_window.py', - home+'gui/text.py', - home+'lib/util.py', - home+'lib/wallet.py', - home+'lib/simple_config.py', - home+'lib/bitcoin.py', - home+'lib/dnssec.py', - home+'lib/commands.py', - home+'plugins/cosigner_pool/qt.py', - home+'plugins/email_requests/qt.py', - home+'plugins/trezor/client.py', - home+'plugins/trezor/qt.py', - home+'plugins/keepkey/qt.py', - home+'plugins/ledger/qt.py', - ], - datas=datas, - hiddenimports=hiddenimports, - hookspath=[]) - -# http://stackoverflow.com/questions/19055089/pyinstaller-onefile-warning-pyconfig-h-when-importing-scipy-or-scipy-signal -for d in a.datas: - if 'pyconfig' in d[0]: - a.datas.remove(d) - break - -pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) - -exe = EXE(pyz, - a.scripts, - a.binaries, - a.datas, - name='Electrum', - debug=False, - strip=False, - upx=True, - icon=home+'electrum.icns', - console=False) - -app = BUNDLE(exe, - version = VERSION, - name='Electrum.app', - icon=home+'electrum.icns', - bundle_identifier=None, - info_plist = { - 'NSHighResolutionCapable':'True' - } -) - diff --git a/contrib/requirements/requirements-hw.txt b/contrib/requirements/requirements-hw.txt new file mode 100644 index 00000000..5647f3ca --- /dev/null +++ b/contrib/requirements/requirements-hw.txt @@ -0,0 +1,4 @@ +Cython>=0.27 +trezor>=0.9.0 +keepkey +btchip-python diff --git a/contrib/requirements/requirements.txt b/contrib/requirements/requirements.txt new file mode 100644 index 00000000..227ec1cd --- /dev/null +++ b/contrib/requirements/requirements.txt @@ -0,0 +1,9 @@ +pyaes>=0.1a1 +ecdsa>=0.9 +pbkdf2 +requests +qrcode +protobuf +dnspython +jsonrpclib-pelix +PySocks>=1.6.6 diff --git a/contrib/sign-releases.py b/contrib/sign-releases.py new file mode 100755 index 00000000..978f665f --- /dev/null +++ b/contrib/sign-releases.py @@ -0,0 +1,725 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Sign releases on github, make/upload ppa to launchpad.net + +NOTE on ppa: To build a ppa you may need to install some more packages. +On ubuntu: + + sudo apt-get install devscripts libssl-dev python3-dev \ + debhelper python3-setuptools dh-python + +NOTE on apk signing: To create a keystore and sign the apk you need to install + java-8-openjdk, or java-7-openjdk on older systems. + +To create a keystore run the following command: + + mkdir ~/.jks && keytool -genkey -v -keystore ~/.jks/keystore \ + -alias electrum.z.cash -keyalg RSA -keysize 2048 \ + -validity 10000 + +Then it shows a warning about the proprietary format and a command to migrate: + + keytool -importkeystore -srckeystore ~/.jks/keystore \ + -destkeystore ~/.jks/keystore -deststoretype pkcs12 + +Manual signing: + + jarsigner -verbose \ + -tsa http://sha256timestamp.ws.symantec.com/sha256/timestamp \ + -sigalg SHA1withRSA -digestalg SHA1 \ + -sigfile zcash-electrum \ + -keystore ~/.jks/keystore \ + Electrum_Zcash-3.0.6.1-release-unsigned.apk \ + electrum.z.cash + +Zipalign from Android SDK build tools is also required (set path to bin in +settings file or with key -z). To install: + + wget http://dl.google.com/android/android-sdk_r24-linux.tgz \ + && tar xzf android-sdk_r24-linux.tgz \ + && rm android-sdk_r24-linux.tgz \ + && (while sleep 3; do echo "y"; done) \ + | android-sdk-linux/tools/android update sdk -u -a -t \ + 'tools, platform-tools-preview, build-tools-23.0.1' \ + && (while sleep 3; do echo "y"; done) \ + | android-sdk-linux/tools/android update sdk -u -a -t \ + 'tools, platform-tools, build-tools-27.0.3' + +Manual zip aligning: + + android-sdk-linux/build-tools/27.0.3/zipalign -v 4 \ + Electrum_Zcash-3.0.6.1-release-unsigned.apk \ + Electrum_Zcash-3.0.6.1-release.apk + + + +About script settings: + +Settings is read from options, then config file is read. +If setting is already set from options, then it value does +not changes. + +Config file can have one repo form or multiple repo form. + +In one repo form config settings read from root JSON object. +Keys are "repo", "keyid", "token", "count", "sign_drafts", +and others, which is corresponding to program options. + +Example: + + { + "repo": "value" + ... + } + +In multiple repo form, if root "default_repo" key is set, then code +try to read "repos" key as list and cycle through it to find suitable +repo, or if no repo is set before, then "default_repo" is used to match. +If match found, then that list object is used ad one repo form config. + +Example: + + { + "default_repo": "value" + "repos": [ + { + "repo": "value" + ... + } + ] + } +""" + +import os +import os.path +import re +import sys +import time +import getpass +import shutil +import hashlib +import tempfile +import json +import zipfile +from subprocess import check_call, CalledProcessError +from functools import cmp_to_key +from time import localtime, strftime + +try: + import click + import certifi + import gnupg + import dateutil.parser + import colorama + from colorama import Fore, Style + from github_release import (get_releases, gh_asset_download, + gh_asset_upload, gh_asset_delete) + from urllib3 import PoolManager +except ImportError as e: + print('Import error:', e) + print('To run script install required packages with the next command:\n\n' + 'pip install githubrelease python-gnupg pyOpenSSL cryptography idna' + ' certifi python-dateutil click colorama requests LinkHeader') + sys.exit(1) + +HTTP = PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where()) + +FNULL = open(os.devnull, 'w') + +HOME_DIR = os.path.expanduser('~') +CONFIG_NAME = '.sign-releases' +SEARCH_COUNT = 1 +SHA_FNAME = 'SHA256SUMS.txt' + +# make_ppa related definitions +PPA_SERIES = { + 'trusty': '14.04.1', + 'xenial': '16.04.1', + 'artful': '17.10.1', + 'bionic': '18.04.1', +} +PEP440_PUBVER_PATTERN = re.compile('^((\d+)!)?' + '((\d+)(\.\d+)*)' + '([a-zA-Z]+\d+)?' + '((\.[a-zA-Z]+\d+)*)$') +REL_NOTES_PATTERN = re.compile('^#.+?(^[^#].+?)^#.+?', re.M | re.S) +SDIST_NAME_PATTERN = re.compile('^Electrum-Zcash-(.*).tar.gz$') +SDIST_DIR_TEMPLATE = 'Electrum-Zcash-{version}' +PPA_SOURCE_NAME = 'electrum-zcash' +PPA_ORIG_NAME_TEMPLATE = '%s_{version}.orig.tar.gz' % PPA_SOURCE_NAME +CHANGELOG_TEMPLATE = """%s ({ppa_version}) {series}; urgency=medium +{changes} -- {uid} {time}""" % PPA_SOURCE_NAME +PPA_FILES_TEMPLATE = '%s_{0}{1}' % PPA_SOURCE_NAME +LP_API_URL='https://api.launchpad.net/1.0' +LP_SERIES_TEMPLATE = '%s/ubuntu/{0}' % LP_API_URL +LP_ARCHIVES_TEMPLATE = '%s/~{user}/+archive/ubuntu/{ppa}' % LP_API_URL + +# sing_apk related definitions +JKS_KEYSTORE = os.path.join(HOME_DIR, '.jks/keystore') +JKS_ALIAS = 'electrum.z.cash' +JKS_STOREPASS = 'JKS_STOREPASS' +JKS_KEYPASS = 'JKS_KEYPASS' +KEYTOOL_ARGS = ['keytool', '-list', '-storepass:env', JKS_STOREPASS] +JARSIGNER_ARGS = [ + 'jarsigner', '-verbose', + '-tsa', 'http://sha256timestamp.ws.symantec.com/sha256/timestamp', + '-sigalg', 'SHA1withRSA', '-digestalg', 'SHA1', + '-sigfile', 'zcash-electrum', + '-storepass:env', JKS_STOREPASS, + '-keypass:env', JKS_KEYPASS, +] +UNSIGNED_APK_PATTERN = re.compile('^Electrum_Zcash-(.*)-release-unsigned.apk$') +SIGNED_APK_TEMPLATE = 'Electrum_Zcash-{version}-release.apk' + + +os.environ['QUILT_PATCHES'] = 'debian/patches' + + +def pep440_to_deb(version): + """Convert PEP 440 public version to deb upstream version""" + ver_match = PEP440_PUBVER_PATTERN.match(version) + if not ver_match: + raise Exception('Version "%s" does not comply with PEP 440' % version) + + g = ver_match.group + deb_ver = '' + deb_ver += ('%s:' % g(2)) if g(1) else '' + deb_ver += g(3) + deb_ver += ('~%s' % g(6)) if g(6) else '' + deb_ver += ('%s' % g(7)) if g(7) else '' + + return deb_ver + + +def compare_published_times(a, b): + """Releases list sorting comparsion function (last published first)""" + + a = a['published_at'] + b = b['published_at'] + + if not a and not b: + return 0 + elif not a: + return -1 + elif not b: + return 1 + + a = dateutil.parser.parse(a) + b = dateutil.parser.parse(b) + + if a > b: + return -1 + elif b > a: + return 1 + else: + return 0 + + +def sha256_checksum(filename, block_size=65536): + """Gather sha256 hash on filename""" + sha256 = hashlib.sha256() + with open(filename, 'rb') as f: + for block in iter(lambda: f.read(block_size), b''): + sha256.update(block) + return sha256.hexdigest() + + +def read_config(): + """Read and parse JSON from config file from HOME dir""" + config_path = os.path.join(HOME_DIR, CONFIG_NAME) + if not os.path.isfile(config_path): + return {} + + try: + with open(config_path, 'r') as f: + data = f.read() + return json.loads(data) + except Exception as e: + print('Error: Cannot read config file:', e) + return {} + + +def get_next_ppa_num(ppa, source_package_name, ppa_upstr_version, series_name): + """Calculate next ppa num (if older ppa versions whas published earlier)""" + user, ppa_name = ppa.split('/') + archives_url = LP_ARCHIVES_TEMPLATE.format(user=user, ppa=ppa_name) + series_url = LP_SERIES_TEMPLATE.format(series_name) + query = { + 'ws.op': 'getPublishedSources', + 'distro_series': series_url, + 'order_by_date': 'true', + 'source_name': source_package_name, + } + + resp = HTTP.request('GET', archives_url, fields=query) + if resp.status != 200: + raise Exception('Launchpad API error %s %s', (resp.status, + resp.reason)) + data = json.loads(resp.data.decode('utf-8')) + entries = data['entries'] + if len(entries) == 0: + return 1 + + for e in entries: + ppa_version = e['source_package_version'] + version_match = re.match('%s-0ppa(\d+)~ubuntu' % ppa_upstr_version, + ppa_version) + if version_match: + return int(version_match.group(1)) + 1 + + return 1 + + +class ChdirTemporaryDirectory(object): + """Create tmp dir, chdir to it and remove on exit""" + def __enter__(self): + self.prev_wd = os.getcwd() + self.name = tempfile.mkdtemp() + os.chdir(self.name) + return self.name + + def __exit__(self, exc_type, exc_value, traceback): + os.chdir(self.prev_wd) + shutil.rmtree(self.name) + + +class SignApp(object): + def __init__(self, **kwargs): + """Get app settings from options, from curdir git, from config file""" + ask_passphrase = kwargs.pop('ask_passphrase', None) + self.sign_drafts = kwargs.pop('sign_drafts', False) + self.force = kwargs.pop('force', False) + self.tag_name = kwargs.pop('tag_name', None) + self.repo = kwargs.pop('repo', None) + self.ppa = kwargs.pop('ppa', None) + self.token = kwargs.pop('token', None) + self.keyid = kwargs.pop('keyid', None) + self.count = kwargs.pop('count', None) + self.dry_run = kwargs.pop('dry_run', False) + self.no_ppa = kwargs.pop('no_ppa', False) + self.verbose = kwargs.pop('verbose', False) + self.jks_keystore = kwargs.pop('jks_keystore', False) + self.jks_alias = kwargs.pop('jks_alias', False) + self.zipalign_path = kwargs.pop('zipalign_path', False) + + self.config = {} + config_data = read_config() + + default_repo = config_data.get('default_repo', None) + if default_repo: + if not self.repo: + self.repo = default_repo + + for config in config_data.get('repos', []): + config_repo = config.get('repo', None) + if config_repo and config_repo == self.repo: + self.config = config + break + else: + self.config = config_data + + if self.config: + self.repo = self.repo or self.config.get('repo', None) + self.ppa = self.ppa or self.config.get('ppa', None) + self.token = self.token or self.config.get('token', None) + self.keyid = self.keyid or self.config.get('keyid', None) + self.count = self.count or self.config.get('count', None) \ + or SEARCH_COUNT + self.sign_drafts = self.sign_drafts \ + or self.config.get('sign_drafts', False) + self.no_ppa = self.no_ppa \ + or self.config.get('no_ppa', False) + self.verbose = self.verbose or self.config.get('verbose', None) + self.jks_keystore = self.jks_keystore \ + or self.config.get('jks_keystore', JKS_KEYSTORE) + self.jks_alias = self.jks_alias \ + or self.config.get('jks_alias', JKS_ALIAS) + self.zipalign_path = self.zipalign_path \ + or self.config.get('zipalign_path', None) + + if not self.repo: + print('no repo found, exit') + sys.exit(1) + + if self.token: + os.environ['GITHUB_TOKEN'] = self.token + + if not os.environ.get('GITHUB_TOKEN', None): + print('GITHUB_TOKEN environment var not set, exit') + sys.exit(1) + + if self.keyid: + self.keyid = self.keyid.split('/')[-1] + + self.passphrase = None + self.gpg = gnupg.GPG() + + if not self.keyid: + print('no keyid set, exit') + sys.exit(1) + + keylist = self.gpg.list_keys(True, keys=[self.keyid]) + if not keylist: + print('no key with keyid %s found, exit' % self.keyid) + sys.exit(1) + + self.uid = ', '.join(keylist[0].get('uids', ['No uid found'])) + + if ask_passphrase: + while not self.passphrase: + self.read_passphrase() + elif not self.check_key(): + while not self.passphrase: + self.read_passphrase() + + if self.zipalign_path: + try: + check_call(self.zipalign_path, stderr=FNULL) + except CalledProcessError: + pass + self.read_jks_storepass() + self.read_jks_keypass() + + def read_jks_storepass(self): + """Read JKS storepass and keypass""" + while not JKS_STOREPASS in os.environ: + storepass = getpass.getpass('%sInput %s keystore password:%s ' % + (Fore.GREEN, + self.jks_keystore, + Style.RESET_ALL)) + os.environ[JKS_STOREPASS] = storepass + try: + check_call(KEYTOOL_ARGS + ['-keystore', self.jks_keystore], + stdout=FNULL, stderr=FNULL) + except CalledProcessError: + print('%sWrong keystore password%s' % + (Fore.RED, Style.RESET_ALL)) + del os.environ[JKS_STOREPASS] + + def read_jks_keypass(self): + while not JKS_KEYPASS in os.environ: + keypass = getpass.getpass('%sInput alias password for <%s> ' + '[Enter if same as for keystore]:%s ' % + (Fore.YELLOW, + self.jks_alias, + Style.RESET_ALL)) + if not keypass: + os.environ[JKS_KEYPASS] = os.environ[JKS_STOREPASS] + else: + os.environ[JKS_KEYPASS] = keypass + + with ChdirTemporaryDirectory() as tmpdir: + test_file = 'testfile.txt' + test_zipfile = 'testzip.zip' + with open(test_file, 'w') as fdw: + fdw.write('testcontent') + test_zf = zipfile.ZipFile(test_zipfile, mode='w') + test_zf.write(test_file) + test_zf.close() + + sign_args = ['-keystore', self.jks_keystore, + test_zipfile, self.jks_alias] + try: + check_call(JARSIGNER_ARGS + sign_args, stdout=FNULL) + except CalledProcessError: + print('%sWrong key alias password%s' % + (Fore.RED, Style.RESET_ALL)) + del os.environ[JKS_KEYPASS] + + def read_passphrase(self): + """Read passphrase for gpg key until check_key is passed""" + passphrase = getpass.getpass('%sInput passphrase for Key: %s %s:%s ' % + (Fore.GREEN, + self.keyid, + self.uid, + Style.RESET_ALL)) + if self.check_key(passphrase): + self.passphrase = passphrase + + def check_key(self, passphrase=None): + """Try to sign test string, and if some data signed retun True""" + signed_data = self.gpg.sign('test message to check passphrase', + keyid=self.keyid, passphrase=passphrase) + if signed_data.data and self.gpg.verify(signed_data.data).valid: + return True + print('%sWrong passphrase!%s' % (Fore.RED, Style.RESET_ALL)) + return False + + def sign_file_name(self, name, detach=True): + """Sign file with self.keyid, place signature in deteached .asc file""" + with open(name, 'rb') as fdrb: + signed_data = self.gpg.sign_file(fdrb, + keyid=self.keyid, + passphrase=self.passphrase, + detach=detach) + with open('%s.asc' % name, 'wb') as fdw: + fdw.write(signed_data.data) + + def sign_release(self, release, other_names, asc_names, is_newest_release): + """Download/sign unsigned assets, upload .asc counterparts. + Create SHA256SUMS.txt with all assets included and upload it + with SHA256SUMS.txt.asc counterpart. + """ + repo = self.repo + tag = release.get('tag_name', None) + if not tag: + print('Release have no tag name, skip release\n') + return + + with ChdirTemporaryDirectory() as tmpdir: + with open(SHA_FNAME, 'w') as fdw: + sdist_match = None + for name in other_names: + if name == SHA_FNAME: + continue + + gh_asset_download(repo, tag, name) + + if not self.no_ppa: + sdist_match = sdist_match \ + or SDIST_NAME_PATTERN.match(name) + + apk_match = UNSIGNED_APK_PATTERN.match(name) + if apk_match: + unsigned_name = name + name = self.sign_apk(unsigned_name, apk_match.group(1)) + + gh_asset_upload(repo, tag, name, dry_run=self.dry_run) + gh_asset_delete(repo, tag, unsigned_name, + dry_run=self.dry_run) + + if not '%s.asc' % name in asc_names or self.force: + self.sign_file_name(name) + + if self.force: + gh_asset_delete(repo, tag, '%s.asc' % name, + dry_run=self.dry_run) + + gh_asset_upload(repo, tag, '%s.asc' % name, + dry_run=self.dry_run) + + sumline = '%s %s\n' % (sha256_checksum(name), name) + fdw.write(sumline) + + self.sign_file_name(SHA_FNAME, detach=False) + + gh_asset_delete(repo, tag, '%s.asc' % SHA_FNAME, + dry_run=self.dry_run) + + gh_asset_upload(repo, tag, '%s.asc' % SHA_FNAME, + dry_run=self.dry_run) + + if sdist_match and is_newest_release: + self.make_ppa(sdist_match, tmpdir) + + def sign_apk(self, unsigned_name, version): + """Sign unsigned release apk""" + if not (JKS_STOREPASS in os.environ and JKS_KEYPASS in os.environ): + raise Exception('Found unsigned apk and no zipalign path set') + + name = SIGNED_APK_TEMPLATE.format(version=version) + + print('Signing apk: %s' % name) + apk_args = ['-keystore', self.jks_keystore, + unsigned_name, self.jks_alias] + if self.verbose: + check_call(JARSIGNER_ARGS + apk_args) + check_call([self.zipalign_path, '-v', '4', unsigned_name, name]) + else: + check_call(JARSIGNER_ARGS + apk_args, stdout=FNULL) + check_call([self.zipalign_path, '-v', '4', unsigned_name, name], + stdout=FNULL) + + return name + + def make_ppa(self, sdist_match, tmpdir): + """Build, sign and upload dsc to launchpad.net ppa from sdist.tar.gz""" + with ChdirTemporaryDirectory() as ppa_tmpdir: + sdist_name = sdist_match.group(0) + version = sdist_match.group(1) + ppa_upstr_version = pep440_to_deb(version) + ppa_orig_name = PPA_ORIG_NAME_TEMPLATE.format( + version=ppa_upstr_version) + series = list(map(lambda x: x[0], + sorted(PPA_SERIES.items(), key=lambda x: x[1]))) + sdist_dir = SDIST_DIR_TEMPLATE.format(version=version) + sdist_dir = os.path.join(ppa_tmpdir, sdist_dir) + debian_dir = os.path.join(sdist_dir, 'debian') + changelog_name = os.path.join(debian_dir, 'changelog') + relnotes_name = os.path.join(sdist_dir, 'RELEASE-NOTES') + + print('Found sdist: %s, version: %s' % (sdist_name, version)) + print(' Copying sdist to %s, extracting' % ppa_orig_name) + shutil.copy(os.path.join(tmpdir, sdist_name), + os.path.join(ppa_tmpdir, ppa_orig_name)) + check_call(['tar', '-xzvf', ppa_orig_name], stdout=FNULL) + + with open(relnotes_name, 'r') as rnfd: + changes = rnfd.read() + changes_match = REL_NOTES_PATTERN.match(changes) + if changes_match and len(changes_match.group(1)) > 0: + changes = changes_match.group(1).split('\n') + for i in range(len(changes)): + if changes[i] == '': + continue + elif changes[i][0] != ' ': + changes[i] = ' %s' % changes[i] + elif len(changes[i]) > 1 and changes[i][1] != ' ': + changes[i] = ' %s' % changes[i] + changes = '\n'.join(changes) + else: + changes = '\n * Porting to ppa\n\n' + + os.chdir(sdist_dir) + print(' Making PPAs for series: %s' % (', '.join(series))) + now_formatted = strftime('%a, %d %b %Y %H:%M:%S %z', localtime()) + for s in series: + ppa_num = get_next_ppa_num(self.ppa, PPA_SOURCE_NAME, + ppa_upstr_version, s) + rel_version = PPA_SERIES[s] + ppa_version = '%s-0ppa%s~ubuntu%s' % (ppa_upstr_version, + ppa_num, rel_version) + ppa_dsc = os.path.join(ppa_tmpdir, PPA_FILES_TEMPLATE.format( + ppa_version, '.dsc')) + ppa_chgs = os.path.join(ppa_tmpdir, PPA_FILES_TEMPLATE.format( + ppa_version, '_source.changes')) + changelog = CHANGELOG_TEMPLATE.format(ppa_version=ppa_version, + series=s, + changes=changes, + uid=self.uid, + time=now_formatted) + + with open(changelog_name, 'w') as chlfd: + chlfd.write(changelog) + + print(' Make %s ppa, Signing with key: %s, %s' % + (ppa_version, self.keyid, self.uid)) + if self.verbose: + check_call(['debuild', '-S']) + else: + check_call(['debuild', '-S'], stdout=FNULL) + print(' Upload %s ppa to %s' % (ppa_version, self.ppa)) + if self.dry_run: + print(' Dry run: dput ppa:%s %s' % (self.ppa, ppa_chgs)) + else: + check_call(['dput', ('ppa:%s' % self.ppa), ppa_chgs], + stdout=FNULL) + print('\n') + + def search_and_sign_unsinged(self): + """Search through last 'count' releases with assets without + .asc counterparts or releases withouth SHA256SUMS.txt.asc + """ + print('Sign releases on repo: %s' % self.repo) + print(' With key: %s, %s\n' % (self.keyid, self.uid)) + releases = get_releases(self.repo) + + if self.tag_name: + releases = [r for r in releases + if r.get('tag_name', None) == self.tag_name] + + if len(releases) == 0: + print('No release with tag "%s" found, exit' % self.tag_name) + sys.exit(1) + elif not self.sign_drafts: + releases = [r for r in releases if not r.get('draft', False)] + + # cycle through releases sorted by by publication date + releases.sort(key=cmp_to_key(compare_published_times)) + for r in releases[:self.count]: + tag_name = r.get('tag_name', 'No tag_name') + is_draft = r.get('draft', False) + is_prerelease = r.get('prerelease', False) + created_at = r.get('created_at', '') + + msg = 'Found %s%s tagged: %s, created at: %s' % ( + 'draft ' if is_draft else '', + 'prerelease' if is_prerelease else 'release', + tag_name, + created_at + ) + + if not is_draft: + msg += ', published at: %s' % r.get('published_at', '') + + print(msg) + + asset_names = [a['name'] for a in r['assets']] + + if not asset_names: + print(' No assets found, skip release\n') + continue + + asc_names = [a for a in asset_names if a.endswith('.asc')] + other_names = [a for a in asset_names if not a.endswith('.asc')] + need_to_sign = False + + if asset_names and not asc_names: + need_to_sign = True + + if not need_to_sign: + for name in other_names: + if not '%s.asc' % name in asc_names: + need_to_sign = True + break + + if not need_to_sign: + need_to_sign = '%s.asc' % SHA_FNAME not in asc_names + + if need_to_sign or self.force: + self.sign_release(r, other_names, asc_names, r==releases[0]) + else: + print(' Seems already signed, skip release\n') + + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + + +@click.command(context_settings=CONTEXT_SETTINGS) +@click.option('-a', '--jks-alias', + help='jks key alias') +@click.option('-c', '--count', type=int, + help='Number of recently published releases to sign') +@click.option('-d', '--sign-drafts', is_flag=True, + help='Sing draft releases first') +@click.option('-f', '--force', is_flag=True, + help='Sing already signed releases') +@click.option('-g', '--tag-name', + help='Sing only release tagged with tag name') +@click.option('-k', '--keyid', + help='gnupg keyid') +@click.option('-K', '--jks-keystore', + help='jks keystore path') +@click.option('-l', '--ppa', + help='PPA in format uzername/ppa') +@click.option('-L', '--no-ppa', is_flag=True, + help='Do not make launchpad ppa') +@click.option('-n', '--dry-run', is_flag=True, + help='Do not uload signed files') +@click.option('-p', '--ask-passphrase', is_flag=True, + help='Ask to enter passphrase') +@click.option('-r', '--repo', + help='Repository in format username/reponame') +@click.option('-s', '--sleep', type=int, + help='Sleep number of seconds before signing') +@click.option('-t', '--token', + help='GigHub access token, to be set as' + ' GITHUB_TOKEN environmet variable') +@click.option('-v', '--verbose', is_flag=True, + help='Make more verbose output') +@click.option('-z', '--zipalign-path', + help='zipalign path') +def main(**kwargs): + app = SignApp(**kwargs) + + sleep = kwargs.pop('sleep', None) + if (sleep): + print('Sleep for %s seconds' % sleep) + time.sleep(sleep) + + app.search_and_sign_unsinged() + + +if __name__ == '__main__': + colorama.init() + main() diff --git a/contrib/sign_packages b/contrib/sign_packages deleted file mode 100755 index d11ef5fc..00000000 --- a/contrib/sign_packages +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/python2 - -import os -import getpass - -if __name__ == '__main__': - - os.chdir("dist") - password = getpass.getpass("Password:") - for f in os.listdir('.'): - if f.endswith('asc'): - continue - os.system( "gpg --sign --armor --detach --passphrase \"%s\" %s"%(password, f) ) - - os.chdir("..") - - - diff --git a/contrib/zcash/deterministic.spec b/contrib/zcash/deterministic.spec new file mode 100644 index 00000000..ce8bc73f --- /dev/null +++ b/contrib/zcash/deterministic.spec @@ -0,0 +1,161 @@ +# -*- mode: python -*- +import sys +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + + +for i, x in enumerate(sys.argv): + if x == '--name': + cmdline_name = sys.argv[i+1] + break +else: + raise Exception('no name') + +hiddenimports = collect_submodules('trezorlib') +hiddenimports += collect_submodules('btchip') +hiddenimports += collect_submodules('keepkeylib') +hiddenimports += collect_submodules('websocket') +hiddenimports += [ + 'lib', + 'lib.base_wizard', + 'lib.plot', + 'lib.qrscanner', + 'lib.websockets', + 'gui.qt', + + 'plugins', + + 'plugins.hw_wallet.qt', + + 'plugins.audio_modem.qt', + 'plugins.cosigner_pool.qt', + 'plugins.digitalbitbox.qt', + 'plugins.email_requests.qt', + 'plugins.keepkey.qt', + 'plugins.labels.qt', + 'plugins.trezor.qt', + 'plugins.ledger.qt', + 'plugins.virtualkeyboard.qt', +] + +datas = [ + ('lib/servers.json', 'electrum_zcash'), + ('lib/servers_testnet.json', 'electrum_zcash'), + ('lib/servers_regtest.json', 'electrum_zcash'), + ('lib/currencies.json', 'electrum_zcash'), + ('lib/checkpoints.json', 'electrum_zcash'), + ('lib/locale', 'electrum_zcash/locale'), + ('lib/wordlist', 'electrum_zcash/wordlist'), + ('C:\\zbarw', '.'), +] +datas += collect_data_files('trezorlib') +datas += collect_data_files('btchip') +datas += collect_data_files('keepkeylib') + +binaries = [('C:/Python34/libusb-1.0.dll', '.')] + +# https://github.com/pyinstaller/pyinstaller/wiki/Recipe-remove-tkinter-tcl +sys.modules['FixTk'] = None +excludes = ['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'] +excludes += [ + 'PyQt5.QtCLucene', + 'PyQt5.Qt5CLucene', + 'PyQt5.QtDesigner', + 'PyQt5.QtDesignerComponents', + 'PyQt5.QtHelp', + 'PyQt5.QtLocation', + 'PyQt5.QtMultimedia', + 'PyQt5.QtMultimediaQuick_p', + 'PyQt5.QtMultimediaWidgets', + 'PyQt5.QtNetwork', + 'PyQt5.QtOpenGL', + 'PyQt5.QtPositioning', + 'PyQt5.QtPrintSupport', + 'PyQt5.QtQml', + 'PyQt5.QtQuick', + 'PyQt5.QtQuickParticles', + 'PyQt5.QtQuickWidgets', + 'PyQt5.QtSensors', + 'PyQt5.QtSerialPort', + 'PyQt5.QtSql', + 'PyQt5.Qt5Sql', + 'PyQt5.QtTest', + 'PyQt5.QtWebChannel', + 'PyQt5.QtWebKit', + 'PyQt5.QtWebKitWidgets', + 'PyQt5.QtWebSockets', + 'PyQt5.QtXml', + 'PyQt5.QtXmlPatterns', + 'PyQt5.QtWebProcess', + 'PyQt5.QtWinExtras', +] + +a = Analysis(['electrum-zcash'], + pathex=['plugins'], + hiddenimports=hiddenimports, + datas=datas, + binaries=binaries, + excludes=excludes, + runtime_hooks=['pyi_runtimehook.py']) + +# http://stackoverflow.com/questions/19055089/ +for d in a.datas: + if 'pyconfig' in d[0]: + a.datas.remove(d) + break + +# Add TOC to electrum_zcash, electrum_zcash_gui, electrum_zcash_plugins +for p in sorted(a.pure): + if p[0].startswith('lib') and p[2] == 'PYMODULE': + a.pure += [('electrum_zcash%s' % p[0][3:] , p[1], p[2])] + if p[0].startswith('gui') and p[2] == 'PYMODULE': + a.pure += [('electrum_zcash_gui%s' % p[0][3:] , p[1], p[2])] + if p[0].startswith('plugins') and p[2] == 'PYMODULE': + a.pure += [('electrum_zcash_plugins%s' % p[0][7:] , p[1], p[2])] + +pyz = PYZ(a.pure) + +exe = EXE(pyz, + a.scripts, + exclude_binaries=True, + debug=False, + strip=False, + upx=False, + console=False, + icon='icons/electrum-zcash.ico', + name=os.path.join('build\\pyi.win32\\electrum', cmdline_name)) + +# exe with console output +conexe = EXE(pyz, + a.scripts, + exclude_binaries=True, + debug=False, + strip=False, + upx=False, + console=True, + icon='icons/electrum-zcash.ico', + name=os.path.join('build\\pyi.win32\\electrum', + 'console-%s' % cmdline_name)) + +# trezorctl separate executable +tctl_a = Analysis(['C:/Python34/Scripts/trezorctl'], + hiddenimports=['pkgutil'], + excludes=excludes, + runtime_hooks=['pyi_tctl_runtimehook.py']) + +tctl_pyz = PYZ(tctl_a.pure) + +tctl_exe = EXE(tctl_pyz, + tctl_a.scripts, + exclude_binaries=True, + debug=False, + strip=False, + upx=False, + console=True, + name=os.path.join('build\\pyi.win32\\electrum', 'trezorctl.exe')) + +coll = COLLECT(exe, conexe, tctl_exe, + a.binaries, + a.datas, + strip=False, + upx=False, + name=os.path.join('dist', 'electrum-zcash')) diff --git a/contrib/build-wine/electrum.nsi b/contrib/zcash/electrum-zcash.nsi similarity index 79% rename from contrib/build-wine/electrum.nsi rename to contrib/zcash/electrum-zcash.nsi index 0a300332..7e742048 100644 --- a/contrib/build-wine/electrum.nsi +++ b/contrib/zcash/electrum-zcash.nsi @@ -1,22 +1,24 @@ ;-------------------------------- ;Include Modern UI - !include "TextFunc.nsh" ;Needed for the $GetSize fuction. I know, doesn't sound logical, it isn't. + !include "TextFunc.nsh" ;Needed for the $GetSize function. I know, doesn't sound logical, it isn't. !include "MUI2.nsh" + !include "x64.nsh" ;-------------------------------- ;Variables - !define PRODUCT_NAME "Electrum" - !define PRODUCT_WEB_SITE "https://github.com/spesmilo/electrum" + !define PRODUCT_NAME "Electrum-Zcash" + !define PRODUCT_WEB_SITE "https://github.com/zebra-lucky/electrum-zcash" !define PRODUCT_PUBLISHER "Electrum Technologies GmbH" !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" + !define BUILD_ARCH "${WINEARCH}" ;-------------------------------- ;General ;Name and file Name "${PRODUCT_NAME}" - OutFile "dist/electrum-setup.exe" + OutFile "dist/electrum-zcash-${PRODUCT_VERSION}-setup-${BUILD_ARCH}.exe" ;Default installation folder InstallDir "$PROGRAMFILES\${PRODUCT_NAME}" @@ -72,7 +74,7 @@ !define MUI_ABORTWARNING !define MUI_ABORTWARNING_TEXT "Are you sure you wish to abort the installation of ${PRODUCT_NAME}?" - !define MUI_ICON "tmp\electrum\icons\electrum.ico" + !define MUI_ICON "icons\electrum-zcash.ico" ;-------------------------------- ;Pages @@ -99,6 +101,16 @@ Function .onInit SetErrorLevel 740 ;ERROR_ELEVATION_REQUIRED Quit ${EndIf} + + ${If} ${RunningX64} + SetRegView 64 + StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCT_NAME}" + ${Else} + ${If} ${BUILD_ARCH} == "win64" + MessageBox MB_OK|MB_ICONSTOP "Can not Install 64-bit App On 32-bit OS!" + Abort + ${EndIf} + ${EndIf} FunctionEnd Section @@ -108,10 +120,10 @@ Section RMDir /r "$INSTDIR\*.*" Delete "$DESKTOP\${PRODUCT_NAME}.lnk" Delete "$SMPROGRAMS\${PRODUCT_NAME}\*.*" - + ;Files to pack into the installer - File /r "dist\electrum\*.*" - File "..\..\icons\electrum.ico" + File /r "dist\electrum-zcash\*.*" + File "icons\electrum-zcash.ico" ;Store installation folder WriteRegStr HKCU "Software\${PRODUCT_NAME}" "" $INSTDIR @@ -122,29 +134,29 @@ Section ;Create desktop shortcut DetailPrint "Creating desktop shortcut..." - CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" "" + CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\electrum-zcash-${PRODUCT_VERSION}.exe" "" ;Create start-menu items DetailPrint "Creating start-menu items..." CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}" CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0 - CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" "" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" 0 - CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME} Testnet.lnk" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" "--testnet" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" 0 + CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\electrum-zcash-${PRODUCT_VERSION}.exe" "" "$INSTDIR\electrum-zcash-${PRODUCT_VERSION}.exe" 0 + CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME} Testnet.lnk" "$INSTDIR\electrum-zcash-${PRODUCT_VERSION}.exe" "--testnet" "$INSTDIR\electrum-zcash-${PRODUCT_VERSION}.exe" 0 - ;Links bitcoin: URI's to Electrum - WriteRegStr HKCU "Software\Classes\bitcoin" "" "URL:bitcoin Protocol" - WriteRegStr HKCU "Software\Classes\bitcoin" "URL Protocol" "" - WriteRegStr HKCU "Software\Classes\bitcoin" "DefaultIcon" "$\"$INSTDIR\electrum.ico, 0$\"" - WriteRegStr HKCU "Software\Classes\bitcoin\shell\open\command" "" "$\"$INSTDIR\electrum-${PRODUCT_VERSION}.exe$\" $\"%1$\"" + ;Links zcash: URI's to Electrum + WriteRegStr HKCU "Software\Classes\zcash" "" "URL:zcash Protocol" + WriteRegStr HKCU "Software\Classes\zcash" "URL Protocol" "" + WriteRegStr HKCU "Software\Classes\zcash" "DefaultIcon" "$\"$INSTDIR\electrum-zcash.ico, 0$\"" + WriteRegStr HKCU "Software\Classes\zcash\shell\open\command" "" "$\"$INSTDIR\electrum-zcash-${PRODUCT_VERSION}.exe$\" $\"%1$\"" - ;Adds an uninstaller possibilty to Windows Uninstall or change a program section + ;Adds an uninstaller possibility to Windows Uninstall or change a program section WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\Uninstall.exe" WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" - WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\electrum.ico" + WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\electrum-zcash.ico" ;Fixes Windows broken size estimates ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 @@ -167,7 +179,7 @@ Section "Uninstall" Delete "$SMPROGRAMS\${PRODUCT_NAME}\*.*" RMDir "$SMPROGRAMS\${PRODUCT_NAME}" - DeleteRegKey HKCU "Software\Classes\bitcoin" + DeleteRegKey HKCU "Software\Classes\zcash" DeleteRegKey HKCU "Software\${PRODUCT_NAME}" DeleteRegKey HKCU "${PRODUCT_UNINST_KEY}" SectionEnd diff --git a/contrib/zcash/osx.spec b/contrib/zcash/osx.spec new file mode 100644 index 00000000..0fc60106 --- /dev/null +++ b/contrib/zcash/osx.spec @@ -0,0 +1,158 @@ +# -*- mode: python -*- +import os +import os.path +import sys +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + + +for i, x in enumerate(sys.argv): + if x == '--name': + cmdline_name = sys.argv[i+1] + break +else: + raise Exception('no name') + +PY36BINDIR = os.environ.get('PY36BINDIR') + +hiddenimports = collect_submodules('trezorlib') +hiddenimports += collect_submodules('btchip') +hiddenimports += collect_submodules('keepkeylib') +hiddenimports += collect_submodules('websocket') +hiddenimports += [ + 'lib', + 'lib.base_wizard', + 'lib.plot', + 'lib.qrscanner', + 'lib.websockets', + 'gui.qt', + + 'plugins', + + 'plugins.hw_wallet.qt', + + 'plugins.audio_modem.qt', + 'plugins.cosigner_pool.qt', + 'plugins.digitalbitbox.qt', + 'plugins.email_requests.qt', + 'plugins.keepkey.qt', + 'plugins.labels.qt', + 'plugins.trezor.qt', + 'plugins.ledger.qt', + 'plugins.virtualkeyboard.qt', +] + +datas = [ + ('lib/servers.json', 'electrum_zcash'), + ('lib/servers_testnet.json', 'electrum_zcash'), + ('lib/servers_regtest.json', 'electrum_zcash'), + ('lib/currencies.json', 'electrum_zcash'), + ('lib/checkpoints.json', 'electrum_zcash'), + ('lib/locale', 'electrum_zcash/locale'), + ('lib/wordlist', 'electrum_zcash/wordlist'), +] +datas += collect_data_files('trezorlib') +datas += collect_data_files('btchip') +datas += collect_data_files('keepkeylib') + +binaries = [('../libusb-1.0.dylib', '.')] + +# https://github.com/pyinstaller/pyinstaller/wiki/Recipe-remove-tkinter-tcl +sys.modules['FixTk'] = None +excludes = ['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'] +excludes += [ + 'PyQt5.QtCLucene', + 'PyQt5.Qt5CLucene', + 'PyQt5.QtDesigner', + 'PyQt5.QtDesignerComponents', + 'PyQt5.QtHelp', + 'PyQt5.QtLocation', + 'PyQt5.QtMultimedia', + 'PyQt5.QtMultimediaQuick_p', + 'PyQt5.QtMultimediaWidgets', + 'PyQt5.QtNetwork', + 'PyQt5.QtOpenGL', + 'PyQt5.QtPositioning', + 'PyQt5.QtPrintSupport', + 'PyQt5.QtQml', + 'PyQt5.QtQuick', + 'PyQt5.QtQuickParticles', + 'PyQt5.QtQuickWidgets', + 'PyQt5.QtSensors', + 'PyQt5.QtSerialPort', + 'PyQt5.QtSql', + 'PyQt5.Qt5Sql', + 'PyQt5.QtTest', + 'PyQt5.QtWebChannel', + 'PyQt5.QtWebKit', + 'PyQt5.QtWebKitWidgets', + 'PyQt5.QtWebSockets', + 'PyQt5.QtXml', + 'PyQt5.QtXmlPatterns', + 'PyQt5.QtWebProcess', + 'PyQt5.QtWinExtras', +] + +a = Analysis(['electrum-zcash'], + pathex=['plugins'], + hiddenimports=hiddenimports, + datas=datas, + binaries=binaries, + excludes=excludes, + runtime_hooks=['pyi_runtimehook.py']) + +# http://stackoverflow.com/questions/19055089/ +for d in a.datas: + if 'pyconfig' in d[0]: + a.datas.remove(d) + break + +# Add TOC to electrum_zcash, electrum_zcash_gui, electrum_zcash_plugins +for p in sorted(a.pure): + if p[0].startswith('lib') and p[2] == 'PYMODULE': + a.pure += [('electrum_zcash%s' % p[0][3:] , p[1], p[2])] + if p[0].startswith('gui') and p[2] == 'PYMODULE': + a.pure += [('electrum_zcash_gui%s' % p[0][3:] , p[1], p[2])] + if p[0].startswith('plugins') and p[2] == 'PYMODULE': + a.pure += [('electrum_zcash_plugins%s' % p[0][7:] , p[1], p[2])] + +pyz = PYZ(a.pure) + +exe = EXE(pyz, + a.scripts, + exclude_binaries=True, + debug=False, + strip=False, + upx=False, + console=False, + icon='icons/electrum-zcash.ico', + name=os.path.join('build/electrum-zcash/electrum-zcash', cmdline_name)) + +# trezorctl separate bin +tctl_a = Analysis([os.path.join(PY36BINDIR, 'trezorctl')], + hiddenimports=['pkgutil'], + excludes=excludes, + runtime_hooks=['pyi_tctl_runtimehook.py']) + +tctl_pyz = PYZ(tctl_a.pure) + +tctl_exe = EXE(tctl_pyz, + tctl_a.scripts, + exclude_binaries=True, + debug=False, + strip=False, + upx=False, + console=True, + name=os.path.join('build/electrum-zcash/electrum-zcash', 'trezorctl.bin')) + +coll = COLLECT(exe, tctl_exe, + a.binaries, + a.datas, + strip=False, + upx=False, + name=os.path.join('dist', 'electrum-zcash')) + +app = BUNDLE(coll, + name=os.path.join('dist', 'Electrum-Zcash.app'), + appname="Electrum-Zcash", + icon='electrum-zcash.icns', + version = 'ELECTRUM_VERSION') diff --git a/contrib/zcash/pyi_runtimehook.py b/contrib/zcash/pyi_runtimehook.py new file mode 100644 index 00000000..23ee14ad --- /dev/null +++ b/contrib/zcash/pyi_runtimehook.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +"""PyInstaller runtime hook""" +import imp +import sys +import pkgutil + + +_old_find_module = imp.find_module +def _new_find_module(name, *args, **kwargs): + if name in ['lib', 'gui', 'plugins']: + return (None, name, ('', '', 5)) + else: + return _old_find_module(name, *args, **kwargs) +imp.find_module = _new_find_module + + +_old_load_module = imp.load_module +def _new_load_module(name, file, pathname, description): + if pathname in ['lib', 'gui', 'plugins']: + return __import__(name) + else: + return _old_load_module(name, file, pathname, description) +imp.load_module = _new_load_module + + +PLUGINS_PREFIX = 'electrum_zcash_plugins' + +KEYSTORE_PLUGINS = [ + 'hw_wallet', + 'digitalbitbox', + 'keepkey', + 'ledger', + 'trezor', +] + +OTHER_PLUGINS= [ + 'audio_modem', + 'cosigner_pool', + 'email_requests', + 'labels', + 'virtualkeyboard', +] + +OTHER_PLUGINS = list(map(lambda p: '%s.%s' % (PLUGINS_PREFIX, p), OTHER_PLUGINS)) + +PLUGINS = KEYSTORE_PLUGINS + OTHER_PLUGINS + + +class PluginsImporter(object): + def find_module(self, name): + return self + + def load_module(self, name): + if name in KEYSTORE_PLUGINS: + return getattr(__import__('%s.%s' % (PLUGINS_PREFIX, name)), name) + elif name in OTHER_PLUGINS: + return getattr(__import__(name), name.split('.')[-1]) + elif name.endswith('.qt'): + split = name.split('.') + if split[0] != split[1]: + plugin_module = getattr(__import__(name), split[-2]) + return getattr(plugin_module, 'qt') + else: + path = '.'.join(split[1:]) + plugin_module = getattr(__import__(path), split[-2]) + return getattr(plugin_module, 'qt') + else: + raise Exception('Can not import %s' % name) + + +_old_find_loader = pkgutil.find_loader +def _new_find_loader(fullname): + if fullname.startswith('%s.' % PLUGINS_PREFIX): + return PluginsImporter() + else: + return _old_find_loader(fullname) +pkgutil.find_loader = _new_find_loader + + +_old_iter_modules = pkgutil.iter_modules +def _new_iter_modules(path=None, prefix=''): + if path and len(path) == 1 and path[0].endswith(PLUGINS_PREFIX): + for p in PLUGINS: + yield PluginsImporter(), p, True + else: + for loader, name, ispkg in _old_iter_modules(path, prefix): + yield loader, name, ispkg +pkgutil.iter_modules = _new_iter_modules diff --git a/contrib/zcash/pyi_tctl_runtimehook.py b/contrib/zcash/pyi_tctl_runtimehook.py new file mode 100644 index 00000000..942a5698 --- /dev/null +++ b/contrib/zcash/pyi_tctl_runtimehook.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +"""PyInstaller runtime hook for trezorctl""" +from sys import exit diff --git a/contrib/requirements.txt b/contrib/zcash/requirements.txt similarity index 93% rename from contrib/requirements.txt rename to contrib/zcash/requirements.txt index 52fada94..28a2c6f8 100644 --- a/contrib/requirements.txt +++ b/contrib/zcash/requirements.txt @@ -12,3 +12,4 @@ qrcode==5.3 requests==2.18.4 six==1.11.0 urllib3==1.22 +x11_hash==1.4 diff --git a/contrib/zcash/travis/Dockerfile-kivy b/contrib/zcash/travis/Dockerfile-kivy new file mode 100644 index 00000000..7f5518ae --- /dev/null +++ b/contrib/zcash/travis/Dockerfile-kivy @@ -0,0 +1,119 @@ +FROM ubuntu:16.04 +LABEL maintainer "Andriy Khavryuchenko " + +RUN dpkg --add-architecture i386 \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + language-pack-en build-essential ccache git \ + libncurses5:i386 libstdc++6:i386 libgtk2.0-0:i386 \ + libpangox-1.0-0:i386 libpangoxft-1.0-0:i386 libidn11:i386 \ + openjdk-8-jdk unzip zlib1g-dev zlib1g:i386 \ + python3-dev python3-kivy \ + wget vim less autoconf automake libtool \ + ffmpeg \ + libsdl2-dev \ + libsdl2-image-dev \ + libsdl2-mixer-dev \ + libsdl2-ttf-dev \ + libportmidi-dev \ + libswscale-dev \ + libavformat-dev \ + libavcodec-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN wget https://bootstrap.pypa.io/get-pip.py && python3 get-pip.py \ + && pip3 install --upgrade setuptools cython==0.21.2 Pillow + +RUN git config --global user.email "buildozer@example.com" \ + && git config --global user.name "Buildozer" + +RUN adduser --disabled-password --gecos '' buildozer && mkdir /home/buildozer/build + +RUN cd /opt \ + && git clone https://github.com/kivy/python-for-android \ + && cd python-for-android \ + && git remote add agilewalker https://github.com/agilewalker/python-for-android \ + && git fetch --all \ + && git checkout 93759f36ba45c7bbe0456a4b3e6788622924cbac \ + && git merge -m 'merge1' a2fb5ecbc09c4847adbcfd03c6b1ca62b3d09b8d \ + && cd /opt \ + && git clone https://github.com/kivy/buildozer \ + && cd buildozer \ + && python3 setup.py install \ + && chown -R buildozer.buildozer /opt + +RUN cd /opt \ + && wget http://archive.apache.org/dist/ant/binaries/apache-ant-1.9.11-bin.tar.gz \ + && tar xzf apache-ant-1.9.11-bin.tar.gz \ + && rm apache-ant-1.9.11-bin.tar.gz \ + && chown -R buildozer.buildozer /opt + +RUN cd /opt \ + && wget https://www.crystax.net/download/crystax-ndk-10.3.2-linux-x86_64.tar.xz \ + && tar xJf crystax-ndk-10.3.2-linux-x86_64.tar.xz \ + && rm crystax-ndk-10.3.2-linux-x86_64.tar.xz \ + && rm -rf \ + crystax-ndk-10.3.2/platforms/android-*/arch-mips* \ + crystax-ndk-10.3.2/platforms/android-*/arch-x86* \ + crystax-ndk-10.3.2/sources/boost/1.59.0/libs/mips* \ + crystax-ndk-10.3.2/sources/crystax/src/math/mips* \ + crystax-ndk-10.3.2/sources/crystax/src/include/crystax/mips* \ + crystax-ndk-10.3.2/sources/crystax/libs/mips* \ + crystax-ndk-10.3.2/sources/crystax/include/crystax/mips* \ + crystax-ndk-10.3.2/sources/libjpeg-turbo/1.4.2/libs/mips* \ + crystax-ndk-10.3.2/sources/python/2.7/libs/mips* \ + crystax-ndk-10.3.2/sources/python/3.5/libs/mips* \ + crystax-ndk-10.3.2/sources/icu/56.1/libs/mips* \ + crystax-ndk-10.3.2/sources/libjpeg/9a/libs/mips* \ + crystax-ndk-10.3.2/sources/objc/gnustep-libobjc2/libs/mips* \ + crystax-ndk-10.3.2/sources/objc/cocotron/0.1.0/frameworks/mips* \ + crystax-ndk-10.3.2/sources/sqlite/3/libs/mips* \ + crystax-ndk-10.3.2/sources/android/compiler-rt/libs/mips* \ + crystax-ndk-10.3.2/sources/android/gccunwind/libs/mips* \ + crystax-ndk-10.3.2/sources/libtiff/4.0.6/libs/mips* \ + crystax-ndk-10.3.2/sources/libpng/1.6.19/libs/mips* \ + crystax-ndk-10.3.2/sources/boost/1.59.0/libs/x86* \ + crystax-ndk-10.3.2/sources/crystax/src/math/x86* \ + crystax-ndk-10.3.2/sources/crystax/src/include/crystax/x86* \ + crystax-ndk-10.3.2/sources/crystax/libs/x86* \ + crystax-ndk-10.3.2/sources/crystax/include/crystax/x86* \ + crystax-ndk-10.3.2/sources/libjpeg-turbo/1.4.2/libs/x86* \ + crystax-ndk-10.3.2/sources/python/2.7/libs/x86* \ + crystax-ndk-10.3.2/sources/python/3.5/libs/x86* \ + crystax-ndk-10.3.2/sources/icu/56.1/libs/x86* \ + crystax-ndk-10.3.2/sources/libjpeg/9a/libs/x86* \ + crystax-ndk-10.3.2/sources/objc/gnustep-libobjc2/libs/x86* \ + crystax-ndk-10.3.2/sources/objc/cocotron/0.1.0/frameworks/x86* \ + crystax-ndk-10.3.2/sources/sqlite/3/libs/x86* \ + crystax-ndk-10.3.2/sources/android/compiler-rt/libs/x86* \ + crystax-ndk-10.3.2/sources/android/gccunwind/libs/x86* \ + crystax-ndk-10.3.2/sources/libtiff/4.0.6/libs/x86* \ + crystax-ndk-10.3.2/sources/libpng/1.6.19/libs/x86* \ + crystax-ndk-10.3.2/sources/cxx-stl/llvm-libc++/3.6/libs/x86* \ + crystax-ndk-10.3.2/sources/cxx-stl/llvm-libc++/3.6/libs/mips* \ + crystax-ndk-10.3.2/sources/cxx-stl/llvm-libc++/3.7/libs/x86* \ + crystax-ndk-10.3.2/sources/cxx-stl/llvm-libc++/3.7/libs/mips* \ + crystax-ndk-10.3.2/sources/cxx-stl/gnu-libstdc++/4.9/libs/x86* \ + crystax-ndk-10.3.2/sources/cxx-stl/gnu-libstdc++/4.9/libs/mips* \ + crystax-ndk-10.3.2/sources/cxx-stl/gnu-libstdc++/5/libs/x86* \ + crystax-ndk-10.3.2/sources/cxx-stl/gnu-libstdc++/5/libs/mips* \ + && chown -R buildozer.buildozer /opt/crystax-ndk-10.3.2 + +RUN cd /opt \ + && wget http://dl.google.com/android/android-sdk_r24-linux.tgz \ + && tar xzf android-sdk_r24-linux.tgz \ + && rm android-sdk_r24-linux.tgz \ + && (while sleep 3; do echo "y"; done) \ + | android-sdk-linux/tools/android update sdk -u -a -t \ + 'tools, platform-tools-preview, build-tools-23.0.1' \ + && (while sleep 3; do echo "y"; done) \ + | android-sdk-linux/tools/android update sdk -u -a -t \ + 'tools, platform-tools, build-tools-27.0.3' \ + && (while sleep 3; do echo "y"; done) \ + | android-sdk-linux/tools/android update sdk -u -a -t \ + 'android-19,extra-android-m2repository' \ + && chown -R buildozer.buildozer /opt/android-sdk-linux + +USER buildozer + +WORKDIR /home/buildozer/build diff --git a/contrib/zcash/travis/Dockerfile-linux b/contrib/zcash/travis/Dockerfile-linux new file mode 100644 index 00000000..93de86dc --- /dev/null +++ b/contrib/zcash/travis/Dockerfile-linux @@ -0,0 +1,7 @@ +FROM debian:stretch-slim +LABEL maintainer "Andriy Khavryuchenko " + +RUN apt-get update -y \ + && apt-get install -y python3-pip pyqt5-dev-tools \ + gettext python3-pycurl python3-requests \ + && rm -rf /var/lib/apt/lists/* diff --git a/contrib/zcash/travis/Dockerfile-wine b/contrib/zcash/travis/Dockerfile-wine new file mode 100644 index 00000000..96630112 --- /dev/null +++ b/contrib/zcash/travis/Dockerfile-wine @@ -0,0 +1,87 @@ +FROM debian:stretch-slim +LABEL maintainer "Andriy Khavryuchenko " + +USER root +WORKDIR /root + +RUN dpkg --add-architecture i386 \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + wine-development wine32-development wine64-development libwine-development libwine-development:i386 \ + cabextract xauth xvfb wget ca-certificates zip unzip p7zip-full \ + && wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks \ + && chmod +x winetricks && mv winetricks /usr/local/bin \ + && rm -rf /var/lib/apt/lists/* + +ENV WINEPATH c:/git/cmd +ENV WINEDEBUG -all +ENV WINEPREFIX /root/.wine-32 +ENV WINEARCH win32 +ENV PYHOME $WINEPREFIX/drive_c/Python34 + +RUN echo 'download and install 32-bit Python/mingwpy/pywin32/PyQt/git/NSIS/PyInstaller' \ + && wineboot -i \ + && xvfb-run -a winetricks -q vcrun2010 \ + \ + && wget -nv -O python.msi https://www.python.org/ftp/python/3.4.4/python-3.4.4.msi \ + && msiexec /q /i python.msi && rm python.msi \ + \ + && wget -nv -O libusb.7z https://prdownloads.sourceforge.net/project/libusb/libusb-1.0/libusb-1.0.22/libusb-1.0.22.7z?download \ + && 7z x -olibusb libusb.7z -aos && rm libusb.7z \ + && cp libusb/MS32/dll/libusb-1.0.dll $PYHOME/ \ + \ + && wine pip install -i https://pypi.anaconda.org/carlkl/simple mingwpy \ + && /bin/echo -e '[build]\ncompiler=mingw32\n' > $PYHOME/Lib/distutils/distutils.cfg \ + \ + && wget -nv -O pywin32.exe https://github.com/mhammond/pywin32/releases/download/b221/pywin32-221.win32-py3.4.exe \ + && unzip -qq -d pywin32 pywin32.exe; echo && rm pywin32.exe \ + && cp -r pywin32/PLATLIB/* $PYHOME/Lib/site-packages/ \ + && cp -r pywin32/SCRIPTS/* $PYHOME/Scripts/ && rm -rf pywin32 \ + && wine python $PYHOME/Scripts/pywin32_postinstall.py -install \ + \ + && wget -nv -O PyQt.exe "https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.5.1/PyQt5-5.5.1-gpl-Py3.4-Qt5.5.1-x32.exe/download" \ + && wine PyQt.exe /S && rm PyQt.exe \ + \ + && wget -nv -O git.zip https://github.com/git-for-windows/git/releases/download/v2.16.3.windows.1/MinGit-2.16.3-32-bit.zip \ + && unzip -qq -d git git.zip && rm git.zip && mv git $WINEPREFIX/drive_c/ \ + \ + && wget -nv -O nsis.exe "https://sourceforge.net/projects/nsis/files/NSIS%202/2.51/nsis-2.51-setup.exe/download" \ + && wine nsis.exe /S && rm nsis.exe \ + \ + && wine pip install PyInstaller==3.2.1 \ + && rm -rf /tmp/.wine-0 + + +ENV WINEPREFIX /root/.wine-64 +ENV WINEARCH win64 +ENV PYHOME $WINEPREFIX/drive_c/Python34 + +RUN echo 'download and install 64-bit Python/mingwpy/pywin32/PyQt/git/NSIS/PyInstaller' \ + && wineboot -i \ + && xvfb-run -a winetricks -q vcrun2010 \ + \ + && wget -nv -O python.msi https://www.python.org/ftp/python/3.4.4/python-3.4.4.amd64.msi \ + && msiexec /q /i python.msi && rm python.msi \ + \ + && cp libusb/MS64/dll/libusb-1.0.dll $PYHOME/ && rm -rf libusb \ + \ + && wine pip install -i https://pypi.anaconda.org/carlkl/simple mingwpy \ + && /bin/echo -e '[build]\ncompiler=mingw32\n' > $PYHOME/Lib/distutils/distutils.cfg \ + \ + && wget -nv -O pywin32.exe https://github.com/mhammond/pywin32/releases/download/b221/pywin32-221.win-amd64-py3.4.exe \ + && unzip -qq -d pywin32 pywin32.exe; echo && rm pywin32.exe \ + && cp -r pywin32/PLATLIB/* $PYHOME/Lib/site-packages/ \ + && cp -r pywin32/SCRIPTS/* $PYHOME/Scripts/ && rm -rf pywin32 \ + && wine python $PYHOME/Scripts/pywin32_postinstall.py -install \ + \ + && wget -nv -O PyQt.exe "https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.5.1/PyQt5-5.5.1-gpl-Py3.4-Qt5.5.1-x64.exe/download" \ + && wine PyQt.exe /S && rm PyQt.exe \ + \ + && wget -nv -O git.zip https://github.com/git-for-windows/git/releases/download/v2.16.3.windows.1/MinGit-2.16.3-64-bit.zip \ + && unzip -qq -d git git.zip && rm git.zip && mv git $WINEPREFIX/drive_c/ \ + \ + && wget -nv -O nsis.exe "https://sourceforge.net/projects/nsis/files/NSIS%202/2.51/nsis-2.51-setup.exe/download" \ + && wine nsis.exe /S && rm nsis.exe \ + \ + && wine pip install PyInstaller==3.2.1 \ + && rm -rf /tmp/.wine-0 diff --git a/contrib/zcash/travis/before_install-linux-apk.sh b/contrib/zcash/travis/before_install-linux-apk.sh new file mode 100755 index 00000000..55aab552 --- /dev/null +++ b/contrib/zcash/travis/before_install-linux-apk.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -ev + +if [[ -z $TRAVIS_TAG ]]; then + echo TRAVIS_TAG unset, exiting + exit 1 +fi + +docker pull zebralucky/electrum-dash-winebuild:Linux +docker pull zebralucky/electrum-dash-winebuild:Kivy diff --git a/contrib/zcash/travis/before_install-linux.sh b/contrib/zcash/travis/before_install-linux.sh new file mode 100755 index 00000000..80e502bc --- /dev/null +++ b/contrib/zcash/travis/before_install-linux.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -ev + +if [[ -z $TRAVIS_TAG ]]; then + echo TRAVIS_TAG unset, exiting + exit 1 +fi + +docker pull zebralucky/electrum-dash-winebuild:Linux +docker pull zebralucky/electrum-dash-winebuild:Wine diff --git a/contrib/zcash/travis/before_install-osx.sh b/contrib/zcash/travis/before_install-osx.sh new file mode 100755 index 00000000..16d2dfd6 --- /dev/null +++ b/contrib/zcash/travis/before_install-osx.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -ev + +if [[ -z $TRAVIS_TAG ]]; then + echo TRAVIS_TAG unset, exiting + exit 1 +fi + +cd build + +brew update +brew install zebra-lucky/qt5/qt5 +brew install gettext + +curl -O https://www.python.org/ftp/python/3.6.5/python-3.6.5-macosx10.6.pkg +curl -O https://bootstrap.pypa.io/get-pip.py +sudo installer -pkg python-3.6.5-macosx10.6.pkg -target / +sudo python3 get-pip.py + +mkdir libusb +curl https://homebrew.bintray.com/bottles/libusb-1.0.22.el_capitan.bottle.tar.gz | tar xz --directory libusb +cp libusb/libusb/1.0.22/lib/libusb-1.0.dylib . + +sudo pip3 install SIP==4.19.8 +sudo pip3 install PyQt5==5.7.1 +sudo pip3 install Cython==0.28.1 +sudo pip3 install PyInstaller==3.3.1 diff --git a/contrib/zcash/travis/build_linux.sh b/contrib/zcash/travis/build_linux.sh new file mode 100755 index 00000000..7cedcb71 --- /dev/null +++ b/contrib/zcash/travis/build_linux.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +pyrcc5 icons.qrc -o gui/qt/icons_rc.py +./contrib/make_locale +./contrib/make_packages +mv contrib/packages . +python3 setup.py sdist --format=zip,gztar diff --git a/contrib/zcash/travis/build_wine.sh b/contrib/zcash/travis/build_wine.sh new file mode 100755 index 00000000..cd0e5763 --- /dev/null +++ b/contrib/zcash/travis/build_wine.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +source ./contrib/zcash/travis/electrum_zcash_version_env.sh; +echo wine build version is $ELECTRUM_ZCASH_VERSION + +mv /opt/zbarw $WINEPREFIX/drive_c/ +cd $WINEPREFIX/drive_c/electrum-zcash + +rm -rf build +rm -rf dist/electrum-zcash + +cp contrib/zcash/deterministic.spec . +cp contrib/zcash/pyi_runtimehook.py . +cp contrib/zcash/pyi_tctl_runtimehook.py . + +wine pip install --upgrade pip +export PYINSTALLER_TAG=dev180610 +wget https://github.com/zebra-lucky/pyinstaller/archive/$PYINSTALLER_TAG.tar.gz +wine pip install $PYINSTALLER_TAG.tar.gz +rm $PYINSTALLER_TAG.tar.gz + +wine pip install eth-hash==0.1.2 +wine pip install -r contrib/zcash/requirements.txt + +wine pip install x11_hash +wine pip install cython +wine pip install hidapi +wine pip install pycryptodomex==3.6.0 +wine pip install btchip-python==0.1.26 +wine pip install keepkey==4.0.2 +wine pip install trezor==0.9.1 + +mkdir $WINEPREFIX/drive_c/Qt +ln -s $PYHOME/Lib/site-packages/PyQt5/ $WINEPREFIX/drive_c/Qt/5.5.1 + +wine pyinstaller -y \ + --name electrum-zcash-$ELECTRUM_ZCASH_VERSION.exe \ + deterministic.spec + +if [[ $WINEARCH == win32 ]]; then + NSIS_EXE="$WINEPREFIX/drive_c/Program Files/NSIS/makensis.exe" +else + NSIS_EXE="$WINEPREFIX/drive_c/Program Files (x86)/NSIS/makensis.exe" +fi + +wine "$NSIS_EXE" /NOCD -V3 \ + /DPRODUCT_VERSION=$ELECTRUM_ZCASH_VERSION \ + /DWINEARCH=$WINEARCH \ + contrib/zcash/electrum-zcash.nsi diff --git a/contrib/zcash/travis/electrum_zcash_version_env.sh b/contrib/zcash/travis/electrum_zcash_version_env.sh new file mode 100755 index 00000000..79cc4f57 --- /dev/null +++ b/contrib/zcash/travis/electrum_zcash_version_env.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +VERSION_STRING=(`grep ELECTRUM_VERSION lib/version.py`) +ELECTRUM_ZCASH_VERSION=${VERSION_STRING[2]} +ELECTRUM_ZCASH_VERSION=${ELECTRUM_ZCASH_VERSION#\'} +ELECTRUM_ZCASH_VERSION=${ELECTRUM_ZCASH_VERSION%\'} +DOTS=`echo $ELECTRUM_ZCASH_VERSION | grep -o "\." | wc -l` +if [[ $DOTS -lt 3 ]]; then + ELECTRUM_ZCASH_APK_VERSION=$ELECTRUM_ZCASH_VERSION.0 +else + ELECTRUM_ZCASH_APK_VERSION=$ELECTRUM_ZCASH_VERSION +fi +export ELECTRUM_ZCASH_VERSION +export ELECTRUM_ZCASH_APK_VERSION diff --git a/contrib/zcash/travis/travis-build-linux-apk.sh b/contrib/zcash/travis/travis-build-linux-apk.sh new file mode 100755 index 00000000..33daa83b --- /dev/null +++ b/contrib/zcash/travis/travis-build-linux-apk.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -ev + +if [[ -z $TRAVIS_TAG ]]; then + echo TRAVIS_TAG unset, exiting + exit 1 +fi + +BUILD_REPO_URL=https://github.com/zebra-lucky/electrum-zcash + +cd build + +git clone --branch $TRAVIS_TAG $BUILD_REPO_URL electrum-zcash + +docker run --rm \ + -v $(pwd):/opt \ + -w /opt/electrum-zcash \ + -t zebralucky/electrum-dash-winebuild:Linux /opt/build_linux.sh + +sudo find . -name '*.po' -delete +sudo find . -name '*.pot' -delete + +sudo chown -R 1000 electrum-zcash + +docker run --rm \ + -v $(pwd)/electrum-zcash:/home/buildozer/build \ + -t zebralucky/electrum-dash-winebuild:Kivy bash -c \ + 'rm -rf packages && ./contrib/make_packages && ./contrib/make_apk' diff --git a/contrib/zcash/travis/travis-build-linux.sh b/contrib/zcash/travis/travis-build-linux.sh new file mode 100755 index 00000000..8ad9ae57 --- /dev/null +++ b/contrib/zcash/travis/travis-build-linux.sh @@ -0,0 +1,53 @@ +#!/bin/bash +set -ev + +if [[ -z $TRAVIS_TAG ]]; then + echo TRAVIS_TAG unset, exiting + exit 1 +fi + +BUILD_REPO_URL=https://github.com/zebra-lucky/electrum-zcash + +cd build + +git clone --branch $TRAVIS_TAG $BUILD_REPO_URL electrum-zcash + +docker run --rm \ + -v $(pwd):/opt \ + -w /opt/electrum-zcash \ + -t zebralucky/electrum-dash-winebuild:Linux /opt/build_linux.sh + +sudo find . -name '*.po' -delete +sudo find . -name '*.pot' -delete + +export WINEARCH=win32 +export WINEPREFIX=/root/.wine-32 +export PYHOME=$WINEPREFIX/drive_c/Python34 + +wget https://github.com/zebra-lucky/zbarw/releases/download/20180620/zbarw-zbarcam-0.10-win32.zip +unzip zbarw-zbarcam-0.10-win32.zip && rm zbarw-zbarcam-0.10-win32.zip + +docker run --rm \ + -e WINEARCH=$WINEARCH \ + -e WINEPREFIX=$WINEPREFIX \ + -e PYHOME=$PYHOME \ + -v $(pwd):/opt \ + -v $(pwd)/electrum-zcash/:$WINEPREFIX/drive_c/electrum-zcash \ + -w /opt/electrum-zcash \ + -t zebralucky/electrum-dash-winebuild:Wine /opt/build_wine.sh + +export WINEARCH=win64 +export WINEPREFIX=/root/.wine-64 +export PYHOME=$WINEPREFIX/drive_c/Python34 + +wget https://github.com/zebra-lucky/zbarw/releases/download/20180620/zbarw-zbarcam-0.10-win64.zip +unzip zbarw-zbarcam-0.10-win64.zip && rm zbarw-zbarcam-0.10-win64.zip + +docker run --rm \ + -e WINEARCH=$WINEARCH \ + -e WINEPREFIX=$WINEPREFIX \ + -e PYHOME=$PYHOME \ + -v $(pwd):/opt \ + -v $(pwd)/electrum-zcash/:$WINEPREFIX/drive_c/electrum-zcash \ + -w /opt/electrum-zcash \ + -t zebralucky/electrum-dash-winebuild:Wine /opt/build_wine.sh diff --git a/contrib/zcash/travis/travis-build-osx.sh b/contrib/zcash/travis/travis-build-osx.sh new file mode 100755 index 00000000..00e3242a --- /dev/null +++ b/contrib/zcash/travis/travis-build-osx.sh @@ -0,0 +1,49 @@ +#!/bin/bash +set -ev + +if [[ -z $TRAVIS_TAG ]]; then + echo TRAVIS_TAG unset, exiting + exit 1 +fi + +BUILD_REPO_URL=https://github.com/zebra-lucky/electrum-zcash + +cd build + +git clone --branch $TRAVIS_TAG $BUILD_REPO_URL electrum-zcash + +cd electrum-zcash + +export PY36BINDIR=/Library/Frameworks/Python.framework/Versions/3.6/bin/ +export PATH=$PATH:$PY36BINDIR +source ./contrib/zcash/travis/electrum_zcash_version_env.sh; +echo wine build version is $ELECTRUM_ZCASH_VERSION + +sudo pip3 install --upgrade pip +sudo pip3 install -r contrib/deterministic-build/requirements.txt +sudo pip3 install \ + x11_hash>=1.4 \ + pycryptodomex==3.6.0 \ + btchip-python==0.1.26 \ + keepkey==4.0.2 \ + trezor==0.9.1 + +pyrcc5 icons.qrc -o gui/qt/icons_rc.py + +export PATH="/usr/local/opt/gettext/bin:$PATH" +./contrib/make_locale +find . -name '*.po' -delete +find . -name '*.pot' -delete + +cp contrib/zcash/osx.spec . +cp contrib/zcash/pyi_runtimehook.py . +cp contrib/zcash/pyi_tctl_runtimehook.py . + +pyinstaller \ + -y \ + --name electrum-zcash-$ELECTRUM_ZCASH_VERSION.bin \ + osx.spec + +sudo hdiutil create -fs HFS+ -volname "Electrum-Zcash" \ + -srcfolder dist/Electrum-Zcash.app \ + dist/electrum-zcash-$ELECTRUM_ZCASH_VERSION-macosx.dmg