Durable Cashu issuance
acorn.minting.DurableCashuMint is an additive API for callers that persist an
encrypted issuance checkpoint. It moves the restore-first issuance path from
OakGate into Acorn. Existing Acorn.deposit, mint, polling, Clear and transfer
methods are unchanged; Safebox Web need not adopt this API or change its calls.
Responsibilities
Acorn owns quote validation, Cashu blinding, mint requests, NUT-09 restoration, signature and optional DLEQ verification, and proof construction. The caller owns authorization, mint endpoint configuration, encrypted durable storage, job leases, retry scheduling and user presentation. This API neither uses a user private key nor publishes wallet events. Publish proofs and history through the existing Acorn APIs, with their own persisted prepared events.
Calling sequence
from acorn.minting import DurableCashuMint
mint = DurableCashuMint(require_description_hash=False)
item = {"mint": configured_mint_url, "amount": 13}
item.update(await mint.quote(item["mint"], item["amount"], description))
item["prepared"] = await mint.prepare(item)
# Durably encrypt and save item BEFORE returning its invoice to the payer.
# Later, under a per-quote lease:
state = await mint.state(item)
if state.get("state") in {"PAID", "ISSUED"} or state.get("paid") is True:
item["proofs"] = await mint.issue(item)
# Durably save proofs BEFORE publishing them through the wallet API.
quote returns quote, invoice, expiry and description_hash_bound.
With require_description_hash=False, missing or mismatched description hashes
are accepted; the binding flag is informational. Explicit strict mode continues
to require a matching hash. Amount, network, expiry and recovery checks are unchanged.
It requires NUT-09 support and validates the invoice amount, mainnet network and
expiry. Description-hash binding remains optional by default; a hash supplied
by the mint must match, and strict mode requires it.
prepare takes mint and integer sat amount, reads active mint keys, and
returns a JSON-compatible object containing outputs, secrets, and keys.
Each secret entry contains secret, r, and Y. All of this material is
sensitive. Save it encrypted; do not log it or return it to a browser.
issue takes mint, quote, and the exact persisted prepared object. It
calls restore first and matches restored signatures by blinded output, even if
the mint reverses their order. Only an empty restore proceeds to issuance,
using the same outputs. Partial restoration, incomplete responses, mismatched
amounts/keysets or invalid supplied DLEQ proofs raise errors rather than
creating a replacement checkpoint. Do not discard unresolved checkpoints or
blindly retry by calling prepare again.
The application must serialize each quote and save each phase before exposing its result. This library does not itself guarantee persistence or coordinate multiple workers. After an ambiguous issuance result, a fresh API instance can resume with the same checkpoint; successful restoration reconstructs the same proofs without issuing again. Mint availability and correct NUT-09 retention remain external requirements.
Compatibility
The persisted format is unchanged from OakGate's original Cashu adapter.
Existing in-flight prepared payloads and proof dictionaries require no schema
migration. There is no new dependency and no change to mint acceptance policy.
OakGate retains compatibility imports for its old adapter names, but production
must install an Acorn revision containing this module before using them.