CLOISTER DOCS
ENDE
Website App öffnen →

Der abgeschirmte Pool

Der abgeschirmte Pool ist das Herzstück von Cloister: ein einzelner Smart Contract, der Werte als Menge verschlüsselter Commitments verwahrt und diese Werte privat bewegen lässt. Diese Seite erklärt die Datenstrukturen, die er führt, und warum jede davon existiert.

Notes — Werte als Hash

Im Pool ist Geld kein Kontosaldo. Es ist eine Menge von Notes, im Stil der UTXOs von Bitcoin. Eine Note steht für einen Betrag, der einem Schlüssel gehört, und erscheint on-chain nur als ihr Commitment:

C = H(amount, pubKey, blinding)

Da C ein Hash ist, gibt das Commitment nichts preis — weder den Betrag noch den Inhaber. Dennoch kann der Inhaber später in Zero Knowledge beweisen, dass er amount, pubKey und blinding hinter einem bestimmten C kennt.

Eine Zahlung verbraucht Input-Notes und erzeugt Output-Notes. Cloister verwendet eine feste 2-Input/2-Output-Form: bis zu zwei Notes hinein, genau zwei hinaus (die Note des Empfängers und eine „Wechselgeld"-Note zurück an den Absender). Kleinere Zahlungen nutzen einen Dummy-Input mit dem Wert null.

Der Merkle-Baum — Zugehörigkeit ohne Liste

Alle jemals erzeugten Commitments sind Blätter eines Merkle-Baums fester Tiefe (Tiefe 20 → bis zu 2²⁰ ≈ 1,05 Millionen Notes). Die einzelne 32-Byte-Wurzel fasst die gesamte Menge zusammen.

Um eine Note auszugeben, beweisen Sie in Zero Knowledge, dass ihr Commitment ein Blatt unter der aktuellen Wurzel ist — ohne zu verraten, welches Blatt. So prüft der Pool „diese Note existiert wirklich und ist nicht ausgegeben", ohne je zu erfahren, welche Note Sie meinen.

                root
               /    \
            H(·,·)   H(·,·)
            /   \     /   \
          C0    C1  C2    C3   …   (your note is one of these — but which is hidden)

Nullifier — genau einmal ausgeben

Würden Commitments einfach als „ausgegeben" markiert, gäbe das preis, welche Note bewegt wurde. Stattdessen gibt das Ausgeben einer Note ihren Nullifier preis:

nf = H(C, leafIndex, sig)      where  sig = H(privKey, C, leafIndex)

Der Nullifier ist für eine gegebene Note an einer gegebenen Position deterministisch, aber ohne den privaten Schlüssel nicht mit ihrem Commitment verknüpfbar. Der Contract führt eine globale Nullifier-Menge; eine Transaktion, deren Nullifier bereits vorhanden ist, wird abgelehnt. Also:

Off-chain-Merkle-Einfügung

Zwei neue Commitments in einen Merkle-Baum einzufügen bedeutet normalerweise, Hashes im Baum on-chain neu zu berechnen — teuer, weil das Hashing den Gasverbrauch dominiert. Cloister verlagert diese Arbeit in den Beweis.

Die Schaltung beweist zwei Dinge über den Einfügeplatz:

  1. der Platz war zuvor leerclimb(emptyLeaf, slot, siblings) == oldRoot, und
  2. das Einfügen des neuen Paares ergibt die neue Wurzel — climb(pairNode, slot, siblings) == newRoot, unter Verwendung desselben Geschwisterpfades.

Sowohl oldRoot als auch newRoot sind öffentliche Ausgaben des Beweises. Der Contract prüft schlicht den Beweis und speichert newRoot — er führt überhaupt kein Poseidon-Hashing durch. Ergebnis: ≈350k Gas pro Zahlung statt ≈1,74M — rund 5× günstiger. Eine Fälschung erforderte eine Poseidon2-Second-Preimage, was undurchführbar ist.

Lanes — Parallelität

Eine einzelne Wurzel ist ein Engpass: jede Zahlung verändert sie, sodass zwei Zahlungen im selben Block kollidieren (die zweite sieht eine veraltete Wurzel). Cloister führt mehrere unabhängige Lanes, jede mit eigener Merkle-Wurzel, während alle Lanes eine globale Nullifier-Menge teilen.

Das Compliance-Gate

Der Pool speichert außerdem die Association-Root — die Wurzel des Compliance-Good-Sets. Jede echte Input-Note muss ihre Zugehörigkeit dazu beweisen, sodass nur geprüfte Mittel ausgegeben werden können. Dies wird ausführlich behandelt unter Association-Sets & Compliance.

Alles zusammengesetzt

Ein transact-Aufruf trägt: eine Merkle-Root, gegen die bewiesen wird, zwei InputNullifier, zwei OutputCommitment, eine NewRoot, den Einfügeplatz, die AssociationRoot, den externen Nettobetrag (für Ein-/Auszahlungen) und einen Hash, der Empfänger/Relayer/Gebühr bindet. Der Contract leitet diese öffentlichen Signale neu ab, ruft den Verifier auf und gibt bei Erfolg die Nullifier aus, emittiert die Commitments und schreibt die Lane-Wurzel fort. Die vollständige Liste sind die öffentlichen Signale der Schaltung.

Weiter: Mittel abschirmen — wie Werte in den Pool gelangen.

Auf dieser Seite
Notes — Werte als HashDer Merkle-Baum — Zugehörigkeit ohne ListeNullifier — genau einmal ausgebenOff-chain-Merkle-EinfügungLanes — ParallelitätDas Compliance-GateAlles zusammengesetzt