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