From 26afd71d89f635d7df993ea3395838c3fd0aea32 Mon Sep 17 00:00:00 2001
From: Caleb Beery <cjbeery@gmail.com>
Date: Sat, 13 Apr 2024 01:31:05 -0700
Subject: [PATCH 1/2] Restore wallet now restores tokens for all mint keysets.
 (#509)

---
 cashu/wallet/wallet.py | 37 ++++++++++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 11 deletions(-)

diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py
index acd41cfd..7f282853 100644
--- a/cashu/wallet/wallet.py
+++ b/cashu/wallet/wallet.py
@@ -1617,28 +1617,25 @@ async def balance_per_minturl(
                 balances_return[key]["unit"] = unit.name
         return dict(sorted(balances_return.items(), key=lambda item: item[0]))  # type: ignore
 
-    async def restore_wallet_from_mnemonic(
-        self, mnemonic: Optional[str], to: int = 2, batch: int = 25
+    async def restore_tokens_for_keyset(
+        self, keyset_id: str, to: int = 2, batch: int = 25
     ) -> None:
         """
-        Restores the wallet from a mnemonic.
+        Restores tokens for a given keyset_id.
 
         Args:
-            mnemonic (Optional[str]): The mnemonic to restore the wallet from. If None, the mnemonic is loaded from the db.
+            keyset_id (str): The keyset_id to restore tokens for.
             to (int, optional): The number of consecutive empty responses to stop restoring. Defaults to 2.
             batch (int, optional): The number of proofs to restore in one batch. Defaults to 25.
         """
-        await self._init_private_key(mnemonic)
-        await self.load_mint()
-        print("Restoring tokens...")
         stop_counter = 0
         # we get the current secret counter and restore from there on
         spendable_proofs = []
         counter_before = await bump_secret_derivation(
-            db=self.db, keyset_id=self.keyset_id, by=0
+            db=self.db, keyset_id=keyset_id, by=0
         )
         if counter_before != 0:
-            print("This wallet has already been used. Restoring from it's last state.")
+            print("Keyset has already been used. Restoring from it's last state.")
         i = counter_before
         n_last_restored_proofs = 0
         while stop_counter < to:
@@ -1659,16 +1656,34 @@ async def restore_wallet_from_mnemonic(
         logger.debug(f"Reverting secret counter by {revert_counter_by}")
         before = await bump_secret_derivation(
             db=self.db,
-            keyset_id=self.keyset_id,
+            keyset_id=keyset_id,
             by=-revert_counter_by,
         )
         logger.debug(
             f"Secret counter reverted from {before} to {before - revert_counter_by}"
         )
         if n_last_restored_proofs == 0:
-            print("No tokens restored.")
+            print("No tokens restored for keyset.")
             return
 
+    async def restore_wallet_from_mnemonic(
+        self, mnemonic: Optional[str], to: int = 2, batch: int = 25
+    ) -> None:
+        """
+        Restores the wallet from a mnemonic.
+
+        Args:
+            mnemonic (Optional[str]): The mnemonic to restore the wallet from. If None, the mnemonic is loaded from the db.
+            to (int, optional): The number of consecutive empty responses to stop restoring. Defaults to 2.
+            batch (int, optional): The number of proofs to restore in one batch. Defaults to 25.
+        """
+        await self._init_private_key(mnemonic)
+        await self.load_mint()
+        print("Restoring tokens...")
+        keyset_ids = self.mint_keyset_ids
+        for keyset_id in keyset_ids:
+            await self.restore_tokens_for_keyset(keyset_id, to, batch)
+
     async def restore_promises_from_to(
         self, from_counter: int, to_counter: int
     ) -> List[Proof]:

From bdaed8451cc1e6cb3f66b4cf9036384119e0ea08 Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Mon, 15 Apr 2024 00:33:23 +0200
Subject: [PATCH 2/2] [Mint] Migrate duplicate keysets to db (#511)

* wip

* remove all deprecated keyset tests

* fix more tests

* fixups
---
 cashu/core/base.py                | 29 +++++++--------
 cashu/core/settings.py            | 11 +-----
 cashu/mint/ledger.py              | 47 ++----------------------
 cashu/mint/migrations.py          | 49 +++++++++++++++++++++++--
 cashu/mint/router_deprecated.py   |  8 ++---
 cashu/wallet/wallet_deprecated.py |  5 +--
 tests/conftest.py                 | 49 +++++++++++++++----------
 tests/test_mint.py                | 60 -------------------------------
 tests/test_mint_api.py            | 13 ++-----
 tests/test_mint_api_deprecated.py |  6 +---
 tests/test_mint_init.py           | 25 +------------
 tests/test_wallet.py              | 11 ++----
 tests/test_wallet_restore.py      |  5 ---
 13 files changed, 104 insertions(+), 214 deletions(-)

diff --git a/cashu/core/base.py b/cashu/core/base.py
index 1e198306..67326728 100644
--- a/cashu/core/base.py
+++ b/cashu/core/base.py
@@ -656,7 +656,6 @@ def __init__(
         valid_to=None,
         first_seen=None,
         active=True,
-        use_deprecated_id=False,  # BACKWARDS COMPATIBILITY < 0.15.0
     ):
         self.valid_from = valid_from
         self.valid_to = valid_to
@@ -671,19 +670,10 @@ def __init__(
         else:
             self.id = id
 
-        # BEGIN BACKWARDS COMPATIBILITY < 0.15.0
-        if use_deprecated_id:
-            logger.warning(
-                "Using deprecated keyset id derivation for backwards compatibility <"
-                " 0.15.0"
-            )
-            self.id = derive_keyset_id_deprecated(self.public_keys)
-        # END BACKWARDS COMPATIBILITY < 0.15.0
-
         self.unit = Unit[unit]
 
         logger.trace(f"Derived keyset id {self.id} from public keys.")
-        if id and id != self.id and use_deprecated_id:
+        if id and id != self.id:
             logger.warning(
                 f"WARNING: Keyset id {self.id} does not match the given id {id}."
                 " Overwriting."
@@ -738,8 +728,6 @@ class MintKeyset:
     first_seen: Optional[str] = None
     version: Optional[str] = None
 
-    duplicate_keyset_id: Optional[str] = None  # BACKWARDS COMPATIBILITY < 0.15.0
-
     def __init__(
         self,
         *,
@@ -820,6 +808,12 @@ def generate_keys(self):
         assert self.seed, "seed not set"
         assert self.derivation_path, "derivation path not set"
 
+        # we compute the keyset id from the public keys only if it is not
+        # loaded from the database. This is to allow for backwards compatibility
+        # with old keysets with new id's and vice versa. This code can be removed
+        # if there are only new keysets in the mint (> 0.15.0)
+        id_in_db = self.id
+
         if self.version_tuple < (0, 12):
             # WARNING: Broken key derivation for backwards compatibility with < 0.12
             self.private_keys = derive_keys_backwards_compatible_insecure_pre_0_12(
@@ -830,7 +824,8 @@ def generate_keys(self):
                 f"WARNING: Using weak key derivation for keyset {self.id} (backwards"
                 " compatibility < 0.12)"
             )
-            self.id = derive_keyset_id_deprecated(self.public_keys)  # type: ignore
+            # load from db or derive
+            self.id = id_in_db or derive_keyset_id_deprecated(self.public_keys)  # type: ignore
         elif self.version_tuple < (0, 15):
             self.private_keys = derive_keys_sha256(self.seed, self.derivation_path)
             logger.trace(
@@ -838,11 +833,13 @@ def generate_keys(self):
                 " compatibility < 0.15)"
             )
             self.public_keys = derive_pubkeys(self.private_keys)  # type: ignore
-            self.id = derive_keyset_id_deprecated(self.public_keys)  # type: ignore
+            # load from db or derive
+            self.id = id_in_db or derive_keyset_id_deprecated(self.public_keys)  # type: ignore
         else:
             self.private_keys = derive_keys(self.seed, self.derivation_path)
             self.public_keys = derive_pubkeys(self.private_keys)  # type: ignore
-            self.id = derive_keyset_id(self.public_keys)  # type: ignore
+            # load from db or derive
+            self.id = id_in_db or derive_keyset_id(self.public_keys)  # type: ignore
 
 
 # ------- TOKEN -------
diff --git a/cashu/core/settings.py b/cashu/core/settings.py
index 0cf2e755..4be3ccea 100644
--- a/cashu/core/settings.py
+++ b/cashu/core/settings.py
@@ -52,20 +52,12 @@ class MintSettings(CashuSettings):
     mint_private_key: str = Field(default=None)
     mint_seed_decryption_key: Optional[str] = Field(default=None)
     mint_derivation_path: str = Field(default="m/0'/0'/0'")
-    mint_derivation_path_list: List[str] = Field(default=[])
+    mint_derivation_path_list: List[str] = Field(default=[""])
     mint_listen_host: str = Field(default="127.0.0.1")
     mint_listen_port: int = Field(default=3338)
 
     mint_database: str = Field(default="data/mint")
     mint_test_database: str = Field(default="test_data/test_mint")
-    mint_duplicate_old_keysets: bool = Field(
-        default=True,
-        title="Duplicate keysets",
-        description=(
-            "Whether to duplicate keysets for backwards compatibility before v1 API"
-            " (Nutshell 0.15.0)."
-        ),
-    )
 
 
 class MintBackends(MintSettings):
@@ -134,7 +126,6 @@ class MintInformation(CashuSettings):
     mint_info_description: str = Field(default=None)
     mint_info_description_long: str = Field(default=None)
     mint_info_contact: List[List[str]] = Field(default=[["", ""]])
-    mint_info_nuts: List[str] = Field(default=["NUT-07", "NUT-08", "NUT-09"])
     mint_info_motd: str = Field(default=None)
 
 
diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py
index b5b5743f..735a1442 100644
--- a/cashu/mint/ledger.py
+++ b/cashu/mint/ledger.py
@@ -1,5 +1,4 @@
 import asyncio
-import copy
 import time
 from typing import Dict, List, Mapping, Optional, Tuple
 
@@ -26,8 +25,6 @@
 from ..core.crypto import b_dhke
 from ..core.crypto.aes import AESCipher
 from ..core.crypto.keys import (
-    derive_keyset_id,
-    derive_keyset_id_deprecated,
     derive_pubkey,
     random_hash,
 )
@@ -231,19 +228,10 @@ async def activate_keyset(
         # load the new keyset in self.keysets
         self.keysets[keyset.id] = keyset
 
-        # BEGIN BACKWARDS COMPATIBILITY < 0.15.0
-        # set the deprecated id
-        if not keyset.public_keys:
-            raise KeysetError("no public keys for this keyset")
-        keyset.duplicate_keyset_id = derive_keyset_id_deprecated(keyset.public_keys)
-        # END BACKWARDS COMPATIBILITY < 0.15.0
-
         logger.debug(f"Loaded keyset {keyset.id}")
         return keyset
 
-    async def init_keysets(
-        self, autosave: bool = True, duplicate_keysets: Optional[bool] = None
-    ) -> None:
+    async def init_keysets(self, autosave: bool = True) -> None:
         """Initializes all keysets of the mint from the db. Loads all past keysets from db
         and generate their keys. Then activate the current keyset set by self.derivation_path.
 
@@ -251,9 +239,6 @@ async def init_keysets(
             autosave (bool, optional): Whether the current keyset should be saved if it is
                 not in the database yet. Will be passed to `self.activate_keyset` where it is
                 generated from `self.derivation_path`. Defaults to True.
-            duplicate_keysets (bool, optional): Whether to duplicate new keysets and compute
-                their old keyset id, and duplicate old keysets and compute their new keyset id.
-                Defaults to False.
         """
         # load all past keysets from db, the keys will be generated at instantiation
         tmp_keysets: List[MintKeyset] = await self.crud.get_keyset(db=self.db)
@@ -275,31 +260,6 @@ async def init_keysets(
         if not any([k.active for k in self.keysets.values()]):
             raise KeysetError("No active keyset found.")
 
-        # BEGIN BACKWARDS COMPATIBILITY < 0.15.0
-        # we duplicate new keysets and compute their old keyset id, and
-        # we duplicate old keysets and compute their new keyset id
-        if duplicate_keysets is not False and (
-            settings.mint_duplicate_old_keysets or duplicate_keysets
-        ):
-            for _, keyset in copy.copy(self.keysets).items():
-                # if keyset.version_tuple >= (0, 15, 3) and not duplicate_keysets:
-                #     # we do not duplicate keysets from version 0.15.3 and above if not forced by duplicate_keysets
-                #     continue
-                keyset_copy = copy.copy(keyset)
-                if not keyset_copy.public_keys:
-                    raise KeysetError("no public keys for this keyset")
-                if keyset.version_tuple >= (0, 15):
-                    keyset_copy.id = derive_keyset_id_deprecated(
-                        keyset_copy.public_keys
-                    )
-                else:
-                    keyset_copy.id = derive_keyset_id(keyset_copy.public_keys)
-                keyset_copy.duplicate_keyset_id = keyset.id
-                self.keysets[keyset_copy.id] = keyset_copy
-                # remember which keyset this keyset was duplicated from
-                logger.debug(f"Duplicated keyset id {keyset.id} -> {keyset_copy.id}")
-        # END BACKWARDS COMPATIBILITY < 0.15.0
-
     def get_keyset(self, keyset_id: Optional[str] = None) -> Dict[int, str]:
         """Returns a dictionary of hex public keys of a specific keyset for each supported amount"""
         if keyset_id and keyset_id not in self.keysets:
@@ -982,10 +942,7 @@ async def _generate_promises(
             keyset = keyset or self.keysets[output.id]
             if output.id not in self.keysets:
                 raise TransactionError(f"keyset {output.id} not found")
-            if output.id not in [
-                keyset.id,
-                keyset.duplicate_keyset_id,
-            ]:
+            if output.id != keyset.id:
                 raise TransactionError("keyset id does not match output id")
             if not keyset.active:
                 raise TransactionError("keyset is not active")
diff --git a/cashu/mint/migrations.py b/cashu/mint/migrations.py
index 3f9c5377..664b80c4 100644
--- a/cashu/mint/migrations.py
+++ b/cashu/mint/migrations.py
@@ -1,4 +1,7 @@
-from ..core.base import Proof
+import copy
+
+from ..core.base import MintKeyset, Proof
+from ..core.crypto.keys import derive_keyset_id, derive_keyset_id_deprecated
 from ..core.db import Connection, Database, table_with_schema, timestamp_now
 from ..core.settings import settings
 
@@ -699,7 +702,7 @@ async def m017_foreign_keys_proof_tables(db: Database):
                         swap_id TEXT,
 
                         FOREIGN KEY (mint_quote) REFERENCES {table_with_schema(db, 'mint_quotes')}(quote),
-                        
+
                         UNIQUE (b_)
                     );
                 """
@@ -718,3 +721,45 @@ async def m017_foreign_keys_proof_tables(db: Database):
 
     # recreate indices
     await m015_add_index_Y_to_proofs_used_and_pending(db)
+
+
+async def m018_duplicate_deprecated_keyset_ids(db: Database):
+    async with db.connect() as conn:
+        rows = await conn.fetchall(  # type: ignore
+            f"""
+                SELECT * from {table_with_schema(db, 'keysets')}
+                """,
+        )
+        keysets = [MintKeyset(**row) for row in rows]
+        duplicated_keysets: list[MintKeyset] = []
+        for keyset in keysets:
+            keyset_copy = copy.copy(keyset)
+            if not keyset_copy.public_keys:
+                raise Exception(f"keyset {keyset_copy.id} has no public keys")
+            if keyset.version_tuple < (0, 15):
+                keyset_copy.id = derive_keyset_id(keyset_copy.public_keys)
+            else:
+                keyset_copy.id = derive_keyset_id_deprecated(keyset_copy.public_keys)
+            duplicated_keysets.append(keyset_copy)
+
+        for keyset in duplicated_keysets:
+            await conn.execute(
+                f"""
+                INSERT INTO {table_with_schema(db, 'keysets')}
+                (id, derivation_path, valid_from, valid_to, first_seen, active, version, seed, unit, encrypted_seed, seed_encryption_method)
+                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+                """,
+                (
+                    keyset.id,
+                    keyset.derivation_path,
+                    keyset.valid_from,
+                    keyset.valid_to,
+                    keyset.first_seen,
+                    keyset.active,
+                    keyset.version,
+                    keyset.seed,
+                    keyset.unit.name,
+                    keyset.encrypted_seed,
+                    keyset.seed_encryption_method,
+                ),
+            )
diff --git a/cashu/mint/router_deprecated.py b/cashu/mint/router_deprecated.py
index dde54056..5e5bdd50 100644
--- a/cashu/mint/router_deprecated.py
+++ b/cashu/mint/router_deprecated.py
@@ -52,7 +52,7 @@ async def info() -> GetInfoResponse_deprecated:
         description=settings.mint_info_description,
         description_long=settings.mint_info_description_long,
         contact=settings.mint_info_contact,
-        nuts=settings.mint_info_nuts,
+        nuts=["NUT-07", "NUT-08", "NUT-09"],
         motd=settings.mint_info_motd,
         parameter={
             "max_peg_in": settings.mint_max_peg_in,
@@ -178,12 +178,8 @@ async def mint_deprecated(
 
     # BEGIN BACKWARDS COMPATIBILITY < 0.15
     # Mint expects "id" in outputs to know which keyset to use to sign them.
-    # use the deprecated version of the current keyset
-    assert ledger.keyset.duplicate_keyset_id
     outputs: list[BlindedMessage] = [
-        BlindedMessage(
-            id=o.id or ledger.keyset.duplicate_keyset_id, **o.dict(exclude={"id"})
-        )
+        BlindedMessage(id=o.id or ledger.keyset.id, **o.dict(exclude={"id"}))
         for o in payload.outputs
     ]
     # END BACKWARDS COMPATIBILITY < 0.15
diff --git a/cashu/wallet/wallet_deprecated.py b/cashu/wallet/wallet_deprecated.py
index 080a9925..34375a10 100644
--- a/cashu/wallet/wallet_deprecated.py
+++ b/cashu/wallet/wallet_deprecated.py
@@ -160,9 +160,7 @@ async def _get_keys_deprecated(self, url: str) -> WalletKeyset:
             int(amt): PublicKey(bytes.fromhex(val), raw=True)
             for amt, val in keys.items()
         }
-        keyset = WalletKeyset(
-            unit="sat", public_keys=keyset_keys, mint_url=url, use_deprecated_id=True
-        )
+        keyset = WalletKeyset(unit="sat", public_keys=keyset_keys, mint_url=url)
         return keyset
 
     @async_set_httpx_client
@@ -199,7 +197,6 @@ async def _get_keys_of_keyset_deprecated(
             id=keyset_id,
             public_keys=keyset_keys,
             mint_url=url,
-            use_deprecated_id=True,
         )
         return keyset
 
diff --git a/tests/conftest.py b/tests/conftest.py
index 6d1ac1c1..e6f31cab 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -73,28 +73,25 @@ def run(self, *args, **kwargs):
         self.server.run()
 
 
-# # This fixture is used for tests that require API access to the mint
-@pytest.fixture(autouse=True, scope="session")
-def mint():
-    config = uvicorn.Config(
-        "cashu.mint.app:app",
-        port=settings.mint_listen_port,
-        host=settings.mint_listen_host,
-    )
-
-    server = UvicornServer(config=config)
-    server.start()
-    time.sleep(1)
-    yield server
-    server.stop()
-
-
 # This fixture is used for all other tests
 @pytest_asyncio.fixture(scope="function")
 async def ledger():
-    async def start_mint_init(ledger: Ledger):
+    async def start_mint_init(ledger: Ledger) -> Ledger:
         await migrate_databases(ledger.db, migrations_mint)
+        # add a new keyset (with a new ID) which will be duplicated with a keyset with an
+        # old ID by mint migration m018_duplicate_deprecated_keyset_ids
+        # await ledger.activate_keyset(derivation_path=settings.mint_derivation_path, version="0.15.0")
+        # await migrations_mint.m018_duplicate_deprecated_keyset_ids(ledger.db)
+
+        ledger = Ledger(
+            db=Database("mint", settings.mint_database),
+            seed=settings.mint_private_key,
+            derivation_path=settings.mint_derivation_path,
+            backends=backends,
+            crud=LedgerCrudSqlite(),
+        )
         await ledger.startup_ledger()
+        return ledger
 
     if not settings.mint_database.startswith("postgres"):
         # clear sqlite database
@@ -120,6 +117,22 @@ async def start_mint_init(ledger: Ledger):
         backends=backends,
         crud=LedgerCrudSqlite(),
     )
-    await start_mint_init(ledger)
+    ledger = await start_mint_init(ledger)
     yield ledger
     print("teardown")
+
+
+# # This fixture is used for tests that require API access to the mint
+@pytest.fixture(autouse=True, scope="session")
+def mint():
+    config = uvicorn.Config(
+        "cashu.mint.app:app",
+        port=settings.mint_listen_port,
+        host=settings.mint_listen_host,
+    )
+
+    server = UvicornServer(config=config)
+    server.start()
+    time.sleep(1)
+    yield server
+    server.stop()
diff --git a/tests/test_mint.py b/tests/test_mint.py
index 534fc051..0a46b0f3 100644
--- a/tests/test_mint.py
+++ b/tests/test_mint.py
@@ -58,17 +58,6 @@ async def test_keysets(ledger: Ledger):
     assert ledger.keyset.id == "009a1f293253e41e"
 
 
-@pytest.mark.asyncio
-async def test_keysets_backwards_compatibility_pre_v0_15(ledger: Ledger):
-    """Backwards compatibility test for keysets pre v0.15.0
-    We expect two instances of the same keyset but with different IDs.
-    First one is the new hex ID, second one is the old base64 ID.
-    """
-    assert len(ledger.keysets) == 2
-    assert list(ledger.keysets.keys()) == ["009a1f293253e41e", "eGnEWtdJ0PIM"]
-    assert ledger.keyset.id == "009a1f293253e41e"
-
-
 @pytest.mark.asyncio
 async def test_get_keyset(ledger: Ledger):
     keyset = ledger.get_keyset()
@@ -136,55 +125,6 @@ async def test_generate_promises(ledger: Ledger):
     assert promises[0].dleq.e
 
 
-@pytest.mark.asyncio
-async def test_generate_promises_deprecated_keyset_id(ledger: Ledger):
-    blinded_messages_mock = [
-        BlindedMessage(
-            amount=8,
-            B_="02634a2c2b34bec9e8a4aba4361f6bf202d7fa2365379b0840afe249a7a9d71239",
-            id="eGnEWtdJ0PIM",
-        )
-    ]
-    promises = await ledger._generate_promises(blinded_messages_mock)
-    assert (
-        promises[0].C_
-        == "031422eeffb25319e519c68de000effb294cb362ef713a7cf4832cea7b0452ba6e"
-    )
-    assert promises[0].amount == 8
-    assert promises[0].id == "eGnEWtdJ0PIM"
-
-    # DLEQ proof present
-    assert promises[0].dleq
-    assert promises[0].dleq.s
-    assert promises[0].dleq.e
-
-
-@pytest.mark.asyncio
-async def test_generate_promises_keyset_backwards_compatibility_pre_v0_15(
-    ledger: Ledger,
-):
-    """Backwards compatibility test for keysets pre v0.15.0
-    We want to generate promises using the old keyset ID.
-    We expect the promise to have the old base64 ID.
-    """
-    blinded_messages_mock = [
-        BlindedMessage(
-            amount=8,
-            B_="02634a2c2b34bec9e8a4aba4361f6bf202d7fa2365379b0840afe249a7a9d71239",
-            id="eGnEWtdJ0PIM",
-        )
-    ]
-    promises = await ledger._generate_promises(
-        blinded_messages_mock, keyset=ledger.keysets["eGnEWtdJ0PIM"]
-    )
-    assert (
-        promises[0].C_
-        == "031422eeffb25319e519c68de000effb294cb362ef713a7cf4832cea7b0452ba6e"
-    )
-    assert promises[0].amount == 8
-    assert promises[0].id == "eGnEWtdJ0PIM"
-
-
 @pytest.mark.asyncio
 async def test_generate_change_promises(ledger: Ledger):
     # Example slightly adapted from NUT-08 because we want to ensure the dynamic change
diff --git a/tests/test_mint_api.py b/tests/test_mint_api.py
index 3a7acbd3..5b105fcc 100644
--- a/tests/test_mint_api.py
+++ b/tests/test_mint_api.py
@@ -90,13 +90,6 @@ async def test_api_keysets(ledger: Ledger):
                 "unit": "sat",
                 "active": True,
             },
-            # for backwards compatibility of the new keyset ID format,
-            # we also return the same keyset with the old base64 ID
-            {
-                "id": "eGnEWtdJ0PIM",
-                "unit": "sat",
-                "active": True,
-            },
         ]
     }
     assert response.json() == expected
@@ -132,17 +125,17 @@ async def test_api_keyset_keys(ledger: Ledger):
     reason="settings.debug_mint_only_deprecated is set",
 )
 async def test_api_keyset_keys_old_keyset_id(ledger: Ledger):
-    response = httpx.get(f"{BASE_URL}/v1/keys/eGnEWtdJ0PIM")
+    response = httpx.get(f"{BASE_URL}/v1/keys/009a1f293253e41e")
     assert response.status_code == 200, f"{response.url} {response.status_code}"
     assert ledger.keyset.public_keys
     expected = {
         "keysets": [
             {
-                "id": "eGnEWtdJ0PIM",
+                "id": "009a1f293253e41e",
                 "unit": "sat",
                 "keys": {
                     str(k): v.serialize().hex()
-                    for k, v in ledger.keysets["eGnEWtdJ0PIM"].public_keys.items()  # type: ignore
+                    for k, v in ledger.keysets["009a1f293253e41e"].public_keys.items()  # type: ignore
                 },
             }
         ]
diff --git a/tests/test_mint_api_deprecated.py b/tests/test_mint_api_deprecated.py
index fc40589c..f59b9b84 100644
--- a/tests/test_mint_api_deprecated.py
+++ b/tests/test_mint_api_deprecated.py
@@ -9,7 +9,6 @@
     PostRestoreResponse,
     Proof,
 )
-from cashu.core.settings import settings
 from cashu.mint.ledger import Ledger
 from cashu.wallet.crud import bump_secret_derivation
 from cashu.wallet.wallet import Wallet
@@ -141,10 +140,7 @@ async def test_mint(ledger: Ledger, wallet: Wallet):
     assert len(result["promises"]) == 2
     assert result["promises"][0]["amount"] == 32
     assert result["promises"][1]["amount"] == 32
-    if settings.debug_mint_only_deprecated:
-        assert result["promises"][0]["id"] == "eGnEWtdJ0PIM"
-    else:
-        assert result["promises"][0]["id"] == "009a1f293253e41e"
+    assert result["promises"][0]["id"] == "009a1f293253e41e"
     assert result["promises"][0]["dleq"]
     assert "e" in result["promises"][0]["dleq"]
     assert "s" in result["promises"][0]["dleq"]
diff --git a/tests/test_mint_init.py b/tests/test_mint_init.py
index 17263164..e7d23413 100644
--- a/tests/test_mint_init.py
+++ b/tests/test_mint_init.py
@@ -56,31 +56,8 @@ async def wallet(ledger: Ledger):
 
 
 @pytest.mark.asyncio
-async def test_init_keysets_with_duplicates(ledger: Ledger):
+async def test_init_keysets(ledger: Ledger):
     ledger.keysets = {}
-    await ledger.init_keysets(duplicate_keysets=True)
-    assert len(ledger.keysets) == 2
-
-
-@pytest.mark.asyncio
-async def test_init_keysets_with_duplicates_via_settings(ledger: Ledger):
-    ledger.keysets = {}
-    settings.mint_duplicate_old_keysets = True
-    await ledger.init_keysets()
-    assert len(ledger.keysets) == 2
-
-
-@pytest.mark.asyncio
-async def test_init_keysets_without_duplicates(ledger: Ledger):
-    ledger.keysets = {}
-    await ledger.init_keysets(duplicate_keysets=False)
-    assert len(ledger.keysets) == 1
-
-
-@pytest.mark.asyncio
-async def test_init_keysets_without_duplicates_via_settings(ledger: Ledger):
-    ledger.keysets = {}
-    settings.mint_duplicate_old_keysets = False
     await ledger.init_keysets()
     assert len(ledger.keysets) == 1
 
diff --git a/tests/test_wallet.py b/tests/test_wallet.py
index 16d59c8d..8e66f948 100644
--- a/tests/test_wallet.py
+++ b/tests/test_wallet.py
@@ -82,10 +82,7 @@ async def test_get_keys(wallet1: Wallet):
     keyset = keysets[0]
     assert keyset.id is not None
     # assert keyset.id_deprecated == "eGnEWtdJ0PIM"
-    if settings.debug_mint_only_deprecated:
-        assert keyset.id == "eGnEWtdJ0PIM"
-    else:
-        assert keyset.id == "009a1f293253e41e"
+    assert keyset.id == "009a1f293253e41e"
     assert isinstance(keyset.id, str)
     assert len(keyset.id) > 0
 
@@ -441,14 +438,10 @@ async def test_token_state(wallet1: Wallet):
 @pytest.mark.asyncio
 async def test_load_mint_keys_specific_keyset(wallet1: Wallet):
     await wallet1._load_mint_keys()
-    if settings.debug_mint_only_deprecated:
-        assert list(wallet1.keysets.keys()) == ["eGnEWtdJ0PIM"]
-    else:
-        assert list(wallet1.keysets.keys()) == ["009a1f293253e41e", "eGnEWtdJ0PIM"]
+    assert list(wallet1.keysets.keys()) == ["009a1f293253e41e"]
     await wallet1._load_mint_keys(keyset_id=wallet1.keyset_id)
     await wallet1._load_mint_keys(keyset_id="009a1f293253e41e")
     # expect deprecated keyset id to be present
-    await wallet1._load_mint_keys(keyset_id="eGnEWtdJ0PIM")
     await assert_err(
         wallet1._load_mint_keys(keyset_id="nonexistent"),
         KeysetNotFoundError(),
diff --git a/tests/test_wallet_restore.py b/tests/test_wallet_restore.py
index 9064235d..136425b3 100644
--- a/tests/test_wallet_restore.py
+++ b/tests/test_wallet_restore.py
@@ -8,7 +8,6 @@
 from cashu.core.base import Proof
 from cashu.core.crypto.secp import PrivateKey
 from cashu.core.errors import CashuError
-from cashu.core.settings import settings
 from cashu.wallet.wallet import Wallet
 from cashu.wallet.wallet import Wallet as Wallet1
 from cashu.wallet.wallet import Wallet as Wallet2
@@ -86,10 +85,6 @@ async def wallet3():
 
 
 @pytest.mark.asyncio
-@pytest.mark.skipif(
-    settings.debug_mint_only_deprecated,
-    reason="settings.debug_mint_only_deprecated is set",
-)
 async def test_bump_secret_derivation(wallet3: Wallet):
     await wallet3._init_private_key(
         "half depart obvious quality work element tank gorilla view sugar picture"