git / moonbite-network / exchange.py · raw

"""MoonBite internal exchange — non-custodial order book.This module stores *order intents* only: a public offer to trade MBITE against aquote asset (LTC, BTC, or a USD stablecoin). It NEVER holds coins, private keys,or user balances. Settlement happens off this server via an atomic (HTLC) swapdirectly between the two parties' wallets — see settle_hint() for the hand-off.Because the server only matchmakes and never custodies funds, it stays a piece ofsoftware rather than a money transmitter. Keep it that way: do not add deposit,withdrawal, or fiat handling here."""from __future__ import annotationsimport hmacimport secretsimport sqlite3import threadingimport timeimport uuidfrom decimal import Decimal, InvalidOperationfrom pathlib import Pathfrom typing import Optionalfrom swap_verifier import VERIFIER_STATES# Pairs we support first. MBITE is always the base; the quote is what you pay/receive.# "ease" is an honest note surfaced in the UI: LTC/BTC swap natively with MoonBite# (shared Bitcoin script family); the stablecoin needs a smart-contract HTLC leg.SUPPORTED_PAIRS = {    "MBITE/LTC": {"quote": "LTC", "ease": "native", "quote_decimals": 8},    "MBITE/BTC": {"quote": "BTC", "ease": "native", "quote_decimals": 8},    "MBITE/USDT": {"quote": "USDT", "ease": "contract", "quote_decimals": 6},}SIDES = ("buy", "sell")  # buy = want MBITE (pay quote); sell = give MBITE (want quote)# Basic anti-abuse: cap simultaneously-open orders per MBITE address.MAX_OPEN_ORDERS_PER_ADDRESS = 20# --- Phase 2a: atomic-swap settlement coordination ------------------------- ## The server COORDINATES the HTLC hand-off and (from Phase 2b) VERIFIES it# on-chain; it never custodies coins or keys. Phase 2a records only the public# swap parameters and the parties' self-reported funding txids and advances a# state machine. On-chain verification, preimage extraction, the 'redeemed'/# 'settled' transitions, and price discovery all arrive in Phase 2b/2c — until# then a swap can progress no further than 'both_locked' and last_price stays# null (no trade is considered settled without independent on-chain proof).SWAP_STATES = (    "swap_init",     # HTLC parameters registered; nothing funded yet    "base_funded",   # MBITE-leg HTLC funding txid reported (unverified)    "quote_funded",  # quote-leg HTLC funding txid reported (unverified)    "both_locked",   # both legs' funding txids reported (awaiting 2b verify))# Phase 2b bolts the on-chain-verified tail onto the machine. These transitions# are driven ONLY by swap_verifier reading confirmed chain data — never by a# caller's report. See swap_verifier.VERIFIER_STATES for the definitions.ALL_SWAP_STATES = SWAP_STATES + VERIFIER_STATES# Columns swap_verifier is permitted to write back (whitelist: the status/txids/# preimage/confs/assurance it independently derives from chain data). Guards the# dynamic UPDATE in apply_swap_verification against arbitrary column writes._VERIFIER_WRITABLE = frozenset(    {        "status", "preimage", "base_redeem_txid", "quote_redeem_txid",        "base_confs", "quote_confs", "settled_at", "quote_assurance",    })# Swaps the verifier still needs to watch (everything before a terminal state)._VERIFIABLE_STATES = ("both_locked", "quote_redeemed", "base_redeemed")# Safety invariant: the party who redeems second must hold the longer refund# window, so the base (MBITE) timelock must exceed the quote timelock by at# least this margin. Locktimes are unix timestamps (seconds).MIN_TIMELOCK_GAP_SECONDS = 6 * 60 * 60  # 6 hours_DB_PATH = Path(__file__).with_name("exchange.db")_lock = threading.Lock()_conn: Optional[sqlite3.Connection] = Nonedef _connect() -> sqlite3.Connection:    global _conn    if _conn is None:        _conn = sqlite3.connect(str(_DB_PATH), check_same_thread=False)        _conn.row_factory = sqlite3.Row        _conn.execute(            """            CREATE TABLE IF NOT EXISTS orders (                id            TEXT PRIMARY KEY,                side          TEXT NOT NULL,                pair          TEXT NOT NULL,                price         TEXT NOT NULL,   -- quote per 1 MBITE, decimal string                amount        TEXT NOT NULL,   -- MBITE amount, decimal string                mbite_address TEXT NOT NULL,   -- maker's MBITE receive/send address                quote_address TEXT NOT NULL,   -- maker's address on the quote chain                status        TEXT NOT NULL DEFAULT 'open',                created_at    INTEGER NOT NULL,                cancel_token  TEXT             -- secret; returned once to the maker            )            """        )        # Migration for databases created before cancel_token existed.        cols = {r["name"] for r in _conn.execute("PRAGMA table_info(orders)")}        if "cancel_token" not in cols:            _conn.execute("ALTER TABLE orders ADD COLUMN cancel_token TEXT")        # Migration: record the crossing counter-order when a match is found.        if "matched_with" not in cols:            _conn.execute("ALTER TABLE orders ADD COLUMN matched_with TEXT")        # Phase 2a: atomic-swap settlement coordination. One row per matched        # order pair. Holds only PUBLIC swap parameters — no keys, no coins. The        # redeem/preimage/confs/settled_at columns are populated later by the        # on-chain verifier (Phase 2b/2c); in 2a they stay null/zero.        _conn.execute(            """            CREATE TABLE IF NOT EXISTS swaps (                swap_id            TEXT PRIMARY KEY,                buy_order_id       TEXT NOT NULL,                sell_order_id      TEXT NOT NULL,                pair               TEXT NOT NULL,                price              TEXT NOT NULL,   -- agreed execution (maker) price                amount             TEXT NOT NULL,   -- swappable MBITE = min(buy, sell)                hashlock           TEXT NOT NULL UNIQUE,  -- SHA256(preimage); anti-replay                base_recipient_pk  TEXT NOT NULL,   -- who claims the MBITE leg (hex)                base_refund_pk     TEXT NOT NULL,   -- who refunds the MBITE leg (hex)                quote_recipient_pk TEXT NOT NULL,   -- who claims the quote leg (hex)                quote_refund_pk    TEXT NOT NULL,   -- who refunds the quote leg (hex)                base_locktime      INTEGER NOT NULL,-- unix seconds; > quote_locktime                quote_locktime     INTEGER NOT NULL,-- unix seconds                base_htlc_txid     TEXT,            -- reported funding tx, MBITE leg                quote_htlc_txid    TEXT,            -- reported funding tx, quote leg                base_redeem_txid   TEXT,            -- filled by verifier (2b)                quote_redeem_txid  TEXT,            -- filled by verifier (2b)                preimage           TEXT,            -- extracted once public on-chain (2b)                base_confs         INTEGER NOT NULL DEFAULT 0,                quote_confs        INTEGER NOT NULL DEFAULT 0,                status             TEXT NOT NULL DEFAULT 'swap_init',                created_at         INTEGER NOT NULL,                settled_at         INTEGER          -- set only when fully verified (2c)            )            """        )        # Phase 2b migration: records HOW a settlement's quote leg was verified —        # 'node' (full-node read, fully trustless) vs 'explorer' (N-of-M explorer        # agreement, lower assurance). Surfaced so the UI never overstates trust.        swap_cols = {r["name"] for r in _conn.execute("PRAGMA table_info(swaps)")}        if "quote_assurance" not in swap_cols:            _conn.execute("ALTER TABLE swaps ADD COLUMN quote_assurance TEXT")        _conn.commit()    return _conndef _public(order: Optional[dict]) -> Optional[dict]:    """Strip the secret cancel_token from any order shown on a read path."""    if order is not None:        order.pop("cancel_token", None)    return orderdef _pos_decimal(value, field: str) -> Decimal:    try:        d = Decimal(str(value))    except (InvalidOperation, ValueError, TypeError):        raise ValueError(f"{field} must be a number")    if not d.is_finite():  # reject NaN / Infinity / -Infinity before any comparison        raise ValueError(f"{field} must be a finite number")    if d <= 0:        raise ValueError(f"{field} must be greater than zero")    # Bound magnitude/precision without quantize() (which throws on huge    # exponents like 1e400): adjusted() is the power of the leading digit,    # as_tuple().exponent < 0 counts fractional places.    if d.adjusted() > 20 or d.as_tuple().exponent < -20:        raise ValueError(f"{field} has too many digits")    return ddef _clean_address(value, field: str) -> str:    if not isinstance(value, str):        raise ValueError(f"{field} is required")    v = value.strip()    # Deliberately loose: we never spend from these, we only display them so the    # counterparty knows where to send. Reject only clearly-bogus input.    if not (6 <= len(v) <= 120) or any(c.isspace() for c in v):        raise ValueError(f"{field} does not look like a valid address")    return vdef create_order(    side: str,    pair: str,    price,    amount,    mbite_address: str,    quote_address: str,) -> dict:    """Validate and store a public order intent. Returns the stored order."""    if side not in SIDES:        raise ValueError("side must be 'buy' or 'sell'")    if pair not in SUPPORTED_PAIRS:        raise ValueError(f"unsupported pair: {pair}")    price_d = _pos_decimal(price, "price")    amount_d = _pos_decimal(amount, "amount")    mbite = _clean_address(mbite_address, "MBITE address")    quote = _clean_address(quote_address, f"{SUPPORTED_PAIRS[pair]['quote']} address")    with _lock:        conn = _connect()        open_count = conn.execute(            "SELECT COUNT(*) AS n FROM orders WHERE mbite_address = ? AND status = 'open'",            (mbite,),        ).fetchone()["n"]        if open_count >= MAX_OPEN_ORDERS_PER_ADDRESS:            raise ValueError(                f"too many open orders for this address (max {MAX_OPEN_ORDERS_PER_ADDRESS})"            )        order_id = uuid.uuid4().hex        cancel_token = secrets.token_urlsafe(24)        conn.execute(            """INSERT INTO orders               (id, side, pair, price, amount, mbite_address, quote_address,                status, created_at, cancel_token)               VALUES (?, ?, ?, ?, ?, ?, ?, 'open', ?, ?)""",            (                order_id,                side,                pair,                format(price_d, "f"),                format(amount_d, "f"),                mbite,                quote,                int(time.time()),                cancel_token,            ),        )        conn.commit()    # A newly-posted order may cross an existing resting order. If it does, flag    # both as 'matched' so the two makers can settle off-server. This is pure    # matchmaking: no funds are held or moved — settlement is a manual HTLC swap.    match = _try_match(order_id)    # Return the token ONCE, only to the maker who created the order. It is the    # secret proof-of-ownership required to cancel; it is never shown again.    order = get_order(order_id)    order["cancel_token"] = cancel_token    if match is not None:        order["matched_with"] = match    return orderdef _try_match(order_id: str) -> Optional[str]:    """If `order_id` crosses a resting opposite order, mark both 'matched'.    A buy (bid) crosses a sell (ask) when the bid price >= the ask price. We pick    the best price for the incoming taker (lowest ask for a buyer / highest bid    for a seller), breaking ties by oldest resting order (price-time priority).    Returns the counter-order id if matched, else None. Never routes funds.    """    with _lock:        conn = _connect()        row = conn.execute("SELECT * FROM orders WHERE id = ?", (order_id,)).fetchone()        if row is None or row["status"] != "open":            return None        taker = dict(row)        taker_price = Decimal(taker["price"])        if taker["side"] == "buy":            # Want the cheapest ask we can afford (ask price <= our bid).            candidates = conn.execute(                """SELECT * FROM orders                   WHERE pair = ? AND side = 'sell' AND status = 'open'                     AND id != ? AND mbite_address != ?                   ORDER BY CAST(price AS REAL) ASC, created_at ASC""",                (taker["pair"], order_id, taker["mbite_address"]),            ).fetchall()            counter = next(                (c for c in candidates if Decimal(c["price"]) <= taker_price), None            )        else:            # Selling: want the highest bid at or above our ask.            candidates = conn.execute(                """SELECT * FROM orders                   WHERE pair = ? AND side = 'buy' AND status = 'open'                     AND id != ? AND mbite_address != ?                   ORDER BY CAST(price AS REAL) DESC, created_at ASC""",                (taker["pair"], order_id, taker["mbite_address"]),            ).fetchall()            counter = next(                (c for c in candidates if Decimal(c["price"]) >= taker_price), None            )        if counter is None:            return None        conn.execute(            "UPDATE orders SET status = 'matched', matched_with = ? WHERE id = ?",            (counter["id"], order_id),        )        conn.execute(            "UPDATE orders SET status = 'matched', matched_with = ? WHERE id = ?",            (order_id, counter["id"]),        )        conn.commit()        return counter["id"]def list_orders(pair: Optional[str] = None, status: str = "open") -> dict:    """Return the order book for a pair, split into bids (buys) and asks (sells)."""    with _lock:        conn = _connect()        if pair is not None and pair not in SUPPORTED_PAIRS:            raise ValueError(f"unsupported pair: {pair}")        params = [status]        query = "SELECT * FROM orders WHERE status = ?"        if pair is not None:            query += " AND pair = ?"            params.append(pair)        rows = [_public(dict(r)) for r in conn.execute(query, params).fetchall()]    bids = sorted(        (r for r in rows if r["side"] == "buy"),        key=lambda r: Decimal(r["price"]),        reverse=True,  # highest buy price first    )    asks = sorted(        (r for r in rows if r["side"] == "sell"),        key=lambda r: Decimal(r["price"]),  # lowest sell price first    )    last_price = _last_trade_price(pair) if pair else None    return {"pair": pair, "bids": bids, "asks": asks, "last_price": last_price}def get_order(order_id: str) -> Optional[dict]:    with _lock:        conn = _connect()        row = conn.execute("SELECT * FROM orders WHERE id = ?", (order_id,)).fetchone()    return _public(dict(row)) if row else Nonedef cancel_order(order_id: str, cancel_token: str) -> dict:    """Cancel an open order.    Authorization is the secret `cancel_token` minted at creation and returned    only to the maker — NOT the MBITE address, which is public in the order book    and so cannot serve as a secret.    """    with _lock:        conn = _connect()        row = conn.execute("SELECT * FROM orders WHERE id = ?", (order_id,)).fetchone()        if row is None:            raise ValueError("order not found")        if row["status"] != "open":            raise ValueError(f"order is already {row['status']}")        stored = row["cancel_token"] or ""        provided = (cancel_token or "").strip()        if not stored or not hmac.compare_digest(stored, provided):            raise ValueError("invalid or missing cancel token")        conn.execute("UPDATE orders SET status = 'cancelled' WHERE id = ?", (order_id,))        conn.commit()    return get_order(order_id)def _last_trade_price(pair: str) -> Optional[str]:    """Most recent settled trade price for a pair — the internal price discovery."""    conn = _connect()    row = conn.execute(        "SELECT price FROM orders WHERE pair = ? AND status = 'settled' "        "ORDER BY created_at DESC LIMIT 1",        (pair,),    ).fetchone()    return row["price"] if row else Nonedef settle_hint(order_id: str) -> dict:    """Return the atomic-swap hand-off instructions for a matched order.    NOTE (Phase 2): the actual HTLC atomic-swap execution engine is not built yet.    This returns the addresses both parties need so they can perform the swap with    an external atomic-swap tool. Wiring an automated, trustless HTLC coordinator is    the next milestone; until then settlement is a guided/manual step. We must not    pretend the swap is automatic, and we must never route funds through the server.    """    order = get_order(order_id)    if order is None:        raise ValueError("order not found")    quote = SUPPORTED_PAIRS[order["pair"]]["quote"]    counterparty = None    if order.get("matched_with"):        counter = get_order(order["matched_with"])        if counter is not None:            counterparty = {                "order_id": counter["id"],                "side": counter["side"],                "price": counter["price"],                "amount": counter["amount"],                "mbite_address": counter["mbite_address"],                "quote_address": counter["quote_address"],            }    return {        "order": order,        "swap": {            "mechanism": "HTLC atomic swap (non-custodial)",            "base_asset": "MBITE",            "quote_asset": quote,            "maker_mbite_address": order["mbite_address"],            "maker_quote_address": order["quote_address"],            "counterparty": counterparty,            "status": "manual",            "note": (                "Automated HTLC swap coordination is not yet implemented (Phase 2). "                "Perform the swap directly wallet-to-wallet using an atomic-swap tool. "                "The server never holds either side's coins."            ),        },    }# --------------------------------------------------------------------------- ## Phase 2a: atomic-swap settlement coordination## These functions record the HTLC hand-off for a matched order pair and track# self-reported funding, advancing a small state machine. They perform NO# on-chain verification and move NO funds — that is Phase 2b/2c. A swap cannot# progress past 'both_locked' here, and nothing is ever marked 'settled', so# price discovery (last_price) is untouched. The parameters recorded are all# public (hashlock, pubkeys, timelocks, txids); no secret or key is accepted.# --------------------------------------------------------------------------- #def _hexish(value, field: str, min_len: int, max_len: int) -> str:    """Validate a lowercase hex string (optional 0x prefix) of a bounded length."""    if not isinstance(value, str):        raise ValueError(f"{field} is required")    v = value.strip().lower()    if v.startswith("0x"):        v = v[2:]    if not (min_len <= len(v) <= max_len) or any(c not in "0123456789abcdef" for c in v):        raise ValueError(f"{field} must be hex of {min_len}-{max_len} chars")    return vdef _authorize_order(conn, order_id: str, cancel_token) -> dict:    """Return the order row iff the cancel_token proves ownership, else raise.    Reuses the per-order secret minted at creation: a caller proves they own one    side of the matched pair by presenting that order's cancel_token. The address    is public and so cannot serve as the secret.    """    row = conn.execute("SELECT * FROM orders WHERE id = ?", (order_id,)).fetchone()    if row is None:        raise ValueError("order not found")    stored = row["cancel_token"] or ""    provided = (cancel_token or "").strip()    if not stored or not hmac.compare_digest(stored, provided):        raise ValueError("invalid or missing cancel token")    return dict(row)def get_swap(order_id: str) -> Optional[dict]:    """Return the swap coordinating settlement for a matched order, or None.    A read path: no secret to strip (every stored field is public). Callable by    anyone, since the swap parameters are the public hand-off both parties need.    """    with _lock:        conn = _connect()        row = conn.execute(            "SELECT * FROM swaps WHERE buy_order_id = ? OR sell_order_id = ?",            (order_id, order_id),        ).fetchone()    return dict(row) if row else Nonedef init_swap(    order_id: str,    cancel_token,    hashlock,    base_recipient_pk,    base_refund_pk,    quote_recipient_pk,    quote_refund_pk,    base_locktime,    quote_locktime,) -> dict:    """Register the HTLC hand-off for a matched order pair (Phase 2a).    Records only PUBLIC swap parameters so both legs can later be verified    on-chain (Phase 2b). Never accepts a private key or preimage; never moves    funds. Auth: the caller proves they own one side via its cancel_token.    """    with _lock:        conn = _connect()        order = _authorize_order(conn, order_id, cancel_token)        if order["status"] != "matched":            raise ValueError(f"order is {order['status']}, not matched")        counter_id = order.get("matched_with")        counter_row = conn.execute(            "SELECT * FROM orders WHERE id = ?", (counter_id,)        ).fetchone()        if counter_row is None:            raise ValueError("counterparty order not found")        counter = dict(counter_row)        # At most one swap per order pair (either party may have started it).        existing = conn.execute(            "SELECT 1 FROM swaps WHERE buy_order_id IN (?, ?) OR sell_order_id IN (?, ?)",            (order_id, counter_id, order_id, counter_id),        ).fetchone()        if existing is not None:            raise ValueError("a swap already exists for this order pair")        # Hashlock: SHA256 digest (32 bytes = 64 hex). Must be globally fresh.        h = _hexish(hashlock, "hashlock", 64, 64)        if conn.execute("SELECT 1 FROM swaps WHERE hashlock = ?", (h,)).fetchone():            raise ValueError("hashlock already used; use a fresh secret")        # Pubkeys / pubkey-hashes: hex, 20-byte hash (40) up to uncompressed (130).        b_recip = _hexish(base_recipient_pk, "base_recipient_pubkey", 40, 130)        b_refund = _hexish(base_refund_pk, "base_refund_pubkey", 40, 130)        q_recip = _hexish(quote_recipient_pk, "quote_recipient_pubkey", 40, 130)        q_refund = _hexish(quote_refund_pk, "quote_refund_pubkey", 40, 130)        try:            b_lock = int(base_locktime)            q_lock = int(quote_locktime)        except (TypeError, ValueError):            raise ValueError("locktimes must be integers (unix seconds)")        if b_lock <= 0 or q_lock <= 0:            raise ValueError("locktimes must be positive")        if q_lock >= b_lock:            raise ValueError("quote_locktime must be earlier than base_locktime")        if b_lock - q_lock < MIN_TIMELOCK_GAP_SECONDS:            raise ValueError(                "timelock gap too small; base must exceed quote by "                f">= {MIN_TIMELOCK_GAP_SECONDS} seconds"            )        # Resolve buy/sell sides and the agreed execution terms. Trades execute at        # the resting (maker = earlier-created) order's price; the swappable size        # is the smaller of the two orders (no partial-fill accounting here).        if order["side"] == "buy":            buy, sell = order, counter        else:            buy, sell = counter, order        # The maker is the resting order that was crossed. created_at is only        # second-resolution, so same-second matches tie; break the tie by rowid        # (insertion order), which the resting order always wins.        maker_id = conn.execute(            "SELECT id FROM orders WHERE id IN (?, ?) "            "ORDER BY created_at ASC, rowid ASC LIMIT 1",            (order["id"], counter["id"]),        ).fetchone()["id"]        price = order["price"] if maker_id == order["id"] else counter["price"]        amount = min(Decimal(buy["amount"]), Decimal(sell["amount"]))        swap_id = uuid.uuid4().hex        conn.execute(            """INSERT INTO swaps               (swap_id, buy_order_id, sell_order_id, pair, price, amount,                hashlock, base_recipient_pk, base_refund_pk,                quote_recipient_pk, quote_refund_pk, base_locktime, quote_locktime,                status, created_at)               VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,'swap_init',?)""",            (                swap_id, buy["id"], sell["id"], order["pair"], price,                format(amount, "f"), h, b_recip, b_refund, q_recip, q_refund,                b_lock, q_lock, int(time.time()),            ),        )        conn.commit()        row = conn.execute(            "SELECT * FROM swaps WHERE swap_id = ?", (swap_id,)        ).fetchone()    return dict(row)def report_funding(order_id: str, cancel_token, leg: str, txid) -> dict:    """Record a self-reported HTLC funding txid for one leg (Phase 2a).    Stores the report and advances the state machine to base_funded / quote_funded    / both_locked. It does NOT verify the tx on-chain — that is Phase 2b — and it    never treats a report as settlement. Auth: the order's cancel_token.    """    if leg not in ("base", "quote"):        raise ValueError("leg must be 'base' or 'quote'")    tx = _hexish(txid, "txid", 64, 64)    with _lock:        conn = _connect()        _authorize_order(conn, order_id, cancel_token)        row = conn.execute(            "SELECT * FROM swaps WHERE buy_order_id = ? OR sell_order_id = ?",            (order_id, order_id),        ).fetchone()        if row is None:            raise ValueError("no swap for this order; call swap/init first")        if row["status"] not in ("swap_init", "base_funded", "quote_funded"):            raise ValueError(f"swap is {row['status']}; cannot report funding")        # `col` is chosen from string literals, never from user input — safe.        col = "base_htlc_txid" if leg == "base" else "quote_htlc_txid"        conn.execute(            f"UPDATE swaps SET {col} = ? WHERE swap_id = ?", (tx, row["swap_id"])        )        cur = conn.execute(            "SELECT base_htlc_txid, quote_htlc_txid FROM swaps WHERE swap_id = ?",            (row["swap_id"],),        ).fetchone()        if cur["base_htlc_txid"] and cur["quote_htlc_txid"]:            new_status = "both_locked"        elif cur["base_htlc_txid"]:            new_status = "base_funded"        else:            new_status = "quote_funded"        conn.execute(            "UPDATE swaps SET status = ? WHERE swap_id = ?",            (new_status, row["swap_id"]),        )        conn.commit()        final = conn.execute(            "SELECT * FROM swaps WHERE swap_id = ?", (row["swap_id"],)        ).fetchone()    return dict(final)# --------------------------------------------------------------------------- ## Phase 2b: on-chain verification hand-off.## The verifier (swap_verifier.py) READS the chains and independently decides how# far a swap has genuinely progressed. exchange.py stays the sole DB owner: it# hands the verifier the swaps that still need watching and applies the verified# result. Only a swap the verifier drives to 'settled' marks its two orders# 'settled' — the single event that lets _last_trade_price (and thus last_price)# reflect a real, on-chain-proven trade. No caller can reach these transitions.# --------------------------------------------------------------------------- #def list_swaps_for_verification() -> list:    """Return swaps still awaiting on-chain progress (non-terminal, funded)."""    with _lock:        conn = _connect()        placeholders = ",".join("?" for _ in _VERIFIABLE_STATES)        rows = conn.execute(            f"SELECT * FROM swaps WHERE status IN ({placeholders})",            _VERIFIABLE_STATES,        ).fetchall()    return [dict(r) for r in rows]def apply_swap_verification(swap_id: str, updates: dict) -> Optional[dict]:    """Persist the verifier's independently-derived findings for one swap.    Only whitelisted, verifier-owned columns may be written. If the swap reaches    'settled', both underlying orders are marked 'settled' in the SAME    transaction so price discovery and settlement flip atomically. A no-op    ``updates`` leaves the row untouched.    """    clean = {k: v for k, v in (updates or {}).items() if k in _VERIFIER_WRITABLE}    if not clean:        return get_swap_by_id(swap_id)    if clean.get("status") is not None and clean["status"] not in ALL_SWAP_STATES:        raise ValueError(f"illegal swap status: {clean['status']}")    with _lock:        conn = _connect()        row = conn.execute(            "SELECT * FROM swaps WHERE swap_id = ?", (swap_id,)        ).fetchone()        if row is None:            raise ValueError("no such swap")        assignments = ", ".join(f"{col} = ?" for col in clean)  # cols are whitelisted        conn.execute(            f"UPDATE swaps SET {assignments} WHERE swap_id = ?",            (*clean.values(), swap_id),        )        if clean.get("status") == "settled":            # Atomically record the executed trade on both orders so the pair's            # last_price finally reflects an on-chain-proven fill.            conn.execute(                "UPDATE orders SET status = 'settled' WHERE id IN (?, ?)",                (row["buy_order_id"], row["sell_order_id"]),            )        conn.commit()        final = conn.execute(            "SELECT * FROM swaps WHERE swap_id = ?", (swap_id,)        ).fetchone()    return dict(final)def get_swap_by_id(swap_id: str) -> Optional[dict]:    """Fetch a swap by its primary key (verifier/introspection helper)."""    with _lock:        conn = _connect()        row = conn.execute(            "SELECT * FROM swaps WHERE swap_id = ?", (swap_id,)        ).fetchone()    return dict(row) if row else None