wallet recovery: use static methods
This commit is contained in:
parent
0524e5ddd1
commit
7f30573027
|
@ -60,16 +60,23 @@ if __name__ == '__main__':
|
||||||
import gui
|
import gui
|
||||||
|
|
||||||
interface.get_servers()
|
interface.get_servers()
|
||||||
|
gui = gui.ElectrumGui(wallet)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
found = wallet.read()
|
found = wallet.read()
|
||||||
if not found:
|
if not found:
|
||||||
gui.restore_create_dialog(wallet)
|
found = gui.restore_or_create()
|
||||||
except BaseException, e:
|
except BaseException, e:
|
||||||
gui.show_message(e.message)
|
import traceback
|
||||||
|
traceback.print_exc(file=sys.stdout)
|
||||||
|
#gui.show_message(e.message)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
gui = gui.BitcoinGUI(wallet)
|
if not found: exit(1)
|
||||||
|
|
||||||
interface.start(wallet)
|
interface.start(wallet)
|
||||||
|
gui.main()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
if re.match('^bitcoin:', cmd):
|
if re.match('^bitcoin:', cmd):
|
||||||
|
|
||||||
|
|
|
@ -88,8 +88,8 @@ def restore_create_dialog(wallet):
|
||||||
dialog.show()
|
dialog.show()
|
||||||
r = dialog.run()
|
r = dialog.run()
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
if r==2:
|
|
||||||
sys.exit(1)
|
if r==2: return False
|
||||||
|
|
||||||
is_recovery = (r==1)
|
is_recovery = (r==1)
|
||||||
|
|
||||||
|
@ -108,7 +108,6 @@ def restore_create_dialog(wallet):
|
||||||
|
|
||||||
#ask for password
|
#ask for password
|
||||||
change_password_dialog(wallet, None, None)
|
change_password_dialog(wallet, None, None)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# ask for the server.
|
# ask for the server.
|
||||||
run_network_dialog( wallet, parent=None )
|
run_network_dialog( wallet, parent=None )
|
||||||
|
@ -132,7 +131,6 @@ def restore_create_dialog(wallet):
|
||||||
wallet.update_tx_history()
|
wallet.update_tx_history()
|
||||||
wallet.fill_addressbook()
|
wallet.fill_addressbook()
|
||||||
print "recovery successful"
|
print "recovery successful"
|
||||||
wallet.save()
|
|
||||||
|
|
||||||
gobject.idle_add( dialog.destroy )
|
gobject.idle_add( dialog.destroy )
|
||||||
|
|
||||||
|
@ -143,6 +141,9 @@ def restore_create_dialog(wallet):
|
||||||
if not wallet.is_found:
|
if not wallet.is_found:
|
||||||
show_message("No transactions found for this seed")
|
show_message("No transactions found for this seed")
|
||||||
|
|
||||||
|
wallet.save()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def run_recovery_dialog(wallet):
|
def run_recovery_dialog(wallet):
|
||||||
message = "Please enter your wallet seed or the corresponding mnemonic list of words, and the gap limit of your wallet."
|
message = "Please enter your wallet seed or the corresponding mnemonic list of words, and the gap limit of your wallet."
|
||||||
|
@ -215,7 +216,7 @@ def run_recovery_dialog(wallet):
|
||||||
|
|
||||||
def run_settings_dialog(wallet, parent):
|
def run_settings_dialog(wallet, parent):
|
||||||
|
|
||||||
message = "These are the settings of your wallet. For more explanations, click on the question mark buttons next to each input field."
|
message = "Here are the settings of your wallet. For more explanations, click on the question mark buttons next to each input field."
|
||||||
|
|
||||||
dialog = gtk.MessageDialog(
|
dialog = gtk.MessageDialog(
|
||||||
parent = parent,
|
parent = parent,
|
||||||
|
@ -461,7 +462,7 @@ gtk.binding_entry_add_signal(MyWindow, gtk.keysyms.W, gtk.gdk.CONTROL_MASK, 'myk
|
||||||
gtk.binding_entry_add_signal(MyWindow, gtk.keysyms.Q, gtk.gdk.CONTROL_MASK, 'mykeypress', str, 'ctrl+Q')
|
gtk.binding_entry_add_signal(MyWindow, gtk.keysyms.Q, gtk.gdk.CONTROL_MASK, 'mykeypress', str, 'ctrl+Q')
|
||||||
|
|
||||||
|
|
||||||
class BitcoinGUI:
|
class ElectrumWindow:
|
||||||
|
|
||||||
def show_message(self, msg):
|
def show_message(self, msg):
|
||||||
show_message(msg, self.window)
|
show_message(msg, self.window)
|
||||||
|
@ -567,7 +568,7 @@ class BitcoinGUI:
|
||||||
r = r.strip()
|
r = r.strip()
|
||||||
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', r):
|
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', r):
|
||||||
try:
|
try:
|
||||||
to_address = self.get_alias(r, interactive=False)
|
to_address = self.wallet.get_alias(r, interactive=False)
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
if to_address:
|
if to_address:
|
||||||
|
@ -699,7 +700,7 @@ class BitcoinGUI:
|
||||||
|
|
||||||
if signature:
|
if signature:
|
||||||
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', identity):
|
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', identity):
|
||||||
signing_address = self.get_alias(identity, interactive = True)
|
signing_address = self.wallet.get_alias(identity, True, self.show_message, self.question)
|
||||||
elif self.wallet.is_valid(identity):
|
elif self.wallet.is_valid(identity):
|
||||||
signing_address = identity
|
signing_address = identity
|
||||||
else:
|
else:
|
||||||
|
@ -717,7 +718,7 @@ class BitcoinGUI:
|
||||||
#if label and payto:
|
#if label and payto:
|
||||||
# self.labels[payto] = label
|
# self.labels[payto] = label
|
||||||
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', payto):
|
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', payto):
|
||||||
payto_address = self.get_alias(payto, interactive=True)
|
payto_address = self.wallet.get_alias(payto, True, self.show_message, self.question)
|
||||||
if payto_address:
|
if payto_address:
|
||||||
payto = payto + ' <' + payto_address + '>'
|
payto = payto + ' <' + payto_address + '>'
|
||||||
|
|
||||||
|
@ -757,46 +758,6 @@ class BitcoinGUI:
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
return result == gtk.RESPONSE_OK
|
return result == gtk.RESPONSE_OK
|
||||||
|
|
||||||
def get_alias(self, alias, interactive = False):
|
|
||||||
try:
|
|
||||||
target, signing_address, auth_name = self.wallet.read_alias(alias)
|
|
||||||
except BaseException, e:
|
|
||||||
# raise exception if verify fails (verify the chain)
|
|
||||||
if interactive:
|
|
||||||
self.show_message("Alias error: " + e.message)
|
|
||||||
return
|
|
||||||
|
|
||||||
print target, signing_address, auth_name
|
|
||||||
|
|
||||||
if auth_name is None:
|
|
||||||
a = self.wallet.aliases.get(alias)
|
|
||||||
if not a:
|
|
||||||
msg = "Warning: the alias '%s' is self-signed.\nThe signing address is %s.\n\nDo you want to add this alias to your list of contacts?"%(alias,signing_address)
|
|
||||||
if interactive and self.question( msg ):
|
|
||||||
self.wallet.aliases[alias] = (signing_address, target)
|
|
||||||
else:
|
|
||||||
target = None
|
|
||||||
else:
|
|
||||||
if signing_address != a[0]:
|
|
||||||
msg = "Warning: the key of alias '%s' has changed since your last visit! It is possible that someone is trying to do something nasty!!!\nDo you accept to change your trusted key?"%alias
|
|
||||||
if interactive and self.question( msg ):
|
|
||||||
self.wallet.aliases[alias] = (signing_address, target)
|
|
||||||
else:
|
|
||||||
target = None
|
|
||||||
else:
|
|
||||||
if signing_address not in self.wallet.authorities.keys():
|
|
||||||
msg = "The alias: '%s' links to %s\n\nWarning: this alias was signed by an unknown key.\nSigning authority: %s\nSigning address: %s\n\nDo you want to add this key to your list of trusted keys?"%(alias,target,auth_name,signing_address)
|
|
||||||
if interactive and self.question( msg ):
|
|
||||||
self.wallet.authorities[signing_address] = auth_name
|
|
||||||
else:
|
|
||||||
target = None
|
|
||||||
|
|
||||||
if target:
|
|
||||||
self.wallet.aliases[alias] = (signing_address, target)
|
|
||||||
self.update_sending_tab()
|
|
||||||
|
|
||||||
|
|
||||||
return target
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -810,9 +771,12 @@ class BitcoinGUI:
|
||||||
m2 = re.match('(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+) \<([1-9A-HJ-NP-Za-km-z]{26,})\>', r)
|
m2 = re.match('(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+) \<([1-9A-HJ-NP-Za-km-z]{26,})\>', r)
|
||||||
|
|
||||||
if m1:
|
if m1:
|
||||||
to_address = self.get_alias(r, interactive = True)
|
to_address = self.wallet.get_alias(r, True, self.show_message, self.question)
|
||||||
if not to_address:
|
if not to_address:
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
self.update_sending_tab()
|
||||||
|
|
||||||
elif m2:
|
elif m2:
|
||||||
to_address = m2.group(5)
|
to_address = m2.group(5)
|
||||||
else:
|
else:
|
||||||
|
@ -1258,6 +1222,15 @@ class BitcoinGUI:
|
||||||
errorDialog.destroy()
|
errorDialog.destroy()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ElectrumGui():
|
||||||
|
|
||||||
|
def __init__(self, wallet):
|
||||||
|
self.wallet = wallet
|
||||||
|
|
||||||
def main(self):
|
def main(self):
|
||||||
|
ElectrumWindow(self.wallet)
|
||||||
gtk.main()
|
gtk.main()
|
||||||
|
|
||||||
|
def restore_or_create(self):
|
||||||
|
return restore_create_dialog(self.wallet)
|
||||||
|
|
200
client/gui_qt.py
200
client/gui_qt.py
|
@ -10,8 +10,10 @@ import PyQt4.QtGui as QtGui
|
||||||
from wallet import format_satoshis
|
from wallet import format_satoshis
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
def restore_create_dialog(wallet):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Sender(QtCore.QThread):
|
class Sender(QtCore.QThread):
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -33,6 +35,18 @@ class StatusBarButton(QPushButton):
|
||||||
apply(self.func,())
|
apply(self.func,())
|
||||||
|
|
||||||
|
|
||||||
|
def ok_cancel_buttons(dialog):
|
||||||
|
hbox = QHBoxLayout()
|
||||||
|
hbox.addStretch(1)
|
||||||
|
b = QPushButton("OK")
|
||||||
|
hbox.addWidget(b)
|
||||||
|
b.clicked.connect(dialog.accept)
|
||||||
|
b = QPushButton("Cancel")
|
||||||
|
hbox.addWidget(b)
|
||||||
|
b.clicked.connect(dialog.reject)
|
||||||
|
return hbox
|
||||||
|
|
||||||
|
|
||||||
class ElectrumWindow(QMainWindow):
|
class ElectrumWindow(QMainWindow):
|
||||||
|
|
||||||
def __init__(self, wallet):
|
def __init__(self, wallet):
|
||||||
|
@ -58,16 +72,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
QShortcut(QKeySequence("Ctrl+PgUp"), self, lambda: tabs.setCurrentIndex( (tabs.currentIndex() - 1 )%tabs.count() ))
|
QShortcut(QKeySequence("Ctrl+PgUp"), self, lambda: tabs.setCurrentIndex( (tabs.currentIndex() - 1 )%tabs.count() ))
|
||||||
QShortcut(QKeySequence("Ctrl+PgDown"), self, lambda: tabs.setCurrentIndex( (tabs.currentIndex() + 1 )%tabs.count() ))
|
QShortcut(QKeySequence("Ctrl+PgDown"), self, lambda: tabs.setCurrentIndex( (tabs.currentIndex() + 1 )%tabs.count() ))
|
||||||
|
|
||||||
def ok_cancel_buttons(self,d):
|
|
||||||
hbox = QHBoxLayout()
|
|
||||||
hbox.addStretch(1)
|
|
||||||
b = QPushButton("OK")
|
|
||||||
hbox.addWidget(b)
|
|
||||||
b.clicked.connect(d.accept)
|
|
||||||
b = QPushButton("Cancel")
|
|
||||||
hbox.addWidget(b)
|
|
||||||
b.clicked.connect(d.reject)
|
|
||||||
return hbox
|
|
||||||
|
|
||||||
def connect_slots(self, sender):
|
def connect_slots(self, sender):
|
||||||
self.connect(sender, QtCore.SIGNAL('testsignal'), self.update_wallet)
|
self.connect(sender, QtCore.SIGNAL('testsignal'), self.update_wallet)
|
||||||
|
@ -272,7 +277,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
m2 = re.match('(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+) \<([1-9A-HJ-NP-Za-km-z]{26,})\>', r)
|
m2 = re.match('(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+) \<([1-9A-HJ-NP-Za-km-z]{26,})\>', r)
|
||||||
|
|
||||||
if m1:
|
if m1:
|
||||||
to_address = self.get_alias(r, interactive = True)
|
to_address = self.wallet.get_alias(r, True, self.show_message, self.question)
|
||||||
if not to_address:
|
if not to_address:
|
||||||
return
|
return
|
||||||
elif m2:
|
elif m2:
|
||||||
|
@ -439,10 +444,10 @@ class ElectrumWindow(QMainWindow):
|
||||||
def create_status_bar(self):
|
def create_status_bar(self):
|
||||||
sb = QStatusBar()
|
sb = QStatusBar()
|
||||||
sb.setFixedHeight(35)
|
sb.setFixedHeight(35)
|
||||||
sb.addPermanentWidget( StatusBarButton( QIcon("icons/lock.svg"), "Password", self.change_password_dialog ) )
|
sb.addPermanentWidget( StatusBarButton( QIcon("icons/lock.svg"), "Password", lambda: self.change_password_dialog(self.wallet, self) ) )
|
||||||
sb.addPermanentWidget( StatusBarButton( QIcon("icons/preferences.png"), "Preferences", self.settings_dialog ) )
|
sb.addPermanentWidget( StatusBarButton( QIcon("icons/preferences.png"), "Preferences", self.settings_dialog ) )
|
||||||
sb.addPermanentWidget( StatusBarButton( QIcon("icons/seed.png"), "Seed", self.show_seed_dialog ) )
|
sb.addPermanentWidget( StatusBarButton( QIcon("icons/seed.png"), "Seed", lambda: self.show_seed_dialog(self.wallet, self) ) )
|
||||||
self.status_button = StatusBarButton( QIcon("icons/status_disconnected.png"), "Network", self.network_dialog )
|
self.status_button = StatusBarButton( QIcon("icons/status_disconnected.png"), "Network", lambda: self.network_dialog(self.wallet, self) )
|
||||||
sb.addPermanentWidget( self.status_button )
|
sb.addPermanentWidget( self.status_button )
|
||||||
self.setStatusBar(sb)
|
self.setStatusBar(sb)
|
||||||
|
|
||||||
|
@ -458,18 +463,19 @@ class ElectrumWindow(QMainWindow):
|
||||||
else:
|
else:
|
||||||
QMessageBox.warning(self, 'Error', 'Invalid Address', 'OK')
|
QMessageBox.warning(self, 'Error', 'Invalid Address', 'OK')
|
||||||
|
|
||||||
def show_seed_dialog(self):
|
@staticmethod
|
||||||
|
def show_seed_dialog(wallet, parent=None):
|
||||||
import mnemonic
|
import mnemonic
|
||||||
if self.wallet.use_encryption:
|
if wallet.use_encryption:
|
||||||
password = self.password_dialog()
|
password = self.password_dialog()
|
||||||
if not password: return
|
if not password: return
|
||||||
else:
|
else:
|
||||||
password = None
|
password = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
seed = self.wallet.pw_decode( self.wallet.seed, password)
|
seed = wallet.pw_decode( wallet.seed, password)
|
||||||
except:
|
except:
|
||||||
QMessageBox.warning(self, 'Error', 'Invalid Password', 'OK')
|
QMessageBox.warning(parent, 'Error', 'Invalid Password', 'OK')
|
||||||
return
|
return
|
||||||
|
|
||||||
msg = "Your wallet generation seed is:\n\n" + seed \
|
msg = "Your wallet generation seed is:\n\n" + seed \
|
||||||
|
@ -477,11 +483,17 @@ class ElectrumWindow(QMainWindow):
|
||||||
+ "Equivalently, your wallet seed can be stored and recovered with the following mnemonic code:\n\n\"" \
|
+ "Equivalently, your wallet seed can be stored and recovered with the following mnemonic code:\n\n\"" \
|
||||||
+ ' '.join(mnemonic.mn_encode(seed)) + "\""
|
+ ' '.join(mnemonic.mn_encode(seed)) + "\""
|
||||||
|
|
||||||
QMessageBox.information(self, 'Seed', msg, 'OK')
|
QMessageBox.information(parent, 'Seed', msg, 'OK')
|
||||||
|
|
||||||
|
def question(self, msg):
|
||||||
|
return QMessageBox.question(self, 'Message', msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
|
||||||
|
|
||||||
def password_dialog(self):
|
def show_message(self, msg):
|
||||||
d = QDialog(self)
|
QMessageBox.information(self, 'Message', msg, 'OK')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def password_dialog( parent=None ):
|
||||||
|
d = QDialog(parent)
|
||||||
d.setModal(1)
|
d.setModal(1)
|
||||||
|
|
||||||
pw = QLineEdit()
|
pw = QLineEdit()
|
||||||
|
@ -497,14 +509,15 @@ class ElectrumWindow(QMainWindow):
|
||||||
grid.addWidget(pw, 1, 1)
|
grid.addWidget(pw, 1, 1)
|
||||||
vbox.addLayout(grid)
|
vbox.addLayout(grid)
|
||||||
|
|
||||||
vbox.addLayout(self.ok_cancel_buttons(d))
|
vbox.addLayout(ok_cancel_buttons(d))
|
||||||
d.setLayout(vbox)
|
d.setLayout(vbox)
|
||||||
|
|
||||||
if not d.exec_(): return
|
if not d.exec_(): return
|
||||||
return str(pw.text())
|
return str(pw.text())
|
||||||
|
|
||||||
def change_password_dialog(self):
|
@staticmethod
|
||||||
d = QDialog(self)
|
def change_password_dialog( wallet, parent=None ):
|
||||||
|
d = QDialog(parent)
|
||||||
d.setModal(1)
|
d.setModal(1)
|
||||||
|
|
||||||
pw = QLineEdit()
|
pw = QLineEdit()
|
||||||
|
@ -515,13 +528,13 @@ class ElectrumWindow(QMainWindow):
|
||||||
conf_pw.setEchoMode(2)
|
conf_pw.setEchoMode(2)
|
||||||
|
|
||||||
vbox = QVBoxLayout()
|
vbox = QVBoxLayout()
|
||||||
msg = 'Your wallet is encrypted. Use this dialog to change your password.\nTo disable wallet encryption, enter an empty new password.' if self.wallet.use_encryption else 'Your wallet keys are not encrypted'
|
msg = 'Your wallet is encrypted. Use this dialog to change your password.\nTo disable wallet encryption, enter an empty new password.' if wallet.use_encryption else 'Your wallet keys are not encrypted'
|
||||||
vbox.addWidget(QLabel(msg))
|
vbox.addWidget(QLabel(msg))
|
||||||
|
|
||||||
grid = QGridLayout()
|
grid = QGridLayout()
|
||||||
grid.setSpacing(8)
|
grid.setSpacing(8)
|
||||||
|
|
||||||
if self.wallet.use_encryption:
|
if wallet.use_encryption:
|
||||||
grid.addWidget(QLabel('Password'), 1, 0)
|
grid.addWidget(QLabel('Password'), 1, 0)
|
||||||
grid.addWidget(pw, 1, 1)
|
grid.addWidget(pw, 1, 1)
|
||||||
|
|
||||||
|
@ -532,26 +545,76 @@ class ElectrumWindow(QMainWindow):
|
||||||
grid.addWidget(conf_pw, 3, 1)
|
grid.addWidget(conf_pw, 3, 1)
|
||||||
vbox.addLayout(grid)
|
vbox.addLayout(grid)
|
||||||
|
|
||||||
vbox.addLayout(self.ok_cancel_buttons(d))
|
vbox.addLayout(ok_cancel_buttons(d))
|
||||||
d.setLayout(vbox)
|
d.setLayout(vbox)
|
||||||
|
|
||||||
if not d.exec_(): return
|
if not d.exec_(): return
|
||||||
|
|
||||||
password = str(pw.text()) if self.wallet.use_encryption else None
|
password = str(pw.text()) if wallet.use_encryption else None
|
||||||
new_password = str(new_pw.text())
|
new_password = str(new_pw.text())
|
||||||
new_password2 = str(conf_pw.text())
|
new_password2 = str(conf_pw.text())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
seed = self.wallet.pw_decode( self.wallet.seed, password)
|
seed = wallet.pw_decode( wallet.seed, password)
|
||||||
except:
|
except:
|
||||||
QMessageBox.warning(self, 'Error', 'Incorrect Password', 'OK')
|
QMessageBox.warning(parent, 'Error', 'Incorrect Password', 'OK')
|
||||||
return
|
return
|
||||||
|
|
||||||
if new_password != new_password2:
|
if new_password != new_password2:
|
||||||
QMessageBox.warning(self, 'Error', 'Passwords do not match', 'OK')
|
QMessageBox.warning(parent, 'Error', 'Passwords do not match', 'OK')
|
||||||
return
|
return
|
||||||
|
|
||||||
self.wallet.update_password(seed, new_password)
|
wallet.update_password(seed, new_password)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def seed_dialog(wallet, parent=None):
|
||||||
|
d = QDialog(parent)
|
||||||
|
d.setModal(1)
|
||||||
|
|
||||||
|
vbox = QVBoxLayout()
|
||||||
|
msg = "Please enter your wallet seed or the corresponding mnemonic list of words, and the gap limit of your wallet."
|
||||||
|
vbox.addWidget(QLabel(msg))
|
||||||
|
|
||||||
|
grid = QGridLayout()
|
||||||
|
grid.setSpacing(8)
|
||||||
|
|
||||||
|
seed_e = QLineEdit()
|
||||||
|
grid.addWidget(QLabel('Seed or mnemonic'), 1, 0)
|
||||||
|
grid.addWidget(seed_e, 1, 1)
|
||||||
|
|
||||||
|
gap_e = QLineEdit()
|
||||||
|
gap_e.setText("5")
|
||||||
|
grid.addWidget(QLabel('Gap limit'), 2, 0)
|
||||||
|
grid.addWidget(gap_e, 2, 1)
|
||||||
|
|
||||||
|
vbox.addLayout(grid)
|
||||||
|
|
||||||
|
vbox.addLayout(ok_cancel_buttons(d))
|
||||||
|
d.setLayout(vbox)
|
||||||
|
|
||||||
|
if not d.exec_(): return
|
||||||
|
|
||||||
|
try:
|
||||||
|
gap = int(str(gap_e.text()))
|
||||||
|
except:
|
||||||
|
show_message("error")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
seed = str(seed_e.text())
|
||||||
|
seed.decode('hex')
|
||||||
|
except:
|
||||||
|
import mnemonic
|
||||||
|
print "not hex, trying decode"
|
||||||
|
seed = mnemonic.mn_decode( seed.split(' ') )
|
||||||
|
if not seed:
|
||||||
|
show_message("no seed")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
wallet.seed = seed
|
||||||
|
wallet.gap_limit = gap
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def settings_dialog(self):
|
def settings_dialog(self):
|
||||||
d = QDialog(self)
|
d = QDialog(self)
|
||||||
|
@ -559,7 +622,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
|
|
||||||
vbox = QVBoxLayout()
|
vbox = QVBoxLayout()
|
||||||
|
|
||||||
msg = 'These are the settings of your wallet'
|
msg = 'Here are the settings of your wallet'
|
||||||
vbox.addWidget(QLabel(msg))
|
vbox.addWidget(QLabel(msg))
|
||||||
|
|
||||||
grid = QGridLayout()
|
grid = QGridLayout()
|
||||||
|
@ -571,7 +634,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
grid.addWidget(fee_line, 2, 1)
|
grid.addWidget(fee_line, 2, 1)
|
||||||
vbox.addLayout(grid)
|
vbox.addLayout(grid)
|
||||||
|
|
||||||
vbox.addLayout(self.ok_cancel_buttons(d))
|
vbox.addLayout(ok_cancel_buttons(d))
|
||||||
d.setLayout(vbox)
|
d.setLayout(vbox)
|
||||||
|
|
||||||
if not d.exec_(): return
|
if not d.exec_(): return
|
||||||
|
@ -586,8 +649,9 @@ class ElectrumWindow(QMainWindow):
|
||||||
self.wallet.fee = fee
|
self.wallet.fee = fee
|
||||||
self.wallet.save()
|
self.wallet.save()
|
||||||
|
|
||||||
def network_dialog(self):
|
@staticmethod
|
||||||
wallet = self.wallet
|
def network_dialog(wallet, parent=None):
|
||||||
|
|
||||||
if True:
|
if True:
|
||||||
if wallet.interface.is_connected:
|
if wallet.interface.is_connected:
|
||||||
status = "Connected to %s.\n%d blocks\nresponse time: %f"%(wallet.interface.host, wallet.interface.blocks, wallet.interface.rtime)
|
status = "Connected to %s.\n%d blocks\nresponse time: %f"%(wallet.interface.host, wallet.interface.blocks, wallet.interface.rtime)
|
||||||
|
@ -601,7 +665,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
host = random.choice( wallet.interface.servers )
|
host = random.choice( wallet.interface.servers )
|
||||||
port = 50000
|
port = 50000
|
||||||
|
|
||||||
d = QDialog(self)
|
d = QDialog(parent)
|
||||||
d.setModal(1)
|
d.setModal(1)
|
||||||
|
|
||||||
vbox = QVBoxLayout()
|
vbox = QVBoxLayout()
|
||||||
|
@ -615,7 +679,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
grid.addWidget(host_line, 2, 1)
|
grid.addWidget(host_line, 2, 1)
|
||||||
vbox.addLayout(grid)
|
vbox.addLayout(grid)
|
||||||
|
|
||||||
vbox.addLayout(self.ok_cancel_buttons(d))
|
vbox.addLayout(ok_cancel_buttons(d))
|
||||||
d.setLayout(vbox)
|
d.setLayout(vbox)
|
||||||
|
|
||||||
if not d.exec_(): return
|
if not d.exec_(): return
|
||||||
|
@ -636,23 +700,65 @@ class ElectrumWindow(QMainWindow):
|
||||||
return
|
return
|
||||||
|
|
||||||
wallet.interface.set_server(host, port)
|
wallet.interface.set_server(host, port)
|
||||||
|
return True
|
||||||
if parent:
|
|
||||||
wallet.save()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BitcoinGUI():
|
class ElectrumGui():
|
||||||
|
|
||||||
def __init__(self, wallet):
|
def __init__(self, wallet):
|
||||||
self.wallet = wallet
|
self.wallet = wallet
|
||||||
|
self.app = QApplication(sys.argv)
|
||||||
|
|
||||||
|
def restore_or_create(self):
|
||||||
|
|
||||||
|
msg = "Wallet file not found.\nDo you want to create a new wallet,\n or to restore an existing one?"
|
||||||
|
r = QMessageBox.question(None, 'Message', msg, 'create', 'restore', 'cancel', 0, 2)
|
||||||
|
if r==2: return False
|
||||||
|
|
||||||
|
is_recovery = (r==1)
|
||||||
|
wallet = self.wallet
|
||||||
|
if not is_recovery:
|
||||||
|
wallet.new_seed(None)
|
||||||
|
# ask for the server.
|
||||||
|
ElectrumWindow.network_dialog(wallet)
|
||||||
|
# generate first key
|
||||||
|
wallet.synchronize()
|
||||||
|
# run a dialog indicating the seed, ask the user to remember it
|
||||||
|
ElectrumWindow.show_seed_dialog(wallet)
|
||||||
|
#ask for password
|
||||||
|
ElectrumWindow.change_password_dialog(wallet)
|
||||||
|
else:
|
||||||
|
# ask for the server.
|
||||||
|
r = ElectrumWindow.network_dialog( wallet, parent=None )
|
||||||
|
if not r: return False
|
||||||
|
# ask for seed and gap.
|
||||||
|
r = ElectrumWindow.seed_dialog( wallet )
|
||||||
|
if not r: return False
|
||||||
|
|
||||||
|
wallet.init_mpk( wallet.seed ) # not encrypted at this point
|
||||||
|
wallet.synchronize()
|
||||||
|
|
||||||
|
if wallet.is_found():
|
||||||
|
# history and addressbook
|
||||||
|
wallet.update_tx_history()
|
||||||
|
wallet.fill_addressbook()
|
||||||
|
print "recovery successful"
|
||||||
|
wallet.save()
|
||||||
|
else:
|
||||||
|
QMessageBox.information(None, 'Message', "No transactions found for this seed", 'OK')
|
||||||
|
|
||||||
|
wallet.save()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main(self):
|
def main(self):
|
||||||
|
|
||||||
s = Sender()
|
s = Sender()
|
||||||
s.start()
|
s.start()
|
||||||
app = QApplication(sys.argv)
|
|
||||||
w = ElectrumWindow(self.wallet)
|
w = ElectrumWindow(self.wallet)
|
||||||
w.app = app
|
w.app = self.app
|
||||||
w.connect_slots(s)
|
w.connect_slots(s)
|
||||||
app.exec_()
|
self.app.exec_()
|
||||||
|
|
|
@ -769,3 +769,43 @@ class Wallet:
|
||||||
c = self.pw_encode(b, new_password)
|
c = self.pw_encode(b, new_password)
|
||||||
self.imported_keys[k] = c
|
self.imported_keys[k] = c
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
|
||||||
|
def get_alias(self, alias, interactive = False, show_message=None, question = None):
|
||||||
|
try:
|
||||||
|
target, signing_address, auth_name = self.read_alias(alias)
|
||||||
|
except BaseException, e:
|
||||||
|
# raise exception if verify fails (verify the chain)
|
||||||
|
if interactive:
|
||||||
|
show_message("Alias error: " + e.message)
|
||||||
|
return
|
||||||
|
|
||||||
|
print target, signing_address, auth_name
|
||||||
|
|
||||||
|
if auth_name is None:
|
||||||
|
a = self.aliases.get(alias)
|
||||||
|
if not a:
|
||||||
|
msg = "Warning: the alias '%s' is self-signed.\nThe signing address is %s.\n\nDo you want to add this alias to your list of contacts?"%(alias,signing_address)
|
||||||
|
if interactive and question( msg ):
|
||||||
|
self.aliases[alias] = (signing_address, target)
|
||||||
|
else:
|
||||||
|
target = None
|
||||||
|
else:
|
||||||
|
if signing_address != a[0]:
|
||||||
|
msg = "Warning: the key of alias '%s' has changed since your last visit! It is possible that someone is trying to do something nasty!!!\nDo you accept to change your trusted key?"%alias
|
||||||
|
if interactive and question( msg ):
|
||||||
|
self.aliases[alias] = (signing_address, target)
|
||||||
|
else:
|
||||||
|
target = None
|
||||||
|
else:
|
||||||
|
if signing_address not in self.authorities.keys():
|
||||||
|
msg = "The alias: '%s' links to %s\n\nWarning: this alias was signed by an unknown key.\nSigning authority: %s\nSigning address: %s\n\nDo you want to add this key to your list of trusted keys?"%(alias,target,auth_name,signing_address)
|
||||||
|
if interactive and question( msg ):
|
||||||
|
self.authorities[signing_address] = auth_name
|
||||||
|
else:
|
||||||
|
target = None
|
||||||
|
|
||||||
|
if target:
|
||||||
|
self.aliases[alias] = (signing_address, target)
|
||||||
|
|
||||||
|
return target
|
||||||
|
|
Loading…
Reference in New Issue