add 2of3 wallets in wizard
This commit is contained in:
parent
8558488337
commit
0fb6cdcb1a
|
@ -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':
|
|
||||||
|
elif t == '2fa':
|
||||||
|
wallet = Wallet_2of3(self.storage)
|
||||||
|
run_hook('create_cold_seed', wallet, self)
|
||||||
|
self.create_cold_seed(wallet)
|
||||||
|
return
|
||||||
|
|
||||||
|
elif t == '2of2':
|
||||||
|
wallet = Wallet_2of2(self.storage)
|
||||||
action = 'create_2of2_1'
|
action = 'create_2of2_1'
|
||||||
|
|
||||||
if action in ['create']:
|
elif t == '2of3':
|
||||||
wallet = Wallet(self.storage)
|
wallet = Wallet_2of3(self.storage)
|
||||||
elif action in ['create_2of2_1','create_2of2_2']:
|
action = 'create_2of3_1'
|
||||||
wallet = Wallet_2of2(self.storage)
|
|
||||||
|
|
||||||
|
|
||||||
if action == 'create':
|
if action == 'create_2fa_2':
|
||||||
|
wallet = Wallet_2of3(self.storage)
|
||||||
|
|
||||||
|
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, None):
|
sid = None if action == 'create' else 'hot'
|
||||||
|
if not self.show_seed(seed, sid):
|
||||||
return
|
return
|
||||||
if not self.verify_seed(seed, None):
|
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)
|
||||||
wallet.create_accounts(password)
|
if action == 'create':
|
||||||
self.waiting_dialog(wallet.synchronize)
|
wallet.create_accounts(password)
|
||||||
|
self.waiting_dialog(wallet.synchronize)
|
||||||
|
elif action == 'create_2of2_1':
|
||||||
if action == 'create_2of3_1':
|
|
||||||
run_hook('create_cold_seed', self.storage, self)
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
if action in ['create_2of2_1', 'create_2of3_2']:
|
|
||||||
seed = wallet.make_seed()
|
|
||||||
if not self.show_seed(seed, 'hot'):
|
|
||||||
return
|
|
||||||
if not self.verify_seed(seed, 'hot'):
|
|
||||||
return
|
|
||||||
password = self.password_dialog()
|
|
||||||
wallet.add_seed(seed, password)
|
|
||||||
if action == 'create_2of2_1':
|
|
||||||
# display mpk
|
|
||||||
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):
|
||||||
|
|
|
@ -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…
Reference in New Issue