URI: 
       tpy3 in qtgui - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit d304ccdf17be860b2828c1b6b31a6ba7aaa32020
   DIR parent 5be78950ca31ba903b4bd0f575511eeb732e114c
  HTML Author: Dmitry Sorokin <asfins@gmail.com>
       Date:   Mon, 30 Jan 2017 12:36:56 +0300
       
       py3 in qtgui
       
       Diffstat:
         M electrum                            |      10 +++++-----
         M gui/qt/address_list.py              |       4 ++--
         M gui/qt/amountedit.py                |       2 +-
         M gui/qt/console.py                   |       7 ++-----
         M gui/qt/contact_list.py              |      10 +++++-----
         M gui/qt/history_list.py              |       6 +++---
         M gui/qt/installwizard.py             |       6 +++---
         M gui/qt/invoice_list.py              |       6 ++++--
         M gui/qt/main_window.py               |      36 ++++++++++++++++----------------
         M gui/qt/network_dialog.py            |       2 +-
         M gui/qt/password_dialog.py           |       6 +++---
         M gui/qt/paytoedit.py                 |      12 ++++++------
         M gui/qt/qrtextedit.py                |       6 +++---
         M gui/qt/seed_dialog.py               |       7 ++-----
         M gui/qt/util.py                      |      20 ++++++++++----------
         M gui/qt/utxo_list.py                 |       2 +-
         M lib/bitcoin.py                      |       9 +++++----
         M lib/commands.py                     |       8 ++++----
         M lib/daemon.py                       |      40 ++++++++++++++++++-------------
         M lib/exchange_rate.py                |       2 +-
         M lib/interface.py                    |      22 ++++++++++++++--------
         M lib/network.py                      |      33 +++++++++++++++++++------------
         M lib/paymentrequest.py               |      12 ++++++------
         M lib/synchronizer.py                 |       8 ++++----
         M lib/transaction.py                  |      10 +++++-----
         M lib/util.py                         |     125 +++++++-------------------------
         M lib/wallet.py                       |      25 +++++++++----------------
         M lib/x509.py                         |     151 ++++++++++++++-----------------
       
       28 files changed, 255 insertions(+), 332 deletions(-)
       ---
   DIR diff --git a/electrum b/electrum
       t@@ -48,11 +48,11 @@ if jnius:
            threading.Thread.run = thread_check_run
        
        # monkeypatch unicode constructor for py3
       -if six.PY3:
       -    import builtins
       -    builtins.unicode = str
       -    builtins.QString = str
       -    builtins.long = int
       +# if six.PY3:
       +#     import builtins
       +    # builtins.unicode = str
       +    # builtins.QString = str
       +    # builtins.long = int
        
        script_dir = os.path.dirname(os.path.realpath(__file__))
        is_bundle = getattr(sys, 'frozen', False)
   DIR diff --git a/gui/qt/address_list.py b/gui/qt/address_list.py
       t@@ -48,7 +48,7 @@ class AddressList(MyTreeWidget):
            def on_update(self):
                self.wallet = self.parent.wallet
                item = self.currentItem()
       -        current_address = item.data(0, Qt.UserRole).toString() if item else None
       +        current_address = item.data(0, Qt.UserRole) if item else None
                self.clear()
                receiving_addresses = self.wallet.get_receiving_addresses()
                change_addresses = self.wallet.get_change_addresses()
       t@@ -97,7 +97,7 @@ class AddressList(MyTreeWidget):
                can_delete = self.wallet.can_delete_address()
                selected = self.selectedItems()
                multi_select = len(selected) > 1
       -        addrs = [unicode(item.text(0)) for item in selected]
       +        addrs = [item.text(0) for item in selected]
                if not addrs:
                    return
                if not multi_select:
   DIR diff --git a/gui/qt/amountedit.py b/gui/qt/amountedit.py
       t@@ -37,7 +37,7 @@ class AmountEdit(MyLineEdit):
                return 8
        
            def numbify(self):
       -        text = unicode(self.text()).strip()
       +        text = self.text().strip()
                if text == '!':
                    self.shortcut.emit()
                    return
   DIR diff --git a/gui/qt/console.py b/gui/qt/console.py
       t@@ -76,7 +76,7 @@ class Console(QtGui.QPlainTextEdit):
        
            def getCommand(self):
                doc = self.document()
       -        curr_line = unicode(doc.findBlockByLineNumber(doc.lineCount() - 1).text())
       +        curr_line = doc.findBlockByLineNumber(doc.lineCount() - 1).text()
                curr_line = curr_line.rstrip()
                curr_line = curr_line[len(self.prompt):]
                return curr_line
       t@@ -86,7 +86,7 @@ class Console(QtGui.QPlainTextEdit):
                    return
        
                doc = self.document()
       -        curr_line = unicode(doc.findBlockByLineNumber(doc.lineCount() - 1).text())
       +        curr_line = doc.findBlockByLineNumber(doc.lineCount() - 1).text()
                self.moveCursor(QtGui.QTextCursor.End)
                for i in range(len(curr_line) - len(self.prompt)):
                    self.moveCursor(QtGui.QTextCursor.Left, QtGui.QTextCursor.KeepAnchor)
       t@@ -95,7 +95,6 @@ class Console(QtGui.QPlainTextEdit):
                self.textCursor().insertText(command)
                self.moveCursor(QtGui.QTextCursor.End)
        
       -
            def show_completions(self, completions):
                if self.completions_visible:
                    self.hide_completions()
       t@@ -113,7 +112,6 @@ class Console(QtGui.QPlainTextEdit):
                self.moveCursor(QtGui.QTextCursor.End)
                self.completions_visible = True
        
       -
            def hide_completions(self):
                if not self.completions_visible:
                    return
       t@@ -125,7 +123,6 @@ class Console(QtGui.QPlainTextEdit):
                self.moveCursor(QtGui.QTextCursor.End)
                self.completions_visible = False
        
       -
            def getConstruct(self, command):
                if self.construct:
                    prev_command = self.construct[-1]
   DIR diff --git a/gui/qt/contact_list.py b/gui/qt/contact_list.py
       t@@ -55,7 +55,7 @@ class ContactList(MyTreeWidget):
            def on_edited(self, item, column, prior):
                if column == 0:  # Remove old contact if renamed
                    self.parent.contacts.pop(prior)
       -        self.parent.set_contact(unicode(item.text(0)), unicode(item.text(1)))
       +        self.parent.set_contact(item.text(0), item.text(1))
        
            def import_contacts(self):
                wallet_folder = self.parent.get_wallet_folder()
       t@@ -72,11 +72,11 @@ class ContactList(MyTreeWidget):
                    menu.addAction(_("New contact"), lambda: self.parent.new_contact_dialog())
                    menu.addAction(_("Import file"), lambda: self.parent.import_contacts())
                else:
       -            names = [unicode(item.text(0)) for item in selected]
       -            keys = [unicode(item.text(1)) for item in selected]
       +            names = [item.text(0) for item in selected]
       +            keys = [item.text(1) for item in selected]
                    column = self.currentColumn()
                    column_title = self.headerItem().text(column)
       -            column_data = '\n'.join([unicode(item.text(column)) for item in selected])
       +            column_data = '\n'.join([item.text(column) for item in selected])
                    menu.addAction(_("Copy %s")%column_title, lambda: self.parent.app.clipboard().setText(column_data))
                    if column in self.editable_columns:
                        menu.addAction(_("Edit %s")%column_title, lambda: self.editItem(item, column))
       t@@ -91,7 +91,7 @@ class ContactList(MyTreeWidget):
        
            def on_update(self):
                item = self.currentItem()
       -        current_key = item.data(0, Qt.UserRole).toString() if item else None
       +        current_key = item.data(0, Qt.UserRole) if item else None
                self.clear()
                for key in sorted(self.parent.contacts.keys()):
                    _type, name = self.parent.contacts[key]
   DIR diff --git a/gui/qt/history_list.py b/gui/qt/history_list.py
       t@@ -77,7 +77,7 @@ class HistoryList(MyTreeWidget):
                self.wallet = self.parent.wallet
                h = self.wallet.get_history(self.get_domain())
                item = self.currentItem()
       -        current_tx = item.data(0, Qt.UserRole).toString() if item else None
       +        current_tx = item.data(0, Qt.UserRole) if item else None
                self.clear()
                fx = self.parent.fx
                if fx: fx.history_used_spot = False
       t@@ -128,7 +128,7 @@ class HistoryList(MyTreeWidget):
                child_count = root.childCount()
                for i in range(child_count):
                    item = root.child(i)
       -            txid = str(item.data(0, Qt.UserRole).toString())
       +            txid = item.data(0, Qt.UserRole)
                    label = self.wallet.get_label(txid)
                    item.setText(3, label)
        
       t@@ -147,7 +147,7 @@ class HistoryList(MyTreeWidget):
                if not item:
                    return
                column = self.currentColumn()
       -        tx_hash = str(item.data(0, Qt.UserRole).toString())
       +        tx_hash = item.data(0, Qt.UserRole)
                if not tx_hash:
                    return
                if column is 0:
   DIR diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
       t@@ -444,8 +444,8 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
        
            @wizard_dialog
            def choice_dialog(self, title, message, choices, run_next):
       -        c_values = map(lambda x: x[0], choices)
       -        c_titles = map(lambda x: x[1], choices)
       +        c_values = [x[0] for x in choices]
       +        c_titles = [x[1] for x in choices]
                clayout = ChoicesLayout(message, c_titles)
                vbox = QVBoxLayout()
                vbox.addLayout(clayout.layout())
       t@@ -473,7 +473,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                vbox.addWidget(line)
                vbox.addWidget(WWLabel(warning))
                self.exec_layout(vbox, title, next_enabled=test(default))
       -        return ' '.join(unicode(line.text()).split())
       +        return ' '.join(line.text().split())
        
            @wizard_dialog
            def show_xpub_dialog(self, xpub, run_next):
   DIR diff --git a/gui/qt/invoice_list.py b/gui/qt/invoice_list.py
       t@@ -73,8 +73,10 @@ class InvoiceList(MyTreeWidget):
            def create_menu(self, position):
                menu = QMenu()
                item = self.itemAt(position)
       -        key = str(item.data(0, 32).toString())
       -        column = self.currentColumn()
       +        if not item:
       +            return
       +        key = item.data(0, 32)
       +        column = self.currentColumn()        
                column_title = self.headerItem().text(column)
                column_data = item.text(column)
                pr = self.parent.invoices.get(key)
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -384,7 +384,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
        
            def open_wallet(self):
                wallet_folder = self.get_wallet_folder()
       -        filename = unicode(QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder))
       +        filename = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder)
                if not filename:
                    return
                self.gui_object.new_window(filename)
       t@@ -393,7 +393,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
            def backup_wallet(self):
                path = self.wallet.storage.path
                wallet_folder = os.path.dirname(path)
       -        filename = unicode( QFileDialog.getSaveFileName(self, _('Enter a filename for the copy of your wallet'), wallet_folder) )
       +        filename = QFileDialog.getSaveFileName(self, _('Enter a filename for the copy of your wallet'), wallet_folder)
                if not filename:
                    return
        
       t@@ -578,16 +578,16 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
        
            # custom wrappers for getOpenFileName and getSaveFileName, that remember the path selected by the user
            def getOpenFileName(self, title, filter = ""):
       -        directory = self.config.get('io_dir', unicode(os.path.expanduser('~')))
       -        fileName = unicode( QFileDialog.getOpenFileName(self, title, directory, filter) )
       +        directory = self.config.get('io_dir', os.path.expanduser('~'))
       +        fileName = QFileDialog.getOpenFileName(self, title, directory, filter)
                if fileName and directory != os.path.dirname(fileName):
                    self.config.set_key('io_dir', os.path.dirname(fileName), True)
                return fileName
        
            def getSaveFileName(self, title, filename, filter = ""):
       -        directory = self.config.get('io_dir', unicode(os.path.expanduser('~')))
       +        directory = self.config.get('io_dir', os.path.expanduser('~'))
                path = os.path.join( directory, filename )
       -        fileName = unicode( QFileDialog.getSaveFileName(self, title, path, filter) )
       +        fileName = QFileDialog.getSaveFileName(self, title, path, filter)
                if fileName and directory != os.path.dirname(fileName):
                    self.config.set_key('io_dir', os.path.dirname(fileName), True)
                return fileName
       t@@ -880,7 +880,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
            def save_payment_request(self):
                addr = str(self.receive_address_e.text())
                amount = self.receive_amount_e.get_amount()
       -        message = unicode(self.receive_message_e.text())
       +        message = self.receive_message_e.text()
                if not message and not amount:
                    self.show_error(_('No message or amount'))
                    return False
       t@@ -982,7 +982,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
            def update_receive_qr(self):
                addr = str(self.receive_address_e.text())
                amount = self.receive_amount_e.get_amount()
       -        message = unicode(self.receive_message_e.text()).encode('utf8')
       +        message = self.receive_message_e.text()
                self.save_request_button.setEnabled((amount is not None) or (message != ""))
                uri = util.create_URI(addr, amount, message)
                self.receive_qr.setData(uri)
       t@@ -1281,7 +1281,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                if self.payment_request and self.payment_request.has_expired():
                    self.show_error(_('Payment request has expired'))
                    return
       -        label = unicode( self.message_e.text() )
       +        label = self.message_e.text()
        
                if self.payment_request:
                    outputs = self.payment_request.get_outputs()
       t@@ -1513,7 +1513,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                if not URI:
                    return
                try:
       -            out = util.parse_URI(unicode(URI), self.on_pr)
       +            out = util.parse_URI(URI, self.on_pr)
                except BaseException as e:
                    self.show_error(_('Invalid bitcoin URI:') + '\n' + str(e))
                    return
       t@@ -1807,7 +1807,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                vbox.addLayout(grid)
                vbox.addLayout(Buttons(CancelButton(d), OkButton(d)))
                if d.exec_():
       -            self.set_contact(unicode(line2.text()), str(line1.text()))
       +            self.set_contact(line2.text(), line1.text())
        
            def show_master_public_keys(self):
                dialog = WindowModalDialog(self, "Master Public Keys")
       t@@ -1848,7 +1848,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                except BaseException as e:
                    self.show_error(str(e))
                    return
       -        from seed_dialog import SeedDialog
       +        from .seed_dialog import SeedDialog
                d = SeedDialog(self, seed, passphrase)
                d.exec_()
        
       t@@ -1889,7 +1889,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
            @protected
            def do_sign(self, address, message, signature, password):
                address  = str(address.text()).strip()
       -        message = unicode(message.toPlainText()).encode('utf-8').strip()
       +        message = message.toPlainText().strip()
                if not bitcoin.is_address(address):
                    self.show_message('Invalid Bitcoin address.')
                    return
       t@@ -1906,7 +1906,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
        
            def do_verify(self, address, message, signature):
                address  = str(address.text()).strip()
       -        message = unicode(message.toPlainText()).encode('utf-8').strip()
       +        message = message.toPlainText().strip()
                if not bitcoin.is_address(address):
                    self.show_message('Invalid Bitcoin address.')
                    return
       t@@ -1970,10 +1970,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                self.wallet.thread.add(task, on_success=message_e.setText)
        
            def do_encrypt(self, message_e, pubkey_e, encrypted_e):
       -        message = unicode(message_e.toPlainText())
       +        message = message_e.toPlainText()
                message = message.encode('utf-8')
                try:
       -            encrypted = bitcoin.encrypt_message(message, str(pubkey_e.text()))
       +            encrypted = bitcoin.encrypt_message(message, pubkey_e.text())
                    encrypted_e.setText(encrypted)
                except BaseException as e:
                    traceback.print_exc(file=sys.stdout)
       t@@ -2386,7 +2386,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                lang_label = HelpLabel(_('Language') + ':', lang_help)
                lang_combo = QComboBox()
                from electrum.i18n import languages
       -        lang_combo.addItems(languages.values())
       +        lang_combo.addItems(list(languages.values()))
                try:
                    index = languages.keys().index(self.config.get("language",''))
                except Exception:
       t@@ -2570,7 +2570,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                msg = _("Install the zbar package to enable this.")
                qr_label = HelpLabel(_('Video Device') + ':', msg)
                qr_combo.setEnabled(qrscanner.libzbar is not None)
       -        on_video_device = lambda x: self.config.set_key("video_device", str(qr_combo.itemData(x).toString()), True)
       +        on_video_device = lambda x: self.config.set_key("video_device", qr_combo.itemData(x), True)
                qr_combo.currentIndexChanged.connect(on_video_device)
                gui_widgets.append((qr_label, qr_combo))
        
   DIR diff --git a/gui/qt/network_dialog.py b/gui/qt/network_dialog.py
       t@@ -386,7 +386,7 @@ class NetworkChoiceLayout(object):
        
            def change_protocol(self, use_ssl):
                p = 's' if use_ssl else 't'
       -        host = unicode(self.server_host.text())
       +        host = self.server_host.text()
                pp = self.servers.get(host, DEFAULT_PORTS)
                if p not in pp.keys():
                    p = pp.keys()[0]
   DIR diff --git a/gui/qt/password_dialog.py b/gui/qt/password_dialog.py
       t@@ -44,7 +44,7 @@ def check_password_strength(password):
            :param password: password entered by user in New Password
            :return: password strength Weak or Medium or Strong
            '''
       -    password = unicode(password)
       +    password = password
            n = math.log(len(set(password)))
            num = re.search("[0-9]", password) is not None and re.match("^[0-9]*$", password) is None
            caps = password != password.upper() and password != password.lower()
       t@@ -156,11 +156,11 @@ class PasswordLayout(object):
        
            def old_password(self):
                if self.kind == PW_CHANGE:
       -            return unicode(self.pw.text()) or None
       +            return self.pw.text() or None
                return None
        
            def new_password(self):
       -        pw = unicode(self.new_pw.text())
       +        pw = self.new_pw.text()
                # Empty passphrases are fine and returned empty.
                if pw == "" and self.kind != PW_PASSPHRASE:
                    pw = None
   DIR diff --git a/gui/qt/paytoedit.py b/gui/qt/paytoedit.py
       t@@ -120,7 +120,7 @@ class PayToEdit(ScanQRTextEdit):
                if self.is_pr:
                    return
                # filter out empty lines
       -        lines = filter(lambda x: x, self.lines())
       +        lines = [i for i in self.lines() if i]
                outputs = []
                total = 0
                self.payto_address = None
       t@@ -180,7 +180,7 @@ class PayToEdit(ScanQRTextEdit):
                return self.outputs[:]
        
            def lines(self):
       -        return unicode(self.toPlainText()).split('\n')
       +        return self.toPlainText().split('\n')
        
            def is_multiline(self):
                return len(self.lines()) > 1
       t@@ -242,14 +242,14 @@ class PayToEdit(ScanQRTextEdit):
                QPlainTextEdit.keyPressEvent(self, e)
        
                ctrlOrShift = e.modifiers() and (Qt.ControlModifier or Qt.ShiftModifier)
       -        if self.c is None or (ctrlOrShift and e.text().isEmpty()):
       +        if self.c is None or (ctrlOrShift and not e.text()):
                    return
        
       -        eow = QString("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=")
       -        hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift;
       +        eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="
       +        hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift
                completionPrefix = self.textUnderCursor()
        
       -        if hasModifier or e.text().isEmpty() or completionPrefix.length() < 1 or eow.contains(e.text().right(1)):
       +        if hasModifier or not e.text() or completionPrefix.length() < 1 or eow.contains(e.text().right(1)):
                    self.c.popup().hide()
                    return
        
   DIR diff --git a/gui/qt/qrtextedit.py b/gui/qt/qrtextedit.py
       t@@ -22,11 +22,11 @@ class ShowQRTextEdit(ButtonsTextEdit):
                run_hook('show_text_edit', self)
        
            def qr_show(self):
       -        from qrcodewidget import QRDialog
       +        from .qrcodewidget import QRDialog
                try:
                    s = str(self.toPlainText())
                except:
       -            s = unicode(self.toPlainText())
       +            s = self.toPlainText()
                QRDialog(s).exec_()
        
            def contextMenuEvent(self, e):
       t@@ -45,7 +45,7 @@ class ScanQRTextEdit(ButtonsTextEdit, MessageBoxMixin):
                run_hook('scan_text_edit', self)
        
            def file_input(self):
       -        fileName = unicode(QFileDialog.getOpenFileName(self, 'select file'))
       +        fileName = QFileDialog.getOpenFileName(self, 'select file')
                if not fileName:
                    return
                with open(fileName, "r") as f:
   DIR diff --git a/gui/qt/seed_dialog.py b/gui/qt/seed_dialog.py
       t@@ -52,7 +52,6 @@ def seed_warning_msg(seed):
            ]) % len(seed.split())
        
        
       -
        class SeedLayout(QVBoxLayout):
            #options
            is_bip39 = False
       t@@ -92,7 +91,6 @@ class SeedLayout(QVBoxLayout):
                self.is_ext = cb_ext.isChecked() if 'ext' in self.options else False
                self.is_bip39 = cb_bip39.isChecked() if 'bip39' in self.options else False
        
       -
            def __init__(self, seed=None, title=None, icon=True, msg=None, options=None, is_seed=None, passphrase=None, parent=None):
                QVBoxLayout.__init__(self)
                self.parent = parent
       t@@ -140,7 +138,7 @@ class SeedLayout(QVBoxLayout):
                self.addWidget(self.seed_warning)
        
            def get_seed(self):
       -        text = unicode(self.seed_e.text())
       +        text = self.seed_e.text()
                return ' '.join(text.split())
        
            def on_edit(self):
       t@@ -159,7 +157,6 @@ class SeedLayout(QVBoxLayout):
                self.parent.next_button.setEnabled(b)
        
        
       -
        class KeysLayout(QVBoxLayout):
            def __init__(self, parent=None, title=None, is_valid=None):
                QVBoxLayout.__init__(self)
       t@@ -171,7 +168,7 @@ class KeysLayout(QVBoxLayout):
                self.addWidget(self.text_e)
        
            def get_text(self):
       -        return unicode(self.text_e.text())
       +        return self.text_e.text()
        
            def on_edit(self):
                b = self.is_valid(self.get_text())
   DIR diff --git a/gui/qt/util.py b/gui/qt/util.py
       t@@ -260,7 +260,7 @@ def line_dialog(parent, title, label, ok_label, default=None):
            l.addWidget(txt)
            l.addLayout(Buttons(CancelButton(dialog), OkButton(dialog, ok_label)))
            if dialog.exec_():
       -        return unicode(txt.text())
       +        return txt.text()
        
        def text_dialog(parent, title, label, ok_label, default=None):
            from qrtextedit import ScanQRTextEdit
       t@@ -275,7 +275,7 @@ def text_dialog(parent, title, label, ok_label, default=None):
            l.addWidget(txt)
            l.addLayout(Buttons(CancelButton(dialog), OkButton(dialog, ok_label)))
            if dialog.exec_():
       -        return unicode(txt.toPlainText())
       +        return txt.toPlainText()
        
        class ChoicesLayout(object):
            def __init__(self, msg, choices, on_clicked=None, checked_index=0):
       t@@ -341,15 +341,15 @@ def filename_field(parent, config, defaultname, select_msg):
        
            hbox = QHBoxLayout()
        
       -    directory = config.get('io_dir', unicode(os.path.expanduser('~')))
       +    directory = config.get('io_dir', os.path.expanduser('~'))
            path = os.path.join( directory, defaultname )
            filename_e = QLineEdit()
            filename_e.setText(path)
        
            def func():
       -        text = unicode(filename_e.text())
       +        text = filename_e.text()
                _filter = "*.csv" if text.endswith(".csv") else "*.json" if text.endswith(".json") else None
       -        p = unicode( QFileDialog.getSaveFileName(None, select_msg, text, _filter))
       +        p = QFileDialog.getSaveFileName(None, select_msg, text, _filter)
                if p:
                    filename_e.setText(p)
        
       t@@ -360,7 +360,7 @@ def filename_field(parent, config, defaultname, select_msg):
            vbox.addLayout(hbox)
        
            def set_csv(v):
       -        text = unicode(filename_e.text())
       +        text = filename_e.text()
                text = text.replace(".json",".csv") if v else text.replace(".csv",".json")
                filename_e.setText(text)
        
       t@@ -409,7 +409,7 @@ class MyTreeWidget(QTreeWidget):
        
            def editItem(self, item, column):
                if column in self.editable_columns:
       -            self.editing_itemcol = (item, column, unicode(item.text(column)))
       +            self.editing_itemcol = (item, column, item.text(column))
                    # Calling setFlags causes on_changed events for some reason
                    item.setFlags(item.flags() | Qt.ItemIsEditable)
                    QTreeWidget.editItem(self, item, column)
       t@@ -471,7 +471,7 @@ class MyTreeWidget(QTreeWidget):
            def on_edited(self, item, column, prior):
                '''Called only when the text actually changes'''
                key = str(item.data(0, Qt.UserRole).toString())
       -        text = unicode(item.text(column))
       +        text = item.text(column)
                self.parent.wallet.set_label(key, text)
                self.parent.history_list.update_labels()
                self.parent.update_completions()
       t@@ -501,10 +501,10 @@ class MyTreeWidget(QTreeWidget):
        
            def filter(self, p):
                columns = self.__class__.filter_columns
       -        p = unicode(p).lower()
       +        p = p.lower()
                self.current_filter = p
                for item in self.get_leaves(self.invisibleRootItem()):
       -            item.setHidden(all([unicode(item.text(column)).lower().find(p) == -1
       +            item.setHidden(all([item.text(column).lower().find(p) == -1
                                        for column in columns]))
        
        
   DIR diff --git a/gui/qt/utxo_list.py b/gui/qt/utxo_list.py
       t@@ -63,7 +63,7 @@ class UTXOList(MyTreeWidget):
                    self.addChild(utxo_item)
        
            def create_menu(self, position):
       -        selected = [str(x.data(0, Qt.UserRole).toString()) for x in self.selectedItems()]
       +        selected = [x.data(0, Qt.UserRole) for x in self.selectedItems()]
                if not selected:
                    return
                menu = QMenu()
   DIR diff --git a/lib/bitcoin.py b/lib/bitcoin.py
       t@@ -28,10 +28,11 @@ import hashlib
        import base64
        import re
        import hmac
       +import os
        
        from lib.util import bfh, bh2u
        from . import version
       -from .util import print_error, InvalidPassword, assert_bytes, _bytes, to_bytes
       +from .util import print_error, InvalidPassword, assert_bytes, to_bytes
        
        import ecdsa
        import pyaes
       t@@ -206,12 +207,12 @@ def op_push(i):
        
        def sha256(x):
            x = to_bytes(x, 'utf8')
       -    return _bytes(hashlib.sha256(x).digest())
       +    return bytes(hashlib.sha256(x).digest())
        
        
        def Hash(x):
            x = to_bytes(x, 'utf8')
       -    out = _bytes(sha256(sha256(x)))
       +    out = bytes(sha256(sha256(x)))
            return out
        
        
       t@@ -363,7 +364,7 @@ def base_decode(v, length, base):
                chars = __b43chars
            long_value = 0
            for (i, c) in enumerate(v[::-1]):
       -        long_value += chars.find(_bytes([c])) * (base**i)
       +        long_value += chars.find(bytes([c])) * (base**i)
            result = bytearray()
            while long_value >= 256:
                div, mod = divmod(long_value, 256)
   DIR diff --git a/lib/commands.py b/lib/commands.py
       t@@ -243,8 +243,8 @@ class Commands:
                tx = Transaction(tx)
                if privkey:
                    pubkey = bitcoin.public_key_from_private_key(privkey)
       -            h160 = bitcoin.hash_160(pubkey.decode('hex'))
       -            x_pubkey = 'fd' + (chr(0) + h160).encode('hex')
       +            h160 = bitcoin.hash_160(bfh(pubkey))
       +            x_pubkey = 'fd' + bh2u(b'\x00' + h160)
                    tx.sign({x_pubkey:privkey})
                else:
                    self.wallet.sign_transaction(tx, password)
       t@@ -266,8 +266,8 @@ class Commands:
            def createmultisig(self, num, pubkeys):
                """Create multisig address"""
                assert isinstance(pubkeys, list), (type(num), type(pubkeys))
       -        redeem_script = transaction.multisig_script(pubkeys, num)
       -        address = bitcoin.hash160_to_p2sh(hash_160(redeem_script.decode('hex')))
       +        redeem_script = Transaction.multisig_script(pubkeys, num)
       +        address = bitcoin.hash160_to_p2sh(hash_160(bfh(redeem_script)))
                return {'address':address, 'redeemScript':redeem_script}
        
            @command('w')
   DIR diff --git a/lib/daemon.py b/lib/daemon.py
       t@@ -33,8 +33,9 @@ import os
        import sys
        import time
        
       -# import jsonrpclib
       -# from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
       +# from jsonrpc import JSONRPCResponseManager
       +import jsonrpclib
       +from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
        
        from .version import ELECTRUM_VERSION
        from .network import Network
       t@@ -47,12 +48,15 @@ from .simple_config import SimpleConfig
        from .plugins import run_hook
        from .exchange_rate import FxThread
        
       +
        def get_lockfile(config):
            return os.path.join(config.path, 'daemon')
        
       +
        def remove_lockfile(lockfile):
            os.unlink(lockfile)
        
       +
        def get_fd_or_server(config):
            '''Tries to create the lockfile, using O_EXCL to
            prevent races.  If it succeeds it returns the FD.
       t@@ -71,6 +75,7 @@ def get_fd_or_server(config):
                # Couldn't connect; remove lockfile and try again.
                remove_lockfile(lockfile)
        
       +
        def get_server(config):
            lockfile = get_lockfile(config)
            while True:
       t@@ -82,7 +87,8 @@ def get_server(config):
                    # Test daemon is running
                    server.ping()
                    return server
       -        except:
       +        except Exception as e:
       +            print_error(e)
                    pass
                if not create_time or create_time < time.time() - 1.0:
                    return None
       t@@ -90,17 +96,17 @@ def get_server(config):
                time.sleep(1.0)
        
        
       -# class RequestHandler(SimpleJSONRPCRequestHandler):
       -#
       -#     def do_OPTIONS(self):
       -#         self.send_response(200)
       -#         self.end_headers()
       -#
       -#     def end_headers(self):
       -#         self.send_header("Access-Control-Allow-Headers",
       -#                          "Origin, X-Requested-With, Content-Type, Accept")
       -#         self.send_header("Access-Control-Allow-Origin", "*")
       -#         SimpleJSONRPCRequestHandler.end_headers(self)
       +class RequestHandler(SimpleJSONRPCRequestHandler):
       +
       +    def do_OPTIONS(self):
       +        self.send_response(200)
       +        self.end_headers()
       +
       +    def end_headers(self):
       +        self.send_header("Access-Control-Allow-Headers",
       +                         "Origin, X-Requested-With, Content-Type, Accept")
       +        self.send_header("Access-Control-Allow-Origin", "*")
       +        SimpleJSONRPCRequestHandler.end_headers(self)
        
        
        class Daemon(DaemonThread):
       t@@ -129,12 +135,12 @@ class Daemon(DaemonThread):
                try:
                    server = SimpleJSONRPCServer((host, port), logRequests=False,
                                                 requestHandler=RequestHandler)
       -        except:
       -            self.print_error('Warning: cannot initialize RPC server on host', host)
       +        except Exception as e:
       +            self.print_error('Warning: cannot initialize RPC server on host', host, e)
                    self.server = None
                    os.close(fd)
                    return
       -        os.write(fd, repr((server.socket.getsockname(), time.time())))
       +        os.write(fd, bytes(repr((server.socket.getsockname(), time.time())), 'utf8'))
                os.close(fd)
                server.timeout = 0.1
                for cmdname in known_commands:
   DIR diff --git a/lib/exchange_rate.py b/lib/exchange_rate.py
       t@@ -290,7 +290,7 @@ class LocalBitcoins(ExchangeBase):
        class MercadoBitcoin(ExchangeBase):
        
            def get_rates(self, ccy):
       -        json = self.get_json('api.bitvalor.com', '/v1/ticker.json')
       +        json = self.get_json('api.bitvalor.com', '/v1/ticker.json')
                return {'BRL': Decimal(json['ticker_1h']['exchanges']['MBT']['last'])}
        
        
   DIR diff --git a/lib/interface.py b/lib/interface.py
       t@@ -38,6 +38,9 @@ import time
        import traceback
        
        import requests
       +
       +from lib import print_error
       +
        ca_path = requests.certs.where()
        
        from . import util
       t@@ -60,6 +63,7 @@ def Connection(server, queue, config_path):
            c.start()
            return c
        
       +
        class TcpConnection(threading.Thread, util.PrintError):
        
            def __init__(self, server, queue, config_path):
       t@@ -131,8 +135,9 @@ class TcpConnection(threading.Thread, util.PrintError):
                            return
                        # try with CA first
                        try:
       -                    s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_path, do_handshake_on_connect=True)
       +                    s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1_1, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_path, do_handshake_on_connect=True)
                        except ssl.SSLError as e:
       +                    print_error(e)
                            s = None
                        if s and self.check_host_name(s.getpeercert(), self.host):
                            self.print_error("SSL certificate signed by CA")
       t@@ -143,7 +148,7 @@ class TcpConnection(threading.Thread, util.PrintError):
                        if s is None:
                            return
                        try:
       -                    s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_NONE, ca_certs=None)
       +                    s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1_1, cert_reqs=ssl.CERT_NONE, ca_certs=None)
                        except ssl.SSLError as e:
                            self.print_error("SSL error retrieving SSL certificate:", e)
                            return
       t@@ -166,9 +171,9 @@ class TcpConnection(threading.Thread, util.PrintError):
                if self.use_ssl:
                    try:
                        s = ssl.wrap_socket(s,
       -                                    ssl_version=ssl.PROTOCOL_SSLv23,
       +                                    ssl_version=ssl.PROTOCOL_TLSv1_1,
                                            cert_reqs=ssl.CERT_REQUIRED,
       -                                    ca_certs= (temporary_path if is_new else cert_path),
       +                                    ca_certs=(temporary_path if is_new else cert_path),
                                            do_handshake_on_connect=True)
                    except ssl.SSLError as e:
                        self.print_error("SSL error:", e)
       t@@ -196,11 +201,11 @@ class TcpConnection(threading.Thread, util.PrintError):
                                os.unlink(cert_path)
                                return
                            self.print_error("wrong certificate")
       +                if e.errno == 104:
       +                    return
                        return
                    except BaseException as e:
                        self.print_error(e)
       -                if e.errno == 104:
       -                    return
                        traceback.print_exc(file=sys.stderr)
                        return
        
       t@@ -216,6 +221,7 @@ class TcpConnection(threading.Thread, util.PrintError):
                    self.print_error("connected")
                self.queue.put((self.server, socket))
        
       +
        class Interface(util.PrintError):
            """The Interface class handles a socket connected to a single remote
            electrum server.  It's exposed API is:
       t@@ -274,7 +280,7 @@ class Interface(util.PrintError):
                n = self.num_requests()
                wire_requests = self.unsent_requests[0:n]
                try:
       -            self.pipe.send_all(map(make_dict, wire_requests))
       +            self.pipe.send_all([make_dict(*r) for r in wire_requests])
                except socket.error as e:
                    self.print_error("socket error:", e)
                    return False
       t@@ -368,13 +374,13 @@ def _match_hostname(name, val):
        
            return val.startswith('*.') and name.endswith(val[1:])
        
       +
        def test_certificates():
            from .simple_config import SimpleConfig
            config = SimpleConfig()
            mydir = os.path.join(config.path, "certs")
            certs = os.listdir(mydir)
            for c in certs:
       -        print(c)
                p = os.path.join(mydir,c)
                with open(p) as f:
                    cert = f.read()
   DIR diff --git a/lib/network.py b/lib/network.py
       t@@ -103,7 +103,7 @@ SERVER_RETRY_INTERVAL = 10
        
        def parse_servers(result):
            """ parse servers list into dict format"""
       -    from version import PROTOCOL_VERSION
       +    from .version import PROTOCOL_VERSION
            servers = {}
            for item in result:
                host = item[1]
       t@@ -123,7 +123,8 @@ def parse_servers(result):
                        if pruning_level == '': pruning_level = '0'
                try:
                    is_recent = cmp(util.normalize_version(version), util.normalize_version(PROTOCOL_VERSION)) >= 0
       -        except Exception:
       +        except Exception as e:
       +            print_error(e)
                    is_recent = False
        
                if out and is_recent:
       t@@ -152,13 +153,15 @@ from .simple_config import SimpleConfig
        
        proxy_modes = ['socks4', 'socks5', 'http']
        
       +
        def serialize_proxy(p):
       -    if type(p) != dict:
       +    if not isinstance(p, dict):
                return None
            return ':'.join([p.get('mode'),p.get('host'), p.get('port'), p.get('user'), p.get('password')])
        
       +
        def deserialize_proxy(s):
       -    if type(s) not in [str, unicode]:
       +    if not isinstance(s, str):
                return None
            if s.lower() == 'none':
                return None
       t@@ -183,15 +186,18 @@ def deserialize_proxy(s):
                proxy["password"] = args[n]
            return proxy
        
       +
        def deserialize_server(server_str):
            host, port, protocol = str(server_str).split(':')
            assert protocol in 'st'
            int(port)    # Throw if cannot be converted to int
            return host, port, protocol
        
       +
        def serialize_server(host, port, protocol):
            return str(':'.join([host, port, protocol]))
        
       +
        class Network(util.DaemonThread):
            """The Network class manages a set of connections to remote electrum
            servers, each connected socket is handled by an Interface() object.
       t@@ -209,7 +215,7 @@ class Network(util.DaemonThread):
                if config is None:
                    config = {}  # Do not use mutables as default values!
                util.DaemonThread.__init__(self)
       -        self.config = SimpleConfig(config) if type(config) == type({}) else config
       +        self.config = SimpleConfig(config) if isinstance(config, dict) else config
                self.num_server = 10 if not self.config.get('oneserver') else 0
                self.blockchains = blockchain.read_blockchains(self.config)
                self.print_error("blockchains", self.blockchains.keys())
       t@@ -390,7 +396,7 @@ class Network(util.DaemonThread):
        
            def get_interfaces(self):
                '''The interfaces that are in connected state'''
       -        return self.interfaces.keys()
       +        return list(self.interfaces.keys())
        
            def get_servers(self):
                if self.irc_servers:
       t@@ -456,7 +462,7 @@ class Network(util.DaemonThread):
        
            def stop_network(self):
                self.print_error("stopping network")
       -        for interface in self.interfaces.values():
       +        for interface in list(self.interfaces.values()):
                    self.close_interface(interface)
                if self.interface:
                    self.close_interface(self.interface)
       t@@ -596,7 +602,7 @@ class Network(util.DaemonThread):
        
            def get_index(self, method, params):
                """ hashable index for subscriptions and cache"""
       -        return str(method) + (':' + str(params[0]) if params  else '')
       +        return str(method) + (':' + str(params[0]) if params else '')
        
            def process_responses(self, interface):
                responses = interface.get_responses()
       t@@ -647,6 +653,7 @@ class Network(util.DaemonThread):
        
            def send(self, messages, callback):
                '''Messages is a list of (method, params) tuples'''
       +        messages = list(messages)
                with self.lock:
                    self.pending_sends.append((messages, callback))
        
       t@@ -730,7 +737,8 @@ class Network(util.DaemonThread):
                        self.connection_down(server)
        
                # Send pings and shut down stale interfaces
       -        for interface in self.interfaces.values():
       +        # must use copy of values
       +        for interface in list(self.interfaces.values()):
                    if interface.has_timed_out():
                        self.connection_down(interface.server)
                    elif interface.ping_required():
       t@@ -1059,15 +1067,14 @@ class Network(util.DaemonThread):
                    host, port, protocol = server.split(':')
                    self.set_parameters(host, port, protocol, proxy, auto_connect)
        
       -
            def get_local_height(self):
                return self.blockchain().height()
        
            def synchronous_get(self, request, timeout=30):
       -        queue = queue.Queue()
       -        self.send([request], queue.put)
       +        q = queue.Queue()
       +        self.send([request], q.put)
                try:
       -            r = queue.get(True, timeout)
       +            r = q.get(True, timeout)
                except queue.Empty:
                    raise BaseException('Server did not answer')
                if r.get('error'):
   DIR diff --git a/lib/paymentrequest.py b/lib/paymentrequest.py
       t@@ -51,7 +51,7 @@ except ImportError:
        
        from . import bitcoin
        from . import util
       -from .util import print_error
       +from .util import print_error, bh2u, bfh
        from . import transaction
        from . import x509
        from . import rsakey
       t@@ -126,7 +126,7 @@ class PaymentRequest:
            def parse(self, r):
                if self.error:
                    return
       -        self.id = bitcoin.sha256(r)[0:16].encode('hex')
       +        self.id = bh2u(bitcoin.sha256(r)[0:16])
                try:
                    self.data = pb2.PaymentRequest()
                    self.data.ParseFromString(r)
       t@@ -321,7 +321,7 @@ def make_unsigned_request(req):
            if amount is None:
                amount = 0
            memo = req['memo']
       -    script = Transaction.pay_script(TYPE_ADDRESS, addr).decode('hex')
       +    script = bfh(Transaction.pay_script(TYPE_ADDRESS, addr))
            outputs = [(script, amount)]
            pd = pb2.PaymentDetails()
            for script, amount in outputs:
       t@@ -445,7 +445,7 @@ def serialize_request(req):
            signature = req.get('sig')
            requestor = req.get('name')
            if requestor and signature:
       -        pr.signature = signature.decode('hex')
       +        pr.signature = bfh(signature)
                pr.pki_type = 'dnssec+btc'
                pr.pki_data = str(requestor)
            return pr
       t@@ -477,7 +477,7 @@ class InvoiceStore(object):
            def load(self, d):
                for k, v in d.items():
                    try:
       -                pr = PaymentRequest(v.get('hex').decode('hex'))
       +                pr = bfh(PaymentRequest(v.get('hex')))
                        pr.tx = v.get('txid')
                        pr.requestor = v.get('requestor')
                        self.invoices[k] = pr
       t@@ -499,7 +499,7 @@ class InvoiceStore(object):
                l = {}
                for k, pr in self.invoices.items():
                    l[k] = {
       -                'hex': str(pr).encode('hex'),
       +                'hex': bh2u(pr),
                        'requestor': pr.requestor,
                        'txid': pr.tx
                    }
   DIR diff --git a/lib/synchronizer.py b/lib/synchronizer.py
       t@@ -33,7 +33,7 @@ import hashlib
        
        from .bitcoin import Hash, hash_encode
        from .transaction import Transaction
       -from .util import print_error, print_msg, ThreadJob
       +from .util import print_error, print_msg, ThreadJob, bh2u
        
        
        class Synchronizer(ThreadJob):
       t@@ -89,7 +89,7 @@ class Synchronizer(ThreadJob):
                status = ''
                for tx_hash, height in h:
                    status += tx_hash + ':%d:' % height
       -        return hashlib.sha256(status).digest().encode('hex')
       +        return bh2u(hashlib.sha256(status.encode('ascii')).digest())
        
            def addr_subscription_response(self, response):
                params, result = self.parse_response(response)
       t@@ -114,7 +114,7 @@ class Synchronizer(ThreadJob):
                self.print_error("receiving history", addr, len(result))
                server_status = self.requested_histories[addr]
                hashes = set(map(lambda item: item['tx_hash'], result))
       -        hist = map(lambda item: (item['tx_hash'], item['height']), result)
       +        hist = list(map(lambda item: (item['tx_hash'], item['height']), result))
                # tx_fees
                tx_fees = [(item['tx_hash'], item.get('fee')) for item in result]
                tx_fees = dict(filter(lambda x:x[1] is not None, tx_fees))
       t@@ -140,7 +140,7 @@ class Synchronizer(ThreadJob):
                if not params:
                    return
                tx_hash, tx_height = params
       -        #assert tx_hash == hash_encode(Hash(result.decode('hex')))
       +        #assert tx_hash == hash_encode(Hash(bytes.fromhex(result)))
                tx = Transaction(result)
                try:
                    tx.deserialize()
   DIR diff --git a/lib/transaction.py b/lib/transaction.py
       t@@ -170,9 +170,9 @@ class Enumeration:
                for x in enumList:
                    if isinstance(x, tuple):
                        x, i = x
       -            if not isinstance(x, six.text_type):
       +            if not isinstance(x, str):
                        raise EnumException("enum name is not a string: " + x)
       -            if not isinstance(i, six.integer_types):
       +            if not isinstance(i, int):
                        raise EnumException("enum value is not an integer: " + i)
                    if x in uniqueNames:
                        raise EnumException("enum name is not unique: " + x)
       t@@ -715,9 +715,9 @@ class Transaction:
                txin = inputs[i]
                # TODO: py3 hex
                if self.is_segwit_input(txin):
       -            hashPrevouts = Hash(''.join(self.serialize_outpoint(txin) for txin in inputs).decode('hex')).encode('hex')
       -            hashSequence = Hash(''.join(int_to_hex(txin.get('sequence', 0xffffffff - 1), 4) for txin in inputs).decode('hex')).encode('hex')
       -            hashOutputs = Hash(''.join(self.serialize_output(o) for o in outputs).decode('hex')).encode('hex')
       +            hashPrevouts = bh2u(Hash(bfh(''.join(self.serialize_outpoint(txin) for txin in inputs))))
       +            hashSequence = bh2u(Hash(bfh(''.join(int_to_hex(txin.get('sequence', 0xffffffff - 1), 4) for txin in inputs))))
       +            hashOutputs = bh2u(Hash(bfh(''.join(self.serialize_output(o) for o in outputs))))
                    outpoint = self.serialize_outpoint(txin)
                    preimage_script = self.get_preimage_script(txin)
                    scriptCode = var_int(len(preimage_script)/2) + preimage_script
   DIR diff --git a/lib/util.py b/lib/util.py
       t@@ -141,7 +141,7 @@ class DaemonThread(threading.Thread, PrintError):
                    for job in self.jobs:
                        try:
                            job.run()
       -                except:
       +                except Exception as e:
                            traceback.print_exc(file=sys.stderr)
        
            def remove_jobs(self, jobs):
       t@@ -170,7 +170,8 @@ class DaemonThread(threading.Thread, PrintError):
                self.print_error("stopped")
        
        
       -is_verbose = False
       +# TODO: disable
       +is_verbose = True
        def set_verbosity(b):
            global is_verbose
            is_verbose = b
       t@@ -281,63 +282,8 @@ def assert_str(*args):
                assert isinstance(x, six.string_types)
        
        
       -def __str(x, encoding='utf8'):
       -    if six.PY3:
       -        return x.decode(encoding)
       -
       -
       -def _bytes(x=None, encoding=None, **kw):
       -    """
       -    py2-py3 aware wrapper to "bytes()" like constructor
       -    :param x:
       -    :return:
       -    """
       -    if encoding is not None:
       -        kw['encoding'] = encoding
       -    if x is None:
       -        x = []
       -    if six.PY3:
       -        if isinstance(x, bytes):
       -            return x
       -        return bytes(x, **kw)
       -    else:
       -        return bytearray(x, **kw)
       -
       -
       -def _to_bytes2(x, enc):
       -    if isinstance(x, bytearray):
       -        return bytearray(x)
       -    if isinstance(x, six.text_type):
       -        return bytearray(x.encode(enc))
       -    elif isinstance(x, six.binary_type):
       -        return bytearray(x)
       -    else:
       -        raise TypeError("Not a string or bytes like object")
       -
        
       -def _to_bytes3(x, enc):
       -    if isinstance(x, bytes):
       -        return x
       -    if isinstance(x, str):
       -        return x.encode(enc)
       -    elif isinstance(x, bytearray):
       -        return bytes(x)
       -    else:
       -        raise TypeError("Not a string or bytes like object")
       -
       -
       -def _to_string2(x, enc):
       -    if isinstance(x, (str, bytes)):
       -        return x
       -    if isinstance(x, unicode):
       -        return x.encode(enc)
       -    if isinstance(x, bytearray):
       -        return x.decode(enc)
       -    else:
       -        raise TypeError("Not a string or bytes like object")
       -
       -
       -def _to_string3(x, enc):
       +def to_string(x, enc):
            if isinstance(x, (bytes, bytearray)):
                return x.decode(enc)
            if isinstance(x, str):
       t@@ -349,35 +295,16 @@ def to_bytes(something, encoding='utf8'):
            """
            cast string to bytes() like object, but for python2 support it's bytearray copy
            """
       -    raise NotImplementedError("This call should be redefined")
       -
       -def to_bytes(something, encoding='utf8'):
       -    """
       -    cast string to str object
       -    """
       -    raise NotImplementedError("This call should be redefined")
       -
       -if six.PY3:
       -    to_bytes = _to_bytes3
       -    to_string = _to_string3
       -else:
       -    to_bytes = _to_bytes2
       -    to_string = _to_string2
       -
       -if six.PY3:
       -    bfh_builder = lambda x: bytes.fromhex(x)
       -else:
       -    bfh_builder = lambda x: x.decode('hex')  # str(bytearray.fromhex(x))
       -
       +    if isinstance(something, bytes):
       +        return something
       +    if isinstance(something, str):
       +        return something.encode(encoding)
       +    elif isinstance(something, bytearray):
       +        return bytes(something)
       +    else:
       +        raise TypeError("Not a string or bytes like object")
        
       -# def ufh(x):
       -#     """
       -#     py2-py3 aware wrapper for str.decode('hex')
       -#     :param x: str
       -#     :return: str
       -#     """
       -#     if
       -#     return binascii.unhexlify(x)
       +bfh_builder = lambda x: bytes.fromhex(x)
        
        
        def hfu(x):
       t@@ -700,20 +627,18 @@ else:
            builtins.input = raw_input
        
        
       -
        def parse_json(message):
       -    n = message.find('\n')
       +    # TODO: check \r\n pattern
       +    n = message.find(b'\n')
            if n==-1:
                return None, message
            try:
       -        j = json.loads( message[0:n] )
       +        j = json.loads(message[0:n].decode('utf8'))
            except:
                j = None
            return j, message[n+1:]
        
        
       -
       -
        class timeout(Exception):
            pass
        
       t@@ -723,11 +648,11 @@ import json
        import ssl
        import time
        
       -class SocketPipe:
        
       +class SocketPipe:
            def __init__(self, socket):
                self.socket = socket
       -        self.message = ''
       +        self.message = b''
                self.set_timeout(0.1)
                self.recv_time = time.time()
        
       t@@ -757,10 +682,10 @@ class SocketPipe:
                            raise timeout
                        else:
                            print_error("pipe: socket error", err)
       -                    data = ''
       +                    data = b''
                    except:
                        traceback.print_exc(file=sys.stderr)
       -                data = ''
       +                data = b''
        
                    if not data:  # Connection closed remotely
                        return None
       t@@ -769,10 +694,12 @@ class SocketPipe:
        
            def send(self, request):
                out = json.dumps(request) + '\n'
       +        out = out.encode('utf8')
                self._send(out)
        
            def send_all(self, requests):
       -        out = ''.join(map(lambda x: json.dumps(x) + '\n', requests))
       +        print(requests)
       +        out = b''.join(map(lambda x: (json.dumps(x) + '\n').encode('utf8'), requests))
                self._send(out)
        
            def _send(self, out):
       t@@ -798,7 +725,6 @@ class SocketPipe:
                            raise e
        
        
       -
        class QueuePipe:
        
            def __init__(self, send_queue=None, get_queue=None):
       t@@ -833,9 +759,8 @@ class QueuePipe:
                    self.send(request)
        
        
       -
        def check_www_dir(rdir):
       -    import urllib, urlparse, shutil, os
       +    import urllib, shutil, os
            if not os.path.exists(rdir):
                os.mkdir(rdir)
            index = os.path.join(rdir, 'index.html')
       t@@ -850,7 +775,7 @@ def check_www_dir(rdir):
                "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"
            ]
            for URL in files:
       -        path = urlparse.urlsplit(URL).path
       +        path = urllib_parse.urlsplit(URL).path
                filename = os.path.basename(path)
                path = os.path.join(rdir, filename)
                if not os.path.exists(path):
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -51,7 +51,7 @@ from .version import *
        from .keystore import load_keystore, Hardware_KeyStore
        from .storage import multisig_type
        
       -import transaction
       +from . import transaction
        from .transaction import Transaction
        from .plugins import run_hook
        from . import bitcoin
       t@@ -297,6 +297,7 @@ 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@@ -759,7 +760,7 @@ class Abstract_Wallet(PrintError):
                return ''
        
            def get_tx_status(self, tx_hash, height, conf, timestamp):
       -        from util import format_time
       +        from .util import format_time
                if conf == 0:
                    tx = self.transactions.get(tx_hash)
                    if not tx:
       t@@ -1417,16 +1418,11 @@ class Imported_Wallet(Abstract_Wallet):
        
            def add_input_sig_info(self, txin, address):
                addrtype, hash160 = bc_address_to_hash_160(address)
       -        if six.PY3:
       -            x_pubkey = 'fd' + bh2u(bytes([addrtype]) + hash160)
       -        else:
       -            x_pubkey = 'fd' + bh2u(chr(addrtype) + hash160)
       +        x_pubkey = 'fd' + bh2u(bytes([addrtype]) + hash160)
                txin['x_pubkeys'] = [x_pubkey]
                txin['signatures'] = [None]
        
        
       -
       -
        class Deterministic_Wallet(Abstract_Wallet):
        
            def __init__(self, storage):
       t@@ -1508,7 +1504,7 @@ class Deterministic_Wallet(Abstract_Wallet):
                    if len(addresses) < limit:
                        self.create_new_address(for_change)
                        continue
       -            if map(lambda a: self.address_is_old(a), addresses[-limit:] ) == limit*[False]:
       +            if list(map(lambda a: self.address_is_old(a), addresses[-limit:] )) == limit*[False]:
                        break
                    else:
                        self.create_new_address(for_change)
       t@@ -1521,7 +1517,7 @@ class Deterministic_Wallet(Abstract_Wallet):
                    else:
                        if len(self.receiving_addresses) != len(self.keystore.keypairs):
                            pubkeys = self.keystore.keypairs.keys()
       -                    self.receiving_addresses = map(self.pubkeys_to_address, pubkeys)
       +                    self.receiving_addresses = [self.pubkeys_to_address(i) for i in pubkeys]
                            self.save_addresses()
                            for addr in self.receiving_addresses:
                                self.add_address(addr)
       t@@ -1652,7 +1648,7 @@ class P2SH:
        
            def pubkeys_to_address(self, pubkey):
                redeem_script = self.pubkeys_to_redeem_script(pubkey)
       -        return bitcoin.hash160_to_p2sh(hash_160(redeem_script.decode('hex')))
       +        return bitcoin.hash160_to_p2sh(hash_160(bfh(redeem_script)))
        
        
        class Standard_Wallet(Simple_Deterministic_Wallet):
       t@@ -1664,17 +1660,14 @@ class Standard_Wallet(Simple_Deterministic_Wallet):
        
            def pubkeys_to_address(self, pubkey):
                if not self.is_segwit:
       -            return bitcoin.public_key_to_p2pkh(pubkey.decode('hex'))
       +            return bitcoin.public_key_to_p2pkh(bfh(pubkey))
                elif bitcoin.TESTNET:
                    redeem_script = self.pubkeys_to_redeem_script(pubkey)
       -            return bitcoin.hash160_to_p2sh(hash_160(redeem_script.decode('hex')))
       +            return bitcoin.hash160_to_p2sh(hash_160(bfh(redeem_script)))
                else:
                    raise NotImplementedError()
        
        
       -
       -
       -
        class Multisig_Wallet(Deterministic_Wallet, P2SH):
            # generic m of n
            gap_limit = 20
   DIR diff --git a/lib/x509.py b/lib/x509.py
       t@@ -31,7 +31,7 @@ import six
        from datetime import datetime
        import sys
        from . import util
       -from .util import profiler, print_error
       +from .util import profiler, print_error, bh2u
        import ecdsa
        import hashlib
        
       t@@ -74,7 +74,7 @@ class CertificateError(Exception):
        
        # helper functions
        def bitstr_to_bytestr(s):
       -    if s[0] != '\x00':
       +    if s[0] != 0x00:
                raise BaseException('no padding')
            return s[1:]
        
       t@@ -83,14 +83,13 @@ def bytestr_to_int(s):
            i = 0
            for char in s:
                i <<= 8
       -        i |= ord(char)
       +        i |= char
            return i
        
        
        def decode_OID(s):
       -    s = map(ord, s)
            r = []
       -    r.append(s[0] / 40)
       +    r.append(s[0] // 40)
            r.append(s[0] % 40)
            k = 0
            for i in s[1:]:
       t@@ -103,7 +102,7 @@ def decode_OID(s):
        
        
        def encode_OID(oid):
       -    x = map(int, oid.split('.'))
       +    x = [int(i) for i in oid.split('.')]
            s = chr(x[0] * 40 + x[1])
            for i in x[2:]:
                ss = chr(i % 128)
       t@@ -114,11 +113,11 @@ def encode_OID(oid):
            return s
        
        
       -class ASN1_Node(str):
       +class ASN1_Node(bytes):
            def get_node(self, ix):
                # return index of first byte, first content byte and last byte.
       -        first = ord(self[ix + 1])
       -        if (ord(self[ix + 1]) & 0x80) == 0:
       +        first = self[ix + 1]
       +        if (self[ix + 1] & 0x80) == 0:
                    length = first
                    ixf = ix + 2
                    ixl = ixf + length - 1
       t@@ -129,72 +128,62 @@ class ASN1_Node(str):
                    ixl = ixf + length - 1
                return ix, ixf, ixl
        
       -
       -def root(self):
       -    return self.get_node(0)
       -
       -
       -def next_node(self, node):
       -    ixs, ixf, ixl = node
       -    return self.get_node(ixl + 1)
       -
       -
       -def first_child(self, node):
       -    ixs, ixf, ixl = node
       -    if ord(self[ixs]) & 0x20 != 0x20:
       -        raise BaseException('Can only open constructed types.', hex(ord(self[ixs])))
       -    return self.get_node(ixf)
       -
       -
       -def is_child_of(node1, node2):
       -    ixs, ixf, ixl = node1
       -    jxs, jxf, jxl = node2
       -    return ((ixf <= jxs) and (jxl <= ixl)) or ((jxf <= ixs) and (ixl <= jxl))
       -
       -
       -def get_all(self, node):
       -    # return type + length + value
       -    ixs, ixf, ixl = node
       -    return self[ixs:ixl + 1]
       -
       -
       -def get_value_of_type(self, node, asn1_type):
       -    # verify type byte and return content
       -    ixs, ixf, ixl = node
       -    if ASN1_TYPES[asn1_type] != ord(self[ixs]):
       -        raise BaseException('Wrong type:', hex(ord(self[ixs])), hex(ASN1_TYPES[asn1_type]))
       -    return self[ixf:ixl + 1]
       -
       -
       -def get_value(self, node):
       -    ixs, ixf, ixl = node
       -    return self[ixf:ixl + 1]
       -
       -
       -def get_children(self, node):
       -    nodes = []
       -    ii = self.first_child(node)
       -    nodes.append(ii)
       -    while ii[2] < node[2]:
       -        ii = self.next_node(ii)
       +    def root(self):
       +        return self.get_node(0)
       +
       +    def next_node(self, node):
       +        ixs, ixf, ixl = node
       +        return self.get_node(ixl + 1)
       +
       +    def first_child(self, node):
       +        ixs, ixf, ixl = node
       +        if self[ixs] & 0x20 != 0x20:
       +            raise BaseException('Can only open constructed types.', hex(self[ixs]))
       +        return self.get_node(ixf)
       +
       +    def is_child_of(node1, node2):
       +        ixs, ixf, ixl = node1
       +        jxs, jxf, jxl = node2
       +        return ((ixf <= jxs) and (jxl <= ixl)) or ((jxf <= ixs) and (ixl <= jxl))
       +
       +    def get_all(self, node):
       +        # return type + length + value
       +        ixs, ixf, ixl = node
       +        return self[ixs:ixl + 1]
       +
       +    def get_value_of_type(self, node, asn1_type):
       +        # verify type byte and return content
       +        ixs, ixf, ixl = node
       +        if ASN1_TYPES[asn1_type] != self[ixs]:
       +            raise BaseException('Wrong type:', hex(self[ixs]), hex(ASN1_TYPES[asn1_type]))
       +        return self[ixf:ixl + 1]
       +
       +    def get_value(self, node):
       +        ixs, ixf, ixl = node
       +        return self[ixf:ixl + 1]
       +
       +    def get_children(self, node):
       +        nodes = []
       +        ii = self.first_child(node)
                nodes.append(ii)
       -    return nodes
       -
       -
       -def get_sequence(self):
       -    return map(lambda j: self.get_value(j), self.get_children(self.root()))
       -
       -
       -def get_dict(self, node):
       -    p = {}
       -    for ii in self.get_children(node):
       -        for iii in self.get_children(ii):
       -            iiii = self.first_child(iii)
       -            oid = decode_OID(self.get_value_of_type(iiii, 'OBJECT IDENTIFIER'))
       -            iiii = self.next_node(iiii)
       -            value = self.get_value(iiii)
       -            p[oid] = value
       -    return p
       +        while ii[2] < node[2]:
       +            ii = self.next_node(ii)
       +            nodes.append(ii)
       +        return nodes
       +
       +    def get_sequence(self):
       +        return list(map(lambda j: self.get_value(j), self.get_children(self.root())))
       +
       +    def get_dict(self, node):
       +        p = {}
       +        for ii in self.get_children(node):
       +            for iii in self.get_children(ii):
       +                iiii = self.first_child(iii)
       +                oid = decode_OID(self.get_value_of_type(iiii, 'OBJECT IDENTIFIER'))
       +                iiii = self.next_node(iiii)
       +                value = self.get_value(iiii)
       +                p[oid] = value
       +        return p
        
        
        class X509(object):
       t@@ -202,14 +191,14 @@ class X509(object):
        
                self.bytes = bytearray(b)
        
       -        der = ASN1_Node(str(b))
       +        der = ASN1_Node(b)
                root = der.root()
                cert = der.first_child(root)
                # data for signature
                self.data = der.get_all(cert)
        
                # optional version field
       -        if der.get_value(cert)[0] == chr(0xa0):
       +        if der.get_value(cert)[0] == 0xa0:
                    version = der.first_child(cert)
                    serial_number = der.next_node(version)
                else:
       t@@ -269,10 +258,10 @@ class X509(object):
                            # Subject Key Identifier
                            r = value.root()
                            value = value.get_value_of_type(r, 'OCTET STRING')
       -                    self.SKI = value.encode('hex')
       +                    self.SKI = bh2u(value)
                        elif oid == '2.5.29.35':
                            # Authority Key Identifier
       -                    self.AKI = value.get_sequence()[0].encode('hex')
       +                    self.AKI = bh2u(value.get_sequence()[0])
                        else:
                            pass
        
       t@@ -303,8 +292,8 @@ class X509(object):
                import time
                now = time.time()
                TIMESTAMP_FMT = '%y%m%d%H%M%SZ'
       -        not_before = time.mktime(time.strptime(self.notBefore, TIMESTAMP_FMT))
       -        not_after = time.mktime(time.strptime(self.notAfter, TIMESTAMP_FMT))
       +        not_before = time.mktime(time.strptime(self.notBefore.decode('ascii'), TIMESTAMP_FMT))
       +        not_after = time.mktime(time.strptime(self.notAfter.decode('ascii'), TIMESTAMP_FMT))
                if not_before > now:
                    raise CertificateError('Certificate has not entered its valid date range. (%s)' % self.get_common_name())
                if not_after <= now:
       t@@ -320,7 +309,7 @@ def load_certificates(ca_path):
            ca_list = {}
            ca_keyID = {}
            with open(ca_path, 'rb') as f:
       -        s = f.read().decode('utf8')
       +        s = f.read().decode('ascii')
            bList = pem.dePemList(s, "CERTIFICATE")
            for b in bList:
                try: