Repository: rotki/rotki

Issue:
Opening a rotki version before a global DB upgrade botches the global DB
## Problem Definition

Opening an older version of rotki after the global DB has been upgraded changes its version without actually downgrading anything.

This makes it impossible to work with it either in the old or the new version. The only fix if this happens is to do one the following.

1. Delete global.db.   -> warning all custom assets input by you and all price caches would be deleted.
2. Go in with sqlite and edit 1 field. In Linux you would do it like this:

## Task

We shouldn't let this happen. From v1.16.1 when initializing the globalDB we should never reset the version but fail with a big fat error. I think an exception is shown to the user so probably crashing with an exception is the way to go


Discussion:

Resolving patch:
diff --git a/rotkehlchen/globaldb/handler.py b/rotkehlchen/globaldb/handler.py
--- a/rotkehlchen/globaldb/handler.py
+++ b/rotkehlchen/globaldb/handler.py
@@ -56,6 +56,12 @@ def _initialize_globaldb(dbpath: Path) -> sqlite3.Connection:
     connection.executescript(DB_SCRIPT_CREATE_TABLES)
     cursor = connection.cursor()
     db_version = _get_setting_value(cursor, 'version', GLOBAL_DB_VERSION)
+    if db_version > GLOBAL_DB_VERSION:
+        raise ValueError(
+            f'Tried to open a rotki version intended to work with GlobalDB v{GLOBAL_DB_VERSION} '
+            f'but the GlobalDB found in the system is v{db_version}. Bailing ...',
+        )
+
     if db_version == 1:
         upgrade_ethereum_asset_ids(connection)
     cursor.execute(


Test patch:
diff --git a/rotkehlchen/tests/data/v9999999999_global.db b/rotkehlchen/tests/data/v9999999999_global.db
new file mode 100644
Binary files /dev/null and b/rotkehlchen/tests/data/v9999999999_global.db differ
diff --git a/rotkehlchen/tests/unit/test_globaldb.py b/rotkehlchen/tests/unit/test_globaldb.py
--- a/rotkehlchen/tests/unit/test_globaldb.py
+++ b/rotkehlchen/tests/unit/test_globaldb.py
@@ -11,6 +11,11 @@
 from rotkehlchen.history.typing import HistoricalPriceOracle
 from rotkehlchen.tests.utils.factories import make_ethereum_address
 from rotkehlchen.tests.utils.globaldb import INITIAL_TOKENS
+from pathlib import Path
+from rotkehlchen.assets.resolver import AssetResolver
+from shutil import copyfile
+from rotkehlchen.globaldb.handler import GLOBAL_DB_VERSION
+from rotkehlchen.tests.fixtures.globaldb import create_globaldb
 
 
 @pytest.mark.parametrize('use_clean_caching_directory', [True])
@@ -21,6 +26,28 @@ def test_get_ethereum_token_identifier(globaldb):
     assert token_0_id == ethaddress_to_identifier(INITIAL_TOKENS[0].address)
 
 
+def test_open_new_globaldb_with_old_rotki(tmpdir_factory):
+    """Test for https://github.com/rotki/rotki/issues/2781"""
+    # clean the previous resolver memory cache, as it
+    # may have cached results from a discarded database
+    AssetResolver().clean_memory_cache()
+    version = 9999999999
+    root_dir = Path(__file__).resolve().parent.parent.parent
+    source_db_path = root_dir / 'tests' / 'data' / f'v{version}_global.db'
+    new_data_dir = Path(tmpdir_factory.mktemp('test_data_dir'))
+    new_global_dir = new_data_dir / 'global_data'
+    new_global_dir.mkdir(parents=True, exist_ok=True)
+    copyfile(source_db_path, new_global_dir / 'global.db')
+    with pytest.raises(ValueError) as excinfo:
+        create_globaldb(new_data_dir)
+
+    msg = (
+        f'Tried to open a rotki version intended to work with GlobalDB v{GLOBAL_DB_VERSION} '
+        f'but the GlobalDB found in the system is v{version}. Bailing ...'
+    )
+    assert msg in str(excinfo.value)
+
+
 @pytest.mark.parametrize('use_clean_caching_directory', [True])
 def test_add_edit_token_with_wrong_swapped_for(globaldb):
     """Test that giving a non-existing swapped_for token in the DB raises InputError