Einführung
Zero-Knowledge-Beweise, insbesondere zk-SNARKs (Zero-Knowledge Succinct Non-Interactive Knowledge Arguments), sind vielleicht eine der wichtigsten Spitzentechnologien im Web 3. Derzeit konzentriert sich die Aufmerksamkeit der Medien und Investitionen in diesem Teilbereich auf zk-Rollups, eine Skalierungslösung, die L1-Blockchains wie Ethereum enorme Skalierbarkeit bietet. Dennoch sind zk-Rollups alles andere als der einzige Zweck von zk-SNARKs. Dieser Artikel bietet eine eingehende Analyse des Konzepts des Zero-Knowledge-Assembly-Codes (zkASM), bewertet seine Anwendungsfälle in zk-Rollups und anderen Aspekten und untersucht sein Potenzial bei der Neuerfindung des Internets auf theoretischer Ebene.
Technische Grundlagen
Wie der Name schon sagt, besteht zk-ASM hauptsächlich aus zwei technischen Komponenten: ZK und ASM. ZK bezieht sich auf zk-SNARKs, ein prägnantes, nicht interaktives Wissensargument, und ASM bezieht sich auf Assemblercode. Um das Potenzial von zk-ASM zu verstehen, müssen wir zunächst die theoretischen Grundlagen dieser beiden scheinbar obskuren Konzepte verstehen.
zk-SNARKs
zk-SNARKs sind das Kronjuwel von zk-Proofs: Sie bieten eine prägnante Möglichkeit, die Wahrheit einer Aussage zu beweisen, ohne Informationen über die bewiesenen Daten preiszugeben. Angenommen, jemand erklärt: „Ich weiß, dass es ein m mit C(m) = 0 gibt“, wobei m ein Gigabyte an Informationen und C eine Funktion ist. Der zk-SNARK stellt einen kurzen Beweis (<1GB) dar, der die Existenz von m schnell überprüft, ohne jedoch Informationen über m preiszugeben (außer öffentlichen Informationen).
Was genau ist dieses „C(m)“? Was ist der Nutzen? Diese Funktion ist eigentlich eine arithmetische Schaltung oder eine gerichtete azyklische Graphdarstellung (DAG) der spezifischen Funktion, die wir ausführen möchten, wie in der Abbildung gezeigt. Im Wesentlichen handelt es sich bei „m“ um die Eingangsdaten der Schaltung, und die spezifischen „Knoten“ in der Schaltung sind einzelne Logikgatter oder Operationen. Beispielsweise können „2“ und „3“ in den Knoten „+“ eingegeben werden, und dann wird „5“ an den nächsten Operator ausgegeben. Dadurch kann jede arithmetische oder logische Operation in einer „Rechenschaltung“ kodiert werden.

Nachdem der zk-SNARK-Code, den wir ausführen möchten, durch eine Rechenschaltung dargestellt wird, können wir mit der Erstellung dieses zk-SNARK beginnen. Grundsätzlich wird die Machbarkeit von zk-SNARK durch den „Fundamentalsatz der Algebra“ nachgewiesen. Nach dem Fundamentalsatz der Algebra hat ein Polynom vom Grad „d“ höchstens „d“-Wurzeln. Dieser mathematische Trick ist ein zweistufiger Prozess: (1) Konvertieren Sie die zu beweisende Funktion „f(m)“ in ein Polynom und verwenden Sie das Polynom weiterhin, und (2) verwenden Sie den „Grundsatz der Algebra“. Verarbeiten Sie das Polynom und liefern Sie einen prägnanten Beweis. In der Fachsprache heißt der erste Teil „Polynomial Commitment Scheme“ (PCS) und der zweite Teil „Polynomial Interactive Proof of Oracle“ (PIOP).

Die Zusammensetzung einer effizienten Universalschaltung SNARK. Quelle: https://cs251.stanford.edu/lectures/lecture15.pdf
Die spezifische Implementierung von PCS und PIOP würde den Rahmen dieses Artikels sprengen, aber dies gibt uns einen groben Überblick über die Kernschritte von zk-SNARK:
Wählen Sie eine Funktion (Codefunktion, mathematische Gleichung usw.) aus, für die Sie zk-SNARK ausführen möchten
Codieren Sie diese Funktion in eine Rechenschaltung C(m)
Führen Sie PCS aus, um die Polynomdarstellung der Rechenschaltung zu erhalten
Führen Sie PIOP aus und erhalten Sie einen präzisen Beweis der log(m)-Größe
Jetzt gibt es ein benutzerdefiniertes zk-SNARK, das nachweisen kann, dass jemand eine Information kennt, ohne den spezifischen Inhalt der Information preiszugeben.
Assembler-Code
Das zweite Teil des zk-ASM-Puzzles ist der Assembler-Code. Es handelt sich um eine sprachähnliche Sprache, die sehr einfache Sprachanweisungen enthält, die für Maschinen leicht zu lesen, für Menschen jedoch schwer zu entziffern sind. Im Gegensatz zu Hochsprachen wie Python, Java oder sogar C enthält die Assemblersprache einige sehr primitive Funktionen sowie MOVE (verschieben), CMP (vergleichen), ADD (Addition) und JMP (springen) am Prozessor und Registerebenen. Der Python-Code zum Eingeben der Zahlen 1 bis 9 auf dem Bildschirm lautet beispielsweise „123456789“:

Das ist leicht zu verstehen, oder? Werfen wir einen Blick auf die x86-Assembly-Version:

Es ist wirklich viel mühsamer und es handelt sich lediglich um einen sehr einfachen Vorgang. Warum in diesem Fall Assemblersprache verwenden? Obwohl diese Anweisungen, wie oben erwähnt, für Menschen nicht leicht lesbar sind, können sie leicht in den Bytecode „110011001“ „assembliert“ werden, damit eine Maschine sie lesen und ausführen kann (Assembler genannt). Im Vergleich dazu sind Hochsprachen wie Python und Java zwar besser lesbar, der Prozessor kann jedoch in diesen Sprachen geschriebene Programme nicht direkt ausführen. Wir benötigen einen „Compiler“, um den von uns geschriebenen Python- oder Java-Code in den oben genannten Assemblercode umzuwandeln und ihn zur Montage und Ausführung an die Maschine zu übergeben. Der Grund dafür, dass derselbe Teil des Python- oder Java-Codes problemlos auf verschiedenen Prozessoren und Betriebssystemen ausgeführt werden kann, liegt darin, dass der Compiler die schwere Arbeit übernimmt und den Quellcode in die Assemblersprache für den jeweiligen Prozessor oder das jeweilige Betriebssystem kompiliert.
Da alle Sprachen zu Assembler-Code kompiliert werden (der wiederum in ausführbare Binärdateien kompiliert wird), ist Assembler im Wesentlichen wie die „Mutter aller Sprachen“. Unter der Annahme, dass wir alle Operanden in einer Assemblersprache (wie x86 oder RISC-V) in arithmetische Schaltkreisdarstellungen konvertieren können, können wir zk-SNARK-Beweise für alle Operanden in dieser Assemblersprache liefern. Theoretisch bedeutet dies, dass wir zk-SNARKs für jedes Programm bereitstellen können, das in einer beliebigen Hochsprache geschrieben ist, die zu Assembler kompiliert werden kann, beispielsweise Python oder Java. Aus diesem Grund verdient zk-ASM unsere sorgfältige Untersuchung.
Praktische Anwendung
zk-EVM-Rollups: Polygon zk-ASM
Eine der wichtigsten Anwendungen von zk-ASM ist die Erstellung von zk-Rollups, die mit der Ethereum Virtual Machine oder zk-EVM kompatibel sind. zk-EVM ist für die Skalierbarkeit der Blockchain sehr wichtig, da es Programmierern die Bereitstellung auf zk-Rollup-basierten L2-Ketten ermöglicht, ohne zu viele (oder gar keine) Änderungen am Code vorzunehmen. In dieser Hinsicht ist zk-EVM von Polygon ein typisches Beispiel dafür, wie zk-ASM zur Erreichung dieses Ziels eingesetzt werden kann.

Entwickler in der öffentlichen Ethereum L1-Kette verwenden normalerweise die Solidity-Sprache, eine höhere Programmiersprache ähnlich der C-Sprache. Bevor Solidity-Code auf der L1-Blockchain ausgeführt wird, wird er zunächst in eine Reihe von EVM-Operationscodes kompiliert, z. B. ADD, SLOAD, EQ usw. Standardmäßig erstellt dieser Prozess offensichtlich keinen ZK-Proof. Der Einfallsreichtum von Polygon bestand darin, eine Möglichkeit zu schaffen, jeden EVM-Opcode in ihr individuell geschriebenes zk-ASM zu übersetzen, das sehr zk-SNARK-freundlich ist. Ihr L2-zk-EVM führt dann zk-ASM aus und erstellt gleichzeitig die zk-SNARK-Schaltung des ASM, um einen zk-SNARK-Beweis zu erstellen. Beispielsweise würde der ADD-Operationscode im EVM wie folgt in das zk-ASM von Polygon übersetzt:

Da die Magie von Polygon zk-EVM auf der Assembly-Ebene geschieht, liegt sie zwei Ebenen „tiefer“ als die Codeschicht, die reguläres Ethereum berührt, die „Solidity“-Ebene. Aus diesem Grund können die meisten Entwickler den EVM-Code, den sie für das Ethereum-Mainnet erstellt haben, direkt auf Polygon zk-EVM portieren. Gleichzeitig „behält“ Polygon zk-EVM den Ethereum-Technologie-Stack bis hinunter zur Ebene des Operationscodes, und die gesamte Debugging-Infrastruktur, die auf der Analyse des kompilierten Operationscodes basiert, kann weiterhin intakt verwendet werden. Dies unterscheidet sich von anderen zk-EVM-Designs, die keinen zk-Proof auf Opcode-Ebene bieten, wie z. B. zk-Sync. Obwohl Polygon seine eigene Assemblersprache erfunden und verifiziert hat, kann es, wie Buterin sagte, „immer noch EVM-Code verifizieren, es verwendet jedoch nur eine andere interne Logik.“
Über Rollups hinaus: zk-WASM
zk-EVM ist keineswegs der einzige Anwendungsfall für zk-ASM. Wie oben erwähnt, ist Assembler im Wesentlichen die „Mutter aller Sprachen“, und durch die Erstellung von zk-ASM werden zk-Proofs für Allzweckprogramme freigeschaltet, die in jeder Sprache geschrieben sind, die in Assembler kompiliert werden kann. Web Assembly (WASM) ist eine der wichtigsten neuen Assemblersprachen. Sie wurde erstmals 2018 veröffentlicht und zielt darauf ab, die Ausführungsgeschwindigkeit von Webanwendungen zu verbessern und Ausführungsergänzungen für Javascript (die wichtigste Programmiersprache hinter dem Web) bereitzustellen.
Da sich das Web im Laufe der Jahre weiterentwickelt hat, sind Webanwendungen im Wesentlichen immer größer und komplexer geworden, was bedeutet, dass Browser alles, was in Javascript geschrieben ist, oft mit extrem langsamer Geschwindigkeit kompilieren und komplexe „Kompilieren-Optimieren-Neuladen“-Vorgänge wiederholen müssen. Verfahren. WebAssembly beseitigt die Abhängigkeit von komplexen Browser-Ausführungs-Engines, indem es eine portierbare, modulare und einfach auszuführende Assemblersprache bereitstellt. Darüber hinaus ermöglicht WASM als Assemblersprache Programmierern das Schreiben von Codeausschnitten in Sprachen wie C, C++, Rust, Java oder Ruby, die direkt im Browser ausgeführt werden können. WASM ist daher zur Technologie der Wahl für die „Bereitstellung verteilter serverloser Funktionen“ geworden.
Welche Rolle können zk-SNARKs in dieser Hinsicht spielen? Das Besondere an WASM ist, dass es sich um eine clientseitige Technologie handelt, die direkt mit vom Benutzer eingegebenen Daten interagiert. Dazu gehören häufig sensible Daten wie Passwörter und persönliche Informationen. Daher benötigen wir eine Technologie, die (1) sicherstellt, dass das Programm korrekt ausgeführt wird, und (2) sicherstellt, dass sensible Informationen nicht verloren gehen. zk-SNARK ist die perfekte Lösung für diese beiden Probleme und daher ein wichtiges Puzzleteil für WASM.
Die Arbeit an der Entwicklung von zk-WASM befindet sich noch in einem frühen Stadium, aber mehrere Projekte haben kürzlich Prototypen von zk-SNARK-Schaltkreisen für WebAssembly veröffentlicht. Beispielsweise bietet der zk-SNARK-Simulator „ZAWA“ von Delphinus Lab eine Möglichkeit, die Operanden und Semantik der virtuellen WASM-Maschine in die Rechenschaltung zu kodieren und so die Ableitung von zk-SNARK-Beweisen zu ermöglichen. Die zk-WASM-Schaltung wird sicherlich weiterhin optimiert, sodass Programme, die in Allzwecksprachen wie C, C++, Rust und Ruby geschrieben sind, das zk-Proofs-Paradigma übernehmen werden.
abschließend
Dieser Artikel untersucht die theoretischen Grundlagen von zk-ASM und untersucht zwei paradigmatische Anwendungsfälle von zk-ASM: Polygon verwendet zk-ASM, um zk-EVM auf der Ebene des Betriebscodes zu erstellen, und wendet zk-SNARKs auf WebAssembly an, um zk-WASM zu erstellen. Letztendlich verspricht zk-ASM, die Interoperabilität und Skalierbarkeit von Web 2 mit der Vertrauenslosigkeit und Sicherheit von Web 3 zu kombinieren.
Einerseits versucht Blockchain zunehmend, aktuelle Engpässe beim Verarbeitungsvolumen zu überwinden, andererseits stehen Web-2-Ansätze zunehmend in der Kritik, dass sie die Daten und Privatsphäre der Nutzer nicht ausreichend schützen. Da Programmierer in der Lage sind, Web-3-Designparadigmen in Web-2-Code zu verwenden und Web-2-Sprachen und -Code in die Blockchain zu bringen, wird erwartet, dass universelles zk-ASM zu einem Treffpunkt zwischen der Web-2- und der Web-3-Welt wird. Vor diesem Hintergrund könnte uns zk-ASM ermöglichen, ein sichereres und vertrauenswürdigeres Internet neu zu erfinden.