URI: 
       tpy3 - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 5be78950ca31ba903b4bd0f575511eeb732e114c
   DIR parent f70408cef5eff3eead108a06ee11a6106253f74d
  HTML Author: Dmitry Sorokin <asfins@gmail.com>
       Date:   Sun, 22 Jan 2017 21:25:24 +0300
       
       py3
       
       Diffstat:
         M electrum                            |      41 ++++++++++++++++++++-----------
         M gui/qt/__init__.py                  |      16 +++++++++-------
         M gui/qt/address_dialog.py            |      12 +++++++++---
         M gui/qt/address_list.py              |       7 ++++++-
         M gui/qt/amountedit.py                |       6 ++++++
         M gui/qt/console.py                   |       8 +++++++-
         M gui/qt/contact_list.py              |       7 ++++++-
         M gui/qt/fee_slider.py                |       6 ++++++
         M gui/qt/history_list.py              |       7 ++++++-
         M gui/qt/installwizard.py             |      14 ++++++++++----
         M gui/qt/invoice_list.py              |       7 ++++++-
         M gui/qt/main_window.py               |      46 +++++++++++++++++--------------
         M gui/qt/network_dialog.py            |      11 +++++++++--
         M gui/qt/password_dialog.py           |       7 ++++++-
         M gui/qt/paytoedit.py                 |       9 +++++++--
         M gui/qt/qrcodewidget.py              |       8 +++++++-
         M gui/qt/qrtextedit.py                |       8 +++++++-
         M gui/qt/qrwindow.py                  |       6 +++++-
         M gui/qt/request_list.py              |       7 ++++++-
         M gui/qt/seed_dialog.py               |       9 +++++++--
         M gui/qt/transaction_dialog.py        |       7 ++++++-
         M gui/qt/util.py                      |      10 ++++++++--
         M gui/qt/utxo_list.py                 |       7 ++++++-
         M gui/stdio.py                        |       6 ++++++
         M gui/text.py                         |       6 ++++++
         M lib/__init__.py                     |      28 ++++++++++++++--------------
         A lib/account.py                      |       0 
         M lib/base_wizard.py                  |      17 +++++++++++------
         M lib/bitcoin.py                      |     240 ++++++++++++++++++-------------
         M lib/blockchain.py                   |      11 ++++++++---
         M lib/coinchooser.py                  |      13 +++++++++----
         M lib/commands.py                     |      31 ++++++++++++++++++-------------
         M lib/contacts.py                     |      14 ++++++++++----
         M lib/daemon.py                       |      52 +++++++++++++++++--------------
         M lib/dnssec.py                       |      31 ++++++++++++++++---------------
         M lib/exchange_rate.py                |      17 ++++++++++++-----
         M lib/i18n.py                         |      18 +++++++++++++-----
         M lib/interface.py                    |      34 ++++++++++++++++++-------------
         M lib/keystore.py                     |      64 +++++++++++++++++--------------
         M lib/mnemonic.py                     |      21 +++++++++++++++------
         M lib/msqr.py                         |      16 +++++++++++-----
         M lib/network.py                      |      40 +++++++++++++++++++-------------
         M lib/old_mnemonic.py                 |      24 +++++++++++++++---------
         M lib/paymentrequest.py               |      45 +++++++++++++++++++-------------
         M lib/pem.py                          |       7 ++++++-
         M lib/plugins.py                      |      18 ++++++++++++------
         M lib/rsakey.py                       |       8 ++++++--
         M lib/simple_config.py                |      21 ++++++++++++++-------
         M lib/storage.py                      |      15 ++++++++++-----
         M lib/synchronizer.py                 |      12 ++++++++----
         M lib/tests/test_account.py           |       6 ++++++
         M lib/tests/test_bitcoin.py           |      13 ++++++++++---
         M lib/tests/test_interface.py         |       6 ++++++
         M lib/tests/test_mnemonic.py          |      10 +++++++++-
         M lib/tests/test_simple_config.py     |      17 +++++++----------
         M lib/tests/test_transaction.py       |      22 ++++++++++++++++------
         M lib/tests/test_util.py              |       6 ++++++
         M lib/tests/test_wallet.py            |      10 ++++++++--
         M lib/transaction.py                  |     200 +++++++++++++++----------------
         M lib/util.py                         |     245 ++++++++++++++++++++++++++++---
         M lib/verifier.py                     |      10 +++++++---
         M lib/wallet.py                       |      64 ++++++++++++++++----------------
         M lib/websockets.py                   |      14 ++++++++++----
         M lib/x509.py                         |     213 ++++++++++++++++---------------
       
       64 files changed, 1243 insertions(+), 668 deletions(-)
       ---
   DIR diff --git a/electrum b/electrum
       t@@ -1,4 +1,4 @@
       -#!/usr/bin/env python2
       +#!/usr/bin/env python
        # -*- mode: python -*-
        #
        # Electrum - lightweight Bitcoin client
       t@@ -23,9 +23,14 @@
        # 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 os
        import sys
       +import six
        
        # from https://gist.github.com/tito/09c42fb4767721dc323d
        import threading
       t@@ -42,6 +47,12 @@ if jnius:
                    jnius.detach()
            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
        
        script_dir = os.path.dirname(os.path.realpath(__file__))
        is_bundle = getattr(sys, 'frozen', False)
       t@@ -54,6 +65,7 @@ os.environ['KIVY_DATA_DIR'] = os.path.abspath(os.path.dirname(__file__)) + '/gui
        if is_local or is_android:
            sys.path.insert(0, os.path.join(script_dir, 'packages'))
        elif is_bundle and sys.platform=='darwin':
       +    # TODO: py3
            sys.path.insert(0, os.getcwd() + "/lib/python2.7/packages")
        
        
       t@@ -68,7 +80,7 @@ def check_imports():
                import qrcode
                import pbkdf2
                import google.protobuf
       -        import jsonrpclib
       +        # import jsonrpclib
            except ImportError as e:
                sys.exit("Error: %s. Try 'sudo pip install <module-name>'"%e.message)
            # the following imports are for pyinstaller
       t@@ -76,7 +88,7 @@ def check_imports():
            from google.protobuf import message
            from google.protobuf import reflection
            from google.protobuf import descriptor_pb2
       -    from jsonrpclib import SimpleJSONRPCServer
       +    # from jsonrpclib import SimpleJSONRPCServer
            # check that we have the correct version of ecdsa
            try:
                from ecdsa.ecdsa import curve_secp256k1, generator_secp256k1
       t@@ -276,11 +288,11 @@ def run_offline_command(config, config_options):
            if cmd.requires_network:
                print_msg("Warning: running command offline")
            # arguments passed to function
       -    args = map(lambda x: config.get(x), cmd.params)
       +    args = [config.get(x) for x in cmd.params]
            # decode json arguments
       -    args = map(json_decode, args)
       +    args = list(map(json_decode, args))
            # options
       -    args += map(lambda x: (config_options.get(x) if x in ['password', 'new_password'] else config.get(x)), cmd.options)
       +    args += [(config_options.get(x) if x in ['password', 'new_password'] else config.get(x)) for x in cmd.options]
            cmd_runner = Commands(config, wallet, None)
            func = getattr(cmd_runner, cmd.name)
            result = func(*args)
       t@@ -296,10 +308,10 @@ def init_plugins(config, gui_name):
        if __name__ == '__main__':
        
            # on osx, delete Process Serial Number arg generated for apps launched in Finder
       -    sys.argv = filter(lambda x: not x.startswith('-psn'), sys.argv)
       +    sys.argv = list(filter(lambda x: not x.startswith('-psn'), sys.argv))
        
            # old 'help' syntax
       -    if len(sys.argv)>1 and sys.argv[1] == 'help':
       +    if len(sys.argv) > 1 and sys.argv[1] == 'help':
                sys.argv.remove('help')
                sys.argv.append('-h')
        
       t@@ -312,9 +324,9 @@ if __name__ == '__main__':
                    else:
                        raise BaseException('Cannot get argument from stdin')
                elif arg == '?':
       -            sys.argv[i] = raw_input("Enter argument:")
       +            sys.argv[i] = input("Enter argument:")
                elif arg == ':':
       -            sys.argv[i] = prompt_password('Enter argument (will not echo):', False)
       +            sys.argv[i] = prompt_password('Enter argument (will noot echo):', False)
        
            # parse command line
            parser = get_parser()
       t@@ -329,9 +341,8 @@ if __name__ == '__main__':
                }
            else:
                config_options = args.__dict__
       -        for k, v in config_options.items():
       -            if v is None or (k in config_variables.get(args.cmd, {}).keys()):
       -                config_options.pop(k)
       +        f = lambda key: config_options[key] is not None and key not in config_variables.get(args.cmd, {}).keys()
       +        config_options = {key: config_options[key] for key in filter(f, config_options.keys())}
                if config_options.get('server'):
                    config_options['auto_connect'] = False
        
       t@@ -426,8 +437,8 @@ if __name__ == '__main__':
                        init_plugins(config, 'cmdline')
                        result = run_offline_command(config, config_options)
        
       -    # print result
       -    if type(result) in [str, unicode]:
       +                # print result
       +    if isinstance(result, six.text_type):
                print_msg(result)
            elif type(result) is dict and result.get('error'):
                print_stderr(result.get('error'))
   DIR diff --git a/gui/qt/__init__.py b/gui/qt/__init__.py
       t@@ -43,18 +43,20 @@ from electrum.synchronizer import Synchronizer
        from electrum.verifier import SPV
        from electrum.util import DebugMem, UserCancelled, InvalidPassword
        from electrum.wallet import Abstract_Wallet
       -from installwizard import InstallWizard, GoBack
       +
       +from .installwizard import InstallWizard, GoBack
        
        
        try:
       -    import icons_rc
       -except Exception:
       -    print "Error: Could not find icons file."
       -    print "Please run 'pyrcc4 icons.qrc -o gui/qt/icons_rc.py', and reinstall Electrum"
       +    from . import icons_rc
       +except Exception as e:
       +    print(e)
       +    print("Error: Could not find icons file.")
       +    print("Please run 'pyrcc4 icons.qrc -o gui/qt/icons_rc.py', and reinstall Electrum")
            sys.exit(1)
        
       -from util import *   # * needed for plugins
       -from main_window import ElectrumWindow
       +from .util import *   # * needed for plugins
       +from .main_window import ElectrumWindow
        
        
        class OpenFileEventFilter(QObject):
   DIR diff --git a/gui/qt/address_dialog.py b/gui/qt/address_dialog.py
       t@@ -22,16 +22,22 @@
        # 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 electrum.i18n import _
        
        import PyQt4
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
        
       -from util import *
       -from history_list import HistoryList
       -from qrtextedit import ShowQRTextEdit
       +from .util import *
       +from .history_list import HistoryList
       +from .qrtextedit import ShowQRTextEdit
       +
        
        class AddressDialog(WindowModalDialog):
        
   DIR diff --git a/gui/qt/address_list.py b/gui/qt/address_list.py
       t@@ -22,11 +22,16 @@
        # 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 webbrowser
        
       -from util import *
       +from .util import *
        from electrum.i18n import _
        from electrum.util import block_explorer_URL, format_satoshis, format_time
        from electrum.plugins import run_hook
   DIR diff --git a/gui/qt/amountedit.py b/gui/qt/amountedit.py
       t@@ -1,11 +1,17 @@
        # -*- coding: utf-8 -*-
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
        
       +import six
        from PyQt4.QtCore import *
        from PyQt4.QtGui import *
        
        from decimal import Decimal
        from electrum.util import format_satoshis_plain
        
       +
        class MyLineEdit(QLineEdit):
            frozen = pyqtSignal()
        
   DIR diff --git a/gui/qt/console.py b/gui/qt/console.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        # source: http://stackoverflow.com/questions/2758159/how-to-embed-a-python-interpreter-in-a-pyqt-widget
        
        import sys, os, re
       t@@ -220,7 +226,7 @@ class Console(QtGui.QPlainTextEdit):
                                    self.appendPlainText(repr(result))
                        except SyntaxError:
                            # exec is generally considered bad practice. use it wisely!
       -                    exec command in self.namespace
       +                    exec(command) in self.namespace
                    except SystemExit:
                        self.close()
                    except Exception:
   DIR diff --git a/gui/qt/contact_list.py b/gui/qt/contact_list.py
       t@@ -22,8 +22,13 @@
        # 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 webbrowser
       +import six
        
        from electrum.i18n import _
        from electrum.bitcoin import is_address
       t@@ -32,7 +37,7 @@ from electrum.plugins import run_hook
        from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
       -from util import MyTreeWidget, pr_tooltips, pr_icons
       +from .util import MyTreeWidget, pr_tooltips, pr_icons
        
        
        class ContactList(MyTreeWidget):
   DIR diff --git a/gui/qt/fee_slider.py b/gui/qt/fee_slider.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        from electrum.i18n import _
        
        import PyQt4
   DIR diff --git a/gui/qt/history_list.py b/gui/qt/history_list.py
       t@@ -22,11 +22,16 @@
        # 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 webbrowser
        
       -from util import *
       +from .util import *
        from electrum.i18n import _
        from electrum.util import block_explorer_URL, format_satoshis, format_time
        from electrum.plugins import run_hook
   DIR diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import sys
        import os
        
       t@@ -11,10 +17,10 @@ from electrum.util import UserCancelled, InvalidPassword
        from electrum.base_wizard import BaseWizard
        from electrum.i18n import _
        
       -from seed_dialog import SeedLayout, KeysLayout
       -from network_dialog import NetworkChoiceLayout
       -from util import *
       -from password_dialog import PasswordLayout, PW_NEW
       +from .seed_dialog import SeedLayout, KeysLayout
       +from .network_dialog import NetworkChoiceLayout
       +from .util import *
       +from .password_dialog import PasswordLayout, PW_NEW
        
        
        class GoBack(Exception):
   DIR diff --git a/gui/qt/invoice_list.py b/gui/qt/invoice_list.py
       t@@ -22,9 +22,14 @@
        # 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 *
       +from .util import *
        from electrum.i18n import _
        from electrum.util import block_explorer_URL, format_satoshis, format_time
        from electrum.plugins import run_hook
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -22,7 +22,12 @@
        # 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 sys, time, threading
        import os, json, traceback
        import shutil
       t@@ -39,7 +44,7 @@ from PyQt4.QtGui import *
        from PyQt4.QtCore import *
        import PyQt4.QtCore as QtCore
        
       -import icons_rc
       +from . import icons_rc
        
        from electrum import keystore
        from electrum.bitcoin import COIN, is_valid, TYPE_ADDRESS
       t@@ -57,17 +62,17 @@ try:
        except:
            plot_history = None
        
       -from amountedit import AmountEdit, BTCAmountEdit, MyLineEdit, BTCkBEdit
       -from qrcodewidget import QRCodeWidget, QRDialog
       -from qrtextedit import ShowQRTextEdit
       -from transaction_dialog import show_transaction
       -from fee_slider import FeeSlider
       +from .amountedit import AmountEdit, BTCAmountEdit, MyLineEdit, BTCkBEdit
       +from .qrcodewidget import QRCodeWidget, QRDialog
       +from .qrtextedit import ShowQRTextEdit
       +from .transaction_dialog import show_transaction
       +from .fee_slider import FeeSlider
        
        
        from electrum import ELECTRUM_VERSION
        import re
        
       -from util import *
       +from .util import *
        
        
        class StatusBarButton(QPushButton):
       t@@ -397,7 +402,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                    try:
                        shutil.copy2(path, new_path)
                        self.show_message(_("A copy of your wallet file was created in")+" '%s'" % str(new_path), title=_("Wallet backup created"))
       -            except (IOError, os.error), reason:
       +            except (IOError, os.error) as reason:
                        self.show_critical(_("Electrum was unable to copy your wallet file to the specified location.") + "\n" + str(reason), title=_("Unable to create backup"))
        
            def update_recently_visited(self, filename):
       t@@ -722,13 +727,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                self.update_completions()
        
            def create_history_tab(self):
       -        from history_list import HistoryList
       +        from .history_list import HistoryList
                self.history_list = l = HistoryList(self)
                l.searchable_list = l
                return l
        
            def show_address(self, addr):
       -        import address_dialog
       +        from . import address_dialog
                d = address_dialog.AddressDialog(self, addr)
                d.exec_()
        
       t@@ -770,7 +775,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                self.connect_fields(self, self.receive_amount_e, self.fiat_receive_e, None)
        
                self.expires_combo = QComboBox()
       -        self.expires_combo.addItems(map(lambda x:x[0], expiration_values))
       +        self.expires_combo.addItems([i[0] for i in expiration_values])
                self.expires_combo.setCurrentIndex(3)
                self.expires_combo.setFixedWidth(self.receive_amount_e.width())
                msg = ' '.join([
       t@@ -806,7 +811,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
        
                self.receive_requests_label = QLabel(_('Requests'))
        
       -        from request_list import RequestList
       +        from .request_list import RequestList
                self.request_list = RequestList(self)
        
                # layout
       t@@ -991,7 +996,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                grid.setSpacing(8)
                grid.setColumnStretch(3, 1)
        
       -        from paytoedit import PayToEdit
       +        from .paytoedit import PayToEdit
                self.amount_e = BTCAmountEdit(self.get_decimal_point)
                self.payto_e = PayToEdit(self)
                msg = _('Recipient of the funds.') + '\n\n'\
       t@@ -1123,7 +1128,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                self.fee_e.textChanged.connect(entry_changed)
        
                self.invoices_label = QLabel(_('Invoices'))
       -        from invoice_list import InvoiceList
       +        from .invoice_list import InvoiceList
                self.invoice_list = InvoiceList(self)
        
                vbox0 = QVBoxLayout()
       t@@ -1567,17 +1572,17 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                return w
        
            def create_addresses_tab(self):
       -        from address_list import AddressList
       +        from .address_list import AddressList
                self.address_list = l = AddressList(self)
                return self.create_list_tab(l)
        
            def create_utxo_tab(self):
       -        from utxo_list import UTXOList
       +        from .utxo_list import UTXOList
                self.utxo_list = l = UTXOList(self)
                return self.create_list_tab(l)
        
            def create_contacts_tab(self):
       -        from contact_list import ContactList
       +        from .contact_list import ContactList
                self.contact_list = l = ContactList(self)
                return self.create_list_tab(l)
        
       t@@ -1693,11 +1698,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                    self.payment_request_error()
        
            def create_console_tab(self):
       -        from console import Console
       +        from .console import Console
                self.console = console = Console()
                return console
        
       -
            def update_console(self):
                console = self.console
                console.history = self.config.get("console-history",[])
       t@@ -2202,7 +2206,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                        with open(fileName, 'w+') as f:
                            json.dump(labels, f, indent=4, sort_keys=True)
                        self.show_message(_("Your labels were exported to") + " '%s'" % str(fileName))
       -        except (IOError, os.error), reason:
       +        except (IOError, os.error) as reason:
                    self.show_critical(_("Electrum was unable to export your labels.") + "\n" + str(reason))
        
        
       t@@ -2226,7 +2230,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                    return
                try:
                    self.do_export_history(self.wallet, filename, csv_button.isChecked())
       -        except (IOError, os.error), reason:
       +        except (IOError, os.error) as reason:
                    export_error_label = _("Electrum was unable to produce a transaction export.")
                    self.show_critical(export_error_label + "\n" + str(reason), title=_("Unable to export history"))
                    return
   DIR diff --git a/gui/qt/network_dialog.py b/gui/qt/network_dialog.py
       t@@ -22,8 +22,15 @@
        # 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.
       -import socket
        
       +
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import socket
       +import six
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
        import PyQt4.QtCore as QtCore
       t@@ -32,7 +39,7 @@ from electrum.i18n import _
        from electrum.network import DEFAULT_PORTS
        from electrum.network import serialize_server, deserialize_server
        
       -from util import *
       +from .util import *
        
        protocol_names = ['TCP', 'SSL']
        protocol_letters = 'ts'
   DIR diff --git a/gui/qt/password_dialog.py b/gui/qt/password_dialog.py
       t@@ -22,11 +22,16 @@
        # 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 PyQt4.QtGui import *
        from PyQt4.QtCore import *
        from electrum.i18n import _
       -from util import *
       +from .util import *
        import re
        import math
        
   DIR diff --git a/gui/qt/paytoedit.py b/gui/qt/paytoedit.py
       t@@ -22,16 +22,21 @@
        # 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 PyQt4.QtCore import *
        from PyQt4.QtGui import *
       -from qrtextedit import ScanQRTextEdit
       +from .qrtextedit import ScanQRTextEdit
        
        import re
        from decimal import Decimal
        from electrum import bitcoin
        
       -import util
       +from . import util
        
        RE_ADDRESS = '[1-9A-HJ-NP-Za-km-z]{26,}'
        RE_ALIAS = '(.*?)\s*\<([1-9A-HJ-NP-Za-km-z]{26,})\>'
   DIR diff --git a/gui/qt/qrcodewidget.py b/gui/qt/qrcodewidget.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
        import PyQt4.QtGui as QtGui
       t@@ -7,7 +13,7 @@ import qrcode
        
        import electrum
        from electrum.i18n import _
       -from util import WindowModalDialog
       +from .util import WindowModalDialog
        
        
        class QRCodeWidget(QWidget):
   DIR diff --git a/gui/qt/qrtextedit.py b/gui/qt/qrtextedit.py
       t@@ -1,9 +1,15 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        from electrum.i18n import _
        from electrum.plugins import run_hook
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
        
       -from util import ButtonsTextEdit, MessageBoxMixin
       +from .util import ButtonsTextEdit, MessageBoxMixin
        
        
        class ShowQRTextEdit(ButtonsTextEdit):
   DIR diff --git a/gui/qt/qrwindow.py b/gui/qt/qrwindow.py
       t@@ -22,11 +22,15 @@
        # 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 re
        import platform
        from decimal import Decimal
       -from urllib import quote
        
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
   DIR diff --git a/gui/qt/request_list.py b/gui/qt/request_list.py
       t@@ -22,7 +22,12 @@
        # 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 electrum.i18n import _
        from electrum.util import block_explorer_URL, format_satoshis, format_time, age
       t@@ -30,7 +35,7 @@ from electrum.plugins import run_hook
        from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
       -from util import MyTreeWidget, pr_tooltips, pr_icons
       +from .util import MyTreeWidget, pr_tooltips, pr_icons
        
        
        class RequestList(MyTreeWidget):
   DIR diff --git a/gui/qt/seed_dialog.py b/gui/qt/seed_dialog.py
       t@@ -22,13 +22,18 @@
        # 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 PyQt4.QtGui import *
        from PyQt4.QtCore import *
        from electrum.i18n import _
        
       -from util import *
       -from qrtextedit import ShowQRTextEdit, ScanQRTextEdit
       +from .util import *
       +from .qrtextedit import ShowQRTextEdit, ScanQRTextEdit
        
        
        def seed_warning_msg(seed):
   DIR diff --git a/gui/qt/transaction_dialog.py b/gui/qt/transaction_dialog.py
       t@@ -22,7 +22,12 @@
        # 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 copy
        import datetime
        import json
       t@@ -37,7 +42,7 @@ from electrum.bitcoin import base_encode
        from electrum.i18n import _
        from electrum.plugins import run_hook
        
       -from util import *
       +from .util import *
        
        dialogs = []  # Otherwise python randomly garbage collects the dialogs...
        
   DIR diff --git a/gui/qt/util.py b/gui/qt/util.py
       t@@ -1,10 +1,16 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import os.path
        import time
        import traceback
        import sys
        import threading
        import platform
       -import Queue
       +from six.moves import queue
        from collections import namedtuple
        from functools import partial
        
       t@@ -565,7 +571,7 @@ class TaskThread(QThread):
            def __init__(self, parent, on_error=None):
                super(TaskThread, self).__init__(parent)
                self.on_error = on_error
       -        self.tasks = Queue.Queue()
       +        self.tasks = queue.Queue()
                self.doneSig.connect(self.on_done)
                self.start()
        
   DIR diff --git a/gui/qt/utxo_list.py b/gui/qt/utxo_list.py
       t@@ -22,8 +22,13 @@
        # 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
        
       -from util import *
       +import six
       +from .util import *
        from electrum.i18n import _
        from electrum.bitcoin import is_address
        
   DIR diff --git a/gui/stdio.py b/gui/stdio.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        from decimal import Decimal
        _ = lambda x:x
        #from i18n import _
   DIR diff --git a/gui/text.py b/gui/text.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import tty, sys
        import curses, datetime, locale
        from decimal import Decimal
   DIR diff --git a/lib/__init__.py b/lib/__init__.py
       t@@ -1,14 +1,14 @@
       -from version import ELECTRUM_VERSION
       -from util import format_satoshis, print_msg, print_error, set_verbosity
       -from wallet import Synchronizer, Wallet, Imported_Wallet
       -from storage import WalletStorage
       -from coinchooser import COIN_CHOOSERS
       -from network import Network, pick_random_server
       -from interface import Connection, Interface
       -from simple_config import SimpleConfig, get_config, set_config
       -import bitcoin
       -import transaction
       -import daemon
       -from transaction import Transaction
       -from plugins import BasePlugin
       -from commands import Commands, known_commands
       +from .version import ELECTRUM_VERSION
       +from .util import format_satoshis, print_msg, print_error, set_verbosity
       +from .wallet import Synchronizer, Wallet, Imported_Wallet
       +from .storage import WalletStorage
       +from .coinchooser import COIN_CHOOSERS
       +from .network import Network, pick_random_server
       +from .interface import Connection, Interface
       +from .simple_config import SimpleConfig, get_config, set_config
       +from . import bitcoin
       +from . import transaction
       +from . import daemon
       +from .transaction import Transaction
       +from .plugins import BasePlugin
       +from .commands import Commands, known_commands
   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@@ -22,14 +22,19 @@
        # 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 bitcoin
       -import keystore
       -from keystore import bip44_derivation
       -from wallet import Wallet, Imported_Wallet, Standard_Wallet, Multisig_Wallet, wallet_types
       -from i18n import _
       -from plugins import run_hook
       +from . import bitcoin
       +from . import keystore
       +from .keystore import bip44_derivation
       +from .wallet import Wallet, Imported_Wallet, Standard_Wallet, Multisig_Wallet, wallet_types
       +from .i18n import _
       +from .plugins import run_hook
        
        class BaseWizard(object):
        
   DIR diff --git a/lib/bitcoin.py b/lib/bitcoin.py
       t@@ -26,12 +26,12 @@
        
        import hashlib
        import base64
       -import os
        import re
        import hmac
        
       -import version
       -from util import print_error, InvalidPassword
       +from lib.util import bfh, bh2u
       +from . import version
       +from .util import print_error, InvalidPassword, assert_bytes, _bytes, to_bytes
        
        import ecdsa
        import pyaes
       t@@ -98,6 +98,9 @@ except:
            AES = None
        
        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@@ -112,6 +115,9 @@ def aes_encrypt_with_iv(key, iv, data):
                return e
        
        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@@ -127,14 +133,21 @@ def aes_decrypt_with_iv(key, iv, data):
                return s
        
        def EncodeAES(secret, s):
       -    iv = bytes(os.urandom(16))
       +    assert_bytes(s)
       +    iv = _bytes(os.urandom(16))
       +    # aes_cbc = pyaes.AESModeOfOperationCBC(secret, iv=iv)
       +    # aes = pyaes.Encrypter(aes_cbc)
       +    # e = iv + aes.feed(s) + aes.feed()
            ct = aes_encrypt_with_iv(secret, iv, s)
            e = iv + ct
            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)
       +    # s = aes.feed(e) + aes.feed()
            s = aes_decrypt_with_iv(secret, iv, e)
            return s
        
       t@@ -158,10 +171,11 @@ def pw_decode(s, password):
        
        
        def rev_hex(s):
       -    return s.decode('hex')[::-1].encode('hex')
       +    return bh2u(bfh(s)[::-1])
        
        
        def int_to_hex(i, length=1):
       +    assert isinstance(i, int)
            s = hex(i)[2:].rstrip('L')
            s = "0"*(2*length - len(s)) + s
            return rev_hex(s)
       t@@ -191,26 +205,30 @@ def op_push(i):
        
        
        def sha256(x):
       -    return hashlib.sha256(x).digest()
       +    x = to_bytes(x, 'utf8')
       +    return _bytes(hashlib.sha256(x).digest())
        
        
        def Hash(x):
       -    if type(x) is unicode: x=x.encode('utf-8')
       -    return sha256(sha256(x))
       +    x = to_bytes(x, 'utf8')
       +    out = _bytes(sha256(sha256(x)))
       +    return out
       +
       +
       +hash_encode = lambda x: bh2u(x[::-1])
       +hash_decode = lambda x: bfh(x)[::-1]
       +hmac_sha_512 = lambda x, y: _bytes(hmac.new(x, y, hashlib.sha512).digest())
        
       -hash_encode = lambda x: x[::-1].encode('hex')
       -hash_decode = lambda x: x.decode('hex')[::-1]
       -hmac_sha_512 = lambda x,y: hmac.new(x, y, hashlib.sha512).digest()
        
        def is_new_seed(x, prefix=version.SEED_PREFIX):
       -    import mnemonic
       +    from . import mnemonic
            x = mnemonic.normalize_text(x)
       -    s = hmac_sha_512("Seed version", x.encode('utf8')).encode('hex')
       +    s = bh2u(hmac_sha_512(b"Seed version", x.encode('utf8')))
            return s.startswith(prefix)
        
        
        def is_old_seed(seed):
       -    import old_mnemonic
       +    from . import old_mnemonic
            words = seed.strip().split()
            try:
                old_mnemonic.mn_decode(words)
       t@@ -218,8 +236,8 @@ def is_old_seed(seed):
            except Exception:
                uses_electrum_words = False
            try:
       -        seed.decode('hex')
       -        is_hex = (len(seed) == 32 or len(seed) == 64)
       +        seed = bfh(seed)
       +        is_hex = (len(seed) == 16 or len(seed) == 32)
            except Exception:
                is_hex = False
            return is_hex or (uses_electrum_words and (len(words) == 12 or len(words) == 24))
       t@@ -255,37 +273,38 @@ def i2o_ECPublicKey(pubkey, compressed=False):
                      '%064x' % pubkey.point.x() + \
                      '%064x' % pubkey.point.y()
        
       -    return key.decode('hex')
       -
       +    return bfh(key)
        # end pywallet openssl private key implementation
        
        
       -
        ############ functions from pywallet #####################
       -
        def hash_160(public_key):
            if 'ANDROID_DATA' in os.environ:
                from Crypto.Hash import RIPEMD
                md = RIPEMD.new()
            else:
                md = hashlib.new('ripemd')
       +    public_key = to_bytes(public_key, 'ascii')
            md.update(sha256(public_key))
            return md.digest()
        
        def hash_160_to_bc_address(h160, addrtype, witness_program_version=1):
       -    s = chr(addrtype)
       +    s = bytes([addrtype])
            if addrtype == ADDRTYPE_P2WPKH:
       -        s += chr(witness_program_version) + chr(0)
       +        s += bytes([witness_program_version]) + b'\x00'
            s += h160
            return base_encode(s+Hash(s)[0:4], base=58)
        
       +
        def bc_address_to_hash_160(addr):
       -    bytes = base_decode(addr, 25, base=58)
       -    return ord(bytes[0]), bytes[1:21]
       +    addr = to_bytes(addr, 'ascii')
       +    _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)
        
       +
        def hash160_to_p2sh(h160):
            return hash_160_to_bc_address(h160, ADDRTYPE_P2SH)
        
       t@@ -298,60 +317,70 @@ def public_key_to_p2wpkh(public_key):
        
        
        
       -__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
       +__b58chars = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
        assert len(__b58chars) == 58
        
       -__b43chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$*+-./:'
       +__b43chars = b'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$*+-./:'
        assert len(__b43chars) == 43
        
        
        def base_encode(v, base):
            """ encode v, which is a string of bytes, to base58."""
       -    if base == 58:
       -        chars = __b58chars
       -    elif base == 43:
       +    assert_bytes(v)
       +    assert base in (58, 43)
       +    chars = __b58chars
       +    if base == 43:
                chars = __b43chars
       -    long_value = 0L
       +    long_value = 0
            for (i, c) in enumerate(v[::-1]):
       -        long_value += (256**i) * ord(c)
       -    result = ''
       +        long_value += (256**i) * c
       +    result = bytearray()
            while long_value >= base:
                div, mod = divmod(long_value, base)
       -        result = chars[mod] + result
       +        result.append(chars[mod])
                long_value = div
       -    result = chars[long_value] + result
       +    result.append(chars[long_value])
            # Bitcoin does a little leading-zero-compression:
            # leading 0-bytes in the input become leading-1s
            nPad = 0
            for c in v:
       -        if c == '\0': nPad += 1
       -        else: break
       -    return (chars[0]*nPad) + result
       +        if c == 0x00:
       +            nPad += 1
       +        else:
       +            break
       +    result.extend([chars[0]] * nPad)
       +    result.reverse()
       +    return result.decode('ascii')
        
        
        def base_decode(v, length, base):
            """ decode v into a string of len bytes."""
       -    if base == 58:
       -        chars = __b58chars
       -    elif base == 43:
       +    # assert_bytes(v)
       +    v = to_bytes(v, 'ascii')
       +    assert base in (58, 43)
       +    chars = __b58chars
       +    if base == 43:
                chars = __b43chars
       -    long_value = 0L
       +    long_value = 0
            for (i, c) in enumerate(v[::-1]):
       -        long_value += chars.find(c) * (base**i)
       -    result = ''
       +        long_value += chars.find(_bytes([c])) * (base**i)
       +    result = bytearray()
            while long_value >= 256:
                div, mod = divmod(long_value, 256)
       -        result = chr(mod) + result
       +        result.append(mod)
                long_value = div
       -    result = chr(long_value) + result
       +    result.append(long_value)
            nPad = 0
            for c in v:
       -        if c == chars[0]: nPad += 1
       -        else: break
       -    result = chr(0)*nPad + result
       +        if c == chars[0]:
       +            nPad += 1
       +        else:
       +            break
       +    result.extend(b'\x00' * nPad)
            if length is not None and len(result) != length:
                return None
       -    return result
       +    result.reverse()
       +    return bytes(result)
        
        
        def EncodeBase58Check(vchIn):
       t@@ -377,14 +406,15 @@ def PrivKeyToSecret(privkey):
        
        def SecretToASecret(secret, compressed=False):
            addrtype = ADDRTYPE_P2PKH
       -    vchIn = chr((addrtype+128)&255) + secret
       -    if compressed: vchIn += '\01'
       +    vchIn = bytes([(addrtype+128)&255]) + secret
       +    if compressed: vchIn += b'\01'
            return EncodeBase58Check(vchIn)
        
       +
        def ASecretToSecret(key):
            addrtype = ADDRTYPE_P2PKH
            vch = DecodeBase58Check(key)
       -    if vch and vch[0] == chr((addrtype+128)&255):
       +    if vch and vch[0] == ((addrtype+128)&255):
                return vch[1:]
            elif is_minikey(key):
                return minikey_to_private_key(key)
       t@@ -404,7 +434,7 @@ def GetPubKey(pubkey, compressed=False):
        
        
        def GetSecret(pkey):
       -    return ('%064x' % pkey.secret).decode('hex')
       +    return bfh('%064x' % pkey.secret)
        
        
        def is_compressed(sec):
       t@@ -418,12 +448,12 @@ def public_key_from_private_key(sec):
            assert pkey
            compressed = is_compressed(sec)
            public_key = GetPubKey(pkey.pubkey, compressed)
       -    return public_key.encode('hex')
       +    return bh2u(public_key)
        
        
        def address_from_private_key(sec):
            public_key = public_key_from_private_key(sec)
       -    address = public_key_to_p2pkh(public_key.decode('hex'))
       +    address = public_key_to_p2pkh(bfh(public_key))
            return address
        
        
       t@@ -434,7 +464,7 @@ def is_valid(addr):
        def is_address(addr):
            try:
                addrtype, h = bc_address_to_hash_160(addr)
       -    except Exception:
       +    except Exception as e:
                return False
            if addrtype not in [ADDRTYPE_P2PKH, ADDRTYPE_P2SH]:
                return False
       t@@ -478,10 +508,14 @@ from ecdsa.curves import SECP256k1
        from ecdsa.ellipticcurve import Point
        from ecdsa.util import string_to_number, number_to_string
        
       +
        def msg_magic(message):
            varint = var_int(len(message))
       -    encoded_varint = "".join([chr(int(varint[i:i+2], 16)) for i in xrange(0, len(varint), 2)])
       -    return "\x18Bitcoin Signed Message:\n" + encoded_varint + 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)])
       +    return b"\x18Bitcoin Signed Message:\n" + encoded_varint + message
        
        
        def verify_message(address, sig, message):
       t@@ -502,11 +536,11 @@ def verify_message(address, sig, message):
        
        
        def encrypt_message(message, pubkey):
       -    return EC_KEY.encrypt_message(message, pubkey.decode('hex'))
       +    return EC_KEY.encrypt_message(message, bfh(pubkey))
        
        
        def chunks(l, n):
       -    return [l[i:i+n] for i in xrange(0, len(l), n)]
       +    return [l[i:i+n] for i in range(0, len(l), n)]
        
        
        def ECC_YfromX(x,curved=curve_secp256k1, odd=True):
       t@@ -516,7 +550,7 @@ def ECC_YfromX(x,curved=curve_secp256k1, odd=True):
            for offset in range(128):
                Mx = x + offset
                My2 = pow(Mx, 3, _p) + _a * pow(Mx, 2, _p) + _b % _p
       -        My = pow(My2, (_p+1)/4, _p )
       +        My = pow(My2, (_p+1)//4, _p )
        
                if curved.contains_point(Mx,My):
                    if odd == bool(My&1):
       t@@ -531,20 +565,19 @@ def negative_point(P):
        
        def point_to_ser(P, comp=True ):
            if comp:
       -        return ( ('%02x'%(2+(P.y()&1)))+('%064x'%P.x()) ).decode('hex')
       -    return ( '04'+('%064x'%P.x())+('%064x'%P.y()) ).decode('hex')
       +        return bfh( ('%02x'%(2+(P.y()&1)))+('%064x'%P.x()) )
       +    return bfh( '04'+('%064x'%P.x())+('%064x'%P.y()) )
        
        
        def ser_to_point(Aser):
            curve = curve_secp256k1
            generator = generator_secp256k1
            _r  = generator.order()
       -    assert Aser[0] in ['\x02','\x03','\x04']
       -    if Aser[0] == '\x04':
       +    assert Aser[0] in [0x02, 0x03, 0x04]
       +    if Aser[0] == 0x04:
                return Point( curve, string_to_number(Aser[1:33]), string_to_number(Aser[33:]), _r )
            Mx = string_to_number(Aser[1:])
       -    return Point( curve, Mx, ECC_YfromX(Mx, curve, Aser[0]=='\x03')[0], _r )
       -
       +    return Point( curve, Mx, ECC_YfromX(Mx, curve, Aser[0] == 0x03)[0], _r )
        
        
        class MyVerifyingKey(ecdsa.VerifyingKey):
       t@@ -552,14 +585,14 @@ class MyVerifyingKey(ecdsa.VerifyingKey):
            def from_signature(klass, sig, recid, h, curve):
                """ See http://www.secg.org/download/aid-780/sec1-v2.pdf, chapter 4.1.6 """
                from ecdsa import util, numbertheory
       -        import msqr
       +        from . import msqr
                curveFp = curve.curve
                G = curve.generator
                order = G.order()
                # extract r,s from signature
                r, s = util.sigdecode_string(sig, order)
                # 1.1
       -        x = r + (recid/2) * order
       +        x = r + (recid//2) * order
                # 1.3
                alpha = ( x * x * x  + curveFp.a() * x + curveFp.b() ) % curveFp.p()
                beta = msqr.modular_sqrt(alpha, curveFp.p())
       t@@ -578,7 +611,7 @@ class MyVerifyingKey(ecdsa.VerifyingKey):
        def pubkey_from_signature(sig, h):
            if len(sig) != 65:
                raise Exception("Wrong encoding")
       -    nV = ord(sig[0])
       +    nV = sig[0]
            if nV < 27 or nV >= 35:
                raise Exception("Bad encoding")
            if nV >= 31:
       t@@ -598,7 +631,7 @@ class MySigningKey(ecdsa.SigningKey):
                G = curve.generator
                order = G.order()
                r, s = ecdsa.SigningKey.sign_number(self, number, entropy, k)
       -        if s > order/2:
       +        if s > order//2:
                    s = order - s
                return r, s
        
       t@@ -612,7 +645,7 @@ class EC_KEY(object):
                self.secret = secret
        
            def get_public_key(self, compressed=True):
       -        return point_to_ser(self.pubkey.point, compressed).encode('hex')
       +        return bh2u(point_to_ser(self.pubkey.point, compressed))
        
            def sign(self, msg_hash):
                private_key = MySigningKey.from_secret_exponent(self.secret, curve = SECP256k1)
       t@@ -622,19 +655,20 @@ class EC_KEY(object):
                return signature
        
            def sign_message(self, message, is_compressed):
       +        message = to_bytes(message, 'utf8')
                signature = self.sign(Hash(msg_magic(message)))
                for i in range(4):
       -            sig = chr(27 + i + (4 if is_compressed else 0)) + signature
       +            sig = bytes([27 + i + (4 if is_compressed else 0)]) + signature
                    try:
                        self.verify_message(sig, message)
                        return sig
       -            except Exception:
       +            except Exception as e:
                        continue
                else:
                    raise Exception("error: cannot sign message")
        
       -
            def verify_message(self, sig, message):
       +        assert_bytes(message)
                h = Hash(msg_magic(message))
                public_key, compressed = pubkey_from_signature(sig, h)
                # check public key
       t@@ -648,6 +682,7 @@ class EC_KEY(object):
        
            @classmethod
            def encrypt_message(self, message, pubkey):
       +        assert_bytes(message)
        
                pk = ser_to_point(pubkey)
                if not ecdsa.ecdsa.point_is_valid(generator_secp256k1, pk.x(), pk.y()):
       t@@ -659,13 +694,12 @@ class EC_KEY(object):
                key = hashlib.sha512(ecdh_key).digest()
                iv, key_e, key_m = key[0:16], key[16:32], key[32:]
                ciphertext = aes_encrypt_with_iv(key_e, iv, message)
       -        ephemeral_pubkey = ephemeral.get_public_key(compressed=True).decode('hex')
       -        encrypted = 'BIE1' + ephemeral_pubkey + ciphertext
       +        ephemeral_pubkey = bfh(ephemeral.get_public_key(compressed=True))
       +        encrypted = b'BIE1' + ephemeral_pubkey + ciphertext
                mac = hmac.new(key_m, encrypted, hashlib.sha256).digest()
        
                return base64.b64encode(encrypted + mac)
        
       -
            def decrypt_message(self, encrypted):
                encrypted = base64.b64decode(encrypted)
                if len(encrypted) < 85:
       t@@ -674,11 +708,11 @@ class EC_KEY(object):
                ephemeral_pubkey = encrypted[4:37]
                ciphertext = encrypted[37:-32]
                mac = encrypted[-32:]
       -        if magic != 'BIE1':
       +        if magic != b'BIE1':
                    raise Exception('invalid ciphertext: invalid magic bytes')
                try:
                    ephemeral_pubkey = ser_to_point(ephemeral_pubkey)
       -        except AssertionError, e:
       +        except AssertionError as e:
                    raise Exception('invalid ciphertext: invalid ephemeral pubkey')
                if not ecdsa.ecdsa.point_is_valid(generator_secp256k1, ephemeral_pubkey.x(), ephemeral_pubkey.y()):
                    raise Exception('invalid ciphertext: invalid ephemeral pubkey')
       t@@ -715,13 +749,14 @@ def get_pubkeys_from_secret(secret):
        #  public key can be determined without the master private key.
        def CKD_priv(k, c, n):
            is_prime = n & BIP32_PRIME
       -    return _CKD_priv(k, c, rev_hex(int_to_hex(n,4)).decode('hex'), is_prime)
       +    return _CKD_priv(k, c, bfh(rev_hex(int_to_hex(n,4))), is_prime)
       +
        
        def _CKD_priv(k, c, s, is_prime):
            order = generator_secp256k1.order()
            keypair = EC_KEY(k)
            cK = GetPubKey(keypair.pubkey,True)
       -    data = chr(0) + k + s if is_prime else cK + s
       +    data = bytes([0]) + k + s if is_prime else cK + s
            I = hmac.new(c, data, hashlib.sha512).digest()
            k_n = number_to_string( (string_to_number(I[0:32]) + string_to_number(k)) % order , order )
            c_n = I[32:]
       t@@ -735,7 +770,7 @@ def _CKD_priv(k, c, s, is_prime):
        #  non-negative. If n is negative, we need the master private key to find it.
        def CKD_pub(cK, c, n):
            if n & BIP32_PRIME: raise
       -    return _CKD_pub(cK, c, rev_hex(int_to_hex(n,4)).decode('hex'))
       +    return _CKD_pub(cK, c, bfh(rev_hex(int_to_hex(n,4))))
        
        # helper function, callable with arbitrary string
        def _CKD_pub(cK, c, s):
       t@@ -750,41 +785,48 @@ def _CKD_pub(cK, c, s):
        
        
        def xprv_header(xtype):
       -    return ("%08x"%(XPRV_HEADER + xtype)).decode('hex')
       +    return bfh("%08x" % (XPRV_HEADER + xtype))
       +
        
        def xpub_header(xtype):
       -    return ("%08x"%(XPUB_HEADER + xtype)).decode('hex')
       +    return bfh("%08x" % (XPUB_HEADER + xtype))
       +
        
       -def serialize_xprv(xtype, c, k, depth=0, fingerprint=chr(0)*4, child_number=chr(0)*4):
       -    xprv = xprv_header(xtype) + chr(depth) + fingerprint + child_number + c + chr(0) + k
       +def serialize_xprv(xtype, c, k, depth=0, fingerprint=b'\x00'*4, child_number=b'\x00'*4):
       +    xprv = xprv_header(xtype) + bytes([depth]) + fingerprint + child_number + c + bytes([0]) + k
            return EncodeBase58Check(xprv)
        
       -def serialize_xpub(xtype, c, cK, depth=0, fingerprint=chr(0)*4, child_number=chr(0)*4):
       -    xpub = xpub_header(xtype) + chr(depth) + fingerprint + child_number + c + cK
       +
       +def serialize_xpub(xtype, c, cK, depth=0, fingerprint=b'\x00'*4, child_number=b'\x00'*4):
       +    xpub = xpub_header(xtype) + bytes([depth]) + fingerprint + child_number + c + cK
            return EncodeBase58Check(xpub)
        
       +
        def deserialize_xkey(xkey, prv):
            xkey = DecodeBase58Check(xkey)
            if len(xkey) != 78:
                raise BaseException('Invalid length')
       -    depth = ord(xkey[4])
       +    depth = xkey[4]
            fingerprint = xkey[5:9]
            child_number = xkey[9:13]
            c = xkey[13:13+32]
            header = XPRV_HEADER if prv else XPUB_HEADER
       -    xtype = int('0x' + xkey[0:4].encode('hex'), 16) - header
       +    xtype = int('0x' + bh2u(xkey[0:4]), 16) - header
            if xtype not in ([0, 1] if TESTNET else [0]):
                raise BaseException('Invalid header')
            n = 33 if prv else 32
            K_or_k = xkey[13+n:]
            return xtype, depth, fingerprint, child_number, c, K_or_k
        
       +
        def deserialize_xpub(xkey):
            return deserialize_xkey(xkey, False)
        
       +
        def deserialize_xprv(xkey):
            return deserialize_xkey(xkey, True)
        
       +
        def is_xpub(text):
            try:
                deserialize_xpub(text)
       t@@ -792,6 +834,7 @@ def is_xpub(text):
            except:
                return False
        
       +
        def is_xprv(text):
            try:
                deserialize_xprv(text)
       t@@ -807,7 +850,7 @@ def xpub_from_xprv(xprv):
        
        
        def bip32_root(seed, xtype):
       -    I = hmac.new("Bitcoin seed", seed, hashlib.sha512).digest()
       +    I = hmac.new(b"Bitcoin seed", seed, hashlib.sha512).digest()
            master_k = I[0:32]
            master_c = I[32:]
            K, cK = get_pubkeys_from_secret(master_k)
       t@@ -815,9 +858,10 @@ def bip32_root(seed, xtype):
            xpub = serialize_xpub(xtype, master_c, cK)
            return xprv, xpub
        
       +
        def xpub_from_pubkey(xtype, cK):
       -    assert cK[0] in ['\x02','\x03']
       -    return serialize_xpub(xtype, chr(0)*32, cK)
       +    assert cK[0] in [0x02, 0x03]
       +    return serialize_xpub(xtype, b'\x00'*32, cK)
        
        
        def bip32_derivation(s):
       t@@ -849,7 +893,7 @@ def bip32_private_derivation(xprv, branch, sequence):
                depth += 1
            _, parent_cK = get_pubkeys_from_secret(parent_k)
            fingerprint = hash_160(parent_cK)[0:4]
       -    child_number = ("%08X"%i).decode('hex')
       +    child_number = bfh("%08X"%i)
            K, cK = get_pubkeys_from_secret(k)
            xpub = serialize_xpub(xtype, c, cK, depth, fingerprint, child_number)
            xprv = serialize_xprv(xtype, c, k, depth, fingerprint, child_number)
       t@@ -867,7 +911,7 @@ def bip32_public_derivation(xpub, branch, sequence):
                cK, c = CKD_pub(cK, c, i)
                depth += 1
            fingerprint = hash_160(parent_cK)[0:4]
       -    child_number = ("%08X"%i).decode('hex')
       +    child_number = bfh("%08X"%i)
            return serialize_xpub(xtype, c, cK, depth, fingerprint, child_number)
        
        
       t@@ -878,7 +922,7 @@ def bip32_private_key(sequence, k, chain):
        
        
        def xkeys_from_seed(seed, passphrase, derivation):
       -    from mnemonic import Mnemonic
       +    from .mnemonic import Mnemonic
            xprv, xpub = bip32_root(Mnemonic.mnemonic_to_seed(seed, passphrase), 0)
            xprv, xpub = bip32_private_derivation(xprv, "m/", derivation)
            return xprv, xpub
   DIR diff --git a/lib/blockchain.py b/lib/blockchain.py
       t@@ -22,15 +22,20 @@
        # 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 util
        import threading
        
       -import bitcoin
       -from bitcoin import *
       +from . import util
       +from . import bitcoin
       +from .bitcoin import *
        
        MAX_TARGET = 0x00000000FFFF0000000000000000000000000000000000000000000000000000
        
   DIR diff --git a/lib/coinchooser.py b/lib/coinchooser.py
       t@@ -22,13 +22,19 @@
        # 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 collections import defaultdict, namedtuple
        from math import floor, log10
        
       -from bitcoin import sha256, COIN, TYPE_ADDRESS
       -from transaction import Transaction
       -from util import NotEnoughFunds, PrintError, profiler
       +from .bitcoin import sha256, COIN, TYPE_ADDRESS
       +from .transaction import Transaction
       +from .util import NotEnoughFunds, PrintError, profiler
       +
        
        # A simple deterministic PRNG.  Used to deterministically shuffle a
        # set of coins - the same set of coins should produce the same output.
       t@@ -36,7 +42,6 @@ from util import NotEnoughFunds, PrintError, profiler
        # so if sending twice from the same UTXO set we choose the same UTXOs
        # to spend.  This prevents attacks on users by malicious or stale
        # servers.
       -
        class PRNG:
            def __init__(self, seed):
                self.sha = sha256(seed)
   DIR diff --git a/lib/commands.py b/lib/commands.py
       t@@ -22,7 +22,12 @@
        # 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 sys
        import datetime
       t@@ -35,15 +40,16 @@ import base64
        from functools import wraps
        from decimal import Decimal
        
       -import util
       -from util import print_msg, format_satoshis, print_stderr
       -import bitcoin
       -from bitcoin import is_address, hash_160, COIN, TYPE_ADDRESS
       -import transaction
       -from transaction import Transaction
       -import paymentrequest
       -from paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
       -import contacts
       +from .import util
       +from .util import print_msg, format_satoshis, print_stderr
       +from .import bitcoin
       +from .bitcoin import is_address,  hash_160, COIN, TYPE_ADDRESS
       +from .transaction import Transaction
       +from .import paymentrequest
       +from .paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
       +from .import contacts
       +if six.PY3:
       +    long = int
        known_commands = {}
        
        
       t@@ -53,7 +59,6 @@ def satoshis(amount):
        
        
        class Command:
       -
            def __init__(self, func, s):
                self.name = func.__name__
                self.requires_network = 'n' in s
       t@@ -61,8 +66,8 @@ class Command:
                self.requires_password = 'p' in s
                self.description = func.__doc__
                self.help = self.description.split('.')[0] if self.description else None
       -        varnames = func.func_code.co_varnames[1:func.func_code.co_argcount]
       -        self.defaults = func.func_defaults
       +        varnames = func.__code__.co_varnames[1:func.__code__.co_argcount]
       +        self.defaults = func.__defaults__
                if self.defaults:
                    n = len(self.defaults)
                    self.params = list(varnames[:-n])
       t@@ -728,7 +733,7 @@ command_options = {
        
        
        # don't use floats because of rounding errors
       -from transaction import tx_from_str
       +from .transaction import tx_from_str
        json_loads = lambda x: json.loads(x, parse_float=lambda x: str(Decimal(x)))
        arg_types = {
            'num': int,
   DIR diff --git a/lib/contacts.py b/lib/contacts.py
       t@@ -20,6 +20,12 @@
        # 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 sys
        import re
       t@@ -27,10 +33,10 @@ import dns
        import os
        import json
        
       -import bitcoin
       -import dnssec
       -from util import print_error
       -from i18n import _
       +from . import bitcoin
       +from . import dnssec
       +from .util import print_error
       +from .i18n import _
        
        
        class Contacts(dict):
   DIR diff --git a/lib/daemon.py b/lib/daemon.py
       t@@ -22,25 +22,30 @@
        # 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 ast
        import os
        import sys
        import time
        
       -import jsonrpclib
       -from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
       +# import jsonrpclib
       +# from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
        
       -from version import ELECTRUM_VERSION
       -from network import Network
       -from util import json_decode, DaemonThread
       -from util import print_msg, print_error, print_stderr, UserCancelled
       -from wallet import Wallet
       -from storage import WalletStorage
       -from commands import known_commands, Commands
       -from simple_config import SimpleConfig
       -from plugins import run_hook
       -from exchange_rate import FxThread
       +from .version import ELECTRUM_VERSION
       +from .network import Network
       +from .util import json_decode, DaemonThread
       +from .util import print_msg, print_error, print_stderr, UserCancelled
       +from .wallet import Wallet
       +from .storage import WalletStorage
       +from .commands import known_commands, Commands
       +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')
       t@@ -85,18 +90,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):
   DIR diff --git a/lib/dnssec.py b/lib/dnssec.py
       t@@ -22,7 +22,12 @@
        # 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
        
        
        # Check DNSSEC trust chain.
       t@@ -61,25 +66,21 @@ import dns.rdtypes.IN.AAAA
        from dns.exception import DNSException
        
        
       -
       -"""
       -Pure-Python version of dns.dnssec._validate_rsig
       -"""
       -
       +# Pure-Python version of dns.dnssec._validate_rsig
        import ecdsa
       -import rsakey
       +from . import rsakey
        
        
        def python_validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
            from dns.dnssec import ValidationFailure, ECDSAP256SHA256, ECDSAP384SHA384
            from dns.dnssec import _find_candidate_keys, _make_hash, _is_ecdsa, _is_rsa, _to_rdata, _make_algorithm_id
        
       -    if isinstance(origin, (str, unicode)):
       +    if isinstance(origin, six.text_type):
                origin = dns.name.from_text(origin, dns.name.root)
        
            for candidate_key in _find_candidate_keys(keys, rrsig):
                if not candidate_key:
       -            raise ValidationFailure, 'unknown key'
       +            raise ValidationFailure('unknown key')
        
                # For convenience, allow the rrset to be specified as a (name, rdataset)
                # tuple as well as a proper rrset
       t@@ -93,9 +94,9 @@ def python_validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
                if now is None:
                    now = time.time()
                if rrsig.expiration < now:
       -            raise ValidationFailure, 'expired'
       +            raise ValidationFailure('expired')
                if rrsig.inception > now:
       -            raise ValidationFailure, 'not yet valid'
       +            raise ValidationFailure('not yet valid')
        
                hash = _make_hash(rrsig.algorithm)
        
       t@@ -124,7 +125,7 @@ def python_validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
                        digest_len = 48
                    else:
                        # shouldn't happen
       -                raise ValidationFailure, 'unknown ECDSA curve'
       +                raise ValidationFailure('unknown ECDSA curve')
                    keyptr = candidate_key.key
                    x = ecdsa.util.string_to_number(keyptr[0:key_len])
                    y = ecdsa.util.string_to_number(keyptr[key_len:key_len * 2])
       t@@ -137,7 +138,7 @@ def python_validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
                                                ecdsa.util.string_to_number(s))
        
                else:
       -            raise ValidationFailure, 'unknown algorithm %u' % rrsig.algorithm
       +            raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm)
        
                hash.update(_to_rdata(rrsig, origin)[:18])
                hash.update(rrsig.signer.to_digestable(origin))
       t@@ -170,9 +171,9 @@ def python_validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
                        return
        
                else:
       -            raise ValidationFailure, 'unknown algorithm %u' % rrsig.algorithm
       +            raise ValidationFailure('unknown algorithm %s' % rrsig.algorithm)
        
       -    raise ValidationFailure, 'verify failure'
       +    raise ValidationFailure('verify failure')
        
        
        # replace validate_rrsig
       t@@ -182,7 +183,7 @@ dns.dnssec.validate = dns.dnssec._validate
        
        
        
       -from util import print_error
       +from .util import print_error
        
        
        # hard-coded trust anchors (root KSKs)
   DIR diff --git a/lib/exchange_rate.py b/lib/exchange_rate.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        from datetime import datetime
        import inspect
        import requests
       t@@ -8,10 +14,10 @@ import traceback
        import csv
        from decimal import Decimal
        
       -from bitcoin import COIN
       -from i18n import _
       -from util import PrintError, ThreadJob
       -from util import format_satoshis
       +from .bitcoin import COIN
       +from .i18n import _
       +from .util import PrintError, ThreadJob
       +from .util import format_satoshis
        
        
        # See https://en.wikipedia.org/wiki/ISO_4217
       t@@ -22,6 +28,7 @@ CCY_PRECISIONS = {'BHD': 3, 'BIF': 0, 'BYR': 0, 'CLF': 4, 'CLP': 0,
                          'RWF': 0, 'TND': 3, 'UGX': 0, 'UYI': 0, 'VND': 0,
                          'VUV': 0, 'XAF': 0, 'XAU': 4, 'XOF': 0, 'XPF': 0}
        
       +
        class ExchangeBase(PrintError):
        
            def __init__(self, on_quotes, on_history):
       t@@ -323,7 +330,7 @@ class Winkdex(ExchangeBase):
        
        def dictinvert(d):
            inv = {}
       -    for k, vlist in d.iteritems():
       +    for k, vlist in d.items():
                for v in vlist:
                    keys = inv.setdefault(v, [])
                    keys.append(k)
   DIR diff --git a/lib/i18n.py b/lib/i18n.py
       t@@ -22,16 +22,24 @@
        # 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 gettext, os
       +import gettext, os, six
        
        LOCALE_DIR = os.path.join(os.path.dirname(__file__), 'locale')
        language = gettext.translation('electrum', LOCALE_DIR, fallback = True)
        
       -
       -def _(x):
       -    global language
       -    return language.ugettext(x)
       +if six.PY2:
       +    def _(x):
       +        global language
       +        return language.ugettext(x)
       +else:
       +    def _(x):
       +        global language
       +        return language.gettext(x)
        
        def set_language(x):
            global language
   DIR diff --git a/lib/interface.py b/lib/interface.py
       t@@ -22,8 +22,12 @@
        # 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 re
        import socket
       t@@ -36,9 +40,9 @@ import traceback
        import requests
        ca_path = requests.certs.where()
        
       -import util
       -import x509
       -import pem
       +from . import util
       +from . import x509
       +from . import pem
        
        
        def Connection(server, queue, config_path):
       t@@ -80,7 +84,7 @@ class TcpConnection(threading.Thread, util.PrintError):
                # None/{} is not acceptable.
                if not peercert:
                    return False
       -        if peercert.has_key("subjectAltName"):
       +        if 'subjectAltName' in peercert:
                    for typ, val in peercert["subjectAltName"]:
                        if typ == "DNS" and val == name:
                            return True
       t@@ -102,6 +106,7 @@ class TcpConnection(threading.Thread, util.PrintError):
                except socket.gaierror:
                    self.print_error("cannot resolve hostname")
                    return
       +        e = None
                for res in l:
                    try:
                        s = socket.socket(res[0], socket.SOCK_STREAM)
       t@@ -110,7 +115,8 @@ class TcpConnection(threading.Thread, util.PrintError):
                        s.settimeout(2)
                        s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
                        return s
       -            except BaseException as e:
       +            except BaseException as _e:
       +                e = _e
                        continue
                else:
                    self.print_error("failed to connect", str(e))
       t@@ -126,7 +132,7 @@ class TcpConnection(threading.Thread, util.PrintError):
                        # 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)
       -                except ssl.SSLError, e:
       +                except ssl.SSLError as e:
                            s = None
                        if s and self.check_host_name(s.getpeercert(), self.host):
                            self.print_error("SSL certificate signed by CA")
       t@@ -138,7 +144,7 @@ class TcpConnection(threading.Thread, util.PrintError):
                            return
                        try:
                            s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_NONE, ca_certs=None)
       -                except ssl.SSLError, e:
       +                except ssl.SSLError as e:
                            self.print_error("SSL error retrieving SSL certificate:", e)
                            return
        
       t@@ -164,7 +170,7 @@ class TcpConnection(threading.Thread, util.PrintError):
                                            cert_reqs=ssl.CERT_REQUIRED,
                                            ca_certs= (temporary_path if is_new else cert_path),
                                            do_handshake_on_connect=True)
       -            except ssl.SSLError, e:
       +            except ssl.SSLError as e:
                        self.print_error("SSL error:", e)
                        if e.errno != 1:
                            return
       t@@ -191,7 +197,7 @@ class TcpConnection(threading.Thread, util.PrintError):
                                return
                            self.print_error("wrong certificate")
                        return
       -            except BaseException, e:
       +            except BaseException as e:
                        self.print_error(e)
                        if e.errno == 104:
                            return
       t@@ -264,12 +270,12 @@ class Interface(util.PrintError):
        
            def send_requests(self):
                '''Sends queued requests.  Returns False on failure.'''
       -        make_dict = lambda (m, p, i): {'method': m, 'params': p, 'id': i}
       +        make_dict = lambda m, p, i: {'method': m, 'params': p, 'id': i}
                n = self.num_requests()
                wire_requests = self.unsent_requests[0:n]
                try:
                    self.pipe.send_all(map(make_dict, wire_requests))
       -        except socket.error, e:
       +        except socket.error as e:
                    self.print_error("socket error:", e)
                    return False
                self.unsent_requests = self.unsent_requests[n:]
       t@@ -363,12 +369,12 @@ def _match_hostname(name, val):
            return val.startswith('*.') and name.endswith(val[1:])
        
        def test_certificates():
       -    from simple_config import SimpleConfig
       +    from .simple_config import SimpleConfig
            config = SimpleConfig()
            mydir = os.path.join(config.path, "certs")
            certs = os.listdir(mydir)
            for c in certs:
       -        print c
       +        print(c)
                p = os.path.join(mydir,c)
                with open(p) as f:
                    cert = f.read()
   DIR diff --git a/lib/keystore.py b/lib/keystore.py
       t@@ -28,15 +28,15 @@ import struct
        
        from unicodedata import normalize
        
       -from version import *
       -import bitcoin
       -from bitcoin import pw_encode, pw_decode, bip32_root, bip32_private_derivation, bip32_public_derivation, bip32_private_key, deserialize_xprv, deserialize_xpub
       -from bitcoin import public_key_from_private_key, public_key_to_p2pkh
       -from bitcoin import *
       +from .version import *
       +from . import bitcoin
       +from .bitcoin import pw_encode, pw_decode, bip32_root, bip32_private_derivation, bip32_public_derivation, bip32_private_key, deserialize_xprv, deserialize_xpub
       +from .bitcoin import public_key_from_private_key, public_key_to_p2pkh
       +from .bitcoin import *
        
       -from bitcoin import is_old_seed, is_new_seed, is_seed
       -from util import PrintError, InvalidPassword
       -from mnemonic import Mnemonic, load_wordlist
       +from .bitcoin import is_old_seed, is_new_seed, is_seed
       +from .util import PrintError, InvalidPassword
       +from .mnemonic import Mnemonic, load_wordlist
        
        
        class KeyStore(PrintError):
       t@@ -170,7 +170,7 @@ class Imported_KeyStore(Software_KeyStore):
                    # fixme: this assumes p2pkh
                    _, addr = xpubkey_to_address(x_pubkey)
                    for pubkey in self.keypairs.keys():
       -                if public_key_to_p2pkh(pubkey.decode('hex')) == addr:
       +                if public_key_to_p2pkh(bfh(pubkey)) == addr:
                            return pubkey
        
            def update_password(self, old_password, new_password):
       t@@ -247,22 +247,22 @@ class Xpub:
                _, _, _, _, c, cK = deserialize_xpub(xpub)
                for i in sequence:
                    cK, c = CKD_pub(cK, c, i)
       -        return cK.encode('hex')
       +        return bh2u(cK)
        
            def get_xpubkey(self, c, i):
                s = ''.join(map(lambda x: bitcoin.int_to_hex(x,2), (c, i)))
       -        return 'ff' + bitcoin.DecodeBase58Check(self.xpub).encode('hex') + s
       +        return 'ff' + bh2u(bitcoin.DecodeBase58Check(self.xpub)) + s
        
            @classmethod
            def parse_xpubkey(self, pubkey):
                assert pubkey[0:2] == 'ff'
       -        pk = pubkey.decode('hex')
       +        pk = bfh(pubkey)
                pk = pk[1:]
                xkey = bitcoin.EncodeBase58Check(pk[0:78])
                dd = pk[78:]
                s = []
                while dd:
       -            n = int(bitcoin.rev_hex(dd[0:2].encode('hex')), 16)
       +            n = int(bitcoin.rev_hex(bh2u(dd[0:2])), 16)
                    dd = dd[2:]
                    s.append(n)
                assert len(s) == 2
       t@@ -277,7 +277,6 @@ class Xpub:
                return derivation
        
        
       -
        class BIP32_KeyStore(Deterministic_KeyStore, Xpub):
        
            def __init__(self, d):
       t@@ -363,12 +362,12 @@ class Old_KeyStore(Deterministic_KeyStore):
                self.mpk = mpk
        
            def format_seed(self, seed):
       -        import old_mnemonic
       +        from . import old_mnemonic
                # see if seed was entered as hex
                seed = seed.strip()
                if seed:
                    try:
       -                seed.decode('hex')
       +                bfh(seed)
                        return str(seed)
                    except Exception:
                        pass
       t@@ -379,7 +378,7 @@ class Old_KeyStore(Deterministic_KeyStore):
                return seed
        
            def get_seed(self, password):
       -        import old_mnemonic
       +        from . import old_mnemonic
                s = self.get_hex_seed(password)
                return ' '.join(old_mnemonic.mn_encode(s))
        
       t@@ -388,7 +387,7 @@ class Old_KeyStore(Deterministic_KeyStore):
                secexp = klass.stretch_key(seed)
                master_private_key = ecdsa.SigningKey.from_secret_exponent(secexp, curve = SECP256k1)
                master_public_key = master_private_key.get_verifying_key().to_string()
       -        return master_public_key.encode('hex')
       +        return bh2u(master_public_key)
        
            @classmethod
            def stretch_key(self, seed):
       t@@ -399,20 +398,20 @@ class Old_KeyStore(Deterministic_KeyStore):
        
            @classmethod
            def get_sequence(self, mpk, for_change, n):
       -        return string_to_number(Hash("%d:%d:"%(n, for_change) + mpk.decode('hex')))
       +        return string_to_number(Hash(("%d:%d:"%(n, for_change)).encode('ascii') + bfh(mpk)))
        
            def get_address(self, for_change, n):
                pubkey = self.get_pubkey(for_change, n)
       -        address = public_key_to_p2pkh(pubkey.decode('hex'))
       +        address = public_key_to_p2pkh(bfh(pubkey))
                return address
        
            @classmethod
            def get_pubkey_from_mpk(self, mpk, for_change, n):
                z = self.get_sequence(mpk, for_change, n)
       -        master_public_key = ecdsa.VerifyingKey.from_string(mpk.decode('hex'), curve = SECP256k1)
       +        master_public_key = ecdsa.VerifyingKey.from_string(bfh(mpk), curve = SECP256k1)
                pubkey_point = master_public_key.pubkey.point + z*SECP256k1.generator
                public_key2 = ecdsa.VerifyingKey.from_public_point(pubkey_point, curve = SECP256k1)
       -        return '04' + public_key2.to_string().encode('hex')
       +        return '04' + bh2u(public_key2.to_string())
        
            def derive_pubkey(self, for_change, n):
                return self.get_pubkey_from_mpk(self.mpk, for_change, n)
       t@@ -436,8 +435,8 @@ class Old_KeyStore(Deterministic_KeyStore):
                secexp = self.stretch_key(seed)
                master_private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve = SECP256k1 )
                master_public_key = master_private_key.get_verifying_key().to_string()
       -        if master_public_key != self.mpk.decode('hex'):
       -            print_error('invalid password (mpk)', self.mpk, master_public_key.encode('hex'))
       +        if master_public_key != bfh(self.mpk):
       +            print_error('invalid password (mpk)', self.mpk, bh2u(master_public_key))
                    raise InvalidPassword()
        
            def check_password(self, password):
       t@@ -590,17 +589,20 @@ def bip39_is_checksum_valid(mnemonic):
        def is_xpubkey(x_pubkey):
            return x_pubkey[0:2] == 'ff'
        
       +
        def parse_xpubkey(x_pubkey):
            assert x_pubkey[0:2] == 'ff'
            return BIP32_KeyStore.parse_xpubkey(x_pubkey)
        
       +
        def xpubkey_to_address(x_pubkey):
            if x_pubkey[0:2] == 'fd':
       -        addrtype = ord(x_pubkey[2:4].decode('hex'))
       -        hash160 = x_pubkey[4:].decode('hex')
       +        # TODO: check that ord() is OK here
       +        addrtype = ord(bfh(x_pubkey[2:4]))
       +        hash160 = bfh(x_pubkey[4:])
                address = bitcoin.hash_160_to_bc_address(hash160, addrtype)
                return x_pubkey, address
       -    if x_pubkey[0:2] in ['02','03','04']:
       +    if x_pubkey[0:2] in ['02', '03', '04']:
                pubkey = x_pubkey
            elif x_pubkey[0:2] == 'ff':
                xpub, s = BIP32_KeyStore.parse_xpubkey(x_pubkey)
       t@@ -611,7 +613,7 @@ def xpubkey_to_address(x_pubkey):
            else:
                raise BaseException("Cannot parse pubkey")
            if pubkey:
       -        address = public_key_to_p2pkh(pubkey.decode('hex'))
       +        address = public_key_to_p2pkh(bfh(pubkey))
            return pubkey, address
        
        def xpubkey_to_pubkey(x_pubkey):
       t@@ -649,7 +651,6 @@ def load_keystore(storage, name):
            return k
        
        
       -
        def is_old_mpk(mpk):
            try:
                int(mpk, 16)
       t@@ -657,10 +658,12 @@ def is_old_mpk(mpk):
                return False
            return len(mpk) == 128
        
       +
        def is_address_list(text):
            parts = text.split()
            return bool(parts) and all(bitcoin.is_address(x) for x in parts)
        
       +
        def get_private_keys(text):
            parts = text.split('\n')
            parts = map(lambda x: ''.join(x.split()), parts)
       t@@ -668,15 +671,18 @@ def get_private_keys(text):
            if bool(parts) and all(bitcoin.is_private_key(x) for x in parts):
                return parts
        
       +
        def is_private_key_list(text):
            return bool(get_private_keys(text))
        
       +
        is_mpk = lambda x: is_old_mpk(x) or is_xpub(x)
        is_private = lambda x: is_seed(x) or is_xprv(x) or is_private_key_list(x)
        is_any_key = lambda x: is_old_mpk(x) or is_xprv(x) or is_xpub(x) or is_private_key_list(x)
        is_private_key = lambda x: is_xprv(x) or is_private_key_list(x)
        is_bip32_key = lambda x: is_xprv(x) or is_xpub(x)
        
       +
        def bip44_derivation(account_id):
            if bitcoin.TESTNET:
                return "m/44'/1'/%d'"% int(account_id)
   DIR diff --git a/lib/mnemonic.py b/lib/mnemonic.py
       t@@ -22,6 +22,12 @@
        # 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 hmac
       t@@ -33,10 +39,10 @@ import string
        import ecdsa
        import pbkdf2
        
       -from util import print_error
       -from bitcoin import is_old_seed, is_new_seed
       -import version
       -import i18n
       +from .util import print_error
       +from .bitcoin import is_old_seed, is_new_seed
       +from . import version
       +from . import i18n
        
        # http://www.asahi-net.or.jp/~ax2s-kmtn/ref/unicode/e_asia.html
        CJK_INTERVALS = [
       t@@ -80,7 +86,10 @@ def is_CJK(c):
        
        def normalize_text(seed):
            # normalize
       -    seed = unicodedata.normalize('NFKD', unicode(seed))
       +    if six.PY2:
       +        seed = unicodedata.normalize('NFKD', unicode(seed))
       +    else:
       +        seed = unicodedata.normalize('NFKD', str(seed))
            # lower
            seed = seed.lower()
            # remove accents
       t@@ -139,7 +148,7 @@ class Mnemonic(object):
                words = []
                while i:
                    x = i%n
       -            i = i/n
       +            i = i//n
                    words.append(self.wordlist[x])
                return ' '.join(words)
        
   DIR diff --git a/lib/msqr.py b/lib/msqr.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        # from http://eli.thegreenplace.net/2009/03/07/computing-modular-square-roots-in-python/
        
        def modular_sqrt(a, p):
       t@@ -26,7 +32,7 @@ def modular_sqrt(a, p):
            elif p == 2:
                return p
            elif p % 4 == 3:
       -        return pow(a, (p + 1) / 4, p)
       +        return pow(a, (p + 1) // 4, p)
        
            # Partition p-1 to s * 2^e for an odd s (i.e.
            # reduce all the powers of 2 from p-1)
       t@@ -34,7 +40,7 @@ def modular_sqrt(a, p):
            s = p - 1
            e = 0
            while s % 2 == 0:
       -        s /= 2
       +        s //= 2
                e += 1
        
            # Find some 'n' with a legendre symbol n|p = -1.
       t@@ -59,7 +65,7 @@ def modular_sqrt(a, p):
            # both a and b
            # r is the exponent - decreases with each update
            #
       -    x = pow(a, (s + 1) / 2, p)
       +    x = pow(a, (s + 1) // 2, p)
            b = pow(a, s, p)
            g = pow(n, s, p)
            r = e
       t@@ -67,7 +73,7 @@ def modular_sqrt(a, p):
            while True:
                t = b
                m = 0
       -        for m in xrange(r):
       +        for m in range(r):
                    if t == 1:
                        break
                    t = pow(t, 2, p)
       t@@ -90,5 +96,5 @@ def legendre_symbol(a, p):
            Returns 1 if a has a square root modulo
            p, -1 otherwise.
            """
       -    ls = pow(a, (p - 1) / 2, p)
       +    ls = pow(a, (p - 1) // 2, p)
            return -1 if ls == p - 1 else ls
   DIR diff --git a/lib/network.py b/lib/network.py
       t@@ -20,9 +20,14 @@
        # 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 time
       -import Queue
       +from six.moves import queue
        import os
        import errno
        import sys
       t@@ -32,16 +37,16 @@ import traceback
        from collections import defaultdict, deque
        import threading
        
       -import socks
        import socket
        import json
        
       -import util
       -import bitcoin
       -from bitcoin import *
       -from interface import Connection, Interface
       -import blockchain
       -from version import ELECTRUM_VERSION, PROTOCOL_VERSION
       +from . import socks
       +from . import util
       +from . import bitcoin
       +from .bitcoin import *
       +from .interface import Connection, Interface
       +from . import blockchain
       +from .version import ELECTRUM_VERSION, PROTOCOL_VERSION
        
        DEFAULT_PORTS = {'t':'50001', 's':'50002'}
        
       t@@ -143,7 +148,7 @@ def pick_random_server(hostmap = None, protocol = 's', exclude_set = set()):
            eligible = list(set(filter_protocol(hostmap, protocol)) - exclude_set)
            return random.choice(eligible) if eligible else None
        
       -from simple_config import SimpleConfig
       +from .simple_config import SimpleConfig
        
        proxy_modes = ['socks4', 'socks5', 'http']
        
       t@@ -255,7 +260,7 @@ class Network(util.DaemonThread):
                self.interfaces = {}
                self.auto_connect = self.config.get('auto_connect', True)
                self.connecting = set()
       -        self.socket_queue = Queue.Queue()
       +        self.socket_queue = queue.Queue()
                self.start_network(deserialize_server(self.default_server)[2],
                                   deserialize_proxy(self.config.get('proxy')))
        
       t@@ -436,8 +441,9 @@ class Network(util.DaemonThread):
                    # prevent dns leaks, see http://stackoverflow.com/questions/13184205/dns-over-proxy
                    socket.getaddrinfo = lambda *args: [(socket.AF_INET, socket.SOCK_STREAM, 6, '', (args[0], args[1]))]
                else:
       -            socket.socket = socket._socketobject
       -            socket.getaddrinfo = socket._socket.getaddrinfo
       +            if six.PY2:
       +                socket.socket = socket._socketobject
       +                socket.getaddrinfo = socket._socket.getaddrinfo
        
            def start_network(self, protocol, proxy):
                assert not self.interface and not self.interfaces
       t@@ -458,7 +464,7 @@ class Network(util.DaemonThread):
                assert not self.interfaces
                self.connecting = set()
                # Get a new queue - no old pending connections thanks!
       -        self.socket_queue = Queue.Queue()
       +        self.socket_queue = queue.Queue()
        
            def set_parameters(self, host, port, protocol, proxy, auto_connect):
                proxy_str = serialize_proxy(proxy)
       t@@ -936,7 +942,9 @@ class Network(util.DaemonThread):
                win = [i for i in self.interfaces.values() if i.num_requests()]
                try:
                    rout, wout, xout = select.select(rin, win, [], 0.1)
       -        except socket.error as (code, msg):
       +        except socket.error as e:
       +            # TODO: py3, get code from e
       +            code = None
                    if code == errno.EINTR:
                        return
                    raise
       t@@ -1056,11 +1064,11 @@ class Network(util.DaemonThread):
                return self.blockchain().height()
        
            def synchronous_get(self, request, timeout=30):
       -        queue = Queue.Queue()
       +        queue = queue.Queue()
                self.send([request], queue.put)
                try:
                    r = queue.get(True, timeout)
       -        except Queue.Empty:
       +        except queue.Empty:
                    raise BaseException('Server did not answer')
                if r.get('error'):
                    raise BaseException(r.get('error'))
   DIR diff --git a/lib/old_mnemonic.py b/lib/old_mnemonic.py
       t@@ -22,7 +22,12 @@
        # 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
        
        # list of words from http://en.wiktionary.org/wiki/Wiktionary:Frequency_lists/Contemporary_poetry
        
       t@@ -1665,18 +1670,19 @@ n = 1626
        def mn_encode( message ):
            assert len(message) % 8 == 0
            out = []
       -    for i in range(len(message)/8):
       +    for i in range(len(message)//8):
                word = message[8*i:8*i+8]
                x = int(word, 16)
                w1 = (x%n)
       -        w2 = ((x/n) + w1)%n
       -        w3 = ((x/n/n) + w2)%n
       +        w2 = ((x//n) + w1)%n
       +        w3 = ((x//n//n) + w2)%n
                out += [ words[w1], words[w2], words[w3] ]
            return out
        
       +
        def mn_decode( wlist ):
            out = ''
       -    for i in range(len(wlist)/3):
       +    for i in range(len(wlist)//3):
                word1, word2, word3 = wlist[3*i:3*i+3]
                w1 =  words.index(word1)
                w2 = (words.index(word2))%n
       t@@ -1688,9 +1694,9 @@ def mn_decode( wlist ):
        
        if __name__ == '__main__':
            import sys
       -    if len( sys.argv ) == 1:
       -        print 'I need arguments: a hex string to encode, or a list of words to decode'
       -    elif len( sys.argv ) == 2:
       -        print ' '.join(mn_encode(sys.argv[1]))
       +    if len(sys.argv) == 1:
       +        print('I need arguments: a hex string to encode, or a list of words to decode')
       +    elif len(sys.argv) == 2:
       +        print(' '.join(mn_encode(sys.argv[1])))
            else:
       -        print mn_decode(sys.argv[1:])
       +        print(mn_decode(sys.argv[1:]))
   DIR diff --git a/lib/paymentrequest.py b/lib/paymentrequest.py
       t@@ -22,8 +22,12 @@
        # 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 hashlib
        import os.path
        import re
       t@@ -31,23 +35,28 @@ import sys
        import threading
        import time
        import traceback
       -import urlparse
        import json
        import requests
        
       +from six.moves import urllib_parse
       +
       +
        try:
       -    import paymentrequest_pb2 as pb2
       +    if six.PY3:
       +        from . import paymentrequest_pb2_py3 as pb2
       +    else:
       +        from . import paymentrequest_pb2 as pb2
        except ImportError:
            sys.exit("Error: could not find paymentrequest_pb2.py. Create it with 'protoc --proto_path=lib/ --python_out=lib/ lib/paymentrequest.proto'")
        
       -import bitcoin
       -import util
       -from util import print_error
       -import transaction
       -import x509
       -import rsakey
       +from . import bitcoin
       +from . import util
       +from .util import print_error
       +from . import transaction
       +from . import x509
       +from . import rsakey
        
       -from bitcoin import TYPE_ADDRESS
       +from .bitcoin import TYPE_ADDRESS
        
        REQUEST_HEADERS = {'Accept': 'application/bitcoin-paymentrequest', 'User-Agent': 'Electrum'}
        ACK_HEADERS = {'Content-Type':'application/bitcoin-payment','Accept':'application/bitcoin-paymentack','User-Agent':'Electrum'}
       t@@ -72,7 +81,7 @@ PR_PAID    = 3     # send and propagated
        
        
        def get_payment_request(url):
       -    u = urlparse.urlparse(url)
       +    u = urllib_parse.urlparse(url)
            error = None
            if u.scheme in ['http', 'https']:
                try:
       t@@ -275,15 +284,15 @@ class PaymentRequest:
                paymnt.memo = "Paid using Electrum"
                pm = paymnt.SerializeToString()
        
       -        payurl = urlparse.urlparse(pay_det.payment_url)
       +        payurl = urllib_parse.urlparse(pay_det.payment_url)
                try:
                    r = requests.post(payurl.geturl(), data=pm, headers=ACK_HEADERS, verify=ca_path)
                except requests.exceptions.SSLError:
       -            print "Payment Message/PaymentACK verify Failed"
       +            print("Payment Message/PaymentACK verify Failed")
                    try:
                        r = requests.post(payurl.geturl(), data=pm, headers=ACK_HEADERS, verify=False)
                    except Exception as e:
       -                print e
       +                print(e)
                        return False, "Payment Message/PaymentACK Failed"
        
                if r.status_code >= 500:
       t@@ -295,12 +304,12 @@ class PaymentRequest:
                except Exception:
                    return False, "PaymentACK could not be processed. Payment was sent; please manually verify that payment was received."
        
       -        print "PaymentACK message received: %s" % paymntack.memo
       +        print("PaymentACK message received: %s" % paymntack.memo)
                return True, paymntack.memo
        
        
        def make_unsigned_request(req):
       -    from transaction import Transaction
       +    from .transaction import Transaction
            addr = req['address']
            time = req.get('time', 0)
            exp = req.get('exp', 0)
       t@@ -392,7 +401,7 @@ def verify_cert_chain(chain):
        
        
        def check_ssl_config(config):
       -    import pem
       +    from . import pem
            key_path = config.get('ssl_privkey')
            cert_path = config.get('ssl_chain')
            with open(key_path, 'r') as f:
       t@@ -414,7 +423,7 @@ def check_ssl_config(config):
            return requestor
        
        def sign_request_with_x509(pr, key_path, cert_path):
       -    import pem
       +    from . import pem
            with open(key_path, 'r') as f:
                params = pem.parse_private_key(f.read())
                privkey = rsakey.RSAKey(*params)
   DIR diff --git a/lib/pem.py b/lib/pem.py
       t@@ -22,7 +22,12 @@
        # 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
        
        # This module uses code from TLSLlite
        # TLSLite Author: Trevor Perrin)
       t@@ -30,7 +35,7 @@
        
        import binascii
        
       -from x509 import ASN1_Node, bytestr_to_int, decode_OID
       +from .x509 import ASN1_Node, bytestr_to_int, decode_OID
        
        
        def a2b_base64(s):
   DIR diff --git a/lib/plugins.py b/lib/plugins.py
       t@@ -22,7 +22,12 @@
        # 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 collections import namedtuple
        import traceback
        import sys
       t@@ -30,10 +35,11 @@ import os
        import imp
        import pkgutil
        import time
       +import threading
        
       -from util import *
       -from i18n import _
       -from util import profiler, PrintError, DaemonThread, UserCancelled
       +from .util import *
       +from .i18n import _
       +from .util import profiler, PrintError, DaemonThread, UserCancelled, ThreadJob
        
        plugin_loaders = {}
        hook_names = set()
       t@@ -156,7 +162,7 @@ class Plugins(DaemonThread):
                return out
        
            def register_wallet_type(self, name, gui_good, wallet_type):
       -        from wallet import register_wallet_type, register_constructor
       +        from .wallet import register_wallet_type, register_constructor
                self.print_error("registering wallet type", (wallet_type, name))
                def loader():
                    plugin = self.get_plugin(name)
       t@@ -165,7 +171,7 @@ class Plugins(DaemonThread):
                plugin_loaders[wallet_type] = loader
        
            def register_keystore(self, name, gui_good, details):
       -        from keystore import register_keystore
       +        from .keystore import register_keystore
                def dynamic_constructor(d):
                    return self.get_plugin(name).keystore_class(d)
                if details[0] == 'hardware':
       t@@ -299,7 +305,7 @@ class DeviceMgr(ThreadJob, PrintError):
        
            def __init__(self, config):
                super(DeviceMgr, self).__init__()
       -        # Keyed by xpub.  The value is the device id 
       +        # Keyed by xpub.  The value is the device id
                # has been paired, and None otherwise.
                self.xpub_ids = {}
                # A list of clients.  The key is the client, the value is
   DIR diff --git a/lib/rsakey.py b/lib/rsakey.py
       t@@ -33,15 +33,19 @@
        
        """Pure-Python RSA implementation."""
        
       -
       +from __future__ import absolute_import
       +from __future__ import division
        from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import os
        import math
        import base64
        import binascii
        import hashlib
        
       -from pem import *
       +from .pem import *
        
        
        def SHA1(x):
   DIR diff --git a/lib/simple_config.py b/lib/simple_config.py
       t@@ -1,12 +1,18 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import ast
        import json
        import threading
        import os
        
        from copy import deepcopy
       -from util import user_dir, print_error, print_msg, print_stderr, PrintError
       +from .util import user_dir, print_error, print_msg, print_stderr, PrintError
        
       -from bitcoin import MAX_FEE_RATE, FEE_TARGETS
       +from .bitcoin import MAX_FEE_RATE, FEE_TARGETS
        
        SYSTEM_CONFIG_PATH = "/etc/electrum.conf"
        
       t@@ -96,7 +102,7 @@ class SimpleConfig(PrintError):
        
            def fixup_config_keys(self, config, keypairs):
                updated = False
       -        for old_key, new_key in keypairs.iteritems():
       +        for old_key, new_key in keypairs.items():
                    if old_key in config:
                        if not new_key in config:
                            config[new_key] = config[old_key]
       t@@ -252,17 +258,18 @@ def read_system_config(path=SYSTEM_CONFIG_PATH):
            result = {}
            if os.path.exists(path):
                try:
       -            import ConfigParser
       +            from six.moves import configparser
       +            # import ConfigParser
                except ImportError:
       -            print "cannot parse electrum.conf. please install ConfigParser"
       +            print("cannot parse electrum.conf. please install ConfigParser")
                    return
        
       -        p = ConfigParser.ConfigParser()
       +        p = configparser.ConfigParser()
                try:
                    p.read(path)
                    for k, v in p.items('client'):
                        result[k] = v
       -        except (ConfigParser.NoSectionError, ConfigParser.MissingSectionHeaderError):
       +        except (configparser.NoSectionError, configparser.MissingSectionHeaderError):
                    pass
        
            return result
   DIR diff --git a/lib/storage.py b/lib/storage.py
       t@@ -22,7 +22,12 @@
        # 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 ast
        import threading
       t@@ -36,11 +41,11 @@ import pbkdf2, hmac, hashlib
        import base64
        import zlib
        
       -from i18n import _
       -from util import NotEnoughFunds, PrintError, profiler
       -from plugins import run_hook, plugin_loaders
       -from keystore import bip44_derivation
       -import bitcoin
       +from .i18n import _
       +from .util import NotEnoughFunds, PrintError, profiler
       +from .plugins import run_hook, plugin_loaders
       +from .keystore import bip44_derivation
       +import .bitcoin
        
        
        # seed_version is now used for the version of the wallet file
   DIR diff --git a/lib/synchronizer.py b/lib/synchronizer.py
       t@@ -22,14 +22,18 @@
        # 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 threading import Lock
        import hashlib
        
       -from bitcoin import Hash, hash_encode
       -from transaction import Transaction
       -from util import print_error, print_msg, ThreadJob
       +from .bitcoin import Hash, hash_encode
       +from .transaction import Transaction
       +from .util import print_error, print_msg, ThreadJob
        
        
        class Synchronizer(ThreadJob):
   DIR diff --git a/lib/tests/test_account.py b/lib/tests/test_account.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import unittest
        
        class Test_Account(unittest.TestCase):
   DIR diff --git a/lib/tests/test_bitcoin.py b/lib/tests/test_bitcoin.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import unittest
        import sys
        from ecdsa.util import number_to_string
       t@@ -8,6 +14,7 @@ from lib.bitcoin import (
            pw_decode, Hash, public_key_from_private_key, address_from_private_key,
            is_valid, is_private_key, xpub_from_xprv, is_new_seed, is_old_seed,
            var_int, op_push)
       +from lib.util import bfh
        
        try:
            import ecdsa
       t@@ -18,7 +25,7 @@ except ImportError:
        class Test_bitcoin(unittest.TestCase):
        
            def test_crypto(self):
       -        for message in ["Chancellor on brink of second bailout for banks", chr(255)*512]:
       +        for message in [b"Chancellor on brink of second bailout for banks", b'\xff'*512]:
                    self._do_test_crypto(message)
        
            def _do_test_crypto(self, message):
       t@@ -60,7 +67,7 @@ class Test_bitcoin(unittest.TestCase):
                assert xprv == "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"
        
            def _do_test_bip32(self, seed, sequence):
       -        xprv, xpub = bip32_root(seed.decode('hex'), 0)
       +        xprv, xpub = bip32_root(bfh(seed), 0)
                assert sequence[0:2] == "m/"
                path = 'm'
                sequence = sequence[2:]
       t@@ -106,7 +113,7 @@ class Test_bitcoin(unittest.TestCase):
            def test_hash(self):
                """Make sure the Hash function does sha256 twice"""
                payload = u"test"
       -        expected = '\x95MZI\xfdp\xd9\xb8\xbc\xdb5\xd2R&x)\x95\x7f~\xf7\xfalt\xf8\x84\x19\xbd\xc5\xe8"\t\xf4'
       +        expected = b'\x95MZI\xfdp\xd9\xb8\xbc\xdb5\xd2R&x)\x95\x7f~\xf7\xfalt\xf8\x84\x19\xbd\xc5\xe8"\t\xf4'
        
                result = Hash(payload)
                self.assertEqual(expected, result)
   DIR diff --git a/lib/tests/test_interface.py b/lib/tests/test_interface.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import unittest
        
        from lib import interface
   DIR diff --git a/lib/tests/test_mnemonic.py b/lib/tests/test_mnemonic.py
       t@@ -1,13 +1,21 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import unittest
        from lib import keystore
        from lib import mnemonic
        from lib import old_mnemonic
       +from lib.util import bh2u
       +
        
        class Test_NewMnemonic(unittest.TestCase):
        
            def test_to_seed(self):
                seed = mnemonic.Mnemonic.mnemonic_to_seed(mnemonic='foobar', passphrase='none')
       -        self.assertEquals(seed.encode('hex'),
       +        self.assertEquals(bh2u(seed),
                                  '741b72fd15effece6bfe5a26a52184f66811bd2be363190e07a42cca442b1a5b'
                                  'b22b3ad0eb338197287e6d314866c7fba863ac65d3f156087a5052ebc7157fce')
        
   DIR diff --git a/lib/tests/test_simple_config.py b/lib/tests/test_simple_config.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import ast
        import sys
        import os
       t@@ -6,7 +12,7 @@ import tempfile
        import shutil
        import json
        
       -from StringIO import StringIO
       +from six.moves import StringIO
        from lib.simple_config import (SimpleConfig, read_system_config,
                                       read_user_config)
        
       t@@ -230,15 +236,6 @@ class TestUserConfig(unittest.TestCase):
               result = read_user_config(None)
               self.assertEqual({}, result)
        
       -    def test_path_with_reprd_dict(self):
       -        thefile = os.path.join(self.user_dir, "config")
       -        payload = {"gap_limit": 5}
       -        with open(thefile, "w") as f:
       -            f.write(json.dumps(payload))
       -
       -        result = read_user_config(self.user_dir)
       -        self.assertEqual(payload, result)
       -
            def test_path_without_config_file(self):
                """We pass a path but if does not contain a "config" file."""
                result = read_user_config(self.user_dir)
   DIR diff --git a/lib/tests/test_transaction.py b/lib/tests/test_transaction.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import unittest
        from lib import transaction
        from lib.bitcoin import TYPE_ADDRESS
       t@@ -5,6 +11,10 @@ from lib.bitcoin import TYPE_ADDRESS
        import pprint
        from lib.keystore import xpubkey_to_address
        
       +from lib.util import bh2u
       +
       +from lib.util import bh2u
       +
        unsigned_blob = '01000000012a5c9a94fcde98f5581cd00162c60a13936ceb75389ea65bf38633b424eb4031000000005701ff4c53ff0488b21e03ef2afea18000000089689bff23e1e7fb2f161daa37270a97a3d8c2e537584b2d304ecb47b86d21fc021b010d3bd425f8cf2e04824bfdf1f1f5ff1d51fadd9a41f9e3fb8dd3403b1bfe00000000ffffffff0140420f00000000001976a914230ac37834073a42146f11ef8414ae929feaafc388ac00000000'
        signed_blob = '01000000012a5c9a94fcde98f5581cd00162c60a13936ceb75389ea65bf38633b424eb4031000000006c493046022100a82bbc57a0136751e5433f41cf000b3f1a99c6744775e76ec764fb78c54ee100022100f9e80b7de89de861dc6fb0c1429d5da72c2b6b2ee2406bc9bfb1beedd729d985012102e61d176da16edd1d258a200ad9759ef63adf8e14cd97f53227bae35cdb84d2f6ffffffff0140420f00000000001976a914230ac37834073a42146f11ef8414ae929feaafc388ac00000000'
        v2_blob = "0200000001191601a44a81e061502b7bfbc6eaa1cef6d1e6af5308ef96c9342f71dbf4b9b5000000006b483045022100a6d44d0a651790a477e75334adfb8aae94d6612d01187b2c02526e340a7fd6c8022028bdf7a64a54906b13b145cd5dab21a26bd4b85d6044e9b97bceab5be44c2a9201210253e8e0254b0c95776786e40984c1aa32a7d03efa6bdacdea5f421b774917d346feffffff026b20fa04000000001976a914024db2e87dd7cfd0e5f266c5f212e21a31d805a588aca0860100000000001976a91421919b94ae5cefcdf0271191459157cdb41c4cbf88aca6240700"
       t@@ -20,7 +30,7 @@ class TestBCDataStream(unittest.TestCase):
                with self.assertRaises(transaction.SerializationError):
                    s.write_compact_size(-1)
        
       -        self.assertEquals(s.input.encode('hex'),
       +        self.assertEquals(bh2u(s.input),
                                  '0001fcfdfd00fdfffffe00000100feffffffffff0000000001000000ffffffffffffffffff')
                for v in values:
                    self.assertEquals(s.read_compact_size(), v)
       t@@ -44,11 +54,11 @@ class TestBCDataStream(unittest.TestCase):
        
            def test_bytes(self):
                s = transaction.BCDataStream()
       -        s.write('foobar')
       -        self.assertEquals(s.read_bytes(3), 'foo')
       -        self.assertEquals(s.read_bytes(2), 'ba')
       -        self.assertEquals(s.read_bytes(4), 'r')
       -        self.assertEquals(s.read_bytes(1), '')
       +        s.write(b'foobar')
       +        self.assertEquals(s.read_bytes(3), b'foo')
       +        self.assertEquals(s.read_bytes(2), b'ba')
       +        self.assertEquals(s.read_bytes(4), b'r')
       +        self.assertEquals(s.read_bytes(1), b'')
        
        class TestTransaction(unittest.TestCase):
        
   DIR diff --git a/lib/tests/test_util.py b/lib/tests/test_util.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import unittest
        from lib.util import format_satoshis, parse_URI
        
   DIR diff --git a/lib/tests/test_wallet.py b/lib/tests/test_wallet.py
       t@@ -1,3 +1,9 @@
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
        import shutil
        import tempfile
        import sys
       t@@ -5,8 +11,8 @@ import unittest
        import os
        import json
        
       -from StringIO import StringIO
       -from electrum.storage import WalletStorage, FINAL_SEED_VERSION
       +from six.moves import StringIO
       +from lib.storage import WalletStorage, FINAL_SEED_VERSION
        
        
        class FakeSynchronizer(object):
   DIR diff --git a/lib/transaction.py b/lib/transaction.py
       t@@ -27,11 +27,12 @@
        
        # Note: The deserialization code originally comes from ABE.
        
       +from . import bitcoin
       +from .bitcoin import *
       +from .util import print_error, profiler, to_string
        
       -import bitcoin
       -from bitcoin import *
       -from bitcoin import hash160_to_p2sh, hash160_to_p2pkh
       -from util import print_error, profiler
       +from . import bitcoin
       +from .bitcoin import *
        import time
        import sys
        import struct
       t@@ -40,9 +41,9 @@ import struct
        # Workalike python implementation of Bitcoin's CDataStream class.
        #
        import struct
       -import StringIO
       +from six import StringIO
        import random
       -from keystore import xpubkey_to_address, xpubkey_to_pubkey
       +from .keystore import xpubkey_to_address, xpubkey_to_pubkey
        
        NO_SIGNATURE = 'ff'
        
       t@@ -50,6 +51,7 @@ NO_SIGNATURE = 'ff'
        class SerializationError(Exception):
            """ Thrown when there's a problem deserializing or serializing """
        
       +
        class BCDataStream(object):
            def __init__(self):
                self.input = None
       t@@ -59,13 +61,13 @@ class BCDataStream(object):
                self.input = None
                self.read_cursor = 0
        
       -    def write(self, bytes):  # Initialize with string of bytes
       +    def write(self, _bytes):  # Initialize with string of _bytes
                if self.input is None:
       -            self.input = bytes
       +            self.input = bytearray(_bytes)
                else:
       -            self.input += bytes
       +            self.input += bytearray(_bytes)
        
       -    def read_string(self):
       +    def read_string(self, encoding='ascii'):
                # Strings are encoded depending on length:
                # 0 to 252 :  1-byte-length followed by bytes (if any)
                # 253 to 65,535 : byte'253' 2-byte-length followed by bytes
       t@@ -81,9 +83,10 @@ class BCDataStream(object):
                except IndexError:
                    raise SerializationError("attempt to read past end of buffer")
        
       -        return self.read_bytes(length)
       +        return self.read_bytes(length).decode(encoding)
        
       -    def write_string(self, string):
       +    def write_string(self, string, encoding='ascii'):
       +        string = to_bytes(string, encoding)
                # Length-encoded as with read-string
                self.write_compact_size(len(string))
                self.write(string)
       t@@ -115,7 +118,7 @@ class BCDataStream(object):
            def write_uint64(self, val): return self._write_num('<Q', val)
        
            def read_compact_size(self):
       -        size = ord(self.input[self.read_cursor])
       +        size = self.input[self.read_cursor]
                self.read_cursor += 1
                if size == 253:
                    size = self._read_num('<H')
       t@@ -129,15 +132,15 @@ class BCDataStream(object):
                if size < 0:
                    raise SerializationError("attempt to write size < 0")
                elif size < 253:
       -            self.write(chr(size))
       +            self.write(bytes([size]))
                elif size < 2**16:
       -            self.write('\xfd')
       +            self.write(b'\xfd')
                    self._write_num('<H', size)
                elif size < 2**32:
       -            self.write('\xfe')
       +            self.write(b'\xfe')
                    self._write_num('<I', size)
                elif size < 2**64:
       -            self.write('\xff')
       +            self.write(b'\xff')
                    self._write_num('<Q', size)
        
            def _read_num(self, format):
       t@@ -149,15 +152,13 @@ class BCDataStream(object):
                s = struct.pack(format, num)
                self.write(s)
        
       -#
       +
        # enum-like type
        # From the Python Cookbook, downloaded from http://code.activestate.com/recipes/67107/
       -#
       -import types, string, exceptions
       -
       -class EnumException(exceptions.Exception):
       +class EnumException(Exception):
            pass
        
       +
        class Enumeration:
            def __init__(self, name, enumList):
                self.__doc__ = name
       t@@ -167,16 +168,16 @@ class Enumeration:
                uniqueNames = [ ]
                uniqueValues = [ ]
                for x in enumList:
       -            if type(x) == types.TupleType:
       +            if isinstance(x, tuple):
                        x, i = x
       -            if type(x) != types.StringType:
       -                raise EnumException, "enum name is not a string: " + x
       -            if type(i) != types.IntType:
       -                raise EnumException, "enum value is not an integer: " + i
       +            if not isinstance(x, six.text_type):
       +                raise EnumException("enum name is not a string: " + x)
       +            if not isinstance(i, six.integer_types):
       +                raise EnumException("enum value is not an integer: " + i)
                    if x in uniqueNames:
       -                raise EnumException, "enum name is not unique: " + x
       +                raise EnumException("enum name is not unique: " + x)
                    if i in uniqueValues:
       -                raise EnumException, "enum value is not unique for " + x
       +                raise EnumException("enum value is not unique for " + x)
                    uniqueNames.append(x)
                    uniqueValues.append(i)
                    lookup[x] = i
       t@@ -184,8 +185,9 @@ class Enumeration:
                    i = i + 1
                self.lookup = lookup
                self.reverseLookup = reverseLookup
       +
            def __getattr__(self, attr):
       -        if not self.lookup.has_key(attr):
       +        if attr not in self.lookup:
                    raise AttributeError
                return self.lookup[attr]
            def whatis(self, value):
       t@@ -228,32 +230,32 @@ opcodes = Enumeration("Opcodes", [
        ])
        
        
       -def script_GetOp(bytes):
       +def script_GetOp(_bytes):
            i = 0
       -    while i < len(bytes):
       +    while i < len(_bytes):
                vch = None
       -        opcode = ord(bytes[i])
       +        opcode = _bytes[i]
                i += 1
                if opcode >= opcodes.OP_SINGLEBYTE_END:
                    opcode <<= 8
       -            opcode |= ord(bytes[i])
       +            opcode |= _bytes[i]
                    i += 1
        
                if opcode <= opcodes.OP_PUSHDATA4:
                    nSize = opcode
                    if opcode == opcodes.OP_PUSHDATA1:
       -                nSize = ord(bytes[i])
       +                nSize = _bytes[i]
                        i += 1
                    elif opcode == opcodes.OP_PUSHDATA2:
       -                (nSize,) = struct.unpack_from('<H', bytes, i)
       +                (nSize,) = struct.unpack_from('<H', _bytes, i)
                        i += 2
                    elif opcode == opcodes.OP_PUSHDATA4:
       -                (nSize,) = struct.unpack_from('<I', bytes, i)
       +                (nSize,) = struct.unpack_from('<I', _bytes, i)
                        i += 4
       -            vch = bytes[i:i+nSize]
       +            vch = _bytes[i:i + nSize]
                    i += nSize
        
       -        yield (opcode, vch, i)
       +        yield opcode, vch, i
        
        
        def script_GetOpName(opcode):
       t@@ -292,21 +294,20 @@ def safe_parse_pubkey(x):
            except:
                return x
        
       -
       -def parse_scriptSig(d, bytes):
       +def parse_scriptSig(d, _bytes):
            try:
       -        decoded = [ x for x in script_GetOp(bytes) ]
       -    except Exception:
       +        decoded = [ x for x in script_GetOp(_bytes) ]
       +    except Exception as e:
                # coinbase transactions raise an exception
       -        print_error("cannot find address in input script", bytes.encode('hex'))
       +        print_error("cannot find address in input script", bh2u(_bytes))
                return
        
            match = [ opcodes.OP_PUSHDATA4 ]
            if match_decoded(decoded, match):
                item = decoded[0][1]
       -        if item[0] == chr(0):
       -            redeemScript = item.encode('hex')
       -            d['address'] = bitcoin.hash160_to_p2sh(bitcoin.hash_160(redeemScript.decode('hex')))
       +        if item[0] == 0:
       +            redeemScript = bh2u(item)
       +            d['address'] = bitcoin.hash160_to_p2sh(bitcoin.hash_160(item))
                    d['type'] = 'p2wpkh-p2sh'
                    d['redeemScript'] = redeemScript
                    d['x_pubkeys'] = ["(witness)"]
       t@@ -317,7 +318,7 @@ def parse_scriptSig(d, bytes):
                    # payto_pubkey
                    d['type'] = 'p2pk'
                    d['address'] = "(pubkey)"
       -            d['signatures'] = [item.encode('hex')]
       +            d['signatures'] = [bh2u(item)]
                    d['num_sig'] = 1
                    d['x_pubkeys'] = ["(pubkey)"]
                    d['pubkeys'] = ["(pubkey)"]
       t@@ -328,13 +329,13 @@ def parse_scriptSig(d, bytes):
            # (65 bytes) onto the stack:
            match = [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4 ]
            if match_decoded(decoded, match):
       -        sig = decoded[0][1].encode('hex')
       -        x_pubkey = decoded[1][1].encode('hex')
       +        sig = bh2u(decoded[0][1])
       +        x_pubkey = bh2u(decoded[1][1])
                try:
                    signatures = parse_sig([sig])
                    pubkey, address = xpubkey_to_address(x_pubkey)
       -        except BaseException:
       -            print_error("cannot find address in input script", bytes.encode('hex'))
       +        except:
       +            print_error("cannot find address in input script", bh2u(_bytes))
                    return
                d['type'] = 'p2pkh'
                d['signatures'] = signatures
       t@@ -347,9 +348,9 @@ def parse_scriptSig(d, bytes):
            # p2sh transaction, m of n
            match = [ opcodes.OP_0 ] + [ opcodes.OP_PUSHDATA4 ] * (len(decoded) - 1)
            if not match_decoded(decoded, match):
       -        print_error("cannot find address in input script", bytes.encode('hex'))
       +        print_error("cannot find address in input script", bh2u(_bytes))
                return
       -    x_sig = [x[1].encode('hex') for x in decoded[1:-1]]
       +    x_sig = [bh2u(x[1]) for x in decoded[1:-1]]
            dec2 = [ x for x in script_GetOp(decoded[-1][1]) ]
            m = dec2[0][0] - opcodes.OP_1 + 1
            n = dec2[-2][0] - opcodes.OP_1 + 1
       t@@ -357,9 +358,9 @@ def parse_scriptSig(d, bytes):
            op_n = opcodes.OP_1 + n - 1
            match_multisig = [ op_m ] + [opcodes.OP_PUSHDATA4]*n + [ op_n, opcodes.OP_CHECKMULTISIG ]
            if not match_decoded(dec2, match_multisig):
       -        print_error("cannot find address in input script", bytes.encode('hex'))
       +        print_error("cannot find address in input script", bh2u(_bytes))
                return
       -    x_pubkeys = map(lambda x: x[1].encode('hex'), dec2[1:-2])
       +    x_pubkeys = [bh2u(x[1]) for x in dec2[1:-2]]
            pubkeys = [safe_parse_pubkey(x) for x in x_pubkeys]
            redeemScript = multisig_script(pubkeys, m)
            # write result in d
       t@@ -369,19 +370,17 @@ def parse_scriptSig(d, bytes):
            d['x_pubkeys'] = x_pubkeys
            d['pubkeys'] = pubkeys
            d['redeemScript'] = redeemScript
       -    d['address'] = hash160_to_p2sh(hash_160(redeemScript.decode('hex')))
       -
       +    d['address'] = hash160_to_p2sh(hash_160(bfh(redeemScript)))
        
        
       -
       -def get_address_from_output_script(bytes):
       -    decoded = [ x for x in script_GetOp(bytes) ]
       +def get_address_from_output_script(_bytes):
       +    decoded = [x for x in script_GetOp(_bytes)]
        
            # The Genesis Block, self-payments, and pay-by-IP-address payments look like:
            # 65 BYTES:... CHECKSIG
            match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ]
            if match_decoded(decoded, match):
       -        return TYPE_PUBKEY, decoded[0][1].encode('hex')
       +        return TYPE_PUBKEY, bh2u(decoded[0][1])
        
            # Pay-by-Bitcoin-address TxOuts look like:
            # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG
       t@@ -394,10 +393,7 @@ def get_address_from_output_script(bytes):
            if match_decoded(decoded, match):
                return TYPE_ADDRESS, hash160_to_p2sh(decoded[1][1])
        
       -    return TYPE_SCRIPT, bytes
       -
       -
       -
       +    return TYPE_SCRIPT, _bytes
        
        
        def parse_input(vds):
       t@@ -406,7 +402,7 @@ def parse_input(vds):
            prevout_n = vds.read_uint32()
            scriptSig = vds.read_bytes(vds.read_compact_size())
            sequence = vds.read_uint32()
       -    d['scriptSig'] = scriptSig.encode('hex')
       +    d['scriptSig'] = bh2u(scriptSig)
            d['prevout_hash'] = prevout_hash
            d['prevout_n'] = prevout_n
            d['sequence'] = sequence
       t@@ -433,14 +429,14 @@ def parse_output(vds, i):
            d['value'] = vds.read_int64()
            scriptPubKey = vds.read_bytes(vds.read_compact_size())
            d['type'], d['address'] = get_address_from_output_script(scriptPubKey)
       -    d['scriptPubKey'] = scriptPubKey.encode('hex')
       +    d['scriptPubKey'] = bh2u(scriptPubKey)
            d['prevout_n'] = i
            return d
        
        
        def deserialize(raw):
            vds = BCDataStream()
       -    vds.write(raw.decode('hex'))
       +    vds.write(bfh(raw))
            d = {}
            start = vds.read_cursor
            d['version'] = vds.read_int32()
       t@@ -448,13 +444,13 @@ def deserialize(raw):
            is_segwit = (n_vin == 0)
            if is_segwit:
                marker = vds.read_bytes(1)
       -        assert marker == chr(1)
       +        assert marker == 1
                n_vin = vds.read_compact_size()
       -    d['inputs'] = list(parse_input(vds) for i in xrange(n_vin))
       +    d['inputs'] = [parse_input(vds) for i in range(n_vin)]
            n_vout = vds.read_compact_size()
       -    d['outputs'] = list(parse_output(vds,i) for i in xrange(n_vout))
       +    d['outputs'] = [parse_output(vds,i) for i in range(n_vout)]
            if is_segwit:
       -        d['witness'] = list(parse_witness(vds) for i in xrange(n_vin))
       +        d['witness'] = [parse_witness(vds) for i in range(n_vin)]
            d['lockTime'] = vds.read_uint32()
            return d
        
       t@@ -462,27 +458,30 @@ def deserialize(raw):
        # pay & redeem scripts
        
        def push_script(x):
       -    return op_push(len(x)/2) + x
       +    return op_push(len(x)//2) + x
       +
        
        def get_scriptPubKey(addr):
            addrtype, hash_160 = bc_address_to_hash_160(addr)
            if addrtype == bitcoin.ADDRTYPE_P2PKH:
                script = '76a9'                                      # op_dup, op_hash_160
       -        script += push_script(hash_160.encode('hex'))
       +        script += push_script(bh2u(hash_160))
                script += '88ac'                                     # op_equalverify, op_checksig
            elif addrtype == bitcoin.ADDRTYPE_P2SH:
                script = 'a9'                                        # op_hash_160
       -        script += push_script(hash_160.encode('hex'))
       +        script += push_script(bh2u(hash_160))
                script += '87'                                       # op_equal
            else:
                raise BaseException('unknown address type')
            return script
        
       +
        def segwit_script(pubkey):
            pubkey = safe_parse_pubkey(pubkey)
       -    pkh = hash_160(pubkey.decode('hex')).encode('hex')
       +    pkh = bh2u(hash_160(bfh(pubkey)))
            return '00' + push_script(pkh)
        
       +
        def multisig_script(public_keys, m):
            n = len(public_keys)
            assert n <= 15
       t@@ -505,9 +504,9 @@ class Transaction:
            def __init__(self, raw):
                if raw is None:
                    self.raw = None
       -        elif type(raw) in [str, unicode]:
       +        elif isinstance(raw, str):
                    self.raw = raw.strip() if raw else None
       -        elif type(raw) is dict:
       +        elif isinstance(raw, dict):
                    self.raw = raw['hex']
                else:
                    raise BaseException("cannot initialize transaction", raw)
       t@@ -553,15 +552,15 @@ class Transaction:
                    for sig in sigs2:
                        if sig in sigs1:
                            continue
       -                pre_hash = Hash(self.serialize_preimage(i).decode('hex'))
       +                pre_hash = Hash(bfh(self.serialize_preimage(i)))
                        # der to string
                        order = ecdsa.ecdsa.generator_secp256k1.order()
       -                r, s = ecdsa.util.sigdecode_der(sig.decode('hex')[:-1], order)
       +                r, s = ecdsa.util.sigdecode_der(bfh(sig[:-2]), order)
                        sig_string = ecdsa.util.sigencode_string(r, s, order)
                        compressed = True
                        for recid in range(4):
                            public_key = MyVerifyingKey.from_signature(sig_string, recid, pre_hash, curve = SECP256k1)
       -                    pubkey = point_to_ser(public_key.pubkey.point, compressed).encode('hex')
       +                    pubkey = bh2u(point_to_ser(public_key.pubkey.point, compressed))
                            if pubkey in pubkeys:
                                public_key.verify_digest(sig_string, pre_hash, sigdecode = ecdsa.util.sigdecode_string)
                                j = pubkeys.index(pubkey)
       t@@ -572,7 +571,6 @@ class Transaction:
                # redo raw
                self.raw = self.serialize()
        
       -
            def deserialize(self):
                if self.raw is None:
                    return
       t@@ -597,7 +595,7 @@ class Transaction:
            @classmethod
            def pay_script(self, output_type, addr):
                if output_type == TYPE_SCRIPT:
       -            return addr.encode('hex')
       +            return bh2u(addr)
                elif output_type == TYPE_ADDRESS:
                    return get_scriptPubKey(addr)
                else:
       t@@ -616,7 +614,7 @@ class Transaction:
                else:
                    pubkeys, x_pubkeys = self.get_sorted_pubkeys(txin)
                    x_signatures = txin['signatures']
       -            signatures = filter(None, x_signatures)
       +            signatures = list(filter(None, x_signatures))
                    is_complete = len(signatures) == num_sig
                    if is_complete:
                        pk_list = pubkeys
       t@@ -671,21 +669,21 @@ class Transaction:
                    return multisig_script(pubkeys, txin['num_sig'])
                elif txin['type'] == 'p2wpkh-p2sh':
                    pubkey = txin['pubkeys'][0]
       -            pkh = bitcoin.hash_160(pubkey.decode('hex')).encode('hex')
       +            pkh = bh2u(bitcoin.hash_160(bfh(pubkey)))
                    return '76a9' + push_script(pkh) + '88ac'
                else:
                    raise TypeError('Unknown txin type', _type)
        
            @classmethod
            def serialize_outpoint(self, txin):
       -        return txin['prevout_hash'].decode('hex')[::-1].encode('hex') + int_to_hex(txin['prevout_n'], 4)
       +        return bh2u(bfh(txin['prevout_hash'])[::-1]) + int_to_hex(txin['prevout_n'], 4)
        
            @classmethod
            def serialize_input(self, txin, script):
                # Prev hash and index
                s = self.serialize_outpoint(txin)
                # Script length, script, sequence
       -        s += var_int(len(script)/2)
       +        s += var_int(len(script)//2)
                s += script
                s += int_to_hex(txin.get('sequence', 0xffffffff - 1), 4)
                return s
       t@@ -704,7 +702,7 @@ class Transaction:
                output_type, addr, amount = output
                s = int_to_hex(amount, 8)
                script = self.pay_script(output_type, addr)
       -        s += var_int(len(script)/2)
       +        s += var_int(len(script)//2)
                s += script
                return s
        
       t@@ -715,6 +713,7 @@ class Transaction:
                inputs = self.inputs()
                outputs = self.outputs()
                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')
       t@@ -750,7 +749,7 @@ class Transaction:
                    return nVersion + txins + txouts + nLocktime
        
            def hash(self):
       -        print "warning: deprecated tx.hash()"
       +        print("warning: deprecated tx.hash()")
                return self.txid()
        
            def txid(self):
       t@@ -758,11 +757,11 @@ class Transaction:
                if not all_segwit and not self.is_complete():
                    return None
                ser = self.serialize(witness=False)
       -        return Hash(ser.decode('hex'))[::-1].encode('hex')
       +        return bh2u(Hash(bfh(ser))[::-1])
        
            def wtxid(self):
                ser = self.serialize(witness=True)
       -        return Hash(ser.decode('hex'))[::-1].encode('hex')
       +        return bh2u(Hash(bfh(ser))[::-1])
        
            def add_inputs(self, inputs):
                self._inputs.extend(inputs)
       t@@ -787,13 +786,13 @@ class Transaction:
            @profiler
            def estimated_size(self):
                '''Return an estimated tx size in bytes.'''
       -        return len(self.serialize(True)) / 2 if not self.is_complete() or self.raw is None else len(self.raw) / 2 # ASCII hex string
       +        return len(self.serialize(True)) // 2 if not self.is_complete() or self.raw is None else len(self.raw) / 2 # ASCII hex string
        
            @classmethod
            def estimated_input_size(self, txin):
                '''Return an estimated of serialized input size in bytes.'''
                script = self.input_script(txin, True)
       -        return len(self.serialize_input(txin, script)) / 2
       +        return len(self.serialize_input(txin, script)) // 2
        
            def signature_count(self):
                r = 0
       t@@ -801,7 +800,7 @@ class Transaction:
                for txin in self.inputs():
                    if txin['type'] == 'coinbase':
                        continue
       -            signatures = filter(None, txin.get('signatures',[]))
       +            signatures = list(filter(None, txin.get('signatures',[])))
                    s += len(signatures)
                    r += txin.get('num_sig',-1)
                return s, r
       t@@ -824,14 +823,14 @@ class Transaction:
                            sec = keypairs.get(x_pubkey)
                            pubkey = public_key_from_private_key(sec)
                            # add signature
       -                    pre_hash = Hash(self.serialize_preimage(i).decode('hex'))
       +                    pre_hash = Hash(bfh(self.serialize_preimage(i)))
                            pkey = regenerate_key(sec)
                            secexp = pkey.secret
                            private_key = bitcoin.MySigningKey.from_secret_exponent(secexp, curve = SECP256k1)
                            public_key = private_key.get_verifying_key()
                            sig = private_key.sign_digest_deterministic(pre_hash, hashfunc=hashlib.sha256, sigencode = ecdsa.util.sigencode_der)
                            assert public_key.verify_digest(sig, pre_hash, sigdecode = ecdsa.util.sigdecode_der)
       -                    txin['signatures'][j] = sig.encode('hex') + '01'
       +                    txin['signatures'][j] = bh2u(sig) + '01'
                            txin['x_pubkeys'][j] = pubkey
                            txin['pubkeys'][j] = pubkey # needed for fd keys
                            self._inputs[i] = txin
       t@@ -845,9 +844,9 @@ class Transaction:
                    if type == TYPE_ADDRESS:
                        addr = x
                    elif type == TYPE_PUBKEY:
       -                addr = bitcoin.public_key_to_p2pkh(x.decode('hex'))
       +                addr = bitcoin.public_key_to_p2pkh(bfh(x))
                    else:
       -                addr = 'SCRIPT ' + x.encode('hex')
       +                addr = 'SCRIPT ' + bh2u(x)
                    o.append((addr,v))      # consider using yield (addr, v)
                return o
        
       t@@ -869,7 +868,6 @@ class Transaction:
                }
                return out
        
       -
            def requires_fee(self, wallet):
                # see https://en.bitcoin.it/wiki/Transaction_fees
                #
       t@@ -899,7 +897,7 @@ def tx_from_str(txt):
            import json
            txt = txt.strip()
            try:
       -        txt.decode('hex')
       +        bfh(txt)
                is_hex = True
            except:
                is_hex = False
   DIR diff --git a/lib/util.py b/lib/util.py
       t@@ -22,7 +22,12 @@
        # 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 binascii
        import os, sys, re, json
        import platform
        import shutil
       t@@ -30,10 +35,18 @@ from collections import defaultdict
        from datetime import datetime
        from decimal import Decimal
        import traceback
       -import urlparse
        import urllib
        import threading
       -from i18n import _
       +from .i18n import _
       +
       +import six
       +from six.moves import queue, urllib_parse
       +
       +try:
       +    import urllib.parse
       +    import urllib.request, urllib.parse, urllib.error
       +except ImportError:
       +    pass
        
        base_units = {'BTC':8, 'mBTC':5, 'uBTC':2}
        fee_levels = [_('Within 25 blocks'), _('Within 10 blocks'), _('Within 5 blocks'), _('Within 2 blocks'), _('In the next block')]
       t@@ -194,7 +207,7 @@ def json_decode(x):
        # decorator that prints execution time
        def profiler(func):
            def do_profile(func, args, kw_args):
       -        n = func.func_name
       +        n = func.__name__
                t0 = time.time()
                o = func(*args, **kw_args)
                t = time.time() - t0
       t@@ -238,6 +251,182 @@ def android_check_data_dir():
        def get_headers_dir(config):
            return android_headers_dir() if 'ANDROID_DATA' in os.environ else config.path
        
       +
       +def assert_bytes(*args):
       +    """
       +    porting helper, assert args type
       +    """
       +    if six.PY2:
       +        for x in args:
       +            assert isinstance(x, (bytes, bytearray, str))
       +        return
       +
       +    try:
       +        if six.PY3:
       +            for x in args:
       +                assert isinstance(x, (bytes, bytearray))
       +        else:
       +            for x in args:
       +                assert isinstance(x, bytearray)
       +    except:
       +        print('assert bytes failed', list(map(type, args)))
       +        raise
       +
       +
       +def assert_str(*args):
       +    """
       +    porting helper, assert args type
       +    """
       +    for x in 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):
       +    if isinstance(x, (bytes, bytearray)):
       +        return x.decode(enc)
       +    if isinstance(x, str):
       +        return x
       +    else:
       +        raise TypeError("Not a string or bytes like object")
       +
       +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))
       +
       +
       +# def ufh(x):
       +#     """
       +#     py2-py3 aware wrapper for str.decode('hex')
       +#     :param x: str
       +#     :return: str
       +#     """
       +#     if
       +#     return binascii.unhexlify(x)
       +
       +
       +def hfu(x):
       +    """
       +    py2-py3 aware wrapper for str.encode('hex')
       +    :param x: str
       +    :return: str
       +    """
       +    if six.PY3:
       +        assert_bytes(x)
       +        return binascii.hexlify(x)
       +    else:
       +        return x.encode('hex')
       +
       +
       +def bfh(x):
       +    """
       +    py2-py3 aware wrapper to "bytes.fromhex()" func
       +    :param x: str
       +    :rtype: bytes
       +    """
       +    if isinstance(x, six.string_types):
       +        return bfh_builder(x)
       +    # TODO: check for iterator interface
       +    elif isinstance(x, (list, tuple, map)):
       +        return [bfh(sub) for sub in x]
       +    else:
       +        raise TypeError('Unexpected type: ' + type(x))
       +
       +
       +def bh2u(x):
       +    """
       +    unicode with hex representation of bytes()
       +    e.g. x = bytes([1, 2, 10])
       +    bh2u(x) -> '01020A'
       +    :param x: bytes
       +    :rtype: str
       +    """
       +    if six.PY3:
       +        assert_bytes(x)
       +        # x = to_bytes(x, 'ascii')
       +        return binascii.hexlify(x).decode('ascii')
       +    else:
       +        if isinstance(x, bytearray):
       +            return binascii.hexlify(x)
       +        else:
       +            return x.encode('hex')
       +
       +
        def user_dir():
            if 'ANDROID_DATA' in os.environ:
                return android_check_data_dir()
       t@@ -251,12 +440,14 @@ def user_dir():
                #raise Exception("No home directory found in environment variables.")
                return
        
       +
        def format_satoshis_plain(x, decimal_point = 8):
       -    '''Display a satoshi amount scaled.  Always uses a '.' as a decimal
       -    point and has no thousands separator'''
       +    """Display a satoshi amount scaled.  Always uses a '.' as a decimal
       +    point and has no thousands separator"""
            scale_factor = pow(10, decimal_point)
            return "{:.8f}".format(Decimal(x) / scale_factor).rstrip('0').rstrip('.')
        
       +
        def format_satoshis(x, is_diff=False, num_zeros = 0, decimal_point = 8, whitespaces=False):
            from locale import localeconv
            if x is None:
       t@@ -277,7 +468,9 @@ def format_satoshis(x, is_diff=False, num_zeros = 0, decimal_point = 8, whitespa
            if whitespaces:
                result += " " * (decimal_point - len(fract_part))
                result = " " * (15 - len(result)) + result
       -    return result.decode('utf8')
       +    if six.PY2:
       +        result = result.decode('utf8')
       +    return result
        
        def timestamp_to_datetime(timestamp):
            try:
       t@@ -404,15 +597,15 @@ def block_explorer_URL(config, kind, item):
        #urldecode = lambda x: _ud.sub(lambda m: chr(int(m.group(1), 16)), x)
        
        def parse_URI(uri, on_pr=None):
       -    import bitcoin
       -    from bitcoin import COIN
       +    from . import bitcoin
       +    from .bitcoin import COIN
        
            if ':' not in uri:
                if not bitcoin.is_address(uri):
                    raise BaseException("Not a bitcoin address")
                return {'address': uri}
        
       -    u = urlparse.urlparse(uri)
       +    u = urllib_parse.urlparse(uri)
            if u.scheme != 'bitcoin':
                raise BaseException("Not a bitcoin URI")
            address = u.path
       t@@ -420,9 +613,9 @@ def parse_URI(uri, on_pr=None):
            # python for android fails to parse query
            if address.find('?') > 0:
                address, query = u.path.split('?')
       -        pq = urlparse.parse_qs(query)
       +        pq = urllib_parse.parse_qs(query)
            else:
       -        pq = urlparse.parse_qs(u.query)
       +        pq = urllib_parse.parse_qs(u.query)
        
            for k, v in pq.items():
                if len(v)!=1:
       t@@ -443,21 +636,24 @@ def parse_URI(uri, on_pr=None):
                    amount = Decimal(am) * COIN
                out['amount'] = int(amount)
            if 'message' in out:
       -        out['message'] = out['message'].decode('utf8')
       +        if six.PY3:
       +            out['message'] = out['message']
       +        else:
       +            out['message'] = out['message'].decode('utf8')
                out['memo'] = out['message']
            if 'time' in out:
                out['time'] = int(out['time'])
            if 'exp' in out:
                out['exp'] = int(out['exp'])
            if 'sig' in out:
       -        out['sig'] = bitcoin.base_decode(out['sig'], None, base=58).encode('hex')
       +        out['sig'] = bh2u(bitcoin.base_decode(out['sig'], None, base=58))
        
            r = out.get('r')
            sig = out.get('sig')
            name = out.get('name')
            if on_pr and (r or (name and sig)):
                def get_payment_request_thread():
       -            import paymentrequest as pr
       +            from . import paymentrequest as pr
                    if name and sig:
                        s = pr.serialize_request(out).SerializeToString()
                        request = pr.PaymentRequest(s)
       t@@ -472,7 +668,7 @@ def parse_URI(uri, on_pr=None):
        
        
        def create_URI(addr, amount, message):
       -    import bitcoin
       +    from . import bitcoin
            if not bitcoin.is_address(addr):
                return ""
            query = []
       t@@ -482,19 +678,26 @@ def create_URI(addr, amount, message):
                if type(message) == unicode:
                    message = message.encode('utf8')
                query.append('message=%s'%urllib.quote(message))
       -    p = urlparse.ParseResult(scheme='bitcoin', netloc='', path=addr, params='', query='&'.join(query), fragment='')
       -    return urlparse.urlunparse(p)
       +    p = urllib_parse.ParseResult(scheme='bitcoin', netloc='', path=addr, params='', query='&'.join(query), fragment='')
       +    return urllib_parse.urlunparse(p)
        
        
        # Python bug (http://bugs.python.org/issue1927) causes raw_input
        # to be redirected improperly between stdin/stderr on Unix systems
       +#TODO: py3
        def raw_input(prompt=None):
            if prompt:
                sys.stdout.write(prompt)
            return builtin_raw_input()
       -import __builtin__
       -builtin_raw_input = __builtin__.raw_input
       -__builtin__.raw_input = raw_input
       +
       +if six.PY2:
       +    import  __builtin__
       +    builtin_raw_input = __builtin__.raw_input
       +    __builtin__.raw_input = raw_input
       +else:
       +    import builtins
       +    builtin_raw_input = builtins.input
       +    builtins.input = raw_input
        
        
        
       t@@ -596,8 +799,6 @@ class SocketPipe:
        
        
        
       -import Queue
       -
        class QueuePipe:
        
            def __init__(self, send_queue=None, get_queue=None):
   DIR diff --git a/lib/verifier.py b/lib/verifier.py
       t@@ -22,10 +22,14 @@
        # 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
        
       -
       -from util import ThreadJob
       -from bitcoin import *
       +import six
       +from .util import ThreadJob
       +from .bitcoin import *
        
        
        class SPV(ThreadJob):
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -23,13 +23,11 @@
        # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        # SOFTWARE.
        
       -"""
       -Wallet classes:
       -  - Imported_Wallet: imported address, no keystore
       -  - Standard_Wallet: one keystore, P2PKH
       -  - Multisig_Wallet: several keystores, P2SH
       +# Wallet classes:
       +#   - Imported_Wallet: imported address, no keystore
       +#   - Standard_Wallet: one keystore, P2PKH
       +#   - Multisig_Wallet: several keystores, P2SH
        
       -"""
        
        import os
        import hashlib
       t@@ -45,27 +43,26 @@ import errno
        from functools import partial
        from collections import namedtuple, defaultdict
        
       -from i18n import _
       -from util import NotEnoughFunds, PrintError, UserCancelled, profiler
       +from .i18n import _
       +from .util import NotEnoughFunds, PrintError, UserCancelled, profiler
        
       -from bitcoin import *
       -from version import *
       -from keystore import load_keystore, Hardware_KeyStore
       -from storage import multisig_type
       +from .bitcoin import *
       +from .version import *
       +from .keystore import load_keystore, Hardware_KeyStore
       +from .storage import multisig_type
        
        import transaction
       -from transaction import Transaction
       -from plugins import run_hook
       -import bitcoin
       -import coinchooser
       -from synchronizer import Synchronizer
       -from verifier import SPV
       -from mnemonic import Mnemonic
       +from .transaction import Transaction
       +from .plugins import run_hook
       +from . import bitcoin
       +from . import coinchooser
       +from .synchronizer import Synchronizer
       +from .verifier import SPV
       +from .mnemonic import Mnemonic
        
       -import paymentrequest
       -from paymentrequest import InvoiceStore
       -from contacts import Contacts
       +from . import paymentrequest
        
       +from .storage import WalletStorage
        
        TX_STATUS = [
            _('Replaceable'),
       t@@ -197,11 +194,11 @@ class Abstract_Wallet(PrintError):
            @profiler
            def check_history(self):
                save = False
       -        for addr, hist in self.history.items():
       -            if not self.is_mine(addr):
       -                self.history.pop(addr)
       -                save = True
       -                continue
       +        mine_addrs = list(filter(lambda k: self.is_mine(self.history[k]), self.history.keys()))
       +        if len(mine_addrs) != len(self.history.keys()):
       +            save = True
       +        for addr in mine_addrs:
       +            hist = self.history[addr]
        
                    for tx_hash, tx_height in hist:
                        if tx_hash in self.pruned_txo.values() or self.txi.get(tx_hash) or self.txo.get(tx_hash):
       t@@ -625,7 +622,7 @@ class Abstract_Wallet(PrintError):
                        if _type == TYPE_ADDRESS:
                            addr = x
                        elif _type == TYPE_PUBKEY:
       -                    addr = bitcoin.public_key_to_p2pkh(x.decode('hex'))
       +                    addr = bitcoin.public_key_to_p2pkh(bfh(x))
                        else:
                            addr = None
                        if addr and self.is_mine(addr):
       t@@ -947,7 +944,7 @@ class Abstract_Wallet(PrintError):
        
                # if we are on a pruning server, remove unverified transactions
                with self.lock:
       -            vr = self.verified_tx.keys() + self.unverified_tx.keys()
       +            vr = list(self.verified_tx.keys()) + list(self.unverified_tx.keys())
                for tx_hash in self.transactions.keys():
                    if tx_hash not in vr:
                        self.print_error("removing transaction", tx_hash)
       t@@ -1253,7 +1250,7 @@ class Abstract_Wallet(PrintError):
        
            def make_payment_request(self, addr, amount, message, expiration):
                timestamp = int(time.time())
       -        _id = Hash(addr + "%d"%timestamp).encode('hex')[0:10]
       +        _id = bh2u(Hash(addr + "%d"%timestamp))[0:10]
                r = {'time':timestamp, 'amount':amount, 'exp':expiration, 'address':addr, 'memo':message, 'id':_id}
                return r
        
       t@@ -1263,7 +1260,7 @@ class Abstract_Wallet(PrintError):
                pr = paymentrequest.make_unsigned_request(req)
                paymentrequest.sign_request_with_alias(pr, alias, alias_privkey)
                req['name'] = pr.pki_data
       -        req['sig'] = pr.signature.encode('hex')
       +        req['sig'] = bh2u(pr.signature)
                self.receive_requests[key] = req
                self.storage.put('payment_requests', self.receive_requests)
        
       t@@ -1420,7 +1417,10 @@ class Imported_Wallet(Abstract_Wallet):
        
            def add_input_sig_info(self, txin, address):
                addrtype, hash160 = bc_address_to_hash_160(address)
       -        x_pubkey = 'fd' + (chr(addrtype) + hash160).encode('hex')
       +        if six.PY3:
       +            x_pubkey = 'fd' + bh2u(bytes([addrtype]) + hash160)
       +        else:
       +            x_pubkey = 'fd' + bh2u(chr(addrtype) + hash160)
                txin['x_pubkeys'] = [x_pubkey]
                txin['signatures'] = [None]
        
   DIR diff --git a/lib/websockets.py b/lib/websockets.py
       t@@ -22,8 +22,14 @@
        # 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.
       -
       -import threading, Queue, os, json, time
       +from __future__ import absolute_import
       +from __future__ import division
       +from __future__ import print_function
       +from __future__ import unicode_literals
       +
       +import six
       +from six.moves import queue
       +import threading, os, json, time
        from collections import defaultdict
        try:
            from SimpleWebSocketServer import WebSocket, SimpleSSLWebSocketServer
       t@@ -31,9 +37,9 @@ except ImportError:
            import sys
            sys.exit("install SimpleWebSocketServer")
        
       -import util
       +from . import util
        
       -request_queue = Queue.Queue()
       +request_queue = queue.Queue()
        
        class ElectrumWebSocket(WebSocket):
        
   DIR diff --git a/lib/x509.py b/lib/x509.py
       t@@ -22,56 +22,63 @@
        # 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 datetime import datetime
        import sys
       -import util
       -from util import profiler, print_error
       +from . import util
       +from .util import profiler, print_error
        import ecdsa
        import hashlib
        
       -
        # algo OIDs
       -ALGO_RSA_SHA1   = '1.2.840.113549.1.1.5'
       +ALGO_RSA_SHA1 = '1.2.840.113549.1.1.5'
        ALGO_RSA_SHA256 = '1.2.840.113549.1.1.11'
        ALGO_RSA_SHA384 = '1.2.840.113549.1.1.12'
        ALGO_RSA_SHA512 = '1.2.840.113549.1.1.13'
        ALGO_ECDSA_SHA256 = '1.2.840.10045.4.3.2'
        
        # prefixes, see http://stackoverflow.com/questions/3713774/c-sharp-how-to-calculate-asn-1-der-encoding-of-a-particular-hash-algorithm
       -PREFIX_RSA_SHA256 = bytearray([0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20])
       -PREFIX_RSA_SHA384 = bytearray([0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30])
       -PREFIX_RSA_SHA512 = bytearray([0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40])
       +PREFIX_RSA_SHA256 = bytearray(
       +    [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20])
       +PREFIX_RSA_SHA384 = bytearray(
       +    [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30])
       +PREFIX_RSA_SHA512 = bytearray(
       +    [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40])
        
        # types used in ASN1 structured data
        ASN1_TYPES = {
       -    'BOOLEAN':           0x01,
       -    'INTEGER':           0x02,
       -    'BIT STRING':        0x03,
       -    'OCTET STRING':      0x04,
       -    'NULL':              0x05,
       +    'BOOLEAN'          : 0x01,
       +    'INTEGER'          : 0x02,
       +    'BIT STRING'       : 0x03,
       +    'OCTET STRING'     : 0x04,
       +    'NULL'             : 0x05,
            'OBJECT IDENTIFIER': 0x06,
       -    'SEQUENCE':          0x70,
       -    'SET':               0x71,
       -    'PrintableString':   0x13,
       -    'IA5String':         0x16,
       -    'UTCTime':           0x17,
       -    'ENUMERATED':        0x0A,
       -    'UTF8String':        0x0C,
       -    'PrintableString':   0x13,
       +    'SEQUENCE'         : 0x70,
       +    'SET'              : 0x71,
       +    'PrintableString'  : 0x13,
       +    'IA5String'        : 0x16,
       +    'UTCTime'          : 0x17,
       +    'ENUMERATED'       : 0x0A,
       +    'UTF8String'       : 0x0C,
        }
        
       +
        class CertificateError(Exception):
            pass
        
       -# helper functions
        
       +# helper functions
        def bitstr_to_bytestr(s):
            if s[0] != '\x00':
                raise BaseException('no padding')
            return s[1:]
        
       +
        def bytestr_to_int(s):
            i = 0
            for char in s:
       t@@ -79,6 +86,7 @@ def bytestr_to_int(s):
                i |= ord(char)
            return i
        
       +
        def decode_OID(s):
            s = map(ord, s)
            r = []
       t@@ -87,103 +95,109 @@ def decode_OID(s):
            k = 0
            for i in s[1:]:
                if i < 128:
       -            r.append(i + 128*k)
       +            r.append(i + 128 * k)
                    k = 0
                else:
       -            k = (i - 128) + 128*k
       +            k = (i - 128) + 128 * k
            return '.'.join(map(str, r))
        
        
        def encode_OID(oid):
            x = map(int, oid.split('.'))
       -    s = chr(x[0]*40 + x[1])
       +    s = chr(x[0] * 40 + x[1])
            for i in x[2:]:
                ss = chr(i % 128)
                while i > 128:
       -            i = i / 128
       +            i //= 128
                    ss = chr(128 + i % 128) + ss
                s += ss
            return s
        
        
       -
       -
        class ASN1_Node(str):
       -
            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 = ord(self[ix + 1])
       +        if (ord(self[ix + 1]) & 0x80) == 0:
                    length = first
                    ixf = ix + 2
                    ixl = ixf + length - 1
       -        else:
       +        else:
                    lengthbytes = first & 0x7F
       -            length = bytestr_to_int(self[ix+2:ix+2+lengthbytes])
       +            length = bytestr_to_int(self[ix + 2:ix + 2 + lengthbytes])
                    ixf = ix + 2 + lengthbytes
       -            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)
       +            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)
                nodes.append(ii)
       -        while ii[2] < node[2]:
       -            ii = self.next_node(ii)
       -            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
       +    return nodes
        
        
       -class X509(object):
       +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
       +
       +
       +class X509(object):
            def __init__(self, b):
        
                self.bytes = bytearray(b)
       t@@ -292,24 +306,21 @@ class X509(object):
                not_before = time.mktime(time.strptime(self.notBefore, TIMESTAMP_FMT))
                not_after = time.mktime(time.strptime(self.notAfter, TIMESTAMP_FMT))
                if not_before > now:
       -            raise CertificateError('Certificate has not entered its valid date range. (%s)'%self.get_common_name())
       +            raise CertificateError('Certificate has not entered its valid date range. (%s)' % self.get_common_name())
                if not_after <= now:
       -            raise CertificateError('Certificate has expired. (%s)'%self.get_common_name())
       +            raise CertificateError('Certificate has expired. (%s)' % self.get_common_name())
        
            def getFingerprint(self):
                return hashlib.sha1(self.bytes).digest()
        
        
       -
       -
       -
        @profiler
        def load_certificates(ca_path):
       -    import pem
       +    from . import pem
            ca_list = {}
            ca_keyID = {}
       -    with open(ca_path, 'r') as f:
       -        s = f.read()
       +    with open(ca_path, 'rb') as f:
       +        s = f.read().decode('utf8')
            bList = pem.dePemList(s, "CERTIFICATE")
            for b in bList:
                try:
       t@@ -328,7 +339,7 @@ def load_certificates(ca_path):
        
        if __name__ == "__main__":
            import requests
       +
            util.set_verbosity(True)
            ca_path = requests.certs.where()
            ca_list, ca_keyID = load_certificates(ca_path)
       -