tMerge pull request #3047 from SomberNight/storage_upgrade_v13b - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 6b9bfddda2d9b8febf88f1264be70f1e0e359396 DIR parent d55468d1a6f1bee8b42676acb81f19fb2a97128e HTML Author: ThomasV <thomasv@electrum.org> Date: Mon, 16 Oct 2017 07:18:04 +0200 Merge pull request #3047 from SomberNight/storage_upgrade_v13b fix: storage upgrade of pre-2.8 imported key wallets, and tests Diffstat: M lib/storage.py | 43 +++++++++++++++++++++++++++++-- M lib/tests/test_storage_upgrade.py | 175 +++++++++++++++++++++++++++++-- 2 files changed, 210 insertions(+), 8 deletions(-) --- DIR diff --git a/lib/storage.py b/lib/storage.py t@@ -257,9 +257,10 @@ class WalletStorage(PrintError): self.convert_imported() self.convert_wallet_type() self.convert_account() + self.convert_version_13_b() self.convert_version_14() - self.put('seed_version', FINAL_SEED_VERSION) + self.put('seed_version', FINAL_SEED_VERSION) # just to be sure self.write() def convert_wallet_type(self): t@@ -348,10 +349,35 @@ class WalletStorage(PrintError): self.put('keypairs', None) self.put('key_type', None) + def convert_version_13_b(self): + # version 13 is ambiguous, and has an earlier and a later structure + if not self._is_upgrade_method_needed(0, 13): + return + + if self.get('wallet_type') == 'standard': + if self.get('keystore').get('type') == 'imported': + pubkeys = self.get('keystore').get('keypairs').keys() + if self.get('pubkeys'): + pubkeys2 = set(self.get('pubkeys').get('receiving')) + assert len(pubkeys) == len(pubkeys2) + for pubkey in pubkeys: + assert pubkey in pubkeys2 + d = {'change': []} + receiving_addresses = [] + for pubkey in pubkeys: + addr = bitcoin.pubkey_to_address('p2pkh', pubkey) + receiving_addresses.append(addr) + d['receiving'] = receiving_addresses + self.put('addresses', d) + self.put('pubkeys', None) + + self.put('seed_version', 13) + def convert_version_14(self): # convert imported wallets for 3.0 - if self.get_seed_version() >= 14: + if not self._is_upgrade_method_needed(13, 13): return + if self.get('wallet_type') =='imported': addresses = self.get('addresses') if type(addresses) is list: t@@ -375,6 +401,8 @@ class WalletStorage(PrintError): self.put('pubkeys', None) self.put('wallet_type', 'imported') + self.put('seed_version', 14) + def convert_imported(self): # '/x' is the internal ID for imported accounts d = self.get('accounts', {}).get('/x', {}).get('imported',{}) t@@ -404,6 +432,17 @@ class WalletStorage(PrintError): def convert_account(self): self.put('accounts', None) + def _is_upgrade_method_needed(self, min_version, max_version): + cur_version = self.get_seed_version() + if cur_version > max_version: + return False + elif cur_version < min_version: + raise BaseException( + ('storage upgrade: unexpected version %d (should be %d-%d)' + % (cur_version, min_version, max_version))) + else: + return True + def get_action(self): action = run_hook('get_action', self) if action: DIR diff --git a/lib/tests/test_storage_upgrade.py b/lib/tests/test_storage_upgrade.py t@@ -1,21 +1,24 @@ +import shutil +import tempfile + from lib.storage import WalletStorage from lib.wallet import Wallet from lib.tests.test_wallet import WalletTestCase -# TODO add other wallet types: 2fa/multisig/hardware +# TODO add other wallet types: 2fa, xpub-only +# TODO hw wallet with client version 2.6.x (single-, and multiacc) class TestStorageUpgrade(WalletTestCase): def test_upgrade_from_client_1_9_8_seeded(self): - # seed words: flirt angel five creation swim bridge chocolate sport another hill secret whatever wallet_str = "{'addr_history':{'177hEYTccmuYH8u68pYfaLteTxwJrVgvJj':[],'15V7MsQK2vjF5aEXLVG11qi2eZPZsXdnYc':[],'1DgrwN2JCDZ6uPMSvSz8dPeUtaxLxWM2kf':[],'1H3mPXHFzA8UbvhQVabcDjYw3CPb3djvxs':[],'1DjtUCcQwwzA3GSPA7Kd79PMnri7tLDPYC':[],'1PGEgaPG1XJqmuSj68GouotWeYkCtwo4wm':[],'1PAgpPxnL42Hp3cWxmSfdChPqqGiM8g7zj':[],'1HocPduHmQUJerpdaLG8DnmxvnDCVQwWsa':[]},'accounts_expanded':{},'master_public_key':'756d1fe6ded28d43d4fea902a9695feb785447514d6e6c3bdf369f7c3432fdde4409e4efbffbcf10084d57c5a98d1f34d20ac1f133bdb64fa02abf4f7bde1dfb','use_encryption':False,'seed':'2605aafe50a45bdf2eb155302437e678','accounts':{0:{0:['1DjtUCcQwwzA3GSPA7Kd79PMnri7tLDPYC','1PAgpPxnL42Hp3cWxmSfdChPqqGiM8g7zj','177hEYTccmuYH8u68pYfaLteTxwJrVgvJj','1PGEgaPG1XJqmuSj68GouotWeYkCtwo4wm','15V7MsQK2vjF5aEXLVG11qi2eZPZsXdnYc'],1:['1H3mPXHFzA8UbvhQVabcDjYw3CPb3djvxs','1HocPduHmQUJerpdaLG8DnmxvnDCVQwWsa','1DgrwN2JCDZ6uPMSvSz8dPeUtaxLxWM2kf']}},'seed_version':4}" self._upgrade_storage(wallet_str) - def test_upgrade_from_client_1_9_8_mixed(self): - # seed words: flirt angel five creation swim bridge chocolate sport another hill secret whatever parazyd.org:70 /git/electrum/commit/6b9bfddda2d9b8febf88f1264be70f1e0e359396.gph:122: line too long