Browse Source

py3 in qtgui

seed_v14
Dmitry Sorokin 8 years ago
committed by ThomasV
parent
commit
d304ccdf17
  1. 10
      electrum
  2. 4
      gui/qt/address_list.py
  3. 2
      gui/qt/amountedit.py
  4. 7
      gui/qt/console.py
  5. 10
      gui/qt/contact_list.py
  6. 6
      gui/qt/history_list.py
  7. 6
      gui/qt/installwizard.py
  8. 4
      gui/qt/invoice_list.py
  9. 36
      gui/qt/main_window.py
  10. 2
      gui/qt/network_dialog.py
  11. 6
      gui/qt/password_dialog.py
  12. 12
      gui/qt/paytoedit.py
  13. 6
      gui/qt/qrtextedit.py
  14. 7
      gui/qt/seed_dialog.py
  15. 20
      gui/qt/util.py
  16. 2
      gui/qt/utxo_list.py
  17. 9
      lib/bitcoin.py
  18. 8
      lib/commands.py
  19. 40
      lib/daemon.py
  20. 22
      lib/interface.py
  21. 31
      lib/network.py
  22. 12
      lib/paymentrequest.py
  23. 8
      lib/synchronizer.py
  24. 10
      lib/transaction.py
  25. 125
      lib/util.py
  26. 23
      lib/wallet.py
  27. 71
      lib/x509.py

10
electrum

@ -48,11 +48,11 @@ if jnius:
threading.Thread.run = thread_check_run threading.Thread.run = thread_check_run
# monkeypatch unicode constructor for py3 # monkeypatch unicode constructor for py3
if six.PY3: # if six.PY3:
import builtins # import builtins
builtins.unicode = str # builtins.unicode = str
builtins.QString = str # builtins.QString = str
builtins.long = int # builtins.long = int
script_dir = os.path.dirname(os.path.realpath(__file__)) script_dir = os.path.dirname(os.path.realpath(__file__))
is_bundle = getattr(sys, 'frozen', False) is_bundle = getattr(sys, 'frozen', False)

4
gui/qt/address_list.py

@ -48,7 +48,7 @@ class AddressList(MyTreeWidget):
def on_update(self): def on_update(self):
self.wallet = self.parent.wallet self.wallet = self.parent.wallet
item = self.currentItem() item = self.currentItem()
current_address = item.data(0, Qt.UserRole).toString() if item else None current_address = item.data(0, Qt.UserRole) if item else None
self.clear() self.clear()
receiving_addresses = self.wallet.get_receiving_addresses() receiving_addresses = self.wallet.get_receiving_addresses()
change_addresses = self.wallet.get_change_addresses() change_addresses = self.wallet.get_change_addresses()
@ -97,7 +97,7 @@ class AddressList(MyTreeWidget):
can_delete = self.wallet.can_delete_address() can_delete = self.wallet.can_delete_address()
selected = self.selectedItems() selected = self.selectedItems()
multi_select = len(selected) > 1 multi_select = len(selected) > 1
addrs = [unicode(item.text(0)) for item in selected] addrs = [item.text(0) for item in selected]
if not addrs: if not addrs:
return return
if not multi_select: if not multi_select:

2
gui/qt/amountedit.py

@ -37,7 +37,7 @@ class AmountEdit(MyLineEdit):
return 8 return 8
def numbify(self): def numbify(self):
text = unicode(self.text()).strip() text = self.text().strip()
if text == '!': if text == '!':
self.shortcut.emit() self.shortcut.emit()
return return

7
gui/qt/console.py

@ -76,7 +76,7 @@ class Console(QtGui.QPlainTextEdit):
def getCommand(self): def getCommand(self):
doc = self.document() doc = self.document()
curr_line = unicode(doc.findBlockByLineNumber(doc.lineCount() - 1).text()) curr_line = doc.findBlockByLineNumber(doc.lineCount() - 1).text()
curr_line = curr_line.rstrip() curr_line = curr_line.rstrip()
curr_line = curr_line[len(self.prompt):] curr_line = curr_line[len(self.prompt):]
return curr_line return curr_line
@ -86,7 +86,7 @@ class Console(QtGui.QPlainTextEdit):
return return
doc = self.document() doc = self.document()
curr_line = unicode(doc.findBlockByLineNumber(doc.lineCount() - 1).text()) curr_line = doc.findBlockByLineNumber(doc.lineCount() - 1).text()
self.moveCursor(QtGui.QTextCursor.End) self.moveCursor(QtGui.QTextCursor.End)
for i in range(len(curr_line) - len(self.prompt)): for i in range(len(curr_line) - len(self.prompt)):
self.moveCursor(QtGui.QTextCursor.Left, QtGui.QTextCursor.KeepAnchor) self.moveCursor(QtGui.QTextCursor.Left, QtGui.QTextCursor.KeepAnchor)
@ -95,7 +95,6 @@ class Console(QtGui.QPlainTextEdit):
self.textCursor().insertText(command) self.textCursor().insertText(command)
self.moveCursor(QtGui.QTextCursor.End) self.moveCursor(QtGui.QTextCursor.End)
def show_completions(self, completions): def show_completions(self, completions):
if self.completions_visible: if self.completions_visible:
self.hide_completions() self.hide_completions()
@ -113,7 +112,6 @@ class Console(QtGui.QPlainTextEdit):
self.moveCursor(QtGui.QTextCursor.End) self.moveCursor(QtGui.QTextCursor.End)
self.completions_visible = True self.completions_visible = True
def hide_completions(self): def hide_completions(self):
if not self.completions_visible: if not self.completions_visible:
return return
@ -125,7 +123,6 @@ class Console(QtGui.QPlainTextEdit):
self.moveCursor(QtGui.QTextCursor.End) self.moveCursor(QtGui.QTextCursor.End)
self.completions_visible = False self.completions_visible = False
def getConstruct(self, command): def getConstruct(self, command):
if self.construct: if self.construct:
prev_command = self.construct[-1] prev_command = self.construct[-1]

10
gui/qt/contact_list.py

@ -55,7 +55,7 @@ class ContactList(MyTreeWidget):
def on_edited(self, item, column, prior): def on_edited(self, item, column, prior):
if column == 0: # Remove old contact if renamed if column == 0: # Remove old contact if renamed
self.parent.contacts.pop(prior) self.parent.contacts.pop(prior)
self.parent.set_contact(unicode(item.text(0)), unicode(item.text(1))) self.parent.set_contact(item.text(0), item.text(1))
def import_contacts(self): def import_contacts(self):
wallet_folder = self.parent.get_wallet_folder() wallet_folder = self.parent.get_wallet_folder()
@ -72,11 +72,11 @@ class ContactList(MyTreeWidget):
menu.addAction(_("New contact"), lambda: self.parent.new_contact_dialog()) menu.addAction(_("New contact"), lambda: self.parent.new_contact_dialog())
menu.addAction(_("Import file"), lambda: self.parent.import_contacts()) menu.addAction(_("Import file"), lambda: self.parent.import_contacts())
else: else:
names = [unicode(item.text(0)) for item in selected] names = [item.text(0) for item in selected]
keys = [unicode(item.text(1)) for item in selected] keys = [item.text(1) for item in selected]
column = self.currentColumn() column = self.currentColumn()
column_title = self.headerItem().text(column) column_title = self.headerItem().text(column)
column_data = '\n'.join([unicode(item.text(column)) for item in selected]) column_data = '\n'.join([item.text(column) for item in selected])
menu.addAction(_("Copy %s")%column_title, lambda: self.parent.app.clipboard().setText(column_data)) menu.addAction(_("Copy %s")%column_title, lambda: self.parent.app.clipboard().setText(column_data))
if column in self.editable_columns: if column in self.editable_columns:
menu.addAction(_("Edit %s")%column_title, lambda: self.editItem(item, column)) menu.addAction(_("Edit %s")%column_title, lambda: self.editItem(item, column))
@ -91,7 +91,7 @@ class ContactList(MyTreeWidget):
def on_update(self): def on_update(self):
item = self.currentItem() item = self.currentItem()
current_key = item.data(0, Qt.UserRole).toString() if item else None current_key = item.data(0, Qt.UserRole) if item else None
self.clear() self.clear()
for key in sorted(self.parent.contacts.keys()): for key in sorted(self.parent.contacts.keys()):
_type, name = self.parent.contacts[key] _type, name = self.parent.contacts[key]

6
gui/qt/history_list.py

@ -77,7 +77,7 @@ class HistoryList(MyTreeWidget):
self.wallet = self.parent.wallet self.wallet = self.parent.wallet
h = self.wallet.get_history(self.get_domain()) h = self.wallet.get_history(self.get_domain())
item = self.currentItem() item = self.currentItem()
current_tx = item.data(0, Qt.UserRole).toString() if item else None current_tx = item.data(0, Qt.UserRole) if item else None
self.clear() self.clear()
fx = self.parent.fx fx = self.parent.fx
if fx: fx.history_used_spot = False if fx: fx.history_used_spot = False
@ -128,7 +128,7 @@ class HistoryList(MyTreeWidget):
child_count = root.childCount() child_count = root.childCount()
for i in range(child_count): for i in range(child_count):
item = root.child(i) item = root.child(i)
txid = str(item.data(0, Qt.UserRole).toString()) txid = item.data(0, Qt.UserRole)
label = self.wallet.get_label(txid) label = self.wallet.get_label(txid)
item.setText(3, label) item.setText(3, label)
@ -147,7 +147,7 @@ class HistoryList(MyTreeWidget):
if not item: if not item:
return return
column = self.currentColumn() column = self.currentColumn()
tx_hash = str(item.data(0, Qt.UserRole).toString()) tx_hash = item.data(0, Qt.UserRole)
if not tx_hash: if not tx_hash:
return return
if column is 0: if column is 0:

6
gui/qt/installwizard.py

@ -444,8 +444,8 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
@wizard_dialog @wizard_dialog
def choice_dialog(self, title, message, choices, run_next): def choice_dialog(self, title, message, choices, run_next):
c_values = map(lambda x: x[0], choices) c_values = [x[0] for x in choices]
c_titles = map(lambda x: x[1], choices) c_titles = [x[1] for x in choices]
clayout = ChoicesLayout(message, c_titles) clayout = ChoicesLayout(message, c_titles)
vbox = QVBoxLayout() vbox = QVBoxLayout()
vbox.addLayout(clayout.layout()) vbox.addLayout(clayout.layout())
@ -473,7 +473,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
vbox.addWidget(line) vbox.addWidget(line)
vbox.addWidget(WWLabel(warning)) vbox.addWidget(WWLabel(warning))
self.exec_layout(vbox, title, next_enabled=test(default)) self.exec_layout(vbox, title, next_enabled=test(default))
return ' '.join(unicode(line.text()).split()) return ' '.join(line.text().split())
@wizard_dialog @wizard_dialog
def show_xpub_dialog(self, xpub, run_next): def show_xpub_dialog(self, xpub, run_next):

4
gui/qt/invoice_list.py

@ -73,7 +73,9 @@ class InvoiceList(MyTreeWidget):
def create_menu(self, position): def create_menu(self, position):
menu = QMenu() menu = QMenu()
item = self.itemAt(position) item = self.itemAt(position)
key = str(item.data(0, 32).toString()) if not item:
return
key = item.data(0, 32)
column = self.currentColumn() column = self.currentColumn()
column_title = self.headerItem().text(column) column_title = self.headerItem().text(column)
column_data = item.text(column) column_data = item.text(column)

36
gui/qt/main_window.py

@ -384,7 +384,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
def open_wallet(self): def open_wallet(self):
wallet_folder = self.get_wallet_folder() wallet_folder = self.get_wallet_folder()
filename = unicode(QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder)) filename = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder)
if not filename: if not filename:
return return
self.gui_object.new_window(filename) self.gui_object.new_window(filename)
@ -393,7 +393,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
def backup_wallet(self): def backup_wallet(self):
path = self.wallet.storage.path path = self.wallet.storage.path
wallet_folder = os.path.dirname(path) wallet_folder = os.path.dirname(path)
filename = unicode( QFileDialog.getSaveFileName(self, _('Enter a filename for the copy of your wallet'), wallet_folder) ) filename = QFileDialog.getSaveFileName(self, _('Enter a filename for the copy of your wallet'), wallet_folder)
if not filename: if not filename:
return return
@ -578,16 +578,16 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
# custom wrappers for getOpenFileName and getSaveFileName, that remember the path selected by the user # custom wrappers for getOpenFileName and getSaveFileName, that remember the path selected by the user
def getOpenFileName(self, title, filter = ""): def getOpenFileName(self, title, filter = ""):
directory = self.config.get('io_dir', unicode(os.path.expanduser('~'))) directory = self.config.get('io_dir', os.path.expanduser('~'))
fileName = unicode( QFileDialog.getOpenFileName(self, title, directory, filter) ) fileName = QFileDialog.getOpenFileName(self, title, directory, filter)
if fileName and directory != os.path.dirname(fileName): if fileName and directory != os.path.dirname(fileName):
self.config.set_key('io_dir', os.path.dirname(fileName), True) self.config.set_key('io_dir', os.path.dirname(fileName), True)
return fileName return fileName
def getSaveFileName(self, title, filename, filter = ""): def getSaveFileName(self, title, filename, filter = ""):
directory = self.config.get('io_dir', unicode(os.path.expanduser('~'))) directory = self.config.get('io_dir', os.path.expanduser('~'))
path = os.path.join( directory, filename ) path = os.path.join( directory, filename )
fileName = unicode( QFileDialog.getSaveFileName(self, title, path, filter) ) fileName = QFileDialog.getSaveFileName(self, title, path, filter)
if fileName and directory != os.path.dirname(fileName): if fileName and directory != os.path.dirname(fileName):
self.config.set_key('io_dir', os.path.dirname(fileName), True) self.config.set_key('io_dir', os.path.dirname(fileName), True)
return fileName return fileName
@ -880,7 +880,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
def save_payment_request(self): def save_payment_request(self):
addr = str(self.receive_address_e.text()) addr = str(self.receive_address_e.text())
amount = self.receive_amount_e.get_amount() amount = self.receive_amount_e.get_amount()
message = unicode(self.receive_message_e.text()) message = self.receive_message_e.text()
if not message and not amount: if not message and not amount:
self.show_error(_('No message or amount')) self.show_error(_('No message or amount'))
return False return False
@ -982,7 +982,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
def update_receive_qr(self): def update_receive_qr(self):
addr = str(self.receive_address_e.text()) addr = str(self.receive_address_e.text())
amount = self.receive_amount_e.get_amount() amount = self.receive_amount_e.get_amount()
message = unicode(self.receive_message_e.text()).encode('utf8') message = self.receive_message_e.text()
self.save_request_button.setEnabled((amount is not None) or (message != "")) self.save_request_button.setEnabled((amount is not None) or (message != ""))
uri = util.create_URI(addr, amount, message) uri = util.create_URI(addr, amount, message)
self.receive_qr.setData(uri) self.receive_qr.setData(uri)
@ -1281,7 +1281,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
if self.payment_request and self.payment_request.has_expired(): if self.payment_request and self.payment_request.has_expired():
self.show_error(_('Payment request has expired')) self.show_error(_('Payment request has expired'))
return return
label = unicode( self.message_e.text() ) label = self.message_e.text()
if self.payment_request: if self.payment_request:
outputs = self.payment_request.get_outputs() outputs = self.payment_request.get_outputs()
@ -1513,7 +1513,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
if not URI: if not URI:
return return
try: try:
out = util.parse_URI(unicode(URI), self.on_pr) out = util.parse_URI(URI, self.on_pr)
except BaseException as e: except BaseException as e:
self.show_error(_('Invalid bitcoin URI:') + '\n' + str(e)) self.show_error(_('Invalid bitcoin URI:') + '\n' + str(e))
return return
@ -1807,7 +1807,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
vbox.addLayout(grid) vbox.addLayout(grid)
vbox.addLayout(Buttons(CancelButton(d), OkButton(d))) vbox.addLayout(Buttons(CancelButton(d), OkButton(d)))
if d.exec_(): if d.exec_():
self.set_contact(unicode(line2.text()), str(line1.text())) self.set_contact(line2.text(), line1.text())
def show_master_public_keys(self): def show_master_public_keys(self):
dialog = WindowModalDialog(self, "Master Public Keys") dialog = WindowModalDialog(self, "Master Public Keys")
@ -1848,7 +1848,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
except BaseException as e: except BaseException as e:
self.show_error(str(e)) self.show_error(str(e))
return return
from seed_dialog import SeedDialog from .seed_dialog import SeedDialog
d = SeedDialog(self, seed, passphrase) d = SeedDialog(self, seed, passphrase)
d.exec_() d.exec_()
@ -1889,7 +1889,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
@protected @protected
def do_sign(self, address, message, signature, password): def do_sign(self, address, message, signature, password):
address = str(address.text()).strip() address = str(address.text()).strip()
message = unicode(message.toPlainText()).encode('utf-8').strip() message = message.toPlainText().strip()
if not bitcoin.is_address(address): if not bitcoin.is_address(address):
self.show_message('Invalid Bitcoin address.') self.show_message('Invalid Bitcoin address.')
return return
@ -1906,7 +1906,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
def do_verify(self, address, message, signature): def do_verify(self, address, message, signature):
address = str(address.text()).strip() address = str(address.text()).strip()
message = unicode(message.toPlainText()).encode('utf-8').strip() message = message.toPlainText().strip()
if not bitcoin.is_address(address): if not bitcoin.is_address(address):
self.show_message('Invalid Bitcoin address.') self.show_message('Invalid Bitcoin address.')
return return
@ -1970,10 +1970,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
self.wallet.thread.add(task, on_success=message_e.setText) self.wallet.thread.add(task, on_success=message_e.setText)
def do_encrypt(self, message_e, pubkey_e, encrypted_e): def do_encrypt(self, message_e, pubkey_e, encrypted_e):
message = unicode(message_e.toPlainText()) message = message_e.toPlainText()
message = message.encode('utf-8') message = message.encode('utf-8')
try: try:
encrypted = bitcoin.encrypt_message(message, str(pubkey_e.text())) encrypted = bitcoin.encrypt_message(message, pubkey_e.text())
encrypted_e.setText(encrypted) encrypted_e.setText(encrypted)
except BaseException as e: except BaseException as e:
traceback.print_exc(file=sys.stdout) traceback.print_exc(file=sys.stdout)
@ -2386,7 +2386,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
lang_label = HelpLabel(_('Language') + ':', lang_help) lang_label = HelpLabel(_('Language') + ':', lang_help)
lang_combo = QComboBox() lang_combo = QComboBox()
from electrum.i18n import languages from electrum.i18n import languages
lang_combo.addItems(languages.values()) lang_combo.addItems(list(languages.values()))
try: try:
index = languages.keys().index(self.config.get("language",'')) index = languages.keys().index(self.config.get("language",''))
except Exception: except Exception:
@ -2570,7 +2570,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
msg = _("Install the zbar package to enable this.") msg = _("Install the zbar package to enable this.")
qr_label = HelpLabel(_('Video Device') + ':', msg) qr_label = HelpLabel(_('Video Device') + ':', msg)
qr_combo.setEnabled(qrscanner.libzbar is not None) qr_combo.setEnabled(qrscanner.libzbar is not None)
on_video_device = lambda x: self.config.set_key("video_device", str(qr_combo.itemData(x).toString()), True) on_video_device = lambda x: self.config.set_key("video_device", qr_combo.itemData(x), True)
qr_combo.currentIndexChanged.connect(on_video_device) qr_combo.currentIndexChanged.connect(on_video_device)
gui_widgets.append((qr_label, qr_combo)) gui_widgets.append((qr_label, qr_combo))

2
gui/qt/network_dialog.py

@ -386,7 +386,7 @@ class NetworkChoiceLayout(object):
def change_protocol(self, use_ssl): def change_protocol(self, use_ssl):
p = 's' if use_ssl else 't' p = 's' if use_ssl else 't'
host = unicode(self.server_host.text()) host = self.server_host.text()
pp = self.servers.get(host, DEFAULT_PORTS) pp = self.servers.get(host, DEFAULT_PORTS)
if p not in pp.keys(): if p not in pp.keys():
p = pp.keys()[0] p = pp.keys()[0]

6
gui/qt/password_dialog.py

@ -44,7 +44,7 @@ def check_password_strength(password):
:param password: password entered by user in New Password :param password: password entered by user in New Password
:return: password strength Weak or Medium or Strong :return: password strength Weak or Medium or Strong
''' '''
password = unicode(password) password = password
n = math.log(len(set(password))) n = math.log(len(set(password)))
num = re.search("[0-9]", password) is not None and re.match("^[0-9]*$", password) is None num = re.search("[0-9]", password) is not None and re.match("^[0-9]*$", password) is None
caps = password != password.upper() and password != password.lower() caps = password != password.upper() and password != password.lower()
@ -156,11 +156,11 @@ class PasswordLayout(object):
def old_password(self): def old_password(self):
if self.kind == PW_CHANGE: if self.kind == PW_CHANGE:
return unicode(self.pw.text()) or None return self.pw.text() or None
return None return None
def new_password(self): def new_password(self):
pw = unicode(self.new_pw.text()) pw = self.new_pw.text()
# Empty passphrases are fine and returned empty. # Empty passphrases are fine and returned empty.
if pw == "" and self.kind != PW_PASSPHRASE: if pw == "" and self.kind != PW_PASSPHRASE:
pw = None pw = None

12
gui/qt/paytoedit.py

@ -120,7 +120,7 @@ class PayToEdit(ScanQRTextEdit):
if self.is_pr: if self.is_pr:
return return
# filter out empty lines # filter out empty lines
lines = filter(lambda x: x, self.lines()) lines = [i for i in self.lines() if i]
outputs = [] outputs = []
total = 0 total = 0
self.payto_address = None self.payto_address = None
@ -180,7 +180,7 @@ class PayToEdit(ScanQRTextEdit):
return self.outputs[:] return self.outputs[:]
def lines(self): def lines(self):
return unicode(self.toPlainText()).split('\n') return self.toPlainText().split('\n')
def is_multiline(self): def is_multiline(self):
return len(self.lines()) > 1 return len(self.lines()) > 1
@ -242,14 +242,14 @@ class PayToEdit(ScanQRTextEdit):
QPlainTextEdit.keyPressEvent(self, e) QPlainTextEdit.keyPressEvent(self, e)
ctrlOrShift = e.modifiers() and (Qt.ControlModifier or Qt.ShiftModifier) ctrlOrShift = e.modifiers() and (Qt.ControlModifier or Qt.ShiftModifier)
if self.c is None or (ctrlOrShift and e.text().isEmpty()): if self.c is None or (ctrlOrShift and not e.text()):
return return
eow = QString("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=") eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="
hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift; hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift
completionPrefix = self.textUnderCursor() completionPrefix = self.textUnderCursor()
if hasModifier or e.text().isEmpty() or completionPrefix.length() < 1 or eow.contains(e.text().right(1)): if hasModifier or not e.text() or completionPrefix.length() < 1 or eow.contains(e.text().right(1)):
self.c.popup().hide() self.c.popup().hide()
return return

6
gui/qt/qrtextedit.py

@ -22,11 +22,11 @@ class ShowQRTextEdit(ButtonsTextEdit):
run_hook('show_text_edit', self) run_hook('show_text_edit', self)
def qr_show(self): def qr_show(self):
from qrcodewidget import QRDialog from .qrcodewidget import QRDialog
try: try:
s = str(self.toPlainText()) s = str(self.toPlainText())
except: except:
s = unicode(self.toPlainText()) s = self.toPlainText()
QRDialog(s).exec_() QRDialog(s).exec_()
def contextMenuEvent(self, e): def contextMenuEvent(self, e):
@ -45,7 +45,7 @@ class ScanQRTextEdit(ButtonsTextEdit, MessageBoxMixin):
run_hook('scan_text_edit', self) run_hook('scan_text_edit', self)
def file_input(self): def file_input(self):
fileName = unicode(QFileDialog.getOpenFileName(self, 'select file')) fileName = QFileDialog.getOpenFileName(self, 'select file')
if not fileName: if not fileName:
return return
with open(fileName, "r") as f: with open(fileName, "r") as f:

7
gui/qt/seed_dialog.py

@ -52,7 +52,6 @@ def seed_warning_msg(seed):
]) % len(seed.split()) ]) % len(seed.split())
class SeedLayout(QVBoxLayout): class SeedLayout(QVBoxLayout):
#options #options
is_bip39 = False is_bip39 = False
@ -92,7 +91,6 @@ class SeedLayout(QVBoxLayout):
self.is_ext = cb_ext.isChecked() if 'ext' in self.options else False self.is_ext = cb_ext.isChecked() if 'ext' in self.options else False
self.is_bip39 = cb_bip39.isChecked() if 'bip39' in self.options else False self.is_bip39 = cb_bip39.isChecked() if 'bip39' in self.options else False
def __init__(self, seed=None, title=None, icon=True, msg=None, options=None, is_seed=None, passphrase=None, parent=None): def __init__(self, seed=None, title=None, icon=True, msg=None, options=None, is_seed=None, passphrase=None, parent=None):
QVBoxLayout.__init__(self) QVBoxLayout.__init__(self)
self.parent = parent self.parent = parent
@ -140,7 +138,7 @@ class SeedLayout(QVBoxLayout):
self.addWidget(self.seed_warning) self.addWidget(self.seed_warning)
def get_seed(self): def get_seed(self):
text = unicode(self.seed_e.text()) text = self.seed_e.text()
return ' '.join(text.split()) return ' '.join(text.split())
def on_edit(self): def on_edit(self):
@ -159,7 +157,6 @@ class SeedLayout(QVBoxLayout):
self.parent.next_button.setEnabled(b) self.parent.next_button.setEnabled(b)
class KeysLayout(QVBoxLayout): class KeysLayout(QVBoxLayout):
def __init__(self, parent=None, title=None, is_valid=None): def __init__(self, parent=None, title=None, is_valid=None):
QVBoxLayout.__init__(self) QVBoxLayout.__init__(self)
@ -171,7 +168,7 @@ class KeysLayout(QVBoxLayout):
self.addWidget(self.text_e) self.addWidget(self.text_e)
def get_text(self): def get_text(self):
return unicode(self.text_e.text()) return self.text_e.text()
def on_edit(self): def on_edit(self):
b = self.is_valid(self.get_text()) b = self.is_valid(self.get_text())

20
gui/qt/util.py

@ -260,7 +260,7 @@ def line_dialog(parent, title, label, ok_label, default=None):
l.addWidget(txt) l.addWidget(txt)
l.addLayout(Buttons(CancelButton(dialog), OkButton(dialog, ok_label))) l.addLayout(Buttons(CancelButton(dialog), OkButton(dialog, ok_label)))
if dialog.exec_(): if dialog.exec_():
return unicode(txt.text()) return txt.text()
def text_dialog(parent, title, label, ok_label, default=None): def text_dialog(parent, title, label, ok_label, default=None):
from qrtextedit import ScanQRTextEdit from qrtextedit import ScanQRTextEdit
@ -275,7 +275,7 @@ def text_dialog(parent, title, label, ok_label, default=None):
l.addWidget(txt) l.addWidget(txt)
l.addLayout(Buttons(CancelButton(dialog), OkButton(dialog, ok_label))) l.addLayout(Buttons(CancelButton(dialog), OkButton(dialog, ok_label)))
if dialog.exec_(): if dialog.exec_():
return unicode(txt.toPlainText()) return txt.toPlainText()
class ChoicesLayout(object): class ChoicesLayout(object):
def __init__(self, msg, choices, on_clicked=None, checked_index=0): def __init__(self, msg, choices, on_clicked=None, checked_index=0):
@ -341,15 +341,15 @@ def filename_field(parent, config, defaultname, select_msg):
hbox = QHBoxLayout() hbox = QHBoxLayout()
directory = config.get('io_dir', unicode(os.path.expanduser('~'))) directory = config.get('io_dir', os.path.expanduser('~'))
path = os.path.join( directory, defaultname ) path = os.path.join( directory, defaultname )
filename_e = QLineEdit() filename_e = QLineEdit()
filename_e.setText(path) filename_e.setText(path)
def func(): def func():
text = unicode(filename_e.text()) text = filename_e.text()
_filter = "*.csv" if text.endswith(".csv") else "*.json" if text.endswith(".json") else None _filter = "*.csv" if text.endswith(".csv") else "*.json" if text.endswith(".json") else None
p = unicode( QFileDialog.getSaveFileName(None, select_msg, text, _filter)) p = QFileDialog.getSaveFileName(None, select_msg, text, _filter)
if p: if p:
filename_e.setText(p) filename_e.setText(p)
@ -360,7 +360,7 @@ def filename_field(parent, config, defaultname, select_msg):
vbox.addLayout(hbox) vbox.addLayout(hbox)
def set_csv(v): def set_csv(v):
text = unicode(filename_e.text()) text = filename_e.text()
text = text.replace(".json",".csv") if v else text.replace(".csv",".json") text = text.replace(".json",".csv") if v else text.replace(".csv",".json")
filename_e.setText(text) filename_e.setText(text)
@ -409,7 +409,7 @@ class MyTreeWidget(QTreeWidget):
def editItem(self, item, column): def editItem(self, item, column):
if column in self.editable_columns: if column in self.editable_columns:
self.editing_itemcol = (item, column, unicode(item.text(column))) self.editing_itemcol = (item, column, item.text(column))
# Calling setFlags causes on_changed events for some reason # Calling setFlags causes on_changed events for some reason
item.setFlags(item.flags() | Qt.ItemIsEditable) item.setFlags(item.flags() | Qt.ItemIsEditable)
QTreeWidget.editItem(self, item, column) QTreeWidget.editItem(self, item, column)
@ -471,7 +471,7 @@ class MyTreeWidget(QTreeWidget):
def on_edited(self, item, column, prior): def on_edited(self, item, column, prior):
'''Called only when the text actually changes''' '''Called only when the text actually changes'''
key = str(item.data(0, Qt.UserRole).toString()) key = str(item.data(0, Qt.UserRole).toString())
text = unicode(item.text(column)) text = item.text(column)
self.parent.wallet.set_label(key, text) self.parent.wallet.set_label(key, text)
self.parent.history_list.update_labels() self.parent.history_list.update_labels()
self.parent.update_completions() self.parent.update_completions()
@ -501,10 +501,10 @@ class MyTreeWidget(QTreeWidget):
def filter(self, p): def filter(self, p):
columns = self.__class__.filter_columns columns = self.__class__.filter_columns
p = unicode(p).lower() p = p.lower()
self.current_filter = p self.current_filter = p
for item in self.get_leaves(self.invisibleRootItem()): for item in self.get_leaves(self.invisibleRootItem()):
item.setHidden(all([unicode(item.text(column)).lower().find(p) == -1 item.setHidden(all([item.text(column).lower().find(p) == -1
for column in columns])) for column in columns]))

2
gui/qt/utxo_list.py

@ -63,7 +63,7 @@ class UTXOList(MyTreeWidget):
self.addChild(utxo_item) self.addChild(utxo_item)
def create_menu(self, position): def create_menu(self, position):
selected = [str(x.data(0, Qt.UserRole).toString()) for x in self.selectedItems()] selected = [x.data(0, Qt.UserRole) for x in self.selectedItems()]
if not selected: if not selected:
return return
menu = QMenu() menu = QMenu()

9
lib/bitcoin.py

@ -28,10 +28,11 @@ import hashlib
import base64 import base64
import re import re
import hmac import hmac
import os
from lib.util import bfh, bh2u from lib.util import bfh, bh2u
from . import version from . import version
from .util import print_error, InvalidPassword, assert_bytes, _bytes, to_bytes from .util import print_error, InvalidPassword, assert_bytes, to_bytes
import ecdsa import ecdsa
import pyaes import pyaes
@ -206,12 +207,12 @@ def op_push(i):
def sha256(x): def sha256(x):
x = to_bytes(x, 'utf8') x = to_bytes(x, 'utf8')
return _bytes(hashlib.sha256(x).digest()) return bytes(hashlib.sha256(x).digest())
def Hash(x): def Hash(x):
x = to_bytes(x, 'utf8') x = to_bytes(x, 'utf8')
out = _bytes(sha256(sha256(x))) out = bytes(sha256(sha256(x)))
return out return out
@ -363,7 +364,7 @@ def base_decode(v, length, base):
chars = __b43chars chars = __b43chars
long_value = 0 long_value = 0
for (i, c) in enumerate(v[::-1]): for (i, c) in enumerate(v[::-1]):
long_value += chars.find(_bytes([c])) * (base**i) long_value += chars.find(bytes([c])) * (base**i)
result = bytearray() result = bytearray()
while long_value >= 256: while long_value >= 256:
div, mod = divmod(long_value, 256) div, mod = divmod(long_value, 256)

8
lib/commands.py

@ -243,8 +243,8 @@ class Commands:
tx = Transaction(tx) tx = Transaction(tx)
if privkey: if privkey:
pubkey = bitcoin.public_key_from_private_key(privkey) pubkey = bitcoin.public_key_from_private_key(privkey)
h160 = bitcoin.hash_160(pubkey.decode('hex')) h160 = bitcoin.hash_160(bfh(pubkey))
x_pubkey = 'fd' + (chr(0) + h160).encode('hex') x_pubkey = 'fd' + bh2u(b'\x00' + h160)
tx.sign({x_pubkey:privkey}) tx.sign({x_pubkey:privkey})
else: else:
self.wallet.sign_transaction(tx, password) self.wallet.sign_transaction(tx, password)
@ -266,8 +266,8 @@ class Commands:
def createmultisig(self, num, pubkeys): def createmultisig(self, num, pubkeys):
"""Create multisig address""" """Create multisig address"""
assert isinstance(pubkeys, list), (type(num), type(pubkeys)) assert isinstance(pubkeys, list), (type(num), type(pubkeys))
redeem_script = transaction.multisig_script(pubkeys, num) redeem_script = Transaction.multisig_script(pubkeys, num)
address = bitcoin.hash160_to_p2sh(hash_160(redeem_script.decode('hex'))) address = bitcoin.hash160_to_p2sh(hash_160(bfh(redeem_script)))
return {'address':address, 'redeemScript':redeem_script} return {'address':address, 'redeemScript':redeem_script}
@command('w') @command('w')

40
lib/daemon.py

@ -33,8 +33,9 @@ import os
import sys import sys
import time import time
# import jsonrpclib # from jsonrpc import JSONRPCResponseManager
# from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler import jsonrpclib
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
from .version import ELECTRUM_VERSION from .version import ELECTRUM_VERSION
from .network import Network from .network import Network
@ -47,12 +48,15 @@ from .simple_config import SimpleConfig
from .plugins import run_hook from .plugins import run_hook
from .exchange_rate import FxThread from .exchange_rate import FxThread
def get_lockfile(config): def get_lockfile(config):
return os.path.join(config.path, 'daemon') return os.path.join(config.path, 'daemon')
def remove_lockfile(lockfile): def remove_lockfile(lockfile):
os.unlink(lockfile) os.unlink(lockfile)
def get_fd_or_server(config): def get_fd_or_server(config):
'''Tries to create the lockfile, using O_EXCL to '''Tries to create the lockfile, using O_EXCL to
prevent races. If it succeeds it returns the FD. prevent races. If it succeeds it returns the FD.
@ -71,6 +75,7 @@ def get_fd_or_server(config):
# Couldn't connect; remove lockfile and try again. # Couldn't connect; remove lockfile and try again.
remove_lockfile(lockfile) remove_lockfile(lockfile)
def get_server(config): def get_server(config):
lockfile = get_lockfile(config) lockfile = get_lockfile(config)
while True: while True:
@ -82,7 +87,8 @@ def get_server(config):
# Test daemon is running # Test daemon is running
server.ping() server.ping()
return server return server
except: except Exception as e:
print_error(e)
pass pass
if not create_time or create_time < time.time() - 1.0: if not create_time or create_time < time.time() - 1.0:
return None return None
@ -90,17 +96,17 @@ def get_server(config):
time.sleep(1.0) time.sleep(1.0)
# class RequestHandler(SimpleJSONRPCRequestHandler): class RequestHandler(SimpleJSONRPCRequestHandler):
#
# def do_OPTIONS(self): def do_OPTIONS(self):
# self.send_response(200) self.send_response(200)
# self.end_headers() self.end_headers()
#
# def end_headers(self): def end_headers(self):
# self.send_header("Access-Control-Allow-Headers", self.send_header("Access-Control-Allow-Headers",
# "Origin, X-Requested-With, Content-Type, Accept") "Origin, X-Requested-With, Content-Type, Accept")
# self.send_header("Access-Control-Allow-Origin", "*") self.send_header("Access-Control-Allow-Origin", "*")
# SimpleJSONRPCRequestHandler.end_headers(self) SimpleJSONRPCRequestHandler.end_headers(self)
class Daemon(DaemonThread): class Daemon(DaemonThread):
@ -129,12 +135,12 @@ class Daemon(DaemonThread):
try: try:
server = SimpleJSONRPCServer((host, port), logRequests=False, server = SimpleJSONRPCServer((host, port), logRequests=False,
requestHandler=RequestHandler) requestHandler=RequestHandler)
except: except Exception as e:
self.print_error('Warning: cannot initialize RPC server on host', host) self.print_error('Warning: cannot initialize RPC server on host', host, e)
self.server = None self.server = None
os.close(fd) os.close(fd)
return return
os.write(fd, repr((server.socket.getsockname(), time.time()))) os.write(fd, bytes(repr((server.socket.getsockname(), time.time())), 'utf8'))
os.close(fd) os.close(fd)
server.timeout = 0.1 server.timeout = 0.1
for cmdname in known_commands: for cmdname in known_commands:

22
lib/interface.py

@ -38,6 +38,9 @@ import time
import traceback import traceback
import requests import requests
from lib import print_error
ca_path = requests.certs.where() ca_path = requests.certs.where()
from . import util from . import util
@ -60,6 +63,7 @@ def Connection(server, queue, config_path):
c.start() c.start()
return c return c
class TcpConnection(threading.Thread, util.PrintError): class TcpConnection(threading.Thread, util.PrintError):
def __init__(self, server, queue, config_path): def __init__(self, server, queue, config_path):
@ -131,8 +135,9 @@ class TcpConnection(threading.Thread, util.PrintError):
return return
# try with CA first # try with CA first
try: try:
s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_path, do_handshake_on_connect=True) s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1_1, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_path, do_handshake_on_connect=True)
except ssl.SSLError as e: except ssl.SSLError as e:
print_error(e)
s = None s = None
if s and self.check_host_name(s.getpeercert(), self.host): if s and self.check_host_name(s.getpeercert(), self.host):
self.print_error("SSL certificate signed by CA") self.print_error("SSL certificate signed by CA")
@ -143,7 +148,7 @@ class TcpConnection(threading.Thread, util.PrintError):
if s is None: if s is None:
return return
try: try:
s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_NONE, ca_certs=None) s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1_1, cert_reqs=ssl.CERT_NONE, ca_certs=None)
except ssl.SSLError as e: except ssl.SSLError as e:
self.print_error("SSL error retrieving SSL certificate:", e) self.print_error("SSL error retrieving SSL certificate:", e)
return return
@ -166,9 +171,9 @@ class TcpConnection(threading.Thread, util.PrintError):
if self.use_ssl: if self.use_ssl:
try: try:
s = ssl.wrap_socket(s, s = ssl.wrap_socket(s,
ssl_version=ssl.PROTOCOL_SSLv23, ssl_version=ssl.PROTOCOL_TLSv1_1,
cert_reqs=ssl.CERT_REQUIRED, cert_reqs=ssl.CERT_REQUIRED,
ca_certs= (temporary_path if is_new else cert_path), ca_certs=(temporary_path if is_new else cert_path),
do_handshake_on_connect=True) do_handshake_on_connect=True)
except ssl.SSLError as e: except ssl.SSLError as e:
self.print_error("SSL error:", e) self.print_error("SSL error:", e)
@ -196,11 +201,11 @@ class TcpConnection(threading.Thread, util.PrintError):
os.unlink(cert_path) os.unlink(cert_path)
return return
self.print_error("wrong certificate") self.print_error("wrong certificate")
if e.errno == 104:
return
return return
except BaseException as e: except BaseException as e:
self.print_error(e) self.print_error(e)
if e.errno == 104:
return
traceback.print_exc(file=sys.stderr) traceback.print_exc(file=sys.stderr)
return return
@ -216,6 +221,7 @@ class TcpConnection(threading.Thread, util.PrintError):
self.print_error("connected") self.print_error("connected")
self.queue.put((self.server, socket)) self.queue.put((self.server, socket))
class Interface(util.PrintError): class Interface(util.PrintError):
"""The Interface class handles a socket connected to a single remote """The Interface class handles a socket connected to a single remote
electrum server. It's exposed API is: electrum server. It's exposed API is:
@ -274,7 +280,7 @@ class Interface(util.PrintError):
n = self.num_requests() n = self.num_requests()
wire_requests = self.unsent_requests[0:n] wire_requests = self.unsent_requests[0:n]
try: try:
self.pipe.send_all(map(make_dict, wire_requests)) self.pipe.send_all([make_dict(*r) for r in wire_requests])
except socket.error as e: except socket.error as e:
self.print_error("socket error:", e) self.print_error("socket error:", e)
return False return False
@ -368,13 +374,13 @@ def _match_hostname(name, val):
return val.startswith('*.') and name.endswith(val[1:]) return val.startswith('*.') and name.endswith(val[1:])
def test_certificates(): def test_certificates():
from .simple_config import SimpleConfig from .simple_config import SimpleConfig
config = SimpleConfig() config = SimpleConfig()
mydir = os.path.join(config.path, "certs") mydir = os.path.join(config.path, "certs")
certs = os.listdir(mydir) certs = os.listdir(mydir)
for c in certs: for c in certs:
print(c)
p = os.path.join(mydir,c) p = os.path.join(mydir,c)
with open(p) as f: with open(p) as f:
cert = f.read() cert = f.read()

31
lib/network.py

@ -103,7 +103,7 @@ SERVER_RETRY_INTERVAL = 10
def parse_servers(result): def parse_servers(result):
""" parse servers list into dict format""" """ parse servers list into dict format"""
from version import PROTOCOL_VERSION from .version import PROTOCOL_VERSION
servers = {} servers = {}
for item in result: for item in result:
host = item[1] host = item[1]
@ -123,7 +123,8 @@ def parse_servers(result):
if pruning_level == '': pruning_level = '0' if pruning_level == '': pruning_level = '0'
try: try:
is_recent = cmp(util.normalize_version(version), util.normalize_version(PROTOCOL_VERSION)) >= 0 is_recent = cmp(util.normalize_version(version), util.normalize_version(PROTOCOL_VERSION)) >= 0
except Exception: except Exception as e:
print_error(e)
is_recent = False is_recent = False
if out and is_recent: if out and is_recent:
@ -152,13 +153,15 @@ from .simple_config import SimpleConfig
proxy_modes = ['socks4', 'socks5', 'http'] proxy_modes = ['socks4', 'socks5', 'http']
def serialize_proxy(p): def serialize_proxy(p):
if type(p) != dict: if not isinstance(p, dict):
return None return None
return ':'.join([p.get('mode'),p.get('host'), p.get('port'), p.get('user'), p.get('password')]) return ':'.join([p.get('mode'),p.get('host'), p.get('port'), p.get('user'), p.get('password')])
def deserialize_proxy(s): def deserialize_proxy(s):
if type(s) not in [str, unicode]: if not isinstance(s, str):
return None return None
if s.lower() == 'none': if s.lower() == 'none':
return None return None
@ -183,15 +186,18 @@ def deserialize_proxy(s):
proxy["password"] = args[n] proxy["password"] = args[n]
return proxy return proxy
def deserialize_server(server_str): def deserialize_server(server_str):
host, port, protocol = str(server_str).split(':') host, port, protocol = str(server_str).split(':')
assert protocol in 'st' assert protocol in 'st'
int(port) # Throw if cannot be converted to int int(port) # Throw if cannot be converted to int
return host, port, protocol return host, port, protocol
def serialize_server(host, port, protocol): def serialize_server(host, port, protocol):
return str(':'.join([host, port, protocol])) return str(':'.join([host, port, protocol]))
class Network(util.DaemonThread): class Network(util.DaemonThread):
"""The Network class manages a set of connections to remote electrum """The Network class manages a set of connections to remote electrum
servers, each connected socket is handled by an Interface() object. servers, each connected socket is handled by an Interface() object.
@ -209,7 +215,7 @@ class Network(util.DaemonThread):
if config is None: if config is None:
config = {} # Do not use mutables as default values! config = {} # Do not use mutables as default values!
util.DaemonThread.__init__(self) util.DaemonThread.__init__(self)
self.config = SimpleConfig(config) if type(config) == type({}) else config self.config = SimpleConfig(config) if isinstance(config, dict) else config
self.num_server = 10 if not self.config.get('oneserver') else 0 self.num_server = 10 if not self.config.get('oneserver') else 0
self.blockchains = blockchain.read_blockchains(self.config) self.blockchains = blockchain.read_blockchains(self.config)
self.print_error("blockchains", self.blockchains.keys()) self.print_error("blockchains", self.blockchains.keys())
@ -390,7 +396,7 @@ class Network(util.DaemonThread):
def get_interfaces(self): def get_interfaces(self):
'''The interfaces that are in connected state''' '''The interfaces that are in connected state'''
return self.interfaces.keys() return list(self.interfaces.keys())
def get_servers(self): def get_servers(self):
if self.irc_servers: if self.irc_servers:
@ -456,7 +462,7 @@ class Network(util.DaemonThread):
def stop_network(self): def stop_network(self):
self.print_error("stopping network") self.print_error("stopping network")
for interface in self.interfaces.values(): for interface in list(self.interfaces.values()):
self.close_interface(interface) self.close_interface(interface)
if self.interface: if self.interface:
self.close_interface(self.interface) self.close_interface(self.interface)
@ -647,6 +653,7 @@ class Network(util.DaemonThread):
def send(self, messages, callback): def send(self, messages, callback):
'''Messages is a list of (method, params) tuples''' '''Messages is a list of (method, params) tuples'''
messages = list(messages)
with self.lock: with self.lock:
self.pending_sends.append((messages, callback)) self.pending_sends.append((messages, callback))
@ -730,7 +737,8 @@ class Network(util.DaemonThread):
self.connection_down(server) self.connection_down(server)
# Send pings and shut down stale interfaces # Send pings and shut down stale interfaces
for interface in self.interfaces.values(): # must use copy of values
for interface in list(self.interfaces.values()):
if interface.has_timed_out(): if interface.has_timed_out():
self.connection_down(interface.server) self.connection_down(interface.server)
elif interface.ping_required(): elif interface.ping_required():
@ -1059,15 +1067,14 @@ class Network(util.DaemonThread):
host, port, protocol = server.split(':') host, port, protocol = server.split(':')
self.set_parameters(host, port, protocol, proxy, auto_connect) self.set_parameters(host, port, protocol, proxy, auto_connect)
def get_local_height(self): def get_local_height(self):
return self.blockchain().height() return self.blockchain().height()
def synchronous_get(self, request, timeout=30): def synchronous_get(self, request, timeout=30):
queue = queue.Queue() q = queue.Queue()
self.send([request], queue.put) self.send([request], q.put)
try: try:
r = queue.get(True, timeout) r = q.get(True, timeout)
except queue.Empty: except queue.Empty:
raise BaseException('Server did not answer') raise BaseException('Server did not answer')
if r.get('error'): if r.get('error'):

12
lib/paymentrequest.py

@ -51,7 +51,7 @@ except ImportError:
from . import bitcoin from . import bitcoin
from . import util from . import util
from .util import print_error from .util import print_error, bh2u, bfh
from . import transaction from . import transaction
from . import x509 from . import x509
from . import rsakey from . import rsakey
@ -126,7 +126,7 @@ class PaymentRequest:
def parse(self, r): def parse(self, r):
if self.error: if self.error:
return return
self.id = bitcoin.sha256(r)[0:16].encode('hex') self.id = bh2u(bitcoin.sha256(r)[0:16])
try: try:
self.data = pb2.PaymentRequest() self.data = pb2.PaymentRequest()
self.data.ParseFromString(r) self.data.ParseFromString(r)
@ -321,7 +321,7 @@ def make_unsigned_request(req):
if amount is None: if amount is None:
amount = 0 amount = 0
memo = req['memo'] memo = req['memo']
script = Transaction.pay_script(TYPE_ADDRESS, addr).decode('hex') script = bfh(Transaction.pay_script(TYPE_ADDRESS, addr))
outputs = [(script, amount)] outputs = [(script, amount)]
pd = pb2.PaymentDetails() pd = pb2.PaymentDetails()
for script, amount in outputs: for script, amount in outputs:
@ -445,7 +445,7 @@ def serialize_request(req):
signature = req.get('sig') signature = req.get('sig')
requestor = req.get('name') requestor = req.get('name')
if requestor and signature: if requestor and signature:
pr.signature = signature.decode('hex') pr.signature = bfh(signature)
pr.pki_type = 'dnssec+btc' pr.pki_type = 'dnssec+btc'
pr.pki_data = str(requestor) pr.pki_data = str(requestor)
return pr return pr
@ -477,7 +477,7 @@ class InvoiceStore(object):
def load(self, d): def load(self, d):
for k, v in d.items(): for k, v in d.items():
try: try:
pr = PaymentRequest(v.get('hex').decode('hex')) pr = bfh(PaymentRequest(v.get('hex')))
pr.tx = v.get('txid') pr.tx = v.get('txid')
pr.requestor = v.get('requestor') pr.requestor = v.get('requestor')
self.invoices[k] = pr self.invoices[k] = pr
@ -499,7 +499,7 @@ class InvoiceStore(object):
l = {} l = {}
for k, pr in self.invoices.items(): for k, pr in self.invoices.items():
l[k] = { l[k] = {
'hex': str(pr).encode('hex'), 'hex': bh2u(pr),
'requestor': pr.requestor, 'requestor': pr.requestor,
'txid': pr.tx 'txid': pr.tx
} }

8
lib/synchronizer.py

@ -33,7 +33,7 @@ import hashlib
from .bitcoin import Hash, hash_encode from .bitcoin import Hash, hash_encode
from .transaction import Transaction from .transaction import Transaction
from .util import print_error, print_msg, ThreadJob from .util import print_error, print_msg, ThreadJob, bh2u
class Synchronizer(ThreadJob): class Synchronizer(ThreadJob):
@ -89,7 +89,7 @@ class Synchronizer(ThreadJob):
status = '' status = ''
for tx_hash, height in h: for tx_hash, height in h:
status += tx_hash + ':%d:' % height status += tx_hash + ':%d:' % height
return hashlib.sha256(status).digest().encode('hex') return bh2u(hashlib.sha256(status.encode('ascii')).digest())
def addr_subscription_response(self, response): def addr_subscription_response(self, response):
params, result = self.parse_response(response) params, result = self.parse_response(response)
@ -114,7 +114,7 @@ class Synchronizer(ThreadJob):
self.print_error("receiving history", addr, len(result)) self.print_error("receiving history", addr, len(result))
server_status = self.requested_histories[addr] server_status = self.requested_histories[addr]
hashes = set(map(lambda item: item['tx_hash'], result)) hashes = set(map(lambda item: item['tx_hash'], result))
hist = map(lambda item: (item['tx_hash'], item['height']), result) hist = list(map(lambda item: (item['tx_hash'], item['height']), result))
# tx_fees # tx_fees
tx_fees = [(item['tx_hash'], item.get('fee')) for item in result] tx_fees = [(item['tx_hash'], item.get('fee')) for item in result]
tx_fees = dict(filter(lambda x:x[1] is not None, tx_fees)) tx_fees = dict(filter(lambda x:x[1] is not None, tx_fees))
@ -140,7 +140,7 @@ class Synchronizer(ThreadJob):
if not params: if not params:
return return
tx_hash, tx_height = params tx_hash, tx_height = params
#assert tx_hash == hash_encode(Hash(result.decode('hex'))) #assert tx_hash == hash_encode(Hash(bytes.fromhex(result)))
tx = Transaction(result) tx = Transaction(result)
try: try:
tx.deserialize() tx.deserialize()

10
lib/transaction.py

@ -170,9 +170,9 @@ class Enumeration:
for x in enumList: for x in enumList:
if isinstance(x, tuple): if isinstance(x, tuple):
x, i = x x, i = x
if not isinstance(x, six.text_type): if not isinstance(x, str):
raise EnumException("enum name is not a string: " + x) raise EnumException("enum name is not a string: " + x)
if not isinstance(i, six.integer_types): if not isinstance(i, int):
raise EnumException("enum value is not an integer: " + i) raise EnumException("enum value is not an integer: " + i)
if x in uniqueNames: if x in uniqueNames:
raise EnumException("enum name is not unique: " + x) raise EnumException("enum name is not unique: " + x)
@ -715,9 +715,9 @@ class Transaction:
txin = inputs[i] txin = inputs[i]
# TODO: py3 hex # TODO: py3 hex
if self.is_segwit_input(txin): if self.is_segwit_input(txin):
hashPrevouts = Hash(''.join(self.serialize_outpoint(txin) for txin in inputs).decode('hex')).encode('hex') hashPrevouts = bh2u(Hash(bfh(''.join(self.serialize_outpoint(txin) for txin in inputs))))
hashSequence = Hash(''.join(int_to_hex(txin.get('sequence', 0xffffffff - 1), 4) for txin in inputs).decode('hex')).encode('hex') hashSequence = bh2u(Hash(bfh(''.join(int_to_hex(txin.get('sequence', 0xffffffff - 1), 4) for txin in inputs))))
hashOutputs = Hash(''.join(self.serialize_output(o) for o in outputs).decode('hex')).encode('hex') hashOutputs = bh2u(Hash(bfh(''.join(self.serialize_output(o) for o in outputs))))
outpoint = self.serialize_outpoint(txin) outpoint = self.serialize_outpoint(txin)
preimage_script = self.get_preimage_script(txin) preimage_script = self.get_preimage_script(txin)
scriptCode = var_int(len(preimage_script)/2) + preimage_script scriptCode = var_int(len(preimage_script)/2) + preimage_script

125
lib/util.py

@ -141,7 +141,7 @@ class DaemonThread(threading.Thread, PrintError):
for job in self.jobs: for job in self.jobs:
try: try:
job.run() job.run()
except: except Exception as e:
traceback.print_exc(file=sys.stderr) traceback.print_exc(file=sys.stderr)
def remove_jobs(self, jobs): def remove_jobs(self, jobs):
@ -170,7 +170,8 @@ class DaemonThread(threading.Thread, PrintError):
self.print_error("stopped") self.print_error("stopped")
is_verbose = False # TODO: disable
is_verbose = True
def set_verbosity(b): def set_verbosity(b):
global is_verbose global is_verbose
is_verbose = b is_verbose = b
@ -281,63 +282,8 @@ def assert_str(*args):
assert isinstance(x, six.string_types) 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_string(x, enc):
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)): if isinstance(x, (bytes, bytearray)):
return x.decode(enc) return x.decode(enc)
if isinstance(x, str): if isinstance(x, str):
@ -349,35 +295,16 @@ def to_bytes(something, encoding='utf8'):
""" """
cast string to bytes() like object, but for python2 support it's bytearray copy cast string to bytes() like object, but for python2 support it's bytearray copy
""" """
raise NotImplementedError("This call should be redefined") if isinstance(something, bytes):
return something
def to_bytes(something, encoding='utf8'): if isinstance(something, str):
""" return something.encode(encoding)
cast string to str object elif isinstance(something, bytearray):
""" return bytes(something)
raise NotImplementedError("This call should be redefined") else:
raise TypeError("Not a string or bytes like object")
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): bfh_builder = lambda x: bytes.fromhex(x)
# """
# py2-py3 aware wrapper for str.decode('hex')
# :param x: str
# :return: str
# """
# if
# return binascii.unhexlify(x)
def hfu(x): def hfu(x):
@ -700,20 +627,18 @@ else:
builtins.input = raw_input builtins.input = raw_input
def parse_json(message): def parse_json(message):
n = message.find('\n') # TODO: check \r\n pattern
n = message.find(b'\n')
if n==-1: if n==-1:
return None, message return None, message
try: try:
j = json.loads( message[0:n] ) j = json.loads(message[0:n].decode('utf8'))
except: except:
j = None j = None
return j, message[n+1:] return j, message[n+1:]
class timeout(Exception): class timeout(Exception):
pass pass
@ -723,11 +648,11 @@ import json
import ssl import ssl
import time import time
class SocketPipe:
class SocketPipe:
def __init__(self, socket): def __init__(self, socket):
self.socket = socket self.socket = socket
self.message = '' self.message = b''
self.set_timeout(0.1) self.set_timeout(0.1)
self.recv_time = time.time() self.recv_time = time.time()
@ -757,10 +682,10 @@ class SocketPipe:
raise timeout raise timeout
else: else:
print_error("pipe: socket error", err) print_error("pipe: socket error", err)
data = '' data = b''
except: except:
traceback.print_exc(file=sys.stderr) traceback.print_exc(file=sys.stderr)
data = '' data = b''
if not data: # Connection closed remotely if not data: # Connection closed remotely
return None return None
@ -769,10 +694,12 @@ class SocketPipe:
def send(self, request): def send(self, request):
out = json.dumps(request) + '\n' out = json.dumps(request) + '\n'
out = out.encode('utf8')
self._send(out) self._send(out)
def send_all(self, requests): def send_all(self, requests):
out = ''.join(map(lambda x: json.dumps(x) + '\n', requests)) print(requests)
out = b''.join(map(lambda x: (json.dumps(x) + '\n').encode('utf8'), requests))
self._send(out) self._send(out)
def _send(self, out): def _send(self, out):
@ -798,7 +725,6 @@ class SocketPipe:
raise e raise e
class QueuePipe: class QueuePipe:
def __init__(self, send_queue=None, get_queue=None): def __init__(self, send_queue=None, get_queue=None):
@ -833,9 +759,8 @@ class QueuePipe:
self.send(request) self.send(request)
def check_www_dir(rdir): def check_www_dir(rdir):
import urllib, urlparse, shutil, os import urllib, shutil, os
if not os.path.exists(rdir): if not os.path.exists(rdir):
os.mkdir(rdir) os.mkdir(rdir)
index = os.path.join(rdir, 'index.html') index = os.path.join(rdir, 'index.html')
@ -850,7 +775,7 @@ def check_www_dir(rdir):
"https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"
] ]
for URL in files: for URL in files:
path = urlparse.urlsplit(URL).path path = urllib_parse.urlsplit(URL).path
filename = os.path.basename(path) filename = os.path.basename(path)
path = os.path.join(rdir, filename) path = os.path.join(rdir, filename)
if not os.path.exists(path): if not os.path.exists(path):

23
lib/wallet.py

@ -51,7 +51,7 @@ from .version import *
from .keystore import load_keystore, Hardware_KeyStore from .keystore import load_keystore, Hardware_KeyStore
from .storage import multisig_type from .storage import multisig_type
import transaction from . import transaction
from .transaction import Transaction from .transaction import Transaction
from .plugins import run_hook from .plugins import run_hook
from . import bitcoin from . import bitcoin
@ -297,6 +297,7 @@ class Abstract_Wallet(PrintError):
self.verifier.merkle_roots.pop(tx_hash, None) self.verifier.merkle_roots.pop(tx_hash, None)
# tx will be verified only if height > 0 # tx will be verified only if height > 0
print('unverif', tx_hash, tx_height)
if tx_hash not in self.verified_tx: if tx_hash not in self.verified_tx:
self.unverified_tx[tx_hash] = tx_height self.unverified_tx[tx_hash] = tx_height
@ -759,7 +760,7 @@ class Abstract_Wallet(PrintError):
return '' return ''
def get_tx_status(self, tx_hash, height, conf, timestamp): def get_tx_status(self, tx_hash, height, conf, timestamp):
from util import format_time from .util import format_time
if conf == 0: if conf == 0:
tx = self.transactions.get(tx_hash) tx = self.transactions.get(tx_hash)
if not tx: if not tx:
@ -1417,16 +1418,11 @@ class Imported_Wallet(Abstract_Wallet):
def add_input_sig_info(self, txin, address): def add_input_sig_info(self, txin, address):
addrtype, hash160 = bc_address_to_hash_160(address) addrtype, hash160 = bc_address_to_hash_160(address)
if six.PY3:
x_pubkey = 'fd' + bh2u(bytes([addrtype]) + hash160) x_pubkey = 'fd' + bh2u(bytes([addrtype]) + hash160)
else:
x_pubkey = 'fd' + bh2u(chr(addrtype) + hash160)
txin['x_pubkeys'] = [x_pubkey] txin['x_pubkeys'] = [x_pubkey]
txin['signatures'] = [None] txin['signatures'] = [None]
class Deterministic_Wallet(Abstract_Wallet): class Deterministic_Wallet(Abstract_Wallet):
def __init__(self, storage): def __init__(self, storage):
@ -1508,7 +1504,7 @@ class Deterministic_Wallet(Abstract_Wallet):
if len(addresses) < limit: if len(addresses) < limit:
self.create_new_address(for_change) self.create_new_address(for_change)
continue continue
if map(lambda a: self.address_is_old(a), addresses[-limit:] ) == limit*[False]: if list(map(lambda a: self.address_is_old(a), addresses[-limit:] )) == limit*[False]:
break break
else: else:
self.create_new_address(for_change) self.create_new_address(for_change)
@ -1521,7 +1517,7 @@ class Deterministic_Wallet(Abstract_Wallet):
else: else:
if len(self.receiving_addresses) != len(self.keystore.keypairs): if len(self.receiving_addresses) != len(self.keystore.keypairs):
pubkeys = self.keystore.keypairs.keys() pubkeys = self.keystore.keypairs.keys()
self.receiving_addresses = map(self.pubkeys_to_address, pubkeys) self.receiving_addresses = [self.pubkeys_to_address(i) for i in pubkeys]
self.save_addresses() self.save_addresses()
for addr in self.receiving_addresses: for addr in self.receiving_addresses:
self.add_address(addr) self.add_address(addr)
@ -1652,7 +1648,7 @@ class P2SH:
def pubkeys_to_address(self, pubkey): def pubkeys_to_address(self, pubkey):
redeem_script = self.pubkeys_to_redeem_script(pubkey) redeem_script = self.pubkeys_to_redeem_script(pubkey)
return bitcoin.hash160_to_p2sh(hash_160(redeem_script.decode('hex'))) return bitcoin.hash160_to_p2sh(hash_160(bfh(redeem_script)))
class Standard_Wallet(Simple_Deterministic_Wallet): class Standard_Wallet(Simple_Deterministic_Wallet):
@ -1664,17 +1660,14 @@ class Standard_Wallet(Simple_Deterministic_Wallet):
def pubkeys_to_address(self, pubkey): def pubkeys_to_address(self, pubkey):
if not self.is_segwit: if not self.is_segwit:
return bitcoin.public_key_to_p2pkh(pubkey.decode('hex')) return bitcoin.public_key_to_p2pkh(bfh(pubkey))
elif bitcoin.TESTNET: elif bitcoin.TESTNET:
redeem_script = self.pubkeys_to_redeem_script(pubkey) redeem_script = self.pubkeys_to_redeem_script(pubkey)
return bitcoin.hash160_to_p2sh(hash_160(redeem_script.decode('hex'))) return bitcoin.hash160_to_p2sh(hash_160(bfh(redeem_script)))
else: else:
raise NotImplementedError() raise NotImplementedError()
class Multisig_Wallet(Deterministic_Wallet, P2SH): class Multisig_Wallet(Deterministic_Wallet, P2SH):
# generic m of n # generic m of n
gap_limit = 20 gap_limit = 20

71
lib/x509.py

@ -31,7 +31,7 @@ import six
from datetime import datetime from datetime import datetime
import sys import sys
from . import util from . import util
from .util import profiler, print_error from .util import profiler, print_error, bh2u
import ecdsa import ecdsa
import hashlib import hashlib
@ -74,7 +74,7 @@ class CertificateError(Exception):
# helper functions # helper functions
def bitstr_to_bytestr(s): def bitstr_to_bytestr(s):
if s[0] != '\x00': if s[0] != 0x00:
raise BaseException('no padding') raise BaseException('no padding')
return s[1:] return s[1:]
@ -83,14 +83,13 @@ def bytestr_to_int(s):
i = 0 i = 0
for char in s: for char in s:
i <<= 8 i <<= 8
i |= ord(char) i |= char
return i return i
def decode_OID(s): def decode_OID(s):
s = map(ord, s)
r = [] r = []
r.append(s[0] / 40) r.append(s[0] // 40)
r.append(s[0] % 40) r.append(s[0] % 40)
k = 0 k = 0
for i in s[1:]: for i in s[1:]:
@ -103,7 +102,7 @@ def decode_OID(s):
def encode_OID(oid): def encode_OID(oid):
x = map(int, oid.split('.')) x = [int(i) for i in oid.split('.')]
s = chr(x[0] * 40 + x[1]) s = chr(x[0] * 40 + x[1])
for i in x[2:]: for i in x[2:]:
ss = chr(i % 128) ss = chr(i % 128)
@ -114,11 +113,11 @@ def encode_OID(oid):
return s return s
class ASN1_Node(str): class ASN1_Node(bytes):
def get_node(self, ix): def get_node(self, ix):
# return index of first byte, first content byte and last byte. # return index of first byte, first content byte and last byte.
first = ord(self[ix + 1]) first = self[ix + 1]
if (ord(self[ix + 1]) & 0x80) == 0: if (self[ix + 1] & 0x80) == 0:
length = first length = first
ixf = ix + 2 ixf = ix + 2
ixl = ixf + length - 1 ixl = ixf + length - 1
@ -129,49 +128,41 @@ class ASN1_Node(str):
ixl = ixf + length - 1 ixl = ixf + length - 1
return ix, ixf, ixl return ix, ixf, ixl
def root(self):
def root(self):
return self.get_node(0) return self.get_node(0)
def next_node(self, node):
def next_node(self, node):
ixs, ixf, ixl = node ixs, ixf, ixl = node
return self.get_node(ixl + 1) return self.get_node(ixl + 1)
def first_child(self, node):
def first_child(self, node):
ixs, ixf, ixl = node ixs, ixf, ixl = node
if ord(self[ixs]) & 0x20 != 0x20: if self[ixs] & 0x20 != 0x20:
raise BaseException('Can only open constructed types.', hex(ord(self[ixs]))) raise BaseException('Can only open constructed types.', hex(self[ixs]))
return self.get_node(ixf) return self.get_node(ixf)
def is_child_of(node1, node2):
def is_child_of(node1, node2):
ixs, ixf, ixl = node1 ixs, ixf, ixl = node1
jxs, jxf, jxl = node2 jxs, jxf, jxl = node2
return ((ixf <= jxs) and (jxl <= ixl)) or ((jxf <= ixs) and (ixl <= jxl)) return ((ixf <= jxs) and (jxl <= ixl)) or ((jxf <= ixs) and (ixl <= jxl))
def get_all(self, node):
def get_all(self, node):
# return type + length + value # return type + length + value
ixs, ixf, ixl = node ixs, ixf, ixl = node
return self[ixs:ixl + 1] return self[ixs:ixl + 1]
def get_value_of_type(self, node, asn1_type):
def get_value_of_type(self, node, asn1_type):
# verify type byte and return content # verify type byte and return content
ixs, ixf, ixl = node ixs, ixf, ixl = node
if ASN1_TYPES[asn1_type] != ord(self[ixs]): if ASN1_TYPES[asn1_type] != self[ixs]:
raise BaseException('Wrong type:', hex(ord(self[ixs])), hex(ASN1_TYPES[asn1_type])) raise BaseException('Wrong type:', hex(self[ixs]), hex(ASN1_TYPES[asn1_type]))
return self[ixf:ixl + 1] return self[ixf:ixl + 1]
def get_value(self, node):
def get_value(self, node):
ixs, ixf, ixl = node ixs, ixf, ixl = node
return self[ixf:ixl + 1] return self[ixf:ixl + 1]
def get_children(self, node):
def get_children(self, node):
nodes = [] nodes = []
ii = self.first_child(node) ii = self.first_child(node)
nodes.append(ii) nodes.append(ii)
@ -180,12 +171,10 @@ def get_children(self, node):
nodes.append(ii) nodes.append(ii)
return nodes return nodes
def get_sequence(self):
return list(map(lambda j: self.get_value(j), self.get_children(self.root())))
def get_sequence(self): def get_dict(self, node):
return map(lambda j: self.get_value(j), self.get_children(self.root()))
def get_dict(self, node):
p = {} p = {}
for ii in self.get_children(node): for ii in self.get_children(node):
for iii in self.get_children(ii): for iii in self.get_children(ii):
@ -202,14 +191,14 @@ class X509(object):
self.bytes = bytearray(b) self.bytes = bytearray(b)
der = ASN1_Node(str(b)) der = ASN1_Node(b)
root = der.root() root = der.root()
cert = der.first_child(root) cert = der.first_child(root)
# data for signature # data for signature
self.data = der.get_all(cert) self.data = der.get_all(cert)
# optional version field # optional version field
if der.get_value(cert)[0] == chr(0xa0): if der.get_value(cert)[0] == 0xa0:
version = der.first_child(cert) version = der.first_child(cert)
serial_number = der.next_node(version) serial_number = der.next_node(version)
else: else:
@ -269,10 +258,10 @@ class X509(object):
# Subject Key Identifier # Subject Key Identifier
r = value.root() r = value.root()
value = value.get_value_of_type(r, 'OCTET STRING') value = value.get_value_of_type(r, 'OCTET STRING')
self.SKI = value.encode('hex') self.SKI = bh2u(value)
elif oid == '2.5.29.35': elif oid == '2.5.29.35':
# Authority Key Identifier # Authority Key Identifier
self.AKI = value.get_sequence()[0].encode('hex') self.AKI = bh2u(value.get_sequence()[0])
else: else:
pass pass
@ -303,8 +292,8 @@ class X509(object):
import time import time
now = time.time() now = time.time()
TIMESTAMP_FMT = '%y%m%d%H%M%SZ' TIMESTAMP_FMT = '%y%m%d%H%M%SZ'
not_before = time.mktime(time.strptime(self.notBefore, TIMESTAMP_FMT)) not_before = time.mktime(time.strptime(self.notBefore.decode('ascii'), TIMESTAMP_FMT))
not_after = time.mktime(time.strptime(self.notAfter, TIMESTAMP_FMT)) not_after = time.mktime(time.strptime(self.notAfter.decode('ascii'), TIMESTAMP_FMT))
if not_before > now: 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: if not_after <= now:
@ -320,7 +309,7 @@ def load_certificates(ca_path):
ca_list = {} ca_list = {}
ca_keyID = {} ca_keyID = {}
with open(ca_path, 'rb') as f: with open(ca_path, 'rb') as f:
s = f.read().decode('utf8') s = f.read().decode('ascii')
bList = pem.dePemList(s, "CERTIFICATE") bList = pem.dePemList(s, "CERTIFICATE")
for b in bList: for b in bList:
try: try:

Loading…
Cancel
Save