URI: 
       tjson_db: enforce order of 'load_transactions' and 'upgrade' - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit fd58a0cb20881250510f4be68fbbd6274e8417e9
   DIR parent a59e3efd3e80701af78bf7cf4d8c76901d5f93fe
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Mon, 13 May 2019 19:21:26 +0200
       
       json_db: enforce order of 'load_transactions' and 'upgrade'
       
       fixes #5331
       
       Diffstat:
         M electrum/json_db.py                 |      25 +++++++++++++++++--------
         M electrum/tests/test_storage_upgrad… |      23 ++++++++++++++++++-----
       
       2 files changed, 35 insertions(+), 13 deletions(-)
       ---
   DIR diff --git a/electrum/json_db.py b/electrum/json_db.py
       t@@ -59,11 +59,12 @@ class JsonDB(Logger):
                self.data = {}
                self._modified = False
                self.manual_upgrades = manual_upgrades
       -        if raw:
       +        self._called_load_transactions = False
       +        if raw:  # loading existing db
                    self.load_data(raw)
       -        else:
       +        else:  # creating new db
                    self.put('seed_version', FINAL_SEED_VERSION)
       -        self.load_transactions()
       +            self.load_transactions()
        
            def set_modified(self, b):
                with self.lock:
       t@@ -145,11 +146,13 @@ class JsonDB(Logger):
                if not isinstance(self.data, dict):
                    raise WalletFileException("Malformed wallet file (not dict)")
        
       -        if not self.manual_upgrades:
       -            if self.requires_split():
       -                raise WalletFileException("This wallet has multiple accounts and must be split")
       -            if self.requires_upgrade():
       -                self.upgrade()
       +        if not self.manual_upgrades and self.requires_split():
       +            raise WalletFileException("This wallet has multiple accounts and must be split")
       +
       +        self.load_transactions()
       +
       +        if not self.manual_upgrades and self.requires_upgrade():
       +            self.upgrade()
        
            def requires_split(self):
                d = self.get('accounts', {})
       t@@ -201,6 +204,11 @@ class JsonDB(Logger):
            @profiler
            def upgrade(self):
                self.logger.info('upgrading wallet format')
       +        if not self._called_load_transactions:
       +            # note: not sure if this is how we should go about this...
       +            # alternatively, we could make sure load_transactions is always called after upgrade
       +            # still, we need strict ordering between the two.
       +            raise Exception("'load_transactions' must be called before 'upgrade'")
                self._convert_imported()
                self._convert_wallet_type()
                self._convert_account()
       t@@ -738,6 +746,7 @@ class JsonDB(Logger):
        
            @profiler
            def load_transactions(self):
       +        self._called_load_transactions = True
                # references in self.data
                self.txi = self.get_data_ref('txi')  # txid -> address -> list of (prev_outpoint, value)
                self.txo = self.get_data_ref('txo')  # txid -> address -> list of (output_index, value, is_coinbase)
   DIR diff --git a/electrum/tests/test_storage_upgrade.py b/electrum/tests/test_storage_upgrade.py
       t@@ -1,5 +1,6 @@
        import shutil
        import tempfile
       +import os
        
        from electrum.storage import WalletStorage
        from electrum.wallet import Wallet
       t@@ -290,14 +291,25 @@ class TestStorageUpgrade(WalletTestCase):
                shutil.rmtree(cls.electrum_path)
        
            def _upgrade_storage(self, wallet_json, accounts=1):
       -        storage = self._load_storage_from_json_string(wallet_json, manual_upgrades=True)
       -
                if accounts == 1:
       +            # test manual upgrades
       +            storage = self._load_storage_from_json_string(wallet_json=wallet_json,
       +                                                          path=self.wallet_path,
       +                                                          manual_upgrades=True)
                    self.assertFalse(storage.requires_split())
                    if storage.requires_upgrade():
                        storage.upgrade()
                        self._sanity_check_upgraded_storage(storage)
       +            # test automatic upgrades
       +            path2 = os.path.join(self.user_dir, "somewallet2")
       +            storage2 = self._load_storage_from_json_string(wallet_json=wallet_json,
       +                                                           path=path2,
       +                                                           manual_upgrades=False)
       +            self._sanity_check_upgraded_storage(storage2)
                else:
       +            storage = self._load_storage_from_json_string(wallet_json=wallet_json,
       +                                                          path=self.wallet_path,
       +                                                          manual_upgrades=True)
                    self.assertTrue(storage.requires_split())
                    new_paths = storage.split_accounts()
                    self.assertEqual(accounts, len(new_paths))
       t@@ -310,8 +322,9 @@ class TestStorageUpgrade(WalletTestCase):
                self.assertFalse(storage.requires_upgrade())
                w = Wallet(storage)
        
       -    def _load_storage_from_json_string(self, wallet_json, manual_upgrades=True):
       -        with open(self.wallet_path, "w") as f:
       +    @staticmethod
       +    def _load_storage_from_json_string(*, wallet_json, path, manual_upgrades):
       +        with open(path, "w") as f:
                    f.write(wallet_json)
       -        storage = WalletStorage(self.wallet_path, manual_upgrades=manual_upgrades)
       +        storage = WalletStorage(path, manual_upgrades=manual_upgrades)
                return storage