diff --git a/cashu/core/crypto/keys.py b/cashu/core/crypto/keys.py index 36fb7974..14d5b64f 100644 --- a/cashu/core/crypto/keys.py +++ b/cashu/core/crypto/keys.py @@ -3,7 +3,15 @@ import random from typing import Dict -from bip32 import BIP32 +# we import bip32 from embit if bip32 is not installed +try: + from bip32 import BIP32 + + use_bip32_lib = True +except ImportError: + from embit import bip32 # type: ignore + + use_bip32_lib = False from ..settings import settings from .secp import PrivateKey, PublicKey @@ -13,15 +21,28 @@ def derive_keys(mnemonic: str, derivation_path: str): """ Deterministic derivation of keys for 2^n values. """ - bip32 = BIP32.from_seed(mnemonic.encode()) - orders_str = [f"/{i}'" for i in range(settings.max_order)] - return { - 2**i: PrivateKey( - bip32.get_privkey_from_path(derivation_path + orders_str[i]), - raw=True, - ) - for i in range(settings.max_order) - } + if use_bip32_lib: + root = BIP32.from_seed(mnemonic.encode()) # type: ignore + orders_str = [f"/{i}'" for i in range(settings.max_order)] + return { + 2 + ** i: PrivateKey( + root.get_privkey_from_path(derivation_path + orders_str[i]), + raw=True, + ) + for i in range(settings.max_order) + } + else: + root = bip32.HDKey.from_seed(mnemonic.encode()) # type: ignore + orders_str = [f"/{i}'" for i in range(settings.max_order)] + return { + 2 + ** i: PrivateKey( + root.derive(derivation_path + orders_str[i]).key.serialize(), # type: ignore + raw=True, + ) + for i in range(settings.max_order) + } def derive_keys_sha256(seed: str, derivation_path: str = ""): @@ -30,7 +51,8 @@ def derive_keys_sha256(seed: str, derivation_path: str = ""): TODO: Implement BIP32. """ return { - 2**i: PrivateKey( + 2 + ** i: PrivateKey( hashlib.sha256((seed + derivation_path + str(i)).encode("utf-8")).digest()[ :32 ], diff --git a/cashu/mint/migrations.py b/cashu/mint/migrations.py index 2291288c..1c693bf8 100644 --- a/cashu/mint/migrations.py +++ b/cashu/mint/migrations.py @@ -439,6 +439,7 @@ async def m014_proofs_add_Y_column(db: Database): # we have to drop the balance views first and recreate them later await drop_balance_views(db, conn) + async with db.connect() as conn: await conn.execute( f"ALTER TABLE {table_with_schema(db, 'proofs_used')} ADD COLUMN Y TEXT" ) @@ -481,6 +482,7 @@ async def m014_proofs_add_Y_column(db: Database): ) await conn.execute(f"DROP TABLE {table_with_schema(db, 'proofs_used_old')}") + async with db.connect() as conn: # add column Y to proofs_pending await conn.execute( f"ALTER TABLE {table_with_schema(db, 'proofs_pending')} ADD COLUMN Y TEXT" @@ -527,6 +529,7 @@ async def m014_proofs_add_Y_column(db: Database): await conn.execute(f"DROP TABLE {table_with_schema(db, 'proofs_pending_old')}") + async with db.connect() as conn: # recreate the balance views await create_balance_views(db, conn)