Browse Source

add 2of3 wallets in wizard

283
ThomasV 11 years ago
parent
commit
0fb6cdcb1a
  1. 137
      gui/qt/installwizard.py
  2. 3
      lib/wallet.py

137
gui/qt/installwizard.py

@ -97,15 +97,20 @@ class InstallWizard(QDialog):
bb2.setText(_("Wallet with two-factor authentication (plugin)")) bb2.setText(_("Wallet with two-factor authentication (plugin)"))
bb3 = QRadioButton(gb2) bb3 = QRadioButton(gb2)
bb3.setText(_("Multisig wallet (paired manually)")) bb3.setText(_("Multisig wallet (2 of 2)"))
bb4 = QRadioButton(gb2)
bb4.setText(_("Multisig wallet (2 of 3)"))
grid2.addWidget(bb1, 4, 0) grid2.addWidget(bb1, 4, 0)
grid2.addWidget(bb2, 5, 0) grid2.addWidget(bb2, 5, 0)
grid2.addWidget(bb3, 6, 0) grid2.addWidget(bb3, 6, 0)
grid2.addWidget(bb4, 7, 0)
group2.addButton(bb1) group2.addButton(bb1)
group2.addButton(bb2) group2.addButton(bb2)
group2.addButton(bb3) group2.addButton(bb3)
group2.addButton(bb4)
vbox.addLayout(grid2) vbox.addLayout(grid2)
vbox.addStretch(1) vbox.addStretch(1)
@ -120,9 +125,11 @@ class InstallWizard(QDialog):
if bb1.isChecked(): if bb1.isChecked():
t = 'standard' t = 'standard'
elif bb2.isChecked(): elif bb2.isChecked():
t = 'multisig_plugin' t = '2fa'
elif bb3.isChecked(): elif bb3.isChecked():
t = 'multisig_manual' t = '2of2'
elif bb4.isChecked():
t = '2of3'
return action, t return action, t
@ -187,6 +194,29 @@ class InstallWizard(QDialog):
return self.get_seed_text(seed_e2) return self.get_seed_text(seed_e2)
def cold_mpk2_dialog(self, xpub_hot):
vbox = QVBoxLayout()
vbox0, seed_e0 = seed_dialog.enter_seed_box(MSG_SHOW_MPK, 'hot')
seed_e0.setText(xpub_hot)
seed_e0.setReadOnly(True)
vbox1, seed_e1 = seed_dialog.enter_seed_box(MSG_ENTER_COLD_MPK, 'cold')
vbox2, seed_e2 = seed_dialog.enter_seed_box(MSG_ENTER_COLD_MPK, 'cold')
vbox.addLayout(vbox0)
vbox.addLayout(vbox1)
vbox.addLayout(vbox2)
vbox.addStretch(1)
hbox, button = ok_cancel_buttons2(self, _('Next'))
vbox.addLayout(hbox)
button.setEnabled(False)
f = lambda: button.setEnabled(self.is_mpk(seed_e1) and self.is_mpk(seed_e2))
seed_e1.textChanged.connect(f)
seed_e2.textChanged.connect(f)
self.set_layout(vbox)
if not self.exec_():
return
return self.get_seed_text(seed_e1), self.get_seed_text(seed_e2)
def double_seed_dialog(self): def double_seed_dialog(self):
vbox = QVBoxLayout() vbox = QVBoxLayout()
vbox1, seed_e1 = seed_dialog.enter_seed_box(MSG_ENTER_SEED_OR_MPK, 'hot') vbox1, seed_e1 = seed_dialog.enter_seed_box(MSG_ENTER_SEED_OR_MPK, 'hot')
@ -317,6 +347,30 @@ class InstallWizard(QDialog):
return run_password_dialog(self, None, self)[2] return run_password_dialog(self, None, self)[2]
def create_cold_seed(self, wallet):
from electrum.bitcoin import mnemonic_to_seed, bip32_root
msg = _('You are about to generate the cold storage seed of your wallet.') + '\n' \
+ _('For safety, you should do this on an offline computer.')
icon = QPixmap( ':icons/cold_seed.png').scaledToWidth(56)
if not self.question(msg, icon):
return
cold_seed = wallet.make_seed()
if not self.show_seed(cold_seed, 'cold'):
return
if not self.verify_seed(cold_seed, 'cold'):
return
hex_seed = mnemonic_to_seed(cold_seed,'').encode('hex')
xpriv, xpub = bip32_root(hex_seed)
wallet.add_master_public_key('cold/', xpub)
msg = _('Your master public key was saved in your wallet file.') + '\n'\
+ _('Your cold seed must be stored on paper; it is not in the wallet file.')+ '\n\n' \
+ _('This program is about to close itself.') + '\n'\
+ _('You will need to reopen your wallet on an online computer, in order to complete the creation of your wallet')
self.show_message(msg)
def run(self, action): def run(self, action):
@ -328,59 +382,64 @@ class InstallWizard(QDialog):
return return
if action == 'create': if action == 'create':
if t == 'multisig_plugin': if t == 'standard':
action = 'create_2of3_1' wallet = Wallet(self.storage)
if t == 'multisig_manual':
action = 'create_2of2_1'
if action in ['create']:
wallet = Wallet(self.storage)
elif action in ['create_2of2_1','create_2of2_2']:
wallet = Wallet_2of2(self.storage)
if action == 'create': elif t == '2fa':
seed = wallet.make_seed() wallet = Wallet_2of3(self.storage)
if not self.show_seed(seed, None): run_hook('create_cold_seed', wallet, self)
return self.create_cold_seed(wallet)
if not self.verify_seed(seed, None):
return return
password = self.password_dialog()
wallet.add_seed(seed, password)
wallet.create_accounts(password)
self.waiting_dialog(wallet.synchronize)
elif t == '2of2':
wallet = Wallet_2of2(self.storage)
action = 'create_2of2_1'
elif t == '2of3':
wallet = Wallet_2of3(self.storage)
action = 'create_2of3_1'
if action == 'create_2of3_1':
run_hook('create_cold_seed', self.storage, self)
return
if action == 'create_2fa_2':
wallet = Wallet_2of3(self.storage)
if action in ['create_2of2_1', 'create_2of3_2']: if action in ['create', 'create_2of2_1', 'create_2fa_2', 'create_2of3_1']:
seed = wallet.make_seed() seed = wallet.make_seed()
if not self.show_seed(seed, 'hot'): sid = None if action == 'create' else 'hot'
if not self.show_seed(seed, sid):
return return
if not self.verify_seed(seed, 'hot'): if not self.verify_seed(seed, sid):
return return
password = self.password_dialog() password = self.password_dialog()
wallet.add_seed(seed, password) wallet.add_seed(seed, password)
if action == 'create_2of2_1': if action == 'create':
# display mpk wallet.create_accounts(password)
self.waiting_dialog(wallet.synchronize)
elif action == 'create_2of2_1':
action = 'create_2of2_2' action = 'create_2of2_2'
else: elif action == 'create_2of3_1':
action = 'create_2of3_3' action = 'create_2of3_2'
elif action == 'create_2fa_2':
action = 'create_2fa_3'
if action == 'create_2of2_2': if action == 'create_2of2_2':
xpub_hot = wallet.master_public_keys.get("m/") xpub_hot = wallet.master_public_keys.get("m/")
xpub = self.cold_mpk_dialog(xpub_hot) xpub = self.cold_mpk_dialog(xpub_hot)
if not Wallet.is_mpk(xpub):
return
wallet.add_master_public_key("cold/", xpub) wallet.add_master_public_key("cold/", xpub)
wallet.create_account() wallet.create_account()
self.waiting_dialog(wallet.synchronize) self.waiting_dialog(wallet.synchronize)
if action == 'create_2of3_3': if action == 'create_2of3_2':
xpub_hot = wallet.master_public_keys.get("m/")
xpub1, xpub2 = self.cold_mpk2_dialog(xpub_hot)
wallet.add_master_public_key("cold/", xpub1)
wallet.add_master_public_key("remote/", xpub2)
wallet.create_account()
self.waiting_dialog(wallet.synchronize)
if action == 'create_2fa_3':
run_hook('create_remote_key', wallet, self) run_hook('create_remote_key', wallet, self)
if not wallet.master_public_keys.get("remote/"): if not wallet.master_public_keys.get("remote/"):
return return
@ -408,15 +467,17 @@ class InstallWizard(QDialog):
else: else:
raise raise
elif t in ['multisig_plugin', 'multisig_manual']: elif t in ['2fa', '2of2','2of3']:
r = self.double_seed_dialog() r = self.double_seed_dialog()
if not r: if not r:
return return
text1, text2 = r text1, text2 = r
password = self.password_dialog() password = self.password_dialog()
if t == 'multisig_manual': if t == '2of2':
wallet = Wallet_2of2(self.storage) wallet = Wallet_2of2(self.storage)
else: elif t == '2of3':
wallet = Wallet_2of3(self.storage)
elif t == '2fa':
wallet = Wallet_2of3(self.storage) wallet = Wallet_2of3(self.storage)
if Wallet.is_seed(text1): if Wallet.is_seed(text1):

3
lib/wallet.py

@ -1508,6 +1508,9 @@ class Wallet_2of3(Wallet_2of2):
xpub1 = self.master_public_keys.get("m/") xpub1 = self.master_public_keys.get("m/")
xpub2 = self.master_public_keys.get("cold/") xpub2 = self.master_public_keys.get("cold/")
xpub3 = self.master_public_keys.get("remote/") xpub3 = self.master_public_keys.get("remote/")
# fixme: we use order of creation
if xpub2 and xpub1 is None:
return 'create_2fa_2'
if xpub2 is None: if xpub2 is None:
return 'create_2of3_1' return 'create_2of3_1'
if xpub1 is None: if xpub1 is None:

Loading…
Cancel
Save