Skip to content

Permissionless Multi-Asset: eigene Token anlegen, minten, senden, empfangen #191

Description

@TaprootFreak

Ziel

Heute kennt zkCoins genau ein Asset (die faucet-geminte Einheit, fest verdrahtete MINTING_ADDRESS). Dieses Issue erweitert das System so, dass jeder Nutzer beliebig viele eigene Assets anlegen, minten, halten, senden und empfangen kann — permissionless, ohne Whitelist, ohne Namensregister.

Prinzip

Additive Erweiterung des bestehenden Mint/Send-Systems um ein Feld asset_id. Das Trust- und Proof-Modell bleibt unverändert: asset_id reitet als zusätzliches Feld auf Coins, Invoices und im Commitment-Preimage mit; Soundness kommt weiterhin aus dem rekursiven SNARK + der Bitcoin-verankerten Nullifier-Historie. Es wird nichts neu erfunden.

Identität: asset_id, nicht der Name

Der einzige Identifikator und die einzige Eindeutigkeit ist die asset_id:

asset_id = Poseidon(creator_pubkey, name, decimals)

Weil der creator_pubkey im Hash steckt, ist die asset_id global eindeutig ohne jede Koordination — zwei Ersteller, die denselben Namen wählen, erzeugen zwangsläufig verschiedene Assets.

  • Der Name ist ein freies Label (wie ein ERC-20-Ticker), nicht eindeutig. Mehrere Assets dürfen denselben Namen tragen — auch auf derselben Node. Kein name UNIQUE, kein First-come-first-served-Namespace, kein 409 Conflict.
  • Die asset_id ist deterministisch ableitbar; die assets-Tabelle ist nur ein Metadaten-Lookup (Name/Dezimalstellen zu einer asset_id), keine Autorität.
  • Das Wallet zeigt immer Name und asset_id; die asset_id ist der Trust-Anker, der Name ist reine Anzeige.

Funktionsablauf (Nutzersicht)

  1. Anlegen — Name + Dezimalstellen angeben, mit dem Wallet-Key signieren → das Asset existiert (Menge 0). Kein Coin, kein Proof, kein Mint — nur ein Metadaten-Eintrag. Idempotent über die asset_id.
  2. Minten — der Ersteller ruft den bestehenden Mint-Weg für sein Asset auf → erzeugt Einheiten an einen Empfänger. Beliebig oft, kein fixes Supply.
  3. Senden / Empfangen — wie heute, der Nutzer wählt zusätzlich das Asset.

Anlegen und Minten sind getrennt, damit es nur einen Mint-Pfad gibt (der erste Mint ist kein Sonderfall).

Designentscheidungen

  • Anlegen ≠ Minten. asset/create erzeugt nur den Metadaten-Eintrag, keinen Proof. Supply startet bei 0.
  • asset_id = einzige Eindeutigkeit (kryptografisch via creator_pubkey). Name = freies, nicht-eindeutiges Label.
  • Kein fixes Supply — der Ersteller kann jederzeit nachminten. Keine protokollseitige Obergrenze. Vertrauen ins Asset = Vertrauen in den Ersteller.
  • Eine Transaktion bewegt genau ein Asset — kein Mischen, kein protokollinterner Swap.
  • Mint-Autorisierung — Off-circuit-Signaturprüfung gegen den beim Anlegen festgelegten mint_authority_pubkey, identisch zum bestehenden Send-Signatur-Check.

Technische Änderungen

Datenmodell

  • asset_id-Feld an Coin, CoinTemplate, Invoice.
  • Account: balance: u64balances: Map<AssetId, u64> (Persistenz als JSONB-Spalte). Ein Wallet hält beliebig viele Assets nebeneinander.
  • Neue Tabelle assets (PK asset_id, name als gewöhnliche Spalte ohne UNIQUE, decimals, mint_authority_pubkey, creator_address).

Circuit (rein additiv)

  • asset_id als ein neuer Public-Input (N_PROOF_DATA_PUBLIC_INPUTS 16 → 20).
  • Pro Slot ein Gleichheits-Gate: alle Ein-/Ausgangs-Coins einer Transaktion tragen dasselbe asset_id.
  • calculate_coin_identifier um asset_id erweitern.
  • Recursion-Padding (INNER_PAD_BITS…) bei 20 Public-Inputs neu verifizieren.

API

  • POST /api/asset/create (neu) — Name, Dezimalstellen, mint_authority_pubkey, Signatur → Metadaten-Eintrag. Idempotent über asset_id.
  • GET /api/asset/list, GET /api/asset/info/:id (neu).
  • POST /api/mint (erweitert)asset_id + Creator-Signatur; bestehender Mint-Flow pro Asset statt single MINTING_ADDRESS.
  • POST /api/send (erweitert)asset_id; Signatur deckt asset_id mit ab.
  • GET /api/balance (erweitert, breaking) — Map {asset_id: menge} statt Skalar.
  • GET /api/info — neues Capability-Flag multi_asset.

Nicht im Scope

  • Härtung der Ausgabe (D11): Off-circuit-Mint bleibt wie im heutigen System. In-Circuit-Mint-Verifikation und BTC-Bridge sind separate, spätere Themen.
  • Globale Namens-Koordination über Nodes (on-chain-verankertes Namensregister o. Ä.) — siehe Decentralization roadmap: network-layer gaps between today's node and the Shielded CSV peer-to-peer model #170 P5. Hier bewusst nicht gelöst; das Design ist durch asset_id-als-Identität von Anfang an dezentral-kompatibel.
  • Per-Asset-Privacy-Pools / Verstecken der asset_id on-chain.
  • Cross-Asset-Swap im Protokoll.
  • Schlüsselrotation der Mint-Authority, reiche Metadaten (Logo/URI), Burn.
  • Wallet-UI (zk-coins/app) — separater PR in jenem Repo.

Lieferung

  • Ein einziger PR in diesem Repo (kein Splitten). Feature-Branch → Draft-PR nach staging — dem Integrations-Buffer. develop (DEV-Deploy) und main (PRD) sind protected und werden ausschließlich per Auto-Promote-PR befüllt (stagingdevelopmain); siehe CONTRIBUTING.md „Branch model". Agents öffnen PRs als Draft; Maintainer mergen.
  • Interne Reihenfolge: Typen+asset_id → Circuit → Registry+Endpoints → Mint → Send/Balance.
  • 100 % Test-Coverage auf der neuen activated surface + grüne Heavy-Tests (M3-Ultra-Runner) — die CI-Gates des Repos gelten.

Pflicht-Negativtests

  • Zwei verschiedene Assets in einer Transaktion → abgelehnt.
  • Mint ohne gültige Authority-Signatur → abgelehnt.
  • Zwei gleichnamige Assets verschiedener Ersteller koexistieren (verschiedene asset_id).
  • Senden eines Assets ohne Guthaben → abgelehnt.

Referenzen


Session-ID: 99f19e87-cf2b-48f9-866b-99ebf93fd85e

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions