mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-29 16:31:29 +00:00
py3 in qtgui
This commit is contained in:
parent
5be78950ca
commit
d304ccdf17
28 changed files with 246 additions and 323 deletions
10
electrum
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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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]))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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'):
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
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 to_string(x, enc):
|
||||||
def _bytes(x=None, encoding=None, **kw):
|
|
||||||
"""
|
|
||||||
py2-py3 aware wrapper to "bytes()" like constructor
|
|
||||||
:param x:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if encoding is not None:
|
|
||||||
kw['encoding'] = encoding
|
|
||||||
if x is None:
|
|
||||||
x = []
|
|
||||||
if six.PY3:
|
|
||||||
if isinstance(x, bytes):
|
|
||||||
return x
|
|
||||||
return bytes(x, **kw)
|
|
||||||
else:
|
|
||||||
return bytearray(x, **kw)
|
|
||||||
|
|
||||||
|
|
||||||
def _to_bytes2(x, enc):
|
|
||||||
if isinstance(x, bytearray):
|
|
||||||
return bytearray(x)
|
|
||||||
if isinstance(x, six.text_type):
|
|
||||||
return bytearray(x.encode(enc))
|
|
||||||
elif isinstance(x, six.binary_type):
|
|
||||||
return bytearray(x)
|
|
||||||
else:
|
|
||||||
raise TypeError("Not a string or bytes like object")
|
|
||||||
|
|
||||||
|
|
||||||
def _to_bytes3(x, enc):
|
|
||||||
if isinstance(x, bytes):
|
|
||||||
return x
|
|
||||||
if isinstance(x, str):
|
|
||||||
return x.encode(enc)
|
|
||||||
elif isinstance(x, bytearray):
|
|
||||||
return bytes(x)
|
|
||||||
else:
|
|
||||||
raise TypeError("Not a string or bytes like object")
|
|
||||||
|
|
||||||
|
|
||||||
def _to_string2(x, enc):
|
|
||||||
if isinstance(x, (str, bytes)):
|
|
||||||
return x
|
|
||||||
if isinstance(x, unicode):
|
|
||||||
return x.encode(enc)
|
|
||||||
if isinstance(x, bytearray):
|
|
||||||
return x.decode(enc)
|
|
||||||
else:
|
|
||||||
raise TypeError("Not a string or bytes like object")
|
|
||||||
|
|
||||||
|
|
||||||
def _to_string3(x, enc):
|
|
||||||
if isinstance(x, (bytes, bytearray)):
|
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
|
||||||
|
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'):
|
bfh_builder = lambda x: bytes.fromhex(x)
|
||||||
"""
|
|
||||||
cast string to str object
|
|
||||||
"""
|
|
||||||
raise NotImplementedError("This call should be redefined")
|
|
||||||
|
|
||||||
if six.PY3:
|
|
||||||
to_bytes = _to_bytes3
|
|
||||||
to_string = _to_string3
|
|
||||||
else:
|
|
||||||
to_bytes = _to_bytes2
|
|
||||||
to_string = _to_string2
|
|
||||||
|
|
||||||
if six.PY3:
|
|
||||||
bfh_builder = lambda x: bytes.fromhex(x)
|
|
||||||
else:
|
|
||||||
bfh_builder = lambda x: x.decode('hex') # str(bytearray.fromhex(x))
|
|
||||||
|
|
||||||
|
|
||||||
# def ufh(x):
|
|
||||||
# """
|
|
||||||
# py2-py3 aware wrapper for str.decode('hex')
|
|
||||||
# :param x: str
|
|
||||||
# :return: str
|
|
||||||
# """
|
|
||||||
# if
|
|
||||||
# return binascii.unhexlify(x)
|
|
||||||
|
|
||||||
|
|
||||||
def hfu(x):
|
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):
|
||||||
|
|
|
@ -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
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…
Add table
Reference in a new issue