mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 17:47:31 +00:00
Rebase 3.3.8
This commit is contained in:
parent
d97c635d28
commit
48a9c7f9dc
8 changed files with 374 additions and 157 deletions
11
MANIFEST.in
11
MANIFEST.in
|
@ -1,6 +1,5 @@
|
|||
include LICENCE RELEASE-NOTES AUTHORS
|
||||
include README.rst
|
||||
include electrum.conf.sample
|
||||
include electrum.desktop
|
||||
include *.py
|
||||
include run_electrum
|
||||
|
@ -8,11 +7,15 @@ include contrib/requirements/requirements.txt
|
|||
include contrib/requirements/requirements-hw.txt
|
||||
recursive-include packages *.py
|
||||
recursive-include packages cacert.pem
|
||||
include icons.qrc
|
||||
graft icons
|
||||
|
||||
graft electrum
|
||||
prune electrum/tests
|
||||
graft contrib/udev
|
||||
|
||||
exclude electrum/*.so
|
||||
exclude electrum/*.so.0
|
||||
|
||||
global-exclude __pycache__
|
||||
global-exclude *.py[co]
|
||||
global-exclude *.py[co~]
|
||||
global-exclude *.py.orig
|
||||
global-exclude *.py.rej
|
||||
|
|
69
README.rst
69
README.rst
|
@ -26,13 +26,30 @@ Electrum - Lightweight Bitcoin client
|
|||
Getting started
|
||||
===============
|
||||
|
||||
Electrum is a pure python application. If you want to use the
|
||||
Qt interface, install the Qt dependencies::
|
||||
Electrum itself is pure Python, and so are most of the required dependencies.
|
||||
|
||||
Non-python dependencies
|
||||
-----------------------
|
||||
|
||||
If you want to use the Qt interface, install the Qt dependencies::
|
||||
|
||||
sudo apt-get install python3-pyqt5
|
||||
|
||||
For elliptic curve operations, libsecp256k1 is a required dependency::
|
||||
|
||||
sudo apt-get install libsecp256k1-0
|
||||
|
||||
Alternatively, when running from a cloned repository, a script is provided to build
|
||||
libsecp256k1 yourself::
|
||||
|
||||
./contrib/make_libsecp256k1.sh
|
||||
|
||||
|
||||
Running from tar.gz
|
||||
-------------------
|
||||
|
||||
If you downloaded the official package (tar.gz), you can run
|
||||
Electrum from its root directory, without installing it on your
|
||||
Electrum from its root directory without installing it on your
|
||||
system; all the python dependencies are included in the 'packages'
|
||||
directory. To run Electrum from its root directory, just do::
|
||||
|
||||
|
@ -40,40 +57,30 @@ directory. To run Electrum from its root directory, just do::
|
|||
|
||||
You can also install Electrum on your system, by running this command::
|
||||
|
||||
sudo apt-get install python3-setuptools
|
||||
python3 -m pip install .[fast]
|
||||
sudo apt-get install python3-setuptools python3-pip
|
||||
python3 -m pip install --user .
|
||||
|
||||
This will download and install the Python dependencies used by
|
||||
Electrum, instead of using the 'packages' directory.
|
||||
The 'fast' extra contains some optional dependencies that we think
|
||||
are often useful but they are not strictly needed.
|
||||
Electrum instead of using the 'packages' directory.
|
||||
|
||||
If you cloned the git repository, you need to compile extra files
|
||||
before you can run Electrum. Read the next section, "Development
|
||||
Version".
|
||||
|
||||
version".
|
||||
|
||||
|
||||
Development version
|
||||
===================
|
||||
-------------------
|
||||
|
||||
Check out the code from GitHub::
|
||||
|
||||
git clone git://github.com/spesmilo/electrum.git
|
||||
cd electrum
|
||||
git submodule update --init
|
||||
|
||||
Run install (this should install dependencies)::
|
||||
|
||||
python3 -m pip install .[fast]
|
||||
python3 -m pip install --user .
|
||||
|
||||
Render the SVG icons to PNGs (optional)::
|
||||
|
||||
for i in lock unlock confirmed status_lagging status_disconnected status_connected_proxy status_connected status_waiting preferences; do convert -background none icons/$i.svg icons/$i.png; done
|
||||
|
||||
Compile the icons file for Qt::
|
||||
|
||||
sudo apt-get install pyqt5-dev-tools
|
||||
pyrcc5 icons.qrc -o electrum/gui/qt/icons_rc.py
|
||||
|
||||
Compile the protobuf description file::
|
||||
|
||||
|
@ -83,7 +90,7 @@ Compile the protobuf description file::
|
|||
Create translations (optional)::
|
||||
|
||||
sudo apt-get install python-requests gettext
|
||||
./contrib/make_locale
|
||||
./contrib/pull_locale
|
||||
|
||||
|
||||
|
||||
|
@ -91,25 +98,31 @@ Create translations (optional)::
|
|||
Creating Binaries
|
||||
=================
|
||||
|
||||
Linux (tarball)
|
||||
---------------
|
||||
|
||||
To create binaries, create the 'packages' directory::
|
||||
See :code:`contrib/build-linux/README.md`.
|
||||
|
||||
./contrib/make_packages
|
||||
|
||||
This directory contains the python dependencies used by Electrum.
|
||||
Linux (AppImage)
|
||||
----------------
|
||||
|
||||
See :code:`contrib/build-linux/appimage/README.md`.
|
||||
|
||||
|
||||
Mac OS X / macOS
|
||||
--------
|
||||
----------------
|
||||
|
||||
See :code:`contrib/osx/README.md`.
|
||||
|
||||
See `contrib/build-osx/`.
|
||||
|
||||
Windows
|
||||
-------
|
||||
|
||||
See `contrib/build-wine/`.
|
||||
See :code:`contrib/build-wine/README.md`.
|
||||
|
||||
|
||||
Android
|
||||
-------
|
||||
|
||||
See `electrum/gui/kivy/Readme.md` file.
|
||||
See :code:`electrum/gui/kivy/Readme.md`.
|
||||
|
|
171
RELEASE-NOTES
171
RELEASE-NOTES
|
@ -1,3 +1,174 @@
|
|||
# Release 4.0 - (Not released yet; release notes are incomplete)
|
||||
|
||||
* Lightning Network
|
||||
* Qt GUI: Separation between output selection and transaction finalization.
|
||||
* Http PayServer can be configured from GUI
|
||||
|
||||
# Release 3.3.8 - (July 11, 2019)
|
||||
|
||||
* fix some bugs with recent bump fee (RBF) improvements (#5483, #5502)
|
||||
* fix #5491: watch-only wallets could not bump fee in some cases
|
||||
* appimage: URLs could not be opened on some desktop environments (#5425)
|
||||
* faster tx signing for segwit inputs for really large txns (#5494)
|
||||
* A few other minor bugfixes and usability improvements.
|
||||
|
||||
|
||||
# Release 3.3.7 - (July 3, 2019)
|
||||
|
||||
* The AppImage Linux x86_64 binary and the Windows setup.exe
|
||||
(so now all Windows binaries) are now built reproducibly.
|
||||
* Bump fee (RBF) improvements:
|
||||
Implemented a new fee-bump strategy that can add new inputs,
|
||||
so now any tx can be fee-bumped (d0a4366). The old strategy
|
||||
was to decrease the value of outputs (starting with change).
|
||||
We will now try the new strategy first, and only use the old
|
||||
as a fallback (needed e.g. when spending "Max").
|
||||
* CoinChooser improvements:
|
||||
- more likely to construct txs without change (when possible)
|
||||
- less likely to construct txs with really small change (e864fa5)
|
||||
- will now only spend negative effective value coins when
|
||||
beneficial for privacy (cb69aa8)
|
||||
* fix long-standing bug that broke wallets with >65k addresses (#5366)
|
||||
* Windows binaries: we now build the PyInstaller boot loader ourselves,
|
||||
as this seems to reduce anti-virus false positives (1d0f679)
|
||||
* Android: (fix) BIP70 payment requests could not be paid (#5376)
|
||||
* Android: allow copy-pasting partial transactions from/to clipboard
|
||||
* Fix a performance regression for large wallets (c6a54f0)
|
||||
* Qt: fix some high DPI issues related to text fields (37809be)
|
||||
* Trezor:
|
||||
- allow bypassing "too old firmware" error (#5391)
|
||||
- use only the Bridge to scan devices if it is available (#5420)
|
||||
* hw wallets: (known issue) on Win10-1903, some hw devices
|
||||
(that also have U2F functionality) can only be detected with
|
||||
Administrator privileges. (see #5420 and #5437)
|
||||
A workaround is to run as Admin, or for Trezor to install the Bridge.
|
||||
* Several other minor bugfixes and usability improvements.
|
||||
|
||||
|
||||
# Release 3.3.6 - (May 16, 2019)
|
||||
|
||||
* qt: fix crash during 2FA wallet creation (#5334)
|
||||
* fix synchronizer not to keep resubscribing to addresses of
|
||||
already closed wallets (e415c0d9)
|
||||
* fix removing addresses/keys from imported wallets (#4481)
|
||||
* kivy: fix crash when aborting 2FA wallet creation (#5333)
|
||||
* kivy: fix rare crash when changing exchange rate settings (#5329)
|
||||
* A few other minor bugfixes and usability improvements.
|
||||
|
||||
|
||||
# Release 3.3.5 - (May 9, 2019)
|
||||
|
||||
* The logging system has been overhauled (#5296).
|
||||
Logs can now also optionally be written to disk, disabled by default.
|
||||
* Fix a bug in synchronizer (#5122) where client could get stuck.
|
||||
Also, show the progress of history sync in the GUI. (#5319)
|
||||
* fix Revealer in Windows and MacOS binaries (#5027)
|
||||
* fiat rate providers:
|
||||
- added CoinGecko.com and CoinCap.io
|
||||
- BitcoinAverage now only provides historical exchange rates for
|
||||
paying customers. Changed default provider to CoinGecko.com (#5188)
|
||||
* hardware wallets:
|
||||
- Ledger: Nano X is now recognized (#5140)
|
||||
- KeepKey:
|
||||
- device was not getting detected using Windows binary (#5165)
|
||||
- support firmware 6.0.0+ (#5205)
|
||||
- Trezor: implemented "seedless" mode (#5118)
|
||||
* Coin Control in Qt: implemented freezing individual UTXOs
|
||||
in addition to freezing addresses (#5152)
|
||||
* TrustedCoin (2FA wallets):
|
||||
- better error messages (#5184)
|
||||
- longer signing timeout (#5221)
|
||||
* Kivy:
|
||||
- fix bug with local transactions (#5156)
|
||||
- allow selecting fiat rate providers without historical data (#5162)
|
||||
* fix CPFP: the fees already paid by the parent were not included in
|
||||
the calculation, so it always overestimated (#5244)
|
||||
* Testnet: there is now a warning when the client is started in
|
||||
testnet mode as there were a number of reports of users getting
|
||||
scammed through social engineering (#5295)
|
||||
* CoinChooser: performance of creating transactions has been improved
|
||||
significantly for large wallets. (d56917f4)
|
||||
* Importing/sweeping WIF keys: stricter checks (#4638, #5290)
|
||||
* Electrum protocol: the client's "user agent" has been changed from
|
||||
"3.3.5" to "electrum/3.3.5". Other libraries connecting to servers
|
||||
can consider not "spoofing" to be Electrum. (#5246)
|
||||
* Several other minor bugfixes and usability improvements.
|
||||
|
||||
|
||||
# Release 3.3.4 - (February 13, 2019)
|
||||
|
||||
* AppImage: we now also distribute self-contained binaries for x86_64
|
||||
Linux in the form of an AppImage (#5042). The Python interpreter,
|
||||
PyQt5, libsecp256k1, PyCryptodomex, zbar, hidapi/libusb (including
|
||||
hardware wallet libraries) are all bundled. Note that users of
|
||||
hw wallets still need to set udev rules themselves.
|
||||
* hw wallets: fix a regression during transaction signing that prompts
|
||||
the user too many times for confirmations (commit 2729909)
|
||||
* transactions now set nVersion to 2, to mimic Bitcoin Core
|
||||
* fix Qt bug that made all hw wallets unusable on Windows 8.1 (#4960)
|
||||
* fix bugs in wallet creation wizard that resulted in corrupted
|
||||
wallets being created in rare cases (#5082, #5057)
|
||||
* fix compatibility with Qt 5.12 (#5109)
|
||||
|
||||
|
||||
# Release 3.3.3 - (January 25, 2019)
|
||||
|
||||
* Do not expose users to server error messages (#4968)
|
||||
* Notify users of new releases. Release announcements must be signed,
|
||||
and they are verified byElectrum using a hardcoded Bitcoin address.
|
||||
* Hardware wallet fixes (#4991, #4993, #5006)
|
||||
* Display only QR code in QRcode Window
|
||||
* Fixed code signing on MacOS
|
||||
* Randomise locktime of transactions
|
||||
|
||||
|
||||
# Release 3.3.2 - (December 21, 2018)
|
||||
|
||||
* Fix Qt history export bug
|
||||
* Improve network timeouts
|
||||
* Prepend server transaction_broadcast error messages with
|
||||
explanatory message. Render error messages as plain text.
|
||||
|
||||
|
||||
# Release 3.3.1 - (December 20, 2018)
|
||||
|
||||
* Qt: Fix invoices tab crash (#4941)
|
||||
* Android: Minor GUI improvements
|
||||
|
||||
|
||||
# Release 3.3.0 - Hodler's Edition (December 19, 2018)
|
||||
|
||||
* The network layer has been rewritten using asyncio and aiorpcx.
|
||||
In addition to easier maintenance, this makes the client
|
||||
more robust against misbehaving servers.
|
||||
* The minimum python version was increased to 3.6
|
||||
* The blockchain headers and fork handling logic has been generalized.
|
||||
Clients by default now follow chain based on most work, not length.
|
||||
* New wallet creation defaults to native segwit (bech32).
|
||||
* Segwit 2FA: TrustedCoin now supports native segwit p2wsh
|
||||
two-factor wallets.
|
||||
* RBF batching (opt-in): If the wallet has an unconfirmed RBF
|
||||
transaction, new payments will be added to that transaction,
|
||||
instead of creating new transactions.
|
||||
* MacOS: support QR code scanner in binaries.
|
||||
* Android APK:
|
||||
- build using Google NDK instead of Crystax NDK
|
||||
- target API 28
|
||||
- do not use external storage (previously for block headers)
|
||||
* hardware wallets:
|
||||
- Coldcard now supports spending from p2wpkh-p2sh,
|
||||
fixed p2pkh signing for fw 1.1.0
|
||||
- Archos Safe-T mini: fix #4726 signing issue
|
||||
- KeepKey: full segwit support
|
||||
- Trezor: refactoring and compat with python-trezor 0.11
|
||||
- Digital BitBox: support firmware v5.0.0
|
||||
* fix bitcoin URI handling when app already running (#4796)
|
||||
* Qt listings rewritten:
|
||||
the History tab now uses QAbstractItemModel, the other tabs use
|
||||
QStandardItemModel. Performance should be better for large wallets.
|
||||
* Several other minor bugfixes and usability improvements.
|
||||
|
||||
|
||||
# Release 3.2.3 - (September 3, 2018)
|
||||
|
||||
* hardware wallet: the Safe-T mini from Archos is now supported.
|
||||
|
|
19
SECURITY.md
Normal file
19
SECURITY.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
To report security issues send an email to electrumdev@gmail.com.
|
||||
|
||||
The following keys may be used to communicate sensitive information to developers:
|
||||
|
||||
| Name | Fingerprint |
|
||||
|------|-------------|
|
||||
| ThomasV | 6694 D8DE 7BE8 EE56 31BE D950 2BD5 824B 7F94 70E6 |
|
||||
| SomberNight | 4AD6 4339 DFA0 5E20 B3F6 AD51 E7B7 48CD AF5E 5ED9 |
|
||||
|
||||
You can import a key by running the following command with that
|
||||
individual’s fingerprint: `gpg --recv-keys "<fingerprint>"`
|
||||
Ensure that you put quotes around fingerprints containing spaces.
|
||||
|
||||
These public keys can also be found in the Electrum git repository,
|
||||
in the top-level `pubkeys` folder.
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# This script creates a virtualenv named 'env' and installs all
|
||||
# python dependencies before activating the env and running Electrum.
|
||||
|
|
|
@ -10,7 +10,8 @@ Icon=electrum
|
|||
Name[en_US]=Electrum Bitcoin Wallet
|
||||
Name=Electrum Bitcoin Wallet
|
||||
Categories=Finance;Network;
|
||||
StartupNotify=false
|
||||
StartupNotify=true
|
||||
StartupWMClass=electrum
|
||||
Terminal=false
|
||||
Type=Application
|
||||
MimeType=x-scheme-handler/bitcoin;
|
||||
|
|
228
run_electrum
228
run_electrum
|
@ -25,12 +25,26 @@
|
|||
# SOFTWARE.
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
import asyncio
|
||||
|
||||
MIN_PYTHON_VERSION = "3.6.1" # FIXME duplicated from setup.py
|
||||
_min_python_version_tuple = tuple(map(int, (MIN_PYTHON_VERSION.split("."))))
|
||||
|
||||
|
||||
if sys.version_info[:3] < _min_python_version_tuple:
|
||||
sys.exit("Error: Electrum requires Python version >= %s..." % MIN_PYTHON_VERSION)
|
||||
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
is_bundle = getattr(sys, 'frozen', False)
|
||||
is_local = not is_bundle and os.path.exists(os.path.join(script_dir, "electrum.desktop"))
|
||||
is_android = 'ANDROID_DATA' in os.environ
|
||||
|
||||
if is_local: # running from source
|
||||
# developers should probably see all deprecation warnings.
|
||||
warnings.simplefilter('default', DeprecationWarning)
|
||||
|
||||
# move this back to gui/kivy/__init.py once plugins are moved
|
||||
os.environ['KIVY_DATA_DIR'] = os.path.abspath(os.path.dirname(__file__)) + '/electrum/gui/kivy/data/'
|
||||
|
||||
|
@ -44,37 +58,41 @@ def check_imports():
|
|||
import dns
|
||||
import pyaes
|
||||
import ecdsa
|
||||
import requests
|
||||
import certifi
|
||||
import qrcode
|
||||
import google.protobuf
|
||||
import jsonrpclib
|
||||
import aiorpcx
|
||||
except ImportError as e:
|
||||
sys.exit("Error: %s. Try 'sudo pip install <module-name>'"%str(e))
|
||||
sys.exit(f"Error: {str(e)}. Try 'sudo python3 -m pip install <module-name>'")
|
||||
# the following imports are for pyinstaller
|
||||
from google.protobuf import descriptor
|
||||
from google.protobuf import message
|
||||
from google.protobuf import reflection
|
||||
from google.protobuf import descriptor_pb2
|
||||
from jsonrpclib import SimpleJSONRPCServer
|
||||
# make sure that certificates are here
|
||||
assert os.path.exists(requests.utils.DEFAULT_CA_BUNDLE_PATH)
|
||||
assert os.path.exists(certifi.where())
|
||||
|
||||
|
||||
if not is_android:
|
||||
check_imports()
|
||||
|
||||
|
||||
from electrum.logging import get_logger, configure_logging
|
||||
from electrum import util
|
||||
from electrum import constants
|
||||
from electrum import SimpleConfig
|
||||
from electrum.wallet_db import WalletDB
|
||||
from electrum.wallet import Wallet
|
||||
from electrum.storage import WalletStorage, get_derivation_used_for_hw_device_encryption
|
||||
from electrum.util import print_msg, print_stderr, json_encode, json_decode, UserCancelled
|
||||
from electrum.util import set_verbosity, InvalidPassword
|
||||
from electrum.util import InvalidPassword
|
||||
from electrum.commands import get_parser, known_commands, Commands, config_variables
|
||||
from electrum import daemon
|
||||
from electrum import keystore
|
||||
from electrum.util import create_and_start_event_loop
|
||||
|
||||
_logger = get_logger(__name__)
|
||||
|
||||
|
||||
# get password routine
|
||||
def prompt_password(prompt, confirm=True):
|
||||
|
@ -89,31 +107,7 @@ def prompt_password(prompt, confirm=True):
|
|||
return password
|
||||
|
||||
|
||||
def init_daemon(config_options):
|
||||
config = SimpleConfig(config_options)
|
||||
storage = WalletStorage(config.get_wallet_path())
|
||||
if not storage.file_exists():
|
||||
print_msg("Error: Wallet file not found.")
|
||||
print_msg("Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option")
|
||||
sys.exit(0)
|
||||
if storage.is_encrypted():
|
||||
if storage.is_encrypted_with_hw_device():
|
||||
plugins = init_plugins(config, 'cmdline')
|
||||
password = get_password_for_hw_device_encrypted_storage(plugins)
|
||||
elif config.get('password'):
|
||||
password = config.get('password')
|
||||
else:
|
||||
password = prompt_password('Password:', False)
|
||||
if not password:
|
||||
print_msg("Error: Password required")
|
||||
sys.exit(1)
|
||||
else:
|
||||
password = None
|
||||
config_options['password'] = password
|
||||
|
||||
|
||||
def init_cmdline(config_options, server):
|
||||
config = SimpleConfig(config_options)
|
||||
def init_cmdline(config_options, wallet_path, server):
|
||||
cmdname = config.get('cmd')
|
||||
cmd = known_commands[cmdname]
|
||||
|
||||
|
@ -128,12 +122,12 @@ def init_cmdline(config_options, server):
|
|||
cmd.requires_network = True
|
||||
|
||||
# instantiate wallet for command-line
|
||||
storage = WalletStorage(config.get_wallet_path())
|
||||
storage = WalletStorage(wallet_path)
|
||||
|
||||
if cmd.requires_wallet and not storage.file_exists():
|
||||
print_msg("Error: Wallet file not found.")
|
||||
print_msg("Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option")
|
||||
sys.exit(0)
|
||||
sys_exit(1)
|
||||
|
||||
# important warning
|
||||
if cmd.name in ['getprivatekeys']:
|
||||
|
@ -141,9 +135,17 @@ def init_cmdline(config_options, server):
|
|||
print_stderr("Exposing a single private key can compromise your entire wallet!")
|
||||
print_stderr("In particular, DO NOT use 'redeem private key' services proposed by third parties.")
|
||||
|
||||
# will we need a password
|
||||
if not storage.is_encrypted():
|
||||
db = WalletDB(storage.read(), manual_upgrades=False)
|
||||
use_encryption = db.get('use_encryption')
|
||||
else:
|
||||
use_encryption = True
|
||||
|
||||
# commands needing password
|
||||
if (cmd.requires_wallet and storage.is_encrypted() and server is None)\
|
||||
or (cmd.requires_password and (storage.get('use_encryption') or storage.is_encrypted())):
|
||||
if ( (cmd.requires_wallet and storage.is_encrypted() and server is False)\
|
||||
or (cmdname == 'load_wallet' and storage.is_encrypted())\
|
||||
or (cmd.requires_password and use_encryption)):
|
||||
if storage.is_encrypted_with_hw_device():
|
||||
# this case is handled later in the control flow
|
||||
password = None
|
||||
|
@ -153,7 +155,7 @@ def init_cmdline(config_options, server):
|
|||
password = prompt_password('Password:', False)
|
||||
if not password:
|
||||
print_msg("Error: Password required")
|
||||
sys.exit(1)
|
||||
sys_exit(1)
|
||||
else:
|
||||
password = None
|
||||
|
||||
|
@ -173,18 +175,18 @@ def get_connected_hw_devices(plugins):
|
|||
name, plugin = splugin.name, splugin.plugin
|
||||
if not plugin:
|
||||
e = splugin.exception
|
||||
print_stderr(f"{name}: error during plugin init: {repr(e)}")
|
||||
_logger.error(f"{name}: error during plugin init: {repr(e)}")
|
||||
continue
|
||||
try:
|
||||
u = devmgr.unpaired_device_infos(None, plugin)
|
||||
except:
|
||||
devmgr.print_error(f'error getting device infos for {name}: {e}')
|
||||
except Exception as e:
|
||||
_logger.error(f'error getting device infos for {name}: {repr(e)}')
|
||||
continue
|
||||
devices += list(map(lambda x: (name, x), u))
|
||||
return devices
|
||||
|
||||
|
||||
def get_password_for_hw_device_encrypted_storage(plugins):
|
||||
def get_password_for_hw_device_encrypted_storage(plugins) -> str:
|
||||
devices = get_connected_hw_devices(plugins)
|
||||
if len(devices) == 0:
|
||||
print_msg("Error: No connected hw device found. Cannot decrypt this wallet.")
|
||||
|
@ -200,14 +202,16 @@ def get_password_for_hw_device_encrypted_storage(plugins):
|
|||
xpub = plugin.get_xpub(device_info.device.id_, derivation, 'standard', plugin.handler)
|
||||
except UserCancelled:
|
||||
sys.exit(0)
|
||||
password = keystore.Xpub.get_pubkey_from_xpub(xpub, ())
|
||||
password = keystore.Xpub.get_pubkey_from_xpub(xpub, ()).hex()
|
||||
return password
|
||||
|
||||
|
||||
def run_offline_command(config, config_options, plugins):
|
||||
async def run_offline_command(config, config_options, plugins):
|
||||
cmdname = config.get('cmd')
|
||||
cmd = known_commands[cmdname]
|
||||
password = config_options.get('password')
|
||||
if 'wallet_path' in cmd.options and config_options.get('wallet_path') is None:
|
||||
config_options['wallet_path'] = config.get_wallet_path()
|
||||
if cmd.requires_wallet:
|
||||
storage = WalletStorage(config.get_wallet_path())
|
||||
if storage.is_encrypted():
|
||||
|
@ -215,7 +219,9 @@ def run_offline_command(config, config_options, plugins):
|
|||
password = get_password_for_hw_device_encrypted_storage(plugins)
|
||||
config_options['password'] = password
|
||||
storage.decrypt(password)
|
||||
wallet = Wallet(storage)
|
||||
db = WalletDB(storage.read(), manual_upgrades=False)
|
||||
wallet = Wallet(db, storage, config=config)
|
||||
config_options['wallet'] = wallet
|
||||
else:
|
||||
wallet = None
|
||||
# check password
|
||||
|
@ -235,13 +241,13 @@ def run_offline_command(config, config_options, plugins):
|
|||
# options
|
||||
kwargs = {}
|
||||
for x in cmd.options:
|
||||
kwargs[x] = (config_options.get(x) if x in ['password', 'new_password'] else config.get(x))
|
||||
cmd_runner = Commands(config, wallet, None)
|
||||
kwargs[x] = (config_options.get(x) if x in ['wallet_path', 'wallet', 'password', 'new_password'] else config.get(x))
|
||||
cmd_runner = Commands(config=config)
|
||||
func = getattr(cmd_runner, cmd.name)
|
||||
result = func(*args, **kwargs)
|
||||
result = await func(*args, **kwargs)
|
||||
# save wallet
|
||||
if wallet:
|
||||
wallet.storage.write()
|
||||
wallet.save_db()
|
||||
return result
|
||||
|
||||
|
||||
|
@ -249,6 +255,11 @@ def init_plugins(config, gui_name):
|
|||
from electrum.plugin import Plugins
|
||||
return Plugins(config, gui_name)
|
||||
|
||||
def sys_exit(i):
|
||||
# stop event loop and exit
|
||||
loop.call_soon_threadsafe(stop_loop.set_result, 1)
|
||||
loop_thread.join(timeout=1)
|
||||
sys.exit(i)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# The hook will only be used in the Qt GUI right now
|
||||
|
@ -262,6 +273,9 @@ if __name__ == '__main__':
|
|||
sys.argv.append('-h')
|
||||
|
||||
# old '-v' syntax
|
||||
# Due to this workaround that keeps old -v working,
|
||||
# more advanced usages of -v need to use '-v='.
|
||||
# e.g. -v=debug,network=warning,interface=error
|
||||
try:
|
||||
i = sys.argv.index('-v')
|
||||
except ValueError:
|
||||
|
@ -309,8 +323,8 @@ if __name__ == '__main__':
|
|||
if config_options.get('portable'):
|
||||
config_options['electrum_path'] = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'electrum_data')
|
||||
|
||||
# kivy sometimes freezes when we write to sys.stderr
|
||||
set_verbosity(config_options.get('verbosity') if config_options.get('gui') != 'kivy' else '')
|
||||
if not config_options.get('verbosity'):
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
|
||||
# check uri
|
||||
uri = config_options.get('url')
|
||||
|
@ -318,11 +332,9 @@ if __name__ == '__main__':
|
|||
if not uri.startswith('bitcoin:'):
|
||||
print_stderr('unknown command:', uri)
|
||||
sys.exit(1)
|
||||
config_options['url'] = uri
|
||||
|
||||
# todo: defer this to gui
|
||||
# singleton
|
||||
config = SimpleConfig(config_options)
|
||||
cmdname = config.get('cmd')
|
||||
|
||||
if config.get('testnet'):
|
||||
constants.set_testnet()
|
||||
|
@ -331,70 +343,86 @@ if __name__ == '__main__':
|
|||
elif config.get('simnet'):
|
||||
constants.set_simnet()
|
||||
|
||||
cmdname = config.get('cmd')
|
||||
|
||||
if cmdname == 'daemon' and config.get("detach"):
|
||||
# fork before creating the asyncio event loop
|
||||
pid = os.fork()
|
||||
if pid:
|
||||
print_stderr("starting daemon (PID %d)" % pid)
|
||||
sys.exit(0)
|
||||
else:
|
||||
# redirect standard file descriptors
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
si = open(os.devnull, 'r')
|
||||
so = open(os.devnull, 'w')
|
||||
se = open(os.devnull, 'w')
|
||||
os.dup2(si.fileno(), sys.stdin.fileno())
|
||||
os.dup2(so.fileno(), sys.stdout.fileno())
|
||||
os.dup2(se.fileno(), sys.stderr.fileno())
|
||||
|
||||
loop, stop_loop, loop_thread = create_and_start_event_loop()
|
||||
|
||||
if cmdname == 'gui':
|
||||
fd, server = daemon.get_fd_or_server(config)
|
||||
configure_logging(config)
|
||||
fd = daemon.get_file_descriptor(config)
|
||||
if fd is not None:
|
||||
plugins = init_plugins(config, config.get('gui', 'qt'))
|
||||
d = daemon.Daemon(config, fd)
|
||||
d.init_gui(config, plugins)
|
||||
sys.exit(0)
|
||||
d.run_gui(config, plugins)
|
||||
sys_exit(0)
|
||||
else:
|
||||
result = server.gui(config_options)
|
||||
result = daemon.request(config, 'gui', (config_options,))
|
||||
|
||||
elif cmdname == 'daemon':
|
||||
subcommand = config.get('subcommand')
|
||||
if subcommand in ['load_wallet']:
|
||||
init_daemon(config_options)
|
||||
|
||||
if subcommand in [None, 'start']:
|
||||
fd, server = daemon.get_fd_or_server(config)
|
||||
if fd is not None:
|
||||
if subcommand == 'start':
|
||||
pid = os.fork()
|
||||
if pid:
|
||||
print_stderr("starting daemon (PID %d)" % pid)
|
||||
sys.exit(0)
|
||||
init_plugins(config, 'cmdline')
|
||||
d = daemon.Daemon(config, fd)
|
||||
if config.get('websocket_server'):
|
||||
from electrum import websockets
|
||||
websockets.WebSocketServer(config, d.network)
|
||||
if config.get('requests_dir'):
|
||||
path = os.path.join(config.get('requests_dir'), 'index.html')
|
||||
if not os.path.exists(path):
|
||||
print("Requests directory not configured.")
|
||||
print("You can configure it using https://github.com/spesmilo/electrum-merchant")
|
||||
sys.exit(1)
|
||||
d.join()
|
||||
sys.exit(0)
|
||||
else:
|
||||
result = server.daemon(config_options)
|
||||
configure_logging(config)
|
||||
fd = daemon.get_file_descriptor(config)
|
||||
if fd is not None:
|
||||
# run daemon
|
||||
init_plugins(config, 'cmdline')
|
||||
d = daemon.Daemon(config, fd)
|
||||
d.run_daemon()
|
||||
sys_exit(0)
|
||||
else:
|
||||
server = daemon.get_server(config)
|
||||
if server is not None:
|
||||
result = server.daemon(config_options)
|
||||
else:
|
||||
print_msg("Daemon not running")
|
||||
sys.exit(1)
|
||||
print_msg("Daemon already running")
|
||||
sys_exit(1)
|
||||
else:
|
||||
# command line
|
||||
server = daemon.get_server(config)
|
||||
init_cmdline(config_options, server)
|
||||
if server is not None:
|
||||
result = server.run_cmdline(config_options)
|
||||
cmd = known_commands[cmdname]
|
||||
wallet_path = config.get_wallet_path()
|
||||
if not config.get('offline'):
|
||||
init_cmdline(config_options, wallet_path, True)
|
||||
timeout = config.get('timeout', 60)
|
||||
if timeout: timeout = int(timeout)
|
||||
try:
|
||||
result = daemon.request(config, 'run_cmdline', (config_options,), timeout)
|
||||
except daemon.DaemonNotRunning:
|
||||
print_msg("Daemon not running; try 'electrum daemon -d'")
|
||||
if not cmd.requires_network:
|
||||
print_msg("To run this command without a daemon, use --offline")
|
||||
sys_exit(1)
|
||||
except Exception as e:
|
||||
print_stderr(str(e) or repr(e))
|
||||
sys_exit(1)
|
||||
else:
|
||||
cmd = known_commands[cmdname]
|
||||
if cmd.requires_network:
|
||||
print_msg("Daemon not running; try 'electrum daemon start'")
|
||||
sys.exit(1)
|
||||
else:
|
||||
plugins = init_plugins(config, 'cmdline')
|
||||
result = run_offline_command(config, config_options, plugins)
|
||||
# print result
|
||||
print_msg("This command cannot be run offline")
|
||||
sys_exit(1)
|
||||
init_cmdline(config_options, wallet_path, False)
|
||||
plugins = init_plugins(config, 'cmdline')
|
||||
coro = run_offline_command(config, config_options, plugins)
|
||||
fut = asyncio.run_coroutine_threadsafe(coro, loop)
|
||||
try:
|
||||
result = fut.result()
|
||||
except Exception as e:
|
||||
print_stderr(str(e) or repr(e))
|
||||
sys_exit(1)
|
||||
if isinstance(result, str):
|
||||
print_msg(result)
|
||||
elif type(result) is dict and result.get('error'):
|
||||
print_stderr(result.get('error'))
|
||||
elif result is not None:
|
||||
print_msg(json_encode(result))
|
||||
sys.exit(0)
|
||||
sys_exit(0)
|
||||
|
|
28
setup.py
28
setup.py
|
@ -17,7 +17,7 @@ _min_python_version_tuple = tuple(map(int, (MIN_PYTHON_VERSION.split("."))))
|
|||
|
||||
|
||||
if sys.version_info[:3] < _min_python_version_tuple:
|
||||
sys.exit("Error: Electrum requires Python version >= {}...".format(MIN_PYTHON_VERSION))
|
||||
sys.exit("Error: Electrum requires Python version >= %s..." % MIN_PYTHON_VERSION)
|
||||
|
||||
with open('contrib/requirements/requirements.txt') as f:
|
||||
requirements = f.read().splitlines()
|
||||
|
@ -47,34 +47,16 @@ if platform.system() in ['Linux', 'FreeBSD', 'DragonFly']:
|
|||
usr_share = os.path.expanduser('~/.local/share')
|
||||
data_files += [
|
||||
(os.path.join(usr_share, 'applications/'), ['electrum.desktop']),
|
||||
(os.path.join(usr_share, icons_dirname), ['icons/electrum.png'])
|
||||
(os.path.join(usr_share, icons_dirname), ['electrum/gui/icons/electrum.png']),
|
||||
]
|
||||
|
||||
extras_require = {
|
||||
'hardware': requirements_hw,
|
||||
'fast': ['pycryptodomex'],
|
||||
'gui': ['pyqt5'],
|
||||
}
|
||||
extras_require['full'] = [pkg for sublist in list(extras_require.values()) for pkg in sublist]
|
||||
|
||||
|
||||
class CustomInstallCommand(install):
|
||||
def run(self):
|
||||
install.run(self)
|
||||
# potentially build Qt icons file
|
||||
try:
|
||||
import PyQt5
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
path = os.path.join(self.install_lib, "electrum/gui/qt/icons_rc.py")
|
||||
if not os.path.exists(path):
|
||||
subprocess.call(["pyrcc5", "icons.qrc", "-o", path])
|
||||
except Exception as e:
|
||||
print('Warning: building icons file failed with {}'.format(e))
|
||||
|
||||
|
||||
setup(
|
||||
name="Electrum",
|
||||
version=version.ELECTRUM_VERSION,
|
||||
|
@ -96,6 +78,9 @@ setup(
|
|||
'wordlist/*.txt',
|
||||
'locale/*/LC_MESSAGES/electrum.mo',
|
||||
],
|
||||
'electrum.gui': [
|
||||
'icons/*',
|
||||
],
|
||||
},
|
||||
scripts=['electrum/electrum'],
|
||||
data_files=data_files,
|
||||
|
@ -105,7 +90,4 @@ setup(
|
|||
license="MIT Licence",
|
||||
url="https://electrum.org",
|
||||
long_description="""Lightweight Bitcoin Wallet""",
|
||||
cmdclass={
|
||||
'install': CustomInstallCommand,
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue