Files
nutshell/cashu/mint/startup.py
callebtc a0ef44dba0 Blind authentication (#675)
* auth server

* cleaning up

* auth ledger class

* class variables -> instance variables

* annotations

* add models and api route

* custom amount and api prefix

* add auth db

* blind auth token working

* jwt working

* clean up

* JWT works

* using openid connect server

* use oauth server with password flow

* new realm

* add keycloak docker

* hopefully not garbage

* auth works

* auth kinda working

* fix cli

* auth works for send and receive

* pass auth_db to Wallet

* auth in info

* refactor

* fix supported

* cache mint info

* fix settings and endpoints

* add description to .env.example

* track changes for openid connect client

* store mint in db

* store credentials

* clean up v1_api.py

* load mint info into auth wallet

* fix first login

* authenticate if refresh token fails

* clear auth also middleware

* use regex

* add cli command

* pw works

* persist keyset amounts

* add errors.py

* do not start auth server if disabled in config

* upadte poetry

* disvoery url

* fix test

* support device code flow

* adopt latest spec changes

* fix code flow

* mint max bat dynamic

* mypy ignore

* fix test

* do not serialize amount in authproof

* all auth flows working

* fix tests

* submodule

* refactor

* test

* dont sleep

* test

* add wallet auth tests

* test differently

* test only keycloak for now

* fix creds

* daemon

* fix test

* install everything

* install jinja

* delete wallet for every test

* auth: use global rate limiter

* test auth rate limit

* keycloak hostname

* move keycloak test data

* reactivate all tests

* add readme

* load proofs

* remove unused code

* remove unused code

* implement change suggestions by ok300

* add error codes

* test errors
2025-01-29 22:48:51 -06:00

127 lines
3.9 KiB
Python

# startup routine of the standalone app. These are the steps that need
# to be taken by external apps importing the cashu mint.
import asyncio
import importlib
from typing import Dict
from loguru import logger
from ..core.base import Method, Unit
from ..core.db import Database
from ..core.migrations import migrate_databases
from ..core.settings import settings
from ..lightning.base import LightningBackend
from ..mint import migrations as mint_migrations
from ..mint.auth import migrations as auth_migrations
from ..mint.auth.server import AuthLedger
from ..mint.crud import LedgerCrudSqlite
from ..mint.ledger import Ledger
# kill the program if python runs in non-__debug__ mode
# which could lead to asserts not being executed for optimized code
if not __debug__:
raise Exception("Nutshell cannot run in non-debug mode.")
logger.debug("Enviroment Settings:")
for key, value in settings.dict().items():
if key in [
"mint_private_key",
"mint_seed_decryption_key",
"nostr_private_key",
"mint_lnbits_key",
"mint_blink_key",
"mint_strike_key",
"mint_lnd_rest_macaroon",
"mint_lnd_rest_admin_macaroon",
"mint_lnd_rest_invoice_macaroon",
"mint_corelightning_rest_macaroon",
"mint_clnrest_rune",
]:
value = "********" if value is not None else None
if key == "mint_database" and value and value.startswith("postgres://"):
value = "postgres://********"
logger.debug(f"{key}: {value}")
wallets_module = importlib.import_module("cashu.lightning")
backends: Dict[Method, Dict[Unit, LightningBackend]] = {}
if settings.mint_backend_bolt11_sat:
backend_bolt11_sat = getattr(wallets_module, settings.mint_backend_bolt11_sat)(
unit=Unit.sat
)
backends.setdefault(Method.bolt11, {})[Unit.sat] = backend_bolt11_sat
if settings.mint_backend_bolt11_usd:
backend_bolt11_usd = getattr(wallets_module, settings.mint_backend_bolt11_usd)(
unit=Unit.usd
)
backends.setdefault(Method.bolt11, {})[Unit.usd] = backend_bolt11_usd
if settings.mint_backend_bolt11_eur:
backend_bolt11_eur = getattr(wallets_module, settings.mint_backend_bolt11_eur)(
unit=Unit.eur
)
backends.setdefault(Method.bolt11, {})[Unit.eur] = backend_bolt11_eur
if not backends:
raise Exception("No backends are set.")
if not settings.mint_private_key:
raise Exception("No mint private key is set.")
ledger = Ledger(
db=Database("mint", settings.mint_database),
seed=settings.mint_private_key,
seed_decryption_key=settings.mint_seed_decryption_key,
derivation_path=settings.mint_derivation_path,
backends=backends,
crud=LedgerCrudSqlite(),
)
# start auth ledger
auth_ledger = AuthLedger(
db=Database("auth", settings.auth_database),
seed="auth seed here",
amounts=[1],
derivation_path="m/0'/999'/0'",
crud=LedgerCrudSqlite(),
)
async def rotate_keys(n_seconds=60):
"""Rotate keyset epoch every n_seconds.
Note: This is just a helper function for testing purposes.
"""
i = 0
while True:
i += 1
logger.info("Rotating keys.")
incremented_derivation_path = (
f"{'/'.join(ledger.derivation_path.split('/')[:-1])}/{i}"
)
await ledger.activate_keyset(derivation_path=incremented_derivation_path)
logger.info(f"Current keyset: {ledger.keyset.id}")
await asyncio.sleep(n_seconds)
async def start_auth():
await migrate_databases(auth_ledger.db, auth_migrations)
logger.info("Starting auth ledger.")
await auth_ledger.init_keysets()
await auth_ledger.init_auth()
logger.info("Auth ledger started.")
async def start_mint():
await migrate_databases(ledger.db, mint_migrations)
logger.info("Starting mint ledger.")
await ledger.startup_ledger()
logger.info("Mint started.")
# asyncio.create_task(rotate_keys())
async def shutdown_mint():
await ledger.shutdown_ledger()
logger.info("Mint shutdown.")
logger.remove()