Bitcoin Forum
April 10, 2026, 08:20:02 PM *
News: Latest Bitcoin Core release: 30.2 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Minimal standalone Chaumian mint boundary service  (Read 9 times)
reikagi (OP)
Newbie
*
Offline Offline

Activity: 18
Merit: 0


View Profile
April 09, 2026, 06:51:09 AM
 #1

finalis-mint
So far, an idea with minimal implementation
The code and ideas are open to everyone. I'm interested in diverse thoughts and perspectives, and I need support.

Minimal standalone Chaumian mint boundary service for local development and integration work.

This service is intentionally outside consensus.  It consumes the JSON contracts described in:

    [*] the HTTP handlers implemented in server.py
    [*] the finalized-state lightserver surface documented in LIVE_PROTOCOL.md
    [/list]

    It is a narrow scaffold, not a production mint:

      [*] file-backed state
      [*] deterministic RSA blind-signing for development/testing
      [*] persistent issuance ledger
      [*] reserve and accounting summary endpoints
      [*] reserve wallet inventory / fragmentation reporting
      [*] max-input coin selection policy and reserve alerts
      [*] automatic redemption settlement using a configured reserve wallet
      [*] lightserver-backed redemption finalization (pending -> broadcast -> finalized/rejected)
      [*] HMAC-signed operator admin requests
      [*] persistent notifier delivery job queue
      [*] optional single-worker leader lock for queue draining
      [*] notifier secret refs resolved through a pluggable secret backend adapter
      [*] signed reserve attestations / audit exports
      [*] no federation
      [*] no multi-operator quorum custody
      [/list]

      Endpoints

        [*] POST /deposits/register
        [*] POST /issuance/blind
        [*] POST /redemptions/create
        [*] POST /redemptions/approve_broadcast
        [*] POST /reserves/consolidate
        [*] POST /redemptions/status
        [*] POST /redemptions/update
        [*] POST /policy/redemptions
        [*] GET /healthz
        [*] GET /mint/key
        [*] GET /reserves
        [*] GET /reserves/consolidate_plan
        [*] GET /policy/redemptions
        [*] GET /monitoring/reserve_health
        [*] GET /monitoring/alerts/history
        [*] GET /monitoring/events/policy
        [*] GET /monitoring/events/silences
        [*] GET /monitoring/notifiers
        [*] GET /monitoring/dead_letters
        [*] GET /monitoring/incidents/export
        [*] GET /monitoring/metrics
        [*] GET /monitoring/worker
        [*] GET /dashboard
        [*] GET /dashboard/incidents
        [*] POST /monitoring/dead_letters/replay
        [*] GET /accounting/summary
        [*] GET /operator/key
        [*] GET /attestations/reserves
        [*] GET /audit/export (operator-signed request required)
        [/list]

        Run

        Code:
        python3 services/finalis-mint/server.py \
          --host 127.0.0.1 \
          --port 8080 \
          --state-file /tmp/finalis-mint-state.json \
          --confirmations-required 1 \
          --operator-key dev-operator:1111111111111111111111111111111111111111111111111111111111111111 \
          --lightserver-url http://127.0.0.1:19444/rpc \
          --reserve-privkey 5555555555555555555555555555555555555555555555555555555555555555 \
          --reserve-address sc1...  \
          --reserve-fee 1000 \
          --cli-path ./build/finalis-cli \
          --notifier-retry-interval-seconds 5 \
          --notifier-secrets-file /etc/finalis-mint/notifier-secrets.json \
          --notifier-secret-dir /etc/finalis-mint/secrets.d \
          --notifier-secret-env-prefix FINALIS_MINT_SECRET_ \
          --notifier-secret-backend auto \
          --notifier-secret-helper-cmd "" \
          --worker-lock-file /var/lib/finalis-mint/worker.lock

        --confirmations-required is a legacy flag name.  In the current code it acts as the required finalized-depth threshold reported by lightserver get_tx_status.

        Run a separate worker process:

        Code:
        python3 services/finalis-mint/server.py \
          --mode worker \
          --state-file /tmp/finalis-mint-state.json \
          --operator-key dev-operator:1111111111111111111111111111111111111111111111111111111111111111 \
          --lightserver-url http://127.0.0.1:19444/rpc \
          --reserve-privkey 5555555555555555555555555555555555555555555555555555555555555555 \
          --reserve-address sc1...  \
          --cli-path ./build/finalis-cli \
          --notifier-retry-interval-seconds 5 \
          --notifier-secret-backend auto \
          --notifier-secret-dir /etc/finalis-mint/secrets.d \
          --worker-lock-file /var/lib/finalis-mint/worker.lock \
          --worker-stale-timeout-seconds 30

        Example with finalis-cli

        Code:
        ./build/finalis-cli mint_deposit_register \
          --url http://127.0.0.1:8080/deposits/register \
          --deposit-txid 1111111111111111111111111111111111111111111111111111111111111111 \
          --deposit-vout 0 \
          --mint-id 2222222222222222222222222222222222222222222222222222222222222222 \
          --recipient-address sc1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaczjbkjy \
          --amount 100000

        The response now reports finalization_depth_required as the primary finalized-state threshold.  confirmations_required may still appear as a compatibility alias during migration.

        Code:
        ./build/finalis-cli mint_redeem_status \
          --url http://127.0.0.1:8080/redemptions/status \
          --batch-id <opaque-id>

        The redemption status response reports finalization_depth as the primary progress field.  confirmations may still appear as a compatibility alias.

        Code:
        ./build/finalis-cli mint_issue_blinds \
          --url http://127.0.0.1:8080/issuance/blind \
          --mint-deposit-ref <opaque-id> \
          --blind blind-msg-1 --note-amount 40000 \
          --blind blind-msg-2 --note-amount 60000

        Code:
        ./build/finalis-cli mint_redeem_create \
          --url http://127.0.0.1:8080/redemptions/create \
          --redeem-address sc1...  \
          --amount 100000 \
          --note <note-ref-1> \
          --note <note-ref-2>

        Code:
        ./build/finalis-cli mint_redeem_approve_broadcast \
          --url http://127.0.0.1:8080/redemptions/approve_broadcast \
          --batch-id <opaque-id> \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111

        Code:
        ./build/finalis-cli mint_reserve_consolidate \
          --url http://127.0.0.1:8080/reserves/consolidate \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111

        Code:
        ./build/finalis-cli mint_reserve_consolidation_plan \
          --url http://127.0.0.1:8080/reserves/consolidate_plan \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111

        Code:
        ./build/finalis-cli mint_reserve_health \
          --url http://127.0.0.1:8080/monitoring/reserve_health

        Code:
        ./build/finalis-cli mint_reserve_metrics \
          --url http://127.0.0.1:8080/monitoring/metrics

        ./build/finalis-cli mint_alert_history \
          --url http://127.0.0.1:8080/monitoring/alerts/history

        ./build/finalis-cli mint_event_policy \
          --url http://127.0.0.1:8080/monitoring/events/policy

        ./build/finalis-cli mint_alert_silences \
          --url http://127.0.0.1:8080/monitoring/events/silences

        ./build/finalis-cli mint_notifier_list \
          --url http://127.0.0.1:8080/monitoring/notifiers

        ./build/finalis-cli mint_dead_letters \
          --url http://127.0.0.1:8080/monitoring/dead_letters

        ./build/finalis-cli mint_incident_timeline_export \
          --url http://127.0.0.1:8080/monitoring/incidents/export

        ./build/finalis-cli mint_dead_letter_replay \
          --url http://127.0.0.1:8080/monitoring/dead_letters/replay \
          --dead-letter-id <dead-letter-id> \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111

        Code:
        ./build/finalis-cli mint_redemptions_pause \
          --url http://127.0.0.1:8080/policy/redemptions \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111 \
          --reason "reserve low"

        ./build/finalis-cli mint_redemptions_resume \
          --url http://127.0.0.1:8080/policy/redemptions \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111

        ./build/finalis-cli mint_redemptions_auto_pause_enable \
          --url http://127.0.0.1:8080/policy/redemptions \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111

        ./build/finalis-cli mint_redemptions_auto_pause_disable \
          --url http://127.0.0.1:8080/policy/redemptions \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111

        ./build/finalis-cli mint_alert_ack \
          --url http://127.0.0.1:8080/monitoring/events/ack \
          --event-id <event-id> \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111 \
          --note "seen"

        ./build/finalis-cli mint_alert_silence \
          --url http://127.0.0.1:8080/monitoring/events/silence \
          --event-type policy.auto_pause \
          --until 4102444800 \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111 \
          --reason "maintenance"

        ./build/finalis-cli mint_event_policy_update \
          --url http://127.0.0.1:8080/monitoring/events/policy \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111 \
          --retention-limit 128 \
          --export-include-acknowledged false

        ./build/finalis-cli mint_notifier_upsert \
          --url http://127.0.0.1:8080/monitoring/notifiers \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111 \
          --notifier-id ops-webhook \
          --kind webhook \
          --target http://127.0.0.1:9099/webhook \
          --auth-type bearer \
          --auth-token-secret-ref ops_webhook_bearer \
          --tls-verify true \
          --retry-max-attempts 3 \
          --retry-backoff-seconds 30

        Code:
        curl http://127.0.0.1:8080/accounting/summary
        curl http://127.0.0.1:8080/reserves
        curl http://127.0.0.1:8080/operator/key
        curl http://127.0.0.1:8080/attestations/reserves
        ./build/finalis-cli mint_audit_export \
          --url http://127.0.0.1:8080/audit/export \
          --operator-key-id dev-operator \
          --operator-secret-hex 1111111111111111111111111111111111111111111111111111111111111111

        Notes

          [*] Deposit references are deterministic hashes of (txid, vout, mint_id).
          [*] Blind issuance responses are deterministic RSA blind signatures derived from a local seed.
          [*] Each issuance creates persistent note_ref entries with explicit denominations.
          [*] If a reserve wallet and lightserver are configured, signed operators can approve pending redemptions for automatic L1 tx construction and broadcast.
          [*] Broadcasted reserve inputs are excluded from spendable reserve inventory.  Pending in-flight reserve usage is tracked separately via pending_spend_commitment_count and pending_spend_input_count.
          [*] Coin selection uses smallest-sufficient-non-dust-change with min_change=1000 and max_inputs=8; if no non-dust change set can be formed within the max-input budget, the redemption stays pending.
          [*] Redemption batches that cannot yet be funded stay pending; operators may reject them, but broadcast must go through /redemptions/approve_broadcast.
          [*] finalized is derived from observed L1 tx status via the configured lightserver.
          [*] /reserves includes live reserve-wallet UTXO count/value, locked UTXO count/value, simple fragmentation metrics, operator-facing alert fields such as reserve exhaustion risk, max-input pressure, and fragmentation threshold breach, and the active coin-selection thresholds when lightserver + reserve address are configured.
          [*] /policy/redemptions now includes auto-pause recommendations and threshold metadata derived from the current reserve state.
          [*] /reserves/consolidate_plan includes an estimated_post_action section so operators can see expected post-consolidation fragmentation before broadcasting.
          [*] /monitoring/reserve_health provides a compact monitoring/export summary with healthy|warn|critical status, current alert booleans, and the current auto-pause recommendation.
          [*] /monitoring/worker exposes worker leadership / lock-owner state.
          [*] /monitoring/worker also exposes stale lease detection and takeover policy.
          [*] /monitoring/alerts/history provides the recent persisted operator/auto-pause event log.
          [*] /monitoring/events/policy exposes event retention/export settings.
          [*] /monitoring/events/silences exposes active and expired silences.
          [*] /monitoring/notifiers exposes configured notifier hooks.
          [*] /monitoring/dead_letters exposes failed notifier deliveries that exhausted retries.
          [*] /monitoring/incidents/export exposes a signed incident timeline including events, silences, dead letters, and notifier state.
          [*] /dashboard and /dashboard/incidents expose a minimal operator HTML view over reserve health, recent events, queue state, and incident data.
          [*] POST /monitoring/dead_letters/replay requeues a dead-lettered delivery and retries it immediately.
          [*] /monitoring/metrics exports Prometheus-style reserve, pause, and alert counters.
          [*] Notifier hooks currently support:
            [*] webhook
            [*] alertmanager
            [*] email_spool for local .eml drop delivery
            [/list]
            [*] Each notifier supports:
              [*] retry_max_attempts
              [*] retry_backoff_seconds
              [/list]
              [*] webhook and alertmanager notifiers also support:
                [*] auth_type=none|bearer|basic
                [*] auth_token_secret_ref
                [*] auth_user_secret_ref
                [*] auth_pass_secret_ref
                [*] tls_verify
                [*] tls_ca_file
                [/list]
                [*] tls_client_cert_file
                [*] tls_client_key_file
                [*] The service runs a background retry worker (--notifier-retry-interval-seconds) backed by a persisted delivery job queue, so retries survive restart and do not depend on request traffic.
                [*] --mode server runs only the HTTP service.
                [*] --mode worker runs only the queue worker.
                [*] --mode all keeps the old combined behavior when needed.
                [*] If --worker-lock-file is configured, the worker uses a renewable lease file with stale-timeout takeover policy.
                [*] Secret values can come from:
                  [*] --notifier-secret-dir as one file per secret ref
                  [*] FINALIS_MINT_SECRET_<REF> environment variables
                  [*] --notifier-secrets-file as a fallback JSON map
                  [/list]
                  [*] Or from --notifier-secret-helper-cmd <cmd> when --notifier-secret-backend=command; the ref is appended as the final argument.
                  [*] A helper implementation is included at secret_helper.py.
                  [*] --notifier-secret-backend may be auto|dir|env|json|command.
                  [*] The state file stores refs, not the secret values themselves.
                  [/list]

                  systemd units

                  Example split units and env file template live in:

                    [*] finalis-mint-server.service
                    [*] finalis-mint-worker.service
                    [*] finalis-mint.env.example
                    [*] finalis-mint.tmpfiles.conf
                    [*] install_finalis_mint.sh
                    [*] smoke_deploy.sh
                    [/list]

                    The install helper also places:

                      [*] secret_helper.py as /usr/local/libexec/finalis-mint-secret-helper
                      [/list]

                      Operator deployment should follow the service flags and systemd examples in this directory.

                      Event entries now include per-notifier delivery status in their deliveries map.

                      Signed operators can explicitly trigger reserve consolidation; the service persists consolidation records and includes them in audit export.

                      Signed operators can pause new redemptions and inspect a dry-run consolidation plan before broadcasting reserve actions.

                      POST /redemptions/update and GET /audit/export require signed operator headers:
                        [*] X-Finalis-Operator-Key
                        [*] X-Finalis-Timestamp
                        [*] X-Finalis-Signature
                        [/list]

                        Reserve/accounting/attestation endpoints are derived from persisted deposits, issuances, note records, and redemption state.

                        Service tests

                        Code:
                        python3 -m unittest services/finalis-mint/test_state.py
                        python3 -m unittest services/finalis-mint/test_packaging.py
                        python3 -m unittest services/finalis-mint/test_integration.py
                        bash services/finalis-mint/systemd/smoke_deploy.sh

                        CI wiring for the packaging/deploy checks lives in:

                          [*] finalis-mint-packaging.yml
                          [/list]

                          That workflow now runs:
                            [*] packaging/state tests
                            [*] temp-prefix install smoke check
                            [*] split server/worker live integration tests
                            [/list]
                            Pages: [1]
                              Print  
                             
                            Jump to:  

                            Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!