electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit f02d18226bdf7f9463824e74c411ed9d113fc130
parent d304ccdf17be860b2828c1b6b31a6ba7aaa32020
Author: Dmitry Sorokin <asfins@gmail.com>
Date:   Sat,  4 Feb 2017 17:48:13 +0300

misc ui and lib fixes for py3

Diffstat:
Mgui/qt/main_window.py | 27+++++++++++----------------
Mgui/qt/transaction_dialog.py | 4++--
Dlib/account.py | 0
Mlib/base_wizard.py | 8++------
Mlib/bitcoin.py | 21+++++++++------------
Mlib/blockchain.py | 27+++++++++------------------
Mlib/util.py | 2+-
Mlib/verifier.py | 12++----------
Mlib/wallet.py | 5-----
9 files changed, 36 insertions(+), 70 deletions(-)

diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -1888,7 +1888,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): @protected def do_sign(self, address, message, signature, password): - address = str(address.text()).strip() + address = address.text().strip() message = message.toPlainText().strip() if not bitcoin.is_address(address): self.show_message('Invalid Bitcoin address.') @@ -1901,12 +1901,12 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): return task = partial(self.wallet.sign_message, address, message, password) def show_signed_message(sig): - signature.setText(base64.b64encode(sig)) + signature.setText(base64.b64encode(sig).decode('ascii')) self.wallet.thread.add(task, on_success=show_signed_message) def do_verify(self, address, message, signature): - address = str(address.text()).strip() - message = message.toPlainText().strip() + address = address.text().strip() + message = message.toPlainText().strip().encode('utf8') if not bitcoin.is_address(address): self.show_message('Invalid Bitcoin address.') return @@ -1917,14 +1917,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): # This can throw on invalid base64 sig = base64.b64decode(str(signature.toPlainText())) verified = bitcoin.verify_message(address, sig, message) - except: + except Exception as e: verified = False if verified: self.show_message(_("Signature verified")) else: self.show_error(_("Wrong signature")) - def sign_verify_message(self, address=''): d = WindowModalDialog(self, _('Sign/verify Message')) d.setMinimumSize(410, 290) @@ -1964,23 +1963,21 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): @protected def do_decrypt(self, message_e, pubkey_e, encrypted_e, password): - cyphertext = str(encrypted_e.toPlainText()) - task = partial(self.wallet.decrypt_message, str(pubkey_e.text()), - cyphertext, password) - self.wallet.thread.add(task, on_success=message_e.setText) + cyphertext = encrypted_e.toPlainText() + task = partial(self.wallet.decrypt_message, pubkey_e.text(), cyphertext, password) + self.wallet.thread.add(task, on_success=lambda text: message_e.setText(text.decode('utf8'))) def do_encrypt(self, message_e, pubkey_e, encrypted_e): message = message_e.toPlainText() - message = message.encode('utf-8') + message = message.encode('utf8') try: encrypted = bitcoin.encrypt_message(message, pubkey_e.text()) - encrypted_e.setText(encrypted) + encrypted_e.setText(encrypted.decode('ascii')) except BaseException as e: traceback.print_exc(file=sys.stdout) self.show_warning(str(e)) - - def encrypt_message(self, address = ''): + def encrypt_message(self, address=''): d = WindowModalDialog(self, _('Encrypt/decrypt Message')) d.setMinimumSize(610, 490) @@ -2025,7 +2022,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): d = PasswordDialog(parent, msg) return d.run() - def tx_from_text(self, txt): from electrum.transaction import tx_from_str, Transaction try: @@ -2059,7 +2055,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): return self.show_transaction(tx) - def read_tx_from_file(self): fileName = self.getOpenFileName(_("Select your transaction file"), "*.txn") if not fileName: diff --git a/gui/qt/transaction_dialog.py b/gui/qt/transaction_dialog.py @@ -42,6 +42,7 @@ from electrum.bitcoin import base_encode from electrum.i18n import _ from electrum.plugins import run_hook +from lib.util import bfh from .util import * dialogs = [] # Otherwise python randomly garbage collects the dialogs... @@ -150,14 +151,13 @@ class TxDialog(QDialog, MessageBoxMixin): dialogs.remove(self) def show_qr(self): - text = str(self.tx).decode('hex') + text = bfh(str(self.tx)) text = base_encode(text, base=43) try: self.main_window.show_qrcode(text, 'Transaction', parent=self) except Exception as e: self.show_message(str(e)) - def sign(self): def sign_done(success): if success: diff --git a/lib/account.py b/lib/account.py diff --git a/lib/base_wizard.py b/lib/base_wizard.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +# -*- coding: utf-8 -*- # # Electrum - lightweight Bitcoin client # Copyright (C) 2016 Thomas Voegtlin @@ -22,12 +22,7 @@ # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals -import six import os from . import bitcoin from . import keystore @@ -36,6 +31,7 @@ from .wallet import Wallet, Imported_Wallet, Standard_Wallet, Multisig_Wallet, w from .i18n import _ from .plugins import run_hook + class BaseWizard(object): def __init__(self, config, storage): diff --git a/lib/bitcoin.py b/lib/bitcoin.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -#!/usr/bin/env python # # Electrum - lightweight Bitcoin client # Copyright (C) 2011 thomasv@gitorious @@ -100,8 +99,6 @@ except: def aes_encrypt_with_iv(key, iv, data): assert_bytes(key, iv, data) - if six.PY2: - key, iv, data = map(str, (key, iv, data)) if AES: padlen = 16 - (len(data) % 16) if padlen == 0: @@ -117,8 +114,6 @@ def aes_encrypt_with_iv(key, iv, data): def aes_decrypt_with_iv(key, iv, data): assert_bytes(key, iv, data) - if six.PY2: - key, iv, data = map(str, (key, iv, data)) if AES: cipher = AES.new(key, AES.MODE_CBC, iv) data = cipher.decrypt(data) @@ -135,7 +130,7 @@ def aes_decrypt_with_iv(key, iv, data): def EncodeAES(secret, s): assert_bytes(s) - iv = _bytes(os.urandom(16)) + iv = bytes(os.urandom(16)) # aes_cbc = pyaes.AESModeOfOperationCBC(secret, iv=iv) # aes = pyaes.Encrypter(aes_cbc) # e = iv + aes.feed(s) + aes.feed() @@ -144,7 +139,7 @@ def EncodeAES(secret, s): return base64.b64encode(e) def DecodeAES(secret, e): - e = _bytes(base64.b64decode(e)) + e = bytes(base64.b64decode(e)) iv, e = e[:16], e[16:] # aes_cbc = pyaes.AESModeOfOperationCBC(secret, iv=iv) # aes = pyaes.Decrypter(aes_cbc) @@ -289,6 +284,7 @@ def hash_160(public_key): md.update(sha256(public_key)) return md.digest() + def hash_160_to_bc_address(h160, addrtype, witness_program_version=1): s = bytes([addrtype]) if addrtype == ADDRTYPE_P2WPKH: @@ -302,6 +298,7 @@ def bc_address_to_hash_160(addr): _bytes = base_decode(addr, 25, base=58) return _bytes[0], _bytes[1:21] + def hash160_to_p2pkh(h160): return hash_160_to_bc_address(h160, ADDRTYPE_P2PKH) @@ -309,11 +306,13 @@ def hash160_to_p2pkh(h160): def hash160_to_p2sh(h160): return hash_160_to_bc_address(h160, ADDRTYPE_P2SH) + def public_key_to_p2pkh(public_key): return hash160_to_p2pkh(hash_160(public_key)) + def public_key_to_p2wpkh(public_key): - return hash160_to_bc_address(hash_160(public_key), ADDRTYPE_P2WPKH) + return hash_160_to_bc_address(hash_160(public_key), ADDRTYPE_P2WPKH) @@ -512,14 +511,12 @@ from ecdsa.util import string_to_number, number_to_string def msg_magic(message): varint = var_int(len(message)) - if six.PY3: - encoded_varint = varint.encode('ascii') - else: - encoded_varint = b"".join([chr(int(varint[i:i+2], 16)) for i in range(0, len(varint), 2)]) + encoded_varint = varint.encode('ascii') return b"\x18Bitcoin Signed Message:\n" + encoded_varint + message def verify_message(address, sig, message): + assert_bytes(sig, message) try: h = Hash(msg_magic(message)) public_key, compressed = pubkey_from_signature(sig, h) diff --git a/lib/blockchain.py b/lib/blockchain.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python -# # Electrum - lightweight Bitcoin client # Copyright (C) 2012 thomasv@ecdsa.org # @@ -22,14 +20,6 @@ # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -import six - - import os import threading @@ -100,8 +90,9 @@ def can_connect(header): class Blockchain(util.PrintError): - - '''Manages blockchain headers and their verification''' + """ + Manages blockchain headers and their verification + """ def __init__(self, config, checkpoint, parent_id): self.config = config @@ -165,10 +156,10 @@ class Blockchain(util.PrintError): raise BaseException("insufficient proof of work: %s vs target %s" % (int('0x' + _hash, 16), target)) def verify_chunk(self, index, data): - num = len(data) / 80 + num = len(data) // 80 prev_header = None if index != 0: - prev_header = self.read_header(index*2016 - 1) + prev_header = self.read_header(index * 2016 - 1) bits, target = self.get_target(index) for i in range(num): raw_header = data[i*80:(i+1) * 80] @@ -294,17 +285,17 @@ class Blockchain(util.PrintError): nTargetTimespan = 14 * 24 * 60 * 60 nActualTimespan = max(nActualTimespan, nTargetTimespan / 4) nActualTimespan = min(nActualTimespan, nTargetTimespan * 4) - new_target = min(MAX_TARGET, (target*nActualTimespan) / nTargetTimespan) + new_target = min(MAX_TARGET, (target * nActualTimespan) / nTargetTimespan) # convert new target to bits c = ("%064x" % new_target)[2:] while c[:2] == '00' and len(c) > 6: c = c[2:] - bitsN, bitsBase = len(c) / 2, int('0x' + c[:6], 16) + bitsN, bitsBase = len(c) // 2, int('0x' + c[:6], 16) if bitsBase >= 0x800000: bitsN += 1 bitsBase >>= 8 new_bits = bitsN << 24 | bitsBase - return new_bits, bitsBase << (8 * (bitsN-3)) + return new_bits, bitsBase << (8 * (bitsN - 3)) def can_connect(self, header, check_height=True): height = header['block_height'] @@ -327,7 +318,7 @@ class Blockchain(util.PrintError): def connect_chunk(self, idx, hexdata): try: - data = hexdata.decode('hex') + data = bfh(hexdata) self.verify_chunk(idx, data) #self.print_error("validated chunk %d" % idx) self.save_chunk(idx, data) diff --git a/lib/util.py b/lib/util.py @@ -332,7 +332,7 @@ def bfh(x): elif isinstance(x, (list, tuple, map)): return [bfh(sub) for sub in x] else: - raise TypeError('Unexpected type: ' + type(x)) + raise TypeError('Unexpected type: ' + str(type(x))) def bh2u(x): diff --git a/lib/verifier.py b/lib/verifier.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python -# # Electrum - Lightweight Bitcoin Client # Copyright (c) 2012 Thomas Voegtlin # @@ -22,12 +20,6 @@ # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -import six from .util import ThreadJob from .bitcoin import * @@ -48,7 +40,7 @@ class SPV(ThreadJob): unverified = self.wallet.get_unverified_txs() for tx_hash, tx_height in unverified.items(): # do not request merkle branch before headers are available - if tx_height>0 and tx_hash not in self.merkle_roots and tx_height <= lh: + if (tx_height > 0) and (tx_hash not in self.merkle_roots) and (tx_height <= lh): request = ('blockchain.transaction.get_merkle', [tx_hash, tx_height]) self.network.send([request], self.verify_merkle) @@ -86,7 +78,7 @@ class SPV(ThreadJob): h = hash_decode(target_hash) for i in range(len(merkle_s)): item = merkle_s[i] - h = Hash( hash_decode(item) + h ) if ((pos >> i) & 1) else Hash( h + hash_decode(item) ) + h = Hash(hash_decode(item) + h) if ((pos >> i) & 1) else Hash(h + hash_decode(item)) return hash_encode(h) def undo_verifications(self): diff --git a/lib/wallet.py b/lib/wallet.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python -# # Electrum - lightweight Bitcoin client # Copyright (C) 2015 Thomas Voegtlin # @@ -73,7 +71,6 @@ TX_STATUS = [ ] - class Abstract_Wallet(PrintError): """ Wallet classes are created to handle various address generation methods. @@ -297,7 +294,6 @@ class Abstract_Wallet(PrintError): self.verifier.merkle_roots.pop(tx_hash, None) # tx will be verified only if height > 0 - print('unverif', tx_hash, tx_height) if tx_hash not in self.verified_tx: self.unverified_tx[tx_hash] = tx_height @@ -477,7 +473,6 @@ class Abstract_Wallet(PrintError): return tx_hash, status, label, can_broadcast, can_bump, amount, fee, height, conf, timestamp, exp_n - def get_addr_io(self, address): h = self.history.get(address, []) received = {}