URI: 
       tadd 2of3 wallets in wizard - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 0fb6cdcb1a75f7f8f4c7c5b0e8fdaf67145d9326
   DIR parent 8558488337a6043bce8a246f3e7d1d471d13068d
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Fri,  9 May 2014 16:27:12 +0200
       
       add 2of3 wallets in wizard
       
       Diffstat:
         M gui/qt/installwizard.py             |     139 ++++++++++++++++++++++---------
         M lib/wallet.py                       |       3 +++
       
       2 files changed, 103 insertions(+), 39 deletions(-)
       ---
   DIR diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
       t@@ -97,15 +97,20 @@ class InstallWizard(QDialog):
                bb2.setText(_("Wallet with two-factor authentication (plugin)"))
        
                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(bb2, 5, 0)
                grid2.addWidget(bb3, 6, 0)
       +        grid2.addWidget(bb4, 7, 0)
        
                group2.addButton(bb1)
                group2.addButton(bb2)
                group2.addButton(bb3)
       +        group2.addButton(bb4)
         
                vbox.addLayout(grid2)
                vbox.addStretch(1)
       t@@ -120,9 +125,11 @@ class InstallWizard(QDialog):
                if bb1.isChecked():
                    t = 'standard'
                elif bb2.isChecked():
       -            t = 'multisig_plugin'
       +            t = '2fa'
                elif bb3.isChecked():
       -            t = 'multisig_manual'
       +            t = '2of2'
       +        elif bb4.isChecked():
       +            t = '2of3'
        
                return action, t
        
       t@@ -187,6 +194,29 @@ class InstallWizard(QDialog):
                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):
                vbox = QVBoxLayout()
                vbox1, seed_e1 = seed_dialog.enter_seed_box(MSG_ENTER_SEED_OR_MPK, 'hot')
       t@@ -317,6 +347,30 @@ class InstallWizard(QDialog):
                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):
       t@@ -326,61 +380,66 @@ class InstallWizard(QDialog):
        
                if action is None: 
                    return
       -
       +            
                if action == 'create':
       -            if t == 'multisig_plugin':
       -                action = 'create_2of3_1'
       -            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 t == 'standard':
       +                wallet = Wallet(self.storage)
        
       -        if action == 'create':
       -            seed = wallet.make_seed()
       -            if not self.show_seed(seed, None):
       -                return
       -            if not self.verify_seed(seed, None):
       +            elif t == '2fa':
       +                wallet = Wallet_2of3(self.storage)
       +                run_hook('create_cold_seed', wallet, self)
       +                self.create_cold_seed(wallet)
                        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()
       -            if not self.show_seed(seed, 'hot'):
       +            sid = None if action == 'create' else 'hot'
       +            if not self.show_seed(seed, sid):
                        return
       -            if not self.verify_seed(seed, 'hot'):
       +            if not self.verify_seed(seed, sid):
                        return
                    password = self.password_dialog()
                    wallet.add_seed(seed, password)
       -            if action == 'create_2of2_1':
       -                # display mpk
       +            if action == 'create':
       +                wallet.create_accounts(password)
       +                self.waiting_dialog(wallet.synchronize)
       +            elif action == 'create_2of2_1':
                        action = 'create_2of2_2'
       -            else:
       -                action = 'create_2of3_3'
       +            elif action == 'create_2of3_1':
       +                action = 'create_2of3_2'
       +            elif action == 'create_2fa_2':
       +                action = 'create_2fa_3'
        
                if action == 'create_2of2_2':
                    xpub_hot = wallet.master_public_keys.get("m/")
                    xpub = self.cold_mpk_dialog(xpub_hot)
       -            if not Wallet.is_mpk(xpub):
       -                return
                    wallet.add_master_public_key("cold/", xpub)
                    wallet.create_account()
                    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)
                    if not wallet.master_public_keys.get("remote/"):
                        return
       t@@ -408,15 +467,17 @@ class InstallWizard(QDialog):
                        else:
                            raise
        
       -            elif t in ['multisig_plugin', 'multisig_manual']:
       +            elif t in ['2fa', '2of2','2of3']:
                        r = self.double_seed_dialog()
                        if not r: 
                            return
                        text1, text2 = r
                        password = self.password_dialog()
       -                if t == 'multisig_manual':
       +                if t == '2of2':
                            wallet = Wallet_2of2(self.storage)
       -                else:
       +                elif t == '2of3':
       +                    wallet = Wallet_2of3(self.storage)
       +                elif t == '2fa':
                            wallet = Wallet_2of3(self.storage)
        
                        if Wallet.is_seed(text1):
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -1508,6 +1508,9 @@ class Wallet_2of3(Wallet_2of2):
                xpub1 = self.master_public_keys.get("m/")
                xpub2 = self.master_public_keys.get("cold/")
                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:
                    return 'create_2of3_1'
                if xpub1 is None: