[Pkg-bitcoin-commits] [electrum] 02/05: Imported Upstream version 2.5.2
Tristan Seligmann
mithrandi at moszumanska.debian.org
Fri Oct 30 06:54:58 UTC 2015
This is an automated email from the git hooks/post-receive script.
mithrandi pushed a commit to branch master
in repository electrum.
commit 95debb3129ce43783eef81eb554b2f3155e14aac
Author: Tristan Seligmann <mithrandi at debian.org>
Date: Thu Oct 29 02:23:54 2015 +0200
Imported Upstream version 2.5.2
---
Electrum.egg-info/PKG-INFO | 2 +-
PKG-INFO | 2 +-
RELEASE-NOTES | 6 +++
electrum | 55 +++++++++++---------------
gui/qt/address_dialog.py | 27 +++----------
gui/qt/history_widget.py | 7 +++-
gui/qt/icons_rc.py | 2 +-
gui/qt/installwizard.py | 68 ++++++++++++--------------------
gui/qt/main_window.py | 3 +-
gui/qt/network_dialog.py | 15 ++++++--
lib/commands.py | 32 +++++++--------
lib/interface.py | 6 +--
lib/tests/test_transaction.py | 55 --------------------------
lib/transaction.py | 9 ++++-
lib/version.py | 2 +-
lib/wallet.py | 90 +++++++++++++++++++++++++++----------------
lib/websockets.py | 6 +--
plugins/exchange_rate.py | 5 ++-
18 files changed, 167 insertions(+), 225 deletions(-)
diff --git a/Electrum.egg-info/PKG-INFO b/Electrum.egg-info/PKG-INFO
index 272c4e2..d3a75a7 100644
--- a/Electrum.egg-info/PKG-INFO
+++ b/Electrum.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: Electrum
-Version: 2.5.1
+Version: 2.5.2
Summary: Lightweight Bitcoin Wallet
Home-page: https://electrum.org
Author: Thomas Voegtlin
diff --git a/PKG-INFO b/PKG-INFO
index 272c4e2..d3a75a7 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: Electrum
-Version: 2.5.1
+Version: 2.5.2
Summary: Lightweight Bitcoin Wallet
Home-page: https://electrum.org
Author: Thomas Voegtlin
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 0d7b9b1..41a87c0 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,3 +1,9 @@
+# Release 2.5.2 (bugfixes)
+ * fix bug #1513 (client tries to broadcast transaction while not connected)
+ * fix synchronization bug (#1520)
+ * fix command line bug (#1494)
+ * fixes for exchange rate plugin
+
# Release 2.5.1 (bugfixes)
* signatures in transactions were still using the old class
* make sure that setup.py uses python2
diff --git a/electrum b/electrum
index 39a43f4..11877bc 100755
--- a/electrum
+++ b/electrum
@@ -87,7 +87,7 @@ from electrum.commands import get_parser, known_commands, Commands, config_varia
# get password routine
def prompt_password(prompt, confirm=True):
import getpass
- password = getpass.getpass(prompt)
+ password = getpass.getpass(prompt, stream=None)
if password and confirm:
password2 = getpass.getpass("Confirm: ")
if password != password2:
@@ -136,42 +136,31 @@ def init_cmdline(config):
if cmd.name in ['create', 'restore']:
if storage.file_exists:
sys.exit("Error: Remove the existing wallet first!")
- if config.get('password') is not None:
- password = config.get('password')
- elif cmd.name == 'restore' and config.get('mpk'):
- password = None
- else:
- password = prompt_password("Password (hit return if you do not wish to encrypt your wallet):")
- if cmd.name == 'restore':
- mpk = config.get('mpk')
- if mpk:
- if Wallet.is_old_mpk(mpk):
- wallet = Wallet.from_old_mpk(mpk, storage)
- if Wallet.is_xpub(mpk):
- wallet = Wallet.from_xpub(mpk, storage)
- else:
- import getpass
- seed = getpass.getpass(prompt="seed:", stream=None) if config.get('concealed') else raw_input("seed:")
- if not Wallet.is_seed(seed):
- sys.exit("Error: Invalid seed")
- wallet = Wallet.from_seed(seed, password, storage)
+ def password_dialog():
+ return prompt_password("Password (hit return if you do not wish to encrypt your wallet):")
+ if cmd.name == 'restore':
+ text = config.get('text')
+ password = password_dialog() if Wallet.is_seed(text) or Wallet.is_xprv(text) or Wallet.is_private_key(text) else None
+ try:
+ wallet = Wallet.from_text(text, password, storage)
+ except BaseException as e:
+ sys.exit(str(e))
if not config.get('offline'):
network = Network(config)
network.start()
wallet.start_threads(network)
print_msg("Recovering wallet...")
+ wallet.synchronize()
wallet.restore(lambda x: x)
- if wallet.is_found():
- print_msg("Recovery successful")
- else:
- print_msg("Warning: Found no history for this wallet")
+ msg = "Recovery successful" if wallet.is_found() else "Found no history for this wallet"
else:
- wallet.synchronize()
- print_msg("Warning: This wallet was restored offline. It may contain more addresses than displayed.")
+ msg = "This wallet was restored offline. It may contain more addresses than displayed."
+ print_msg(msg)
else:
+ password = password_dialog()
wallet = Wallet(storage)
seed = wallet.make_seed()
wallet.add_seed(seed, password)
@@ -182,10 +171,9 @@ def init_cmdline(config):
print_msg("Please keep it in a safe place; if you lose it, you will not be able to restore your wallet.")
print_msg("Wallet saved in '%s'" % wallet.storage.path)
- # terminate
sys.exit(0)
- if cmd.name not in ['create', 'restore'] and cmd.requires_wallet and not storage.file_exists:
+ 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)
@@ -256,6 +244,9 @@ def run_command(config, network, password):
storage = WalletStorage(config.get_wallet_path())
# create wallet instance
wallet = Wallet(storage) if cmd.requires_wallet else None
+ # start threads
+ if wallet and network:
+ wallet.start_threads(network)
# arguments passed to function
args = map(lambda x: config.get(x), cmd.params)
# decode json arguments
@@ -272,10 +263,9 @@ def run_command(config, network, password):
cmd_runner.password = password
func = getattr(cmd_runner, cmd.name)
result = func(*args)
-
+ # stop threads
if wallet:
wallet.stop_threads()
-
return result
@@ -432,6 +422,8 @@ if __name__ == '__main__':
else:
raise BaseException('Cannot get argument from stdin')
elif arg == '?':
+ sys.argv[i] = raw_input("Enter argument:")
+ elif arg == ':':
sys.argv[i] = prompt_password('Enter argument (will not echo):', False)
# parse command line
@@ -462,9 +454,6 @@ if __name__ == '__main__':
# check uri
uri = config_options.get('url')
if uri:
- if os.path.exists(uri):
- # assume this is a payment request
- uri = "bitcoin:?r=file://"+ os.path.join(os.getcwd(), uri)
if not re.match('^bitcoin:', uri):
print_stderr('unknown command:', uri)
sys.exit(1)
diff --git a/gui/qt/address_dialog.py b/gui/qt/address_dialog.py
index edf90f3..d4812a1 100644
--- a/gui/qt/address_dialog.py
+++ b/gui/qt/address_dialog.py
@@ -16,23 +16,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import sys, time, datetime, re, threading
-from electrum.i18n import _, set_language
-from electrum.util import print_error, print_msg
-import os.path, json, ast, traceback
-import shutil
-import StringIO
-
-
-try:
- import PyQt4
-except Exception:
- sys.exit("Error: Could not import PyQt4 on Linux systems, you may try 'sudo apt-get install python-qt4'")
+from electrum.i18n import _
+import PyQt4
from PyQt4.QtGui import *
from PyQt4.QtCore import *
-import PyQt4.QtCore as QtCore
-
from util import *
from history_widget import HistoryWidget
@@ -63,16 +51,16 @@ class AddressDialog(QDialog):
vbox.addWidget(QLabel(_("History")))
self.hw = HistoryWidget(self.parent)
+ self.hw.get_domain = self.get_domain
vbox.addWidget(self.hw)
vbox.addStretch(1)
vbox.addLayout(Buttons(CloseButton(self)))
self.format_amount = self.parent.format_amount
+ self.hw.update()
- h = self.wallet.get_history([self.address])
- self.hw.update(h)
-
-
+ def get_domain(self):
+ return [self.address]
def show_qr(self):
text = self.address
@@ -80,6 +68,3 @@ class AddressDialog(QDialog):
self.parent.show_qrcode(text, 'Address')
except Exception as e:
self.show_message(str(e))
-
-
-
diff --git a/gui/qt/history_widget.py b/gui/qt/history_widget.py
index 0266abb..dc34ff2 100644
--- a/gui/qt/history_widget.py
+++ b/gui/qt/history_widget.py
@@ -55,10 +55,13 @@ class HistoryWidget(MyTreeWidget):
icon = QIcon(":icons/confirmed.png")
return icon, time_str
+ def get_domain(self):
+ '''Replaced in address_dialog.py'''
+ return self.wallet.get_account_addresses(self.parent.current_account)
+
def on_update(self):
self.wallet = self.parent.wallet
- domain = self.wallet.get_account_addresses(self.parent.current_account)
- h = self.wallet.get_history(domain)
+ h = self.wallet.get_history(self.get_domain())
item = self.currentItem()
current_tx = item.data(0, Qt.UserRole).toString() if item else None
diff --git a/gui/qt/icons_rc.py b/gui/qt/icons_rc.py
index 5f06e27..f886258 100644
--- a/gui/qt/icons_rc.py
+++ b/gui/qt/icons_rc.py
@@ -2,7 +2,7 @@
# Resource object code
#
-# Created: dim. oct. 18 13:04:10 2015
+# Created: mer. oct. 28 13:56:56 2015
# by: The Resource Compiler for PyQt (Qt v4.8.6)
#
# WARNING! All changes made in this file will be lost!
diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
index 0118f65..278d003 100644
--- a/gui/qt/installwizard.py
+++ b/gui/qt/installwizard.py
@@ -561,47 +561,27 @@ class InstallWizard(QDialog):
def restore(self, t):
-
- if t == 'standard':
- text = self.enter_seed_dialog(MSG_ENTER_ANYTHING, None)
- if not text:
- return
- if Wallet.is_xprv(text):
- password = self.password_dialog()
- wallet = Wallet.from_xprv(text, password, self.storage)
- elif Wallet.is_old_mpk(text):
- wallet = Wallet.from_old_mpk(text, self.storage)
- elif Wallet.is_xpub(text):
- wallet = Wallet.from_xpub(text, self.storage)
- elif Wallet.is_address(text):
- wallet = Wallet.from_address(text, self.storage)
- elif Wallet.is_private_key(text):
- password = self.password_dialog()
- wallet = Wallet.from_private_key(text, password, self.storage)
- elif Wallet.is_seed(text):
- password = self.password_dialog()
- wallet = Wallet.from_seed(text, password, self.storage)
- else:
- raise BaseException('unknown wallet type')
-
- elif re.match('(\d+)of(\d+)', t):
- n = int(re.match('(\d+)of(\d+)', t).group(2))
- key_list = self.multi_seed_dialog(n - 1)
- if not key_list:
- return
- password = self.password_dialog() if any(map(lambda x: Wallet.is_seed(x) or Wallet.is_xprv(x), key_list)) else None
- wallet = Wallet.from_multisig(key_list, password, self.storage, t)
-
- else:
- self.storage.put('wallet_type', t, False)
- # call the constructor to load the plugin (side effect)
- Wallet(self.storage)
- wallet = always_hook('installwizard_restore', self, self.storage)
- if not wallet:
- util.print_error("no wallet")
- return
-
- # create first keys offline
- self.waiting_dialog(wallet.synchronize)
-
- return wallet
+ if t == 'standard':
+ text = self.enter_seed_dialog(MSG_ENTER_ANYTHING, None)
+ if not text:
+ return
+ password = self.password_dialog() if Wallet.is_seed(text) or Wallet.is_xprv(text) or Wallet.is_private_key(text) else None
+ wallet = Wallet.from_text(text, password, self.storage)
+ elif re.match('(\d+)of(\d+)', t):
+ n = int(re.match('(\d+)of(\d+)', t).group(2))
+ key_list = self.multi_seed_dialog(n - 1)
+ if not key_list:
+ return
+ password = self.password_dialog() if any(map(lambda x: Wallet.is_seed(x) or Wallet.is_xprv(x), key_list)) else None
+ wallet = Wallet.from_multisig(key_list, password, self.storage, t)
+ else:
+ self.storage.put('wallet_type', t, False)
+ # call the constructor to load the plugin (side effect)
+ Wallet(self.storage)
+ wallet = always_hook('installwizard_restore', self, self.storage)
+ if not wallet:
+ util.print_error("no wallet")
+ return
+ # create first keys offline
+ self.waiting_dialog(wallet.synchronize)
+ return wallet
diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
index 00aa442..fa868b8 100644
--- a/gui/qt/main_window.py
+++ b/gui/qt/main_window.py
@@ -2482,7 +2482,8 @@ class ElectrumWindow(QMainWindow, PrintError):
keys_e.setTabChangesFocus(True)
vbox.addWidget(keys_e)
- h, address_e = address_field(self.wallet.addresses(False))
+ addresses = self.wallet.get_unused_addresses(self.current_account)
+ h, address_e = address_field(addresses)
vbox.addLayout(h)
vbox.addStretch(1)
diff --git a/gui/qt/network_dialog.py b/gui/qt/network_dialog.py
index 6d4baa2..0eb6702 100644
--- a/gui/qt/network_dialog.py
+++ b/gui/qt/network_dialog.py
@@ -17,13 +17,15 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys, time, datetime, re, threading
-from electrum.i18n import _
-from electrum.util import print_error, print_msg
import os.path, json, ast, traceback
from PyQt4.QtGui import *
from PyQt4.QtCore import *
+
+from electrum.i18n import _
+from electrum.util import print_error, print_msg
from electrum import DEFAULT_PORTS
+from electrum.network import serialize_server, deserialize_server
from util import *
@@ -224,9 +226,14 @@ class NetworkDialog(QDialog):
if not self.exec_():
return
- host = str( self.server_host.text() )
- port = str( self.server_port.text() )
+ host = str(self.server_host.text())
+ port = str(self.server_port.text())
protocol = 's' if self.ssl_cb.isChecked() else 't'
+ # sanitize
+ try:
+ deserialize_server(serialize_server(host, port, protocol))
+ except:
+ return
if self.proxy_mode.currentText() != 'NONE':
proxy = { 'mode':str(self.proxy_mode.currentText()).lower(),
diff --git a/lib/commands.py b/lib/commands.py
index 344c776..0943275 100644
--- a/lib/commands.py
+++ b/lib/commands.py
@@ -101,19 +101,26 @@ class Commands:
@command('')
def create(self):
"""Create a new wallet"""
+ raise BaseException('Not a JSON-RPC command')
- @command('')
- def restore(self, concealed=False, mpk=None):
- """Restore a wallet from seed. """
+ @command('wn')
+ def restore(self, text):
+ """Restore a wallet from text. Text can be a seed phrase, a master
+ public key, a master private key, a list of bitcoin addresses
+ or bitcoin private keys. If you want to be prompted for your
+ seed, type '?' or ':' (concealed) """
+ raise BaseException('Not a JSON-RPC command')
@command('w')
def deseed(self):
"""Remove seed from wallet. This creates a seedless, watching-only
wallet."""
+ raise BaseException('Not a JSON-RPC command')
@command('wp')
def password(self):
"""Change wallet password. """
+ raise BaseException('Not a JSON-RPC command')
@command('')
def getconfig(self, key):
@@ -412,26 +419,18 @@ class Commands:
return tx
@command('wp')
- def payto(self, destination, amount, tx_fee=None, from_addr=None, change_addr=None, nocheck=False, unsigned=False, deserialized=False, broadcast=False):
+ def payto(self, destination, amount, tx_fee=None, from_addr=None, change_addr=None, nocheck=False, unsigned=False, deserialized=False):
"""Create a transaction. """
domain = [from_addr] if from_addr else None
tx = self._mktx([(destination, amount)], tx_fee, change_addr, domain, nocheck, unsigned)
- if broadcast:
- r, h = self.wallet.sendtx(tx)
- return h
- else:
- return tx.deserialize() if deserialized else tx
+ return tx.deserialize() if deserialized else tx
@command('wp')
- def paytomany(self, outputs, tx_fee=None, from_addr=None, change_addr=None, nocheck=False, unsigned=False, deserialized=False, broadcast=False):
+ def paytomany(self, outputs, tx_fee=None, from_addr=None, change_addr=None, nocheck=False, unsigned=False, deserialized=False):
"""Create a multi-output transaction. """
domain = [from_addr] if from_addr else None
tx = self._mktx(outputs, tx_fee, change_addr, domain, nocheck, unsigned)
- if broadcast:
- r, h = self.wallet.sendtx(tx)
- return h
- else:
- return tx.deserialize() if deserialized else tx
+ return tx.deserialize() if deserialized else tx
@command('wn')
def history(self):
@@ -620,9 +619,7 @@ param_descriptions = {
}
command_options = {
- 'broadcast': (None, "--broadcast", "Broadcast the transaction to the Bitcoin network"),
'password': ("-W", "--password", "Password"),
- 'concealed': ("-C", "--concealed", "Don't echo seed to console when restoring"),
'receiving': (None, "--receiving", "Show only receiving addresses"),
'change': (None, "--change", "Show only change addresses"),
'frozen': (None, "--frozen", "Show only frozen addresses"),
@@ -638,7 +635,6 @@ command_options = {
'entropy': (None, "--entropy", "Custom entropy"),
'language': ("-L", "--lang", "Default language for wordlist"),
'gap_limit': ("-G", "--gap", "Gap limit"),
- 'mpk': (None, "--mpk", "Restore from master public key"),
'deserialized':("-d", "--deserialized","Return deserialized transaction"),
'privkey': (None, "--privkey", "Private key. Set to '?' to get a prompt."),
'unsigned': ("-u", "--unsigned", "Do not sign transaction"),
diff --git a/lib/interface.py b/lib/interface.py
index 8fea853..659e272 100644
--- a/lib/interface.py
+++ b/lib/interface.py
@@ -117,7 +117,7 @@ class TcpConnection(threading.Thread, util.PrintError):
return
# try with CA first
try:
- s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_path, do_handshake_on_connect=True)
+ s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_path, do_handshake_on_connect=True)
except ssl.SSLError, e:
s = None
if s and self.check_host_name(s.getpeercert(), self.host):
@@ -130,7 +130,7 @@ class TcpConnection(threading.Thread, util.PrintError):
if s is None:
return
try:
- s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, cert_reqs=ssl.CERT_NONE, ca_certs=None)
+ s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_NONE, ca_certs=None)
except ssl.SSLError, e:
self.print_error("SSL error retrieving SSL certificate:", e)
return
@@ -153,7 +153,7 @@ class TcpConnection(threading.Thread, util.PrintError):
if self.use_ssl:
try:
s = ssl.wrap_socket(s,
- ssl_version=ssl.PROTOCOL_TLSv1,
+ ssl_version=ssl.PROTOCOL_SSLv23,
cert_reqs=ssl.CERT_REQUIRED,
ca_certs= (temporary_path if is_new else cert_path),
do_handshake_on_connect=True)
diff --git a/lib/tests/test_transaction.py b/lib/tests/test_transaction.py
index ed893ed..1030065 100644
--- a/lib/tests/test_transaction.py
+++ b/lib/tests/test_transaction.py
@@ -141,61 +141,6 @@ class TestTransaction(unittest.TestCase):
res = transaction.parse_xpub('fd007d260305ef27224bbcf6cf5238d2b3638b5a78d5')
self.assertEquals(res, (None, '1CQj15y1N7LDHp7wTt28eoD1QhHgFgxECH'))
- def test_sign_tx(self):
- tx = transaction.Transaction(unsigned_blob)
- tx.deserialize()
-
- x_pubkey = 'ff0488b21e03ef2afea18000000089689bff23e1e7fb2f161daa37270a97a3d8c2e537584b2d304ecb47b86d21fc021b010d3bd425f8cf2e04824bfdf1f1f5ff1d51fadd9a41f9e3fb8dd3403b1bfe00000000'
- privkey = 'L187zmkzzGgf9QdB23MrZvwJ52WoZuQHtkddjmePtbVjXxicJND2'
-
- tx.sign(keypairs={x_pubkey: privkey})
- self.assertEquals(tx.serialize(), signed_blob)
-
- tx.sign(keypairs={x_pubkey: privkey})
- self.assertEquals(tx.serialize(), signed_blob)
-
- def test_sweep(self):
- privkeys = ['5HuH1SHoSVrgtPEwew9JzVAHGoKyp47x564mBCTgVmUT2Me1Q18']
- unspent = [
- {
- "height": 371447,
- "tx_hash": "8e4d173db094786cc128b0c12eebc2200c0d8bfc3ad04ba39f487222d18bae3c",
- "tx_pos": 0,
- "value": 599995800
- }
- ]
- to_address = '1JtBahwvii2pRkBmb4QMfcJQux1rk3Jkbq'
- network = NetworkMock(unspent)
- tx = transaction.Transaction.sweep(privkeys, network, to_address, fee=5000)
- result = transaction.deserialize(tx.serialize())
- expected = {
- 'inputs': [{
- 'address': '1t28kmZypcPQrunmJk212dcPGPxbBtB6Y',
- 'is_coinbase': False,
- 'num_sig': 1,
- 'prevout_hash': '8e4d173db094786cc128b0c12eebc2200c0d8bfc3ad04ba39f487222d18bae3c',
- 'prevout_n': 0,
- 'pubkeys': ['047b9f9014f8d0d6f24dcaf5681b6ab185bd821e0fcce29d84e0452845baf1b2dbe332a7cd4dbdab786adda6d71b2188298c756b265c63de2794f7317b71a7ac02'],
- 'scriptSig': '48304502203f1ff200490d18bcb802c7cf7ba4264727b089f1db6746a62997285b5ac77969022100e495591ea5111bb23a782984736f32942570fda781b7ed085fc8c88a9756aaac0141047b9f9014f8d0d6f24dcaf5681b6ab185bd821e0fcce29d84e0452845baf1b2dbe332a7cd4dbdab786adda6d71b2188298c756b265c63de2794f7317b71a7ac02',
- 'sequence': 4294967295,
- 'signatures': ['304502203f1ff200490d18bcb802c7cf7ba4264727b089f1db6746a62997285b5ac77969022100e495591ea5111bb23a782984736f32942570fda781b7ed085fc8c88a9756aaac'],
- 'x_pubkeys': ['047b9f9014f8d0d6f24dcaf5681b6ab185bd821e0fcce29d84e0452845baf1b2dbe332a7cd4dbdab786adda6d71b2188298c756b265c63de2794f7317b71a7ac02']}],
- 'lockTime': 0,
- 'outputs': [{'address': '1JtBahwvii2pRkBmb4QMfcJQux1rk3Jkbq',
- 'prevout_n': 0,
- 'scriptPubKey': '76a914c4282f6060b811ee695ebb2068b8788213451d6a88ac',
- 'type': 'address',
- 'value': 599990800}],
- 'version': 1}
- self.assertEquals(result, expected)
-
- network = NetworkMock([])
- tx = transaction.Transaction.sweep(privkeys, network, to_address, fee=5000)
- self.assertEquals(tx, None)
-
- privkeys = []
- tx = transaction.Transaction.sweep(privkeys, network, to_address, fee=5000)
- self.assertEquals(tx, None)
class NetworkMock(object):
diff --git a/lib/transaction.py b/lib/transaction.py
index fa4636f..16202b7 100644
--- a/lib/transaction.py
+++ b/lib/transaction.py
@@ -470,7 +470,14 @@ class Transaction:
return self.raw
def __init__(self, raw):
- self.raw = raw.strip() if raw else None
+ if raw is None:
+ self.raw = None
+ elif type(raw) in [str, unicode]:
+ self.raw = raw.strip() if raw else None
+ elif type(raw) is dict:
+ self.raw = raw['hex']
+ else:
+ raise BaseException("cannot initialize transaction", raw)
self.inputs = None
def update(self, raw):
diff --git a/lib/version.py b/lib/version.py
index 887effa..2a2f71c 100644
--- a/lib/version.py
+++ b/lib/version.py
@@ -1,4 +1,4 @@
-ELECTRUM_VERSION = '2.5.1' # version of the client package
+ELECTRUM_VERSION = '2.5.2' # version of the client package
PROTOCOL_VERSION = '0.10' # protocol version requested
NEW_SEED_VERSION = 11 # electrum versions >= 2.0
OLD_SEED_VERSION = 4 # electrum versions < 2.0
diff --git a/lib/wallet.py b/lib/wallet.py
index 0fab120..b54af7a 100644
--- a/lib/wallet.py
+++ b/lib/wallet.py
@@ -125,6 +125,10 @@ class WalletStorage(PrintError):
f.write(s)
f.flush()
os.fsync(f.fileno())
+
+ if 'ANDROID_DATA' not in os.environ:
+ import stat
+ mode = os.stat(self.path).st_mode if os.path.exists(self.path) else stat.S_IREAD | stat.S_IWRITE
# perform atomic write on POSIX systems
try:
os.rename(temp_path, self.path)
@@ -133,7 +137,7 @@ class WalletStorage(PrintError):
os.rename(temp_path, self.path)
if 'ANDROID_DATA' not in os.environ:
import stat
- os.chmod(self.path,stat.S_IREAD | stat.S_IWRITE)
+ os.chmod(self.path, mode)
self.print_error("saved")
@@ -772,7 +776,7 @@ class Abstract_Wallet(PrintError):
try:
self.txi.pop(tx_hash)
self.txo.pop(tx_hash)
- except KeyErrror:
+ except KeyError:
self.print_error("tx was not in history", tx_hash)
def receive_tx_callback(self, tx_hash, tx, tx_height):
@@ -1043,6 +1047,8 @@ class Abstract_Wallet(PrintError):
def send_tx(self, tx):
# asynchronous
self.tx_event.clear()
+ # fixme: this does not handle the case where server does not answer
+ assert self.network.interface, "Not connected."
self.network.send([('blockchain.transaction.broadcast', [str(tx)])], self.on_broadcast)
return tx.hash()
@@ -1129,8 +1135,28 @@ class Abstract_Wallet(PrintError):
self.verifier = None
self.storage.put('stored_height', self.get_local_height(), True)
- def restore(self, cb):
- pass
+ def restore(self, callback):
+ from i18n import _
+ def wait_for_wallet():
+ self.set_up_to_date(False)
+ while not self.is_up_to_date():
+ msg = "%s\n%s %d"%(
+ _("Please wait..."),
+ _("Addresses generated:"),
+ len(self.addresses(True)))
+ apply(callback, (msg,))
+ time.sleep(0.1)
+ def wait_for_network():
+ while not self.network.is_connected():
+ msg = "%s \n" % (_("Connecting..."))
+ apply(callback, (msg,))
+ time.sleep(0.1)
+ # wait until we are connected, because the user might have selected another server
+ if self.network:
+ wait_for_network()
+ wait_for_wallet()
+ else:
+ self.synchronize()
def get_accounts(self):
return self.accounts
@@ -1254,12 +1280,16 @@ class Abstract_Wallet(PrintError):
def can_change_password(self):
return not self.is_watching_only()
- def get_unused_address(self, account):
+ def get_unused_addresses(self, account):
# fixme: use slots from expired requests
domain = self.get_account_addresses(account, include_change=False)
- for addr in domain:
- if not self.history.get(addr) and addr not in self.receive_requests.keys():
- return addr
+ return [addr for addr in domain if not self.history.get(addr)
+ and addr not in self.receive_requests.keys()]
+
+ def get_unused_address(self, account):
+ addrs = self.get_unused_addresses(account)
+ if addrs:
+ return addrs[0]
def get_payment_request(self, addr, config):
import util
@@ -1499,32 +1529,6 @@ class Deterministic_Wallet(Abstract_Wallet):
for account in self.accounts.values():
account.synchronize(self)
- def restore(self, callback):
- from i18n import _
- def wait_for_wallet():
- self.set_up_to_date(False)
- while not self.is_up_to_date():
- msg = "%s\n%s %d"%(
- _("Please wait..."),
- _("Addresses generated:"),
- len(self.addresses(True)))
-
- apply(callback, (msg,))
- time.sleep(0.1)
-
- def wait_for_network():
- while not self.network.is_connected():
- msg = "%s \n" % (_("Connecting..."))
- apply(callback, (msg,))
- time.sleep(0.1)
-
- # wait until we are connected, because the user might have selected another server
- if self.network:
- wait_for_network()
- wait_for_wallet()
- else:
- self.synchronize()
-
def is_beyond_limit(self, address, account, is_change):
if type(account) == ImportedAccount:
return False
@@ -2077,3 +2081,21 @@ class Wallet(object):
self.storage.put('use_encryption', self.use_encryption, True)
self.create_main_account(password)
return self
+
+ @classmethod
+ def from_text(klass, text, password, storage):
+ if Wallet.is_xprv(text):
+ wallet = klass.from_xprv(text, password, storage)
+ elif Wallet.is_old_mpk(text):
+ wallet = klass.from_old_mpk(text, storage)
+ elif Wallet.is_xpub(text):
+ wallet = klass.from_xpub(text, storage)
+ elif Wallet.is_address(text):
+ wallet = klass.from_address(text, storage)
+ elif Wallet.is_private_key(text):
+ wallet = klass.from_private_key(text, password, storage)
+ elif Wallet.is_seed(text):
+ wallet = klass.from_seed(text, password, storage)
+ else:
+ raise BaseException('Invalid seedphrase or key')
+ return wallet
diff --git a/lib/websockets.py b/lib/websockets.py
index 8014ef2..65c9ded 100644
--- a/lib/websockets.py
+++ b/lib/websockets.py
@@ -21,8 +21,8 @@ from collections import defaultdict
try:
from SimpleWebSocketServer import WebSocket, SimpleSSLWebSocketServer
except ImportError:
- print "install SimpleWebSocketServer"
- sys.exit()
+ import sys
+ sys.exit("install SimpleWebSocketServer")
import util
@@ -93,7 +93,7 @@ class WsClientThread(util.DaemonThread):
except Queue.Empty:
continue
id = r.get('id')
- if id is None:
+ if id is None:
method = r.get('method')
params = r.get('params')
else:
diff --git a/plugins/exchange_rate.py b/plugins/exchange_rate.py
index c8a8e8b..7e08d87 100644
--- a/plugins/exchange_rate.py
+++ b/plugins/exchange_rate.py
@@ -112,8 +112,9 @@ class BitcoinAverage(ExchangeBase):
class BitcoinVenezuela(ExchangeBase):
def get_rates(self, ccy):
json = self.get_json('api.bitcoinvenezuela.com', '/')
- return dict([(r, Decimal(json['BTC'][r]))
- for r in json['BTC']])
+ rates = [(r, json['BTC'][r]) for r in json['BTC']
+ if json['BTC'][r] is not None] # Giving NULL for LTC
+ return dict(rates)
def protocol(self):
return "http"
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-bitcoin/electrum.git
More information about the Pkg-bitcoin-commits
mailing list