URI: 
       tMerge pull request #3630 from SomberNight/bip84 - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 359882d0b18894a0ca55a33e269c9fe8d1a57f76
   DIR parent 3c755aaa90dbbbe02cceb4eb81908f5f0e8ea81f
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Thu, 11 Jan 2018 16:43:34 +0100
       
       Merge pull request #3630 from SomberNight/bip84
       
       bip84 for sw seeds
       Diffstat:
         M lib/base_wizard.py                  |      12 ++++++++----
         M lib/keystore.py                     |      20 +++++++++++++++-----
         M lib/tests/test_wallet_vertical.py   |      19 +++++++++++++++++++
       
       3 files changed, 42 insertions(+), 9 deletions(-)
       ---
   DIR diff --git a/lib/base_wizard.py b/lib/base_wizard.py
       t@@ -232,14 +232,15 @@ class BaseWizard(object):
                    self.derivation_dialog(f)
        
            def derivation_dialog(self, f):
       -        default = bip44_derivation(0, False)
       +        default = bip44_derivation(0, bip43_purpose=44)
                message = '\n'.join([
                    _('Enter your wallet derivation here.'),
                    _('If you are not sure what this is, leave this field unchanged.')
                ])
                presets = (
       -            ('legacy BIP44', bip44_derivation(0, False)),
       -            ('p2sh-segwit BIP49', bip44_derivation(0, True)),
       +            ('legacy BIP44', bip44_derivation(0, bip43_purpose=44)),
       +            ('p2sh-segwit BIP49', bip44_derivation(0, bip43_purpose=49)),
       +            ('native-segwit BIP84', bip44_derivation(0, bip43_purpose=84)),
                )
                self.line_dialog(run_next=f, title=_('Derivation'), message=message,
                                 default=default, test=bitcoin.is_bip32_derivation,
       t@@ -247,7 +248,10 @@ class BaseWizard(object):
        
            def on_hw_derivation(self, name, device_info, derivation):
                from .keystore import hardware_keystore
       -        xtype = 'p2wpkh-p2sh' if derivation.startswith("m/49'/") else 'standard'
       +        xtype = keystore.xtype_from_derivation(derivation)
       +        if xtype not in ('standard', 'p2wpkh-p2sh'):
       +            self.show_error(_('Hardware wallet support for this script type is not yet enabled.'))
       +            return
                try:
                    xpub = self.plugin.get_xpub(device_info.device.id_, derivation, xtype, self)
                except BaseException as e:
   DIR diff --git a/lib/keystore.py b/lib/keystore.py
       t@@ -571,10 +571,21 @@ def bip39_is_checksum_valid(mnemonic):
        def from_bip39_seed(seed, passphrase, derivation):
            k = BIP32_KeyStore({})
            bip32_seed = bip39_to_seed(seed, passphrase)
       -    t = 'p2wpkh-p2sh' if derivation.startswith("m/49'") else 'standard'  # bip43
       -    k.add_xprv_from_seed(bip32_seed, t, derivation)
       +    xtype = xtype_from_derivation(derivation)
       +    k.add_xprv_from_seed(bip32_seed, xtype, derivation)
            return k
        
       +
       +def xtype_from_derivation(derivation):
       +    """Returns the script type to be used for this derivation."""
       +    if derivation.startswith("m/84'"):
       +        return 'p2wpkh'
       +    elif derivation.startswith("m/49'"):
       +        return 'p2wpkh-p2sh'
       +    else:
       +        return 'standard'
       +
       +
        # extended pubkeys
        
        def is_xpubkey(x_pubkey):
       t@@ -671,10 +682,9 @@ is_private_key = lambda x: is_xprv(x) or is_private_key_list(x)
        is_bip32_key = lambda x: is_xprv(x) or is_xpub(x)
        
        
       -def bip44_derivation(account_id, segwit=False):
       -    bip  = 49 if segwit else 44
       +def bip44_derivation(account_id, bip43_purpose=44):
            coin = 1 if bitcoin.NetworkConstants.TESTNET else 0
       -    return "m/%d'/%d'/%d'" % (bip, coin, int(account_id))
       +    return "m/%d'/%d'/%d'" % (bip43_purpose, coin, int(account_id))
        
        def from_seed(seed, passphrase, is_p2sh):
            t = seed_type(seed)
   DIR diff --git a/lib/tests/test_wallet_vertical.py b/lib/tests/test_wallet_vertical.py
       t@@ -176,6 +176,25 @@ class TestWalletKeystoreAddressIntegrity(unittest.TestCase):
                self.assertEqual(w.get_change_addresses()[0], '3KaBTcviBLEJajTEMstsA2GWjYoPzPK7Y7')
        
            @mock.patch.object(storage.WalletStorage, '_write')
       +    def test_bip39_seed_bip84_native_segwit(self, mock_write):
       +        # test case from bip84
       +        seed_words = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
       +        self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True))
       +
       +        ks = keystore.from_bip39_seed(seed_words, '', "m/84'/0'/0'")
       +
       +        self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore))
       +
       +        self.assertEqual(ks.xprv, 'zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE')
       +        self.assertEqual(ks.xpub, 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs')
       +
       +        w = self._create_standard_wallet(ks)
       +        self.assertEqual(w.txin_type, 'p2wpkh')
       +
       +        self.assertEqual(w.get_receiving_addresses()[0], 'bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu')
       +        self.assertEqual(w.get_change_addresses()[0], 'bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el')
       +
       +    @mock.patch.object(storage.WalletStorage, '_write')
            def test_electrum_multisig_seed_standard(self, mock_write):
                seed_words = 'blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure'
                self.assertEqual(bitcoin.seed_type(seed_words), 'standard')