tmisc ui and lib fixes for py3 - electrum - Electrum Bitcoin wallet
 (HTM) git clone https://git.parazyd.org/electrum
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
       ---
 (DIR) commit f02d18226bdf7f9463824e74c411ed9d113fc130
 (DIR) parent d304ccdf17be860b2828c1b6b31a6ba7aaa32020
 (HTM) Author: Dmitry Sorokin <asfins@gmail.com>
       Date:   Sat,  4 Feb 2017 17:48:13 +0300
       
       misc ui and lib fixes for py3
       
       Diffstat:
         M gui/qt/main_window.py               |      27 +++++++++++----------------
         M gui/qt/transaction_dialog.py        |       4 ++--
         D lib/account.py                      |       0 
         M lib/base_wizard.py                  |       8 ++------
         M lib/bitcoin.py                      |      21 +++++++++------------
         M lib/blockchain.py                   |      27 +++++++++------------------
         M lib/util.py                         |       2 +-
         M lib/verifier.py                     |      12 ++----------
         M lib/wallet.py                       |       5 -----
       
       9 files changed, 36 insertions(+), 70 deletions(-)
       ---
 (DIR) diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -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.')
       t@@ -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
       t@@ -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)
       t@@ -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)
        
       t@@ -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:
       t@@ -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:
 (DIR) diff --git a/gui/qt/transaction_dialog.py b/gui/qt/transaction_dialog.py
       t@@ -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...
       t@@ -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:
 (DIR) diff --git a/lib/account.py b/lib/account.py
 (DIR) diff --git a/lib/base_wizard.py b/lib/base_wizard.py
       t@@ -1,4 +1,4 @@
       -#!/usr/bin/env python
       +# -*- coding: utf-8 -*-
        #
        # Electrum - lightweight Bitcoin client
        # Copyright (C) 2016 Thomas Voegtlin
       t@@ -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
       t@@ -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):
 (DIR) diff --git a/lib/bitcoin.py b/lib/bitcoin.py
       t@@ -1,5 +1,4 @@
        # -*- coding: utf-8 -*-
       -#!/usr/bin/env python
        #
        # Electrum - lightweight Bitcoin client
        # Copyright (C) 2011 thomasv@gitorious
       t@@ -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:
       t@@ -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)
       t@@ -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()
       t@@ -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)
       t@@ -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:
       t@@ -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)
        
       t@@ -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)
        
        
        
       t@@ -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)
 (DIR) diff --git a/lib/blockchain.py b/lib/blockchain.py
       t@@ -1,5 +1,3 @@
       -#!/usr/bin/env python
       -#
        # Electrum - lightweight Bitcoin client
        # Copyright (C) 2012 thomasv@ecdsa.org
        #
       t@@ -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
        
       t@@ -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
       t@@ -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]
       t@@ -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']
       t@@ -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)
 (DIR) diff --git a/lib/util.py b/lib/util.py
       t@@ -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):
 (DIR) diff --git a/lib/verifier.py b/lib/verifier.py
       t@@ -1,5 +1,3 @@
       -#!/usr/bin/env python
       -#
        # Electrum - Lightweight Bitcoin Client
        # Copyright (c) 2012 Thomas Voegtlin
        #
       t@@ -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 *
        
       t@@ -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)
       t@@ -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):
 (DIR) diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -1,5 +1,3 @@
       -#!/usr/bin/env python
       -#
        # Electrum - lightweight Bitcoin client
        # Copyright (C) 2015 Thomas Voegtlin
        #
       t@@ -73,7 +71,6 @@ TX_STATUS = [
        ]
        
        
       -
        class Abstract_Wallet(PrintError):
            """
            Wallet classes are created to handle various address generation methods.
       t@@ -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
        
       t@@ -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 = {}