Besonderer Dank geht an Yoav Weiss, Dan Finlay, Martin Koppelmann und die Teams von Arbitrum, Optimism, Polygon, Scroll und SoulWallet für das Feedback und die Bewertung.
In diesem Beitrag über die drei Übergänge habe ich einige Hauptgründe skizziert, warum es wertvoll ist, explizit über L1 + Cross-L2-Unterstützung, Wallet-Sicherheit und Datenschutz als notwendige Grundfunktionen des Ökosystem-Stacks nachzudenken, anstatt jedes dieser Dinge als Addons zu erstellen, die von einzelnen Wallets separat gestaltet werden können.
Dieser Beitrag konzentriert sich direkt auf die technischen Aspekte eines bestimmten Teilproblems: Wie kann man es einfacher machen, L1 von L2, L2 von L1 oder L2 von einem anderen L2 zu lesen? Die Lösung dieses Problems ist entscheidend für die Implementierung einer Asset-/Keystore-Trennungsarchitektur, hat aber auch wertvolle Anwendungsfälle in anderen Bereichen, insbesondere die Optimierung zuverlässiger L2-übergreifender Aufrufe, einschließlich Anwendungsfällen wie dem Verschieben von Assets zwischen L1 und L2.
Sobald L2s mehr zum Mainstream werden, werden die Benutzer über Assets in mehreren L2s und möglicherweise auch über L1 verfügen. Sobald Smart-Contract-Wallets (Multisig, Social Recovery oder andere) zum Mainstream werden, werden sich die Schlüssel, die für den Zugriff auf ein Konto benötigt werden, im Laufe der Zeit ändern, und alte Schlüssel müssten nicht mehr gültig sein. Sobald beides geschieht, muss ein Benutzer eine Möglichkeit haben, die Schlüssel zu ändern, die für den Zugriff auf viele Konten an vielen verschiedenen Orten berechtigt sind, ohne eine extrem hohe Anzahl von Transaktionen durchzuführen.
Insbesondere brauchen wir eine Möglichkeit, mit kontrafaktischen Adressen umzugehen: Adressen, die noch in keiner Weise on-chain "registriert" wurden, die aber dennoch Gelder empfangen und sicher aufbewahren müssen. Wir alle sind auf kontrafaktische Adressen angewiesen: Wenn Sie Ethereum zum ersten Mal verwenden, können Sie eine ETH-Adresse generieren, mit der jemand Sie bezahlen kann, ohne die Adresse auf der Chain zu "registrieren" (was die Zahlung von Txfees erfordern würde und somit bereits einige ETH halten würde).
Bei EOAs beginnen alle Adressen als kontrafaktische Adressen. Mit Smart-Contract-Wallets sind kontrafaktische Adressen immer noch möglich, vor allem dank CREATE2, die es Ihnen ermöglicht, eine ETH-Adresse zu haben, die nur von einem Smart Contract gefüllt werden kann, dessen Code mit einem bestimmten Hash übereinstimmt.
EIP-1014 (CREATE2) Adressberechnungsalgorithmus.
Smart-Contract-Wallets bringen jedoch eine neue Herausforderung mit sich: die Möglichkeit, Zugangsschlüssel zu ändern. Die Adresse, bei der es sich um einen Hash des Initcodes handelt, kann nur den anfänglichen Verifizierungsschlüssel des Wallets enthalten. Der aktuelle Verifizierungsschlüssel wird im Speicher der Wallet gespeichert, aber dieser Speicherdatensatz wird nicht auf magische Weise an andere L2s weitergegeben.
Wenn ein Benutzer viele Adressen auf vielen L2s hat, einschließlich Adressen, die (weil sie kontrafaktisch sind) der L2, auf der er sich befindet, nicht kennt, dann scheint es nur eine Möglichkeit zu geben, Benutzern das Ändern ihrer Schlüssel zu ermöglichen: Asset-/Keystore-Trennungsarchitektur. Jeder Benutzer hat (i) einen "Keystore-Vertrag" (auf L1 oder auf einem bestimmten L2), der den Verifizierungsschlüssel für alle Wallets zusammen mit den Regeln für die Änderung des Schlüssels speichert, und (ii) "Wallet-Verträge" auf L1 und vielen L2s, die Cross-Chain lesen, um den Verifizierungsschlüssel zu erhalten.
Es gibt zwei Möglichkeiten, dies zu implementieren:
Um die volle Komplexität zu zeigen, untersuchen wir den schwierigsten Fall: Wenn sich der Keystore auf einem L2 und die Wallet auf einem anderen L2 befindet. Wenn sich entweder der Keystore oder die Wallet auf L1 befindet, wird nur die Hälfte dieses Designs benötigt.
Nehmen wir an, dass sich der Keystore auf Linea und die Wallet auf Kakarot befindet. Ein vollständiger Nachweis der Schlüssel zum Wallet besteht aus:
Hier gibt es zwei primäre knifflige Implementierungsfragen:
Es gibt fünf Hauptoptionen:
In Bezug auf den Infrastrukturaufwand und die Kosten für die Nutzer ordne ich sie grob wie folgt ein:
"Aggregation" bezieht sich auf die Idee, alle von Benutzern innerhalb jedes Blocks gelieferten Beweise zu einem großen Meta-Beweis zu aggregieren, der alle kombiniert. Dies ist für SNARKs und für KZG möglich, aber nicht für Merkle-Zweige (Sie können Merkle-Zweige ein wenig kombinieren, aber es spart Ihnen nur log(txs pro Block) / log (Gesamtzahl der Keystores), vielleicht 15-30% in der Praxis, also ist es die Kosten wahrscheinlich nicht wert).
Die Aggregation lohnt sich erst, wenn das Schema eine beträchtliche Anzahl von Benutzern hat, daher ist es realistischerweise in Ordnung, wenn eine Implementierung der Version 1 die Aggregation weglässt und für Version 2 implementiert.
Das ist einfach: Folgen Sie direkt dem Diagramm im vorherigen Abschnitt . Genauer gesagt würde jeder "Beweis" (unter der Annahme des maximalen Schwierigkeitsfalls des Beweises eines L2 in ein anderes L2) enthalten:
Leider sind Ethereum-Zustandsnachweise kompliziert, aber es gibt Bibliotheken, um sie zu verifizieren, und wenn Sie diese Bibliotheken verwenden, ist dieser Mechanismus nicht allzu kompliziert zu implementieren.
Das größere Problem sind die Kosten. Merkle-Beweise sind lang, und Patricia-Bäume sind leider ~3,9x länger als nötig (genau: ein idealer Merkle-Beweis für einen Baum, der N Objekte enthält, ist 32 log2(N)-Bytes lang, und da die Patricia-Bäume von Ethereum 16 Blätter pro Kind haben, sind die Beweise für diese Bäume 32 15 log16(N) ~= 125 log2(N) Bytes lang). In einem Staat mit etwa 250 Millionen (~2²⁸) Konten ergibt dies jeden Beweis 125 * 28 = 3500 Bytes oder etwa 56.000 Gas, zuzüglich zusätzlicher Kosten für die Dekodierung und Verifizierung von Hashes.
Zwei Proofs zusammen würden am Ende etwa 100.000 bis 150.000 Gas kosten (ohne Signaturprüfung, wenn diese pro Transaktion verwendet wird) - deutlich mehr als die derzeitige Basis von 21.000 Gas pro Transaktion. Die Diskrepanz wird jedoch noch größer, wenn der Beweis auf L2 verifiziert wird. Die Berechnung innerhalb eines L2 ist billig, da die Berechnung außerhalb der Kette und in einem Ökosystem mit viel weniger Knoten als L1 erfolgt. Die Daten hingegen müssen in L1 gebucht werden. Der Vergleich lautet also nicht 21000 Gas vs. 150.000 Gas; es sind 21.000 L2 Gas gegenüber 100.000 L1 Gas.
Wir können berechnen, was das bedeutet, indem wir uns Vergleiche zwischen den L1-Gaskosten und den L2-Gaskosten ansehen:
L1 ist derzeit etwa 15-25x teurer als L2 für einfache Sendungen und 20-50x teurer für Token-Swaps. Einfache Sendungen sind relativ datenintensiv, aber Swaps sind viel rechenintensiver. Daher sind Swaps ein besserer Maßstab für die Annäherung an die Kosten der L1-Berechnung im Vergleich zur L2-Berechnung. Wenn wir unter Berücksichtigung all dessen von einem 30-fachen Kostenverhältnis zwischen L1-Rechenkosten und L2-Rechenkosten ausgehen, scheint dies zu implizieren, dass das Platzieren eines Merkle-Proofs auf L2 das Äquivalent von vielleicht fünfzig regulären Transaktionen kostet.
Natürlich kann die Verwendung eines binären Merkle-Baums die Kosten um das ~4-fache senken, aber selbst dann werden die Kosten in den meisten Fällen zu hoch sein - und wenn wir bereit sind, das Opfer zu bringen, nicht mehr mit dem aktuellen hexaären Zustandsbaum von Ethereum kompatibel zu sein, können wir genauso gut nach noch besseren Optionen suchen.
Konzeptionell ist die Verwendung von ZK-SNARKs auch einfach zu verstehen: Sie ersetzen einfach die Merkle-Beweise im obigen Diagramm durch einen ZK-SNARK, der beweist, dass diese Merkle-Beweise existieren. Ein ZK-SNARK kostet ~400.000 Gas an Rechenleistung und etwa 400 Bytes (zum Vergleich: 21.000 Gas und 100 Byte für eine einfache Transaktion, in Zukunft reduzierbar auf ~25 Bytes mit Komprimierung). Aus rechnerischer Sicht kostet ein ZK-SNARK heute also das 19-fache der Kosten einer Basistransaktion, und aus Datensicht kostet ein ZK-SNARK heute 4x so viel wie eine Basistransaktion und 16-mal so viel wie eine Basistransaktion in der Zukunft.
Diese Zahlen sind eine massive Verbesserung gegenüber Merkle-Proofs, aber sie sind immer noch ziemlich teuer. Es gibt zwei Möglichkeiten, dies zu verbessern: (i) spezielle KZG-Beweise oder (ii) Aggregation, ähnlich der ERC-4337-Aggregation , aber mit ausgefeilterer Mathematik. Wir können uns mit beidem befassen.
Achtung, dieser Abschnitt ist viel mathematischer als andere Abschnitte. Das liegt daran, dass wir über Allzweckwerkzeuge hinausgehen und etwas Spezielles bauen, um billiger zu sein, also müssen wir viel mehr "unter die Haube" gehen. Wenn du keine tiefgründige Mathematik magst, springe direkt zum nächsten Abschnitt.
Zunächst eine Zusammenfassung der Funktionsweise der KZG-Verpflichtungen:
Einige wichtige Eigenschaften, die es zu verstehen gilt, sind:
Daher haben wir eine Struktur, in der wir einfach am Ende einer ständig wachsenden Liste Werte hinzufügen können, wenn auch mit einer bestimmten Größenbeschränkung (realistisch gesehen könnten Hunderte von Millionen lebensfähig sein). Wir verwenden dies dann als unsere Datenstruktur, um (i) eine Zusage für die Liste der Schlüssel auf jeder L2, die auf dieser L2 gespeichert und auf L1 gespiegelt wird, und (ii) eine Verpflichtung für die Liste der L2-Schlüsselzusagen zu verwalten, die auf der Ethereum-L1 gespeichert und auf jede L2 gespiegelt werden.
Die Verpflichtungen auf dem neuesten Stand zu halten, könnte entweder Teil der Kernlogik von L2 werden, oder sie könnte ohne Änderungen des L2-Kernprotokolls durch Ein- und Auszahlungsbrücken implementiert werden.
Ein vollständiger Nachweis würde daher Folgendes erfordern:
Es ist tatsächlich möglich, die beiden KZG-Beweise zu einem zusammenzuführen, so dass wir eine Gesamtgröße von nur 100 Bytes erhalten.
Beachten Sie eine Feinheit: Da es sich bei der Schlüsselliste um eine Liste und nicht um eine Schlüssel-Wert-Zuordnung wie beim Status handelt, muss die Schlüsselliste Positionen sequenziell zuweisen. Der Schlüsselverpflichtungsvertrag würde eine eigene interne Registrierung enthalten, die jeden Schlüsselspeicher einer ID zuordnet, und für jeden Schlüssel würde er hash (Schlüssel, Adresse des Schlüsselspeichers) anstelle des Schlüssels speichern, um anderen L2s eindeutig mitzuteilen, um welchen Schlüsselspeicher ein bestimmter Eintrag spricht.
Der Vorteil dieser Technik ist, dass sie auf L2 sehr gut funktioniert. Die Daten sind 100 Byte groß, ~4x kürzer als ein ZK-SNARK und waaaay kürzer als ein Merkle-Proof. Die Rechenkosten belaufen sich größtenteils auf eine Pairing-Prüfung der Größe 2 oder etwa 119.000 Gas. Auf L1 sind die Daten weniger wichtig als die Berechnung, und so ist KZG leider etwas teurer als Merkle-Beweise.
Bei Verkle-Bäumen geht es im Wesentlichen darum, KZG-Verpflichtungen (oder IPA-Verpflichtungen, die effizienter sein und einfachere Kryptografie verwenden können) übereinander zu stapeln: Um 2⁴⁸-Werte zu speichern, können Sie eine KZG-Verpflichtung zu einer Liste von 2²⁴-Werten eingehen, von denen jeder selbst eine KZG-Verpflichtung zu 2²⁴-Werten ist. Verkle-Bäume werden <a href="https://notes.ethereum.org/@vbuterin/verkle_tree_eip">stark für den Ethereum-Zustandsbaum in Betracht gezogen, da Verkle-Bäume verwendet werden können, um Schlüssel-Wert-Karten und nicht nur Listen zu speichern (im Grunde können Sie einen Baum der Größe 2²⁵⁶ erstellen, ihn aber leer beginnen und nur bestimmte Teile des Baums ausfüllen, wenn Sie sie tatsächlich füllen müssen).
Wie ein Verkle-Baum aussieht. In der Praxis können Sie jedem Knoten eine Breite von 256 == 2⁸ für IPA-basierte Bäume oder 2²⁴ für KZG-basierte Bäume zuweisen.
Die Nachweise in Verkle-Bäumen sind etwas länger als in KZG; Sie können einige hundert Byte lang sein. Sie sind auch schwer zu überprüfen, vor allem, wenn Sie versuchen, viele Beweise zu einem zu aggregieren.
Realistisch betrachtet sollten Verkle-Bäume als wie Merkle-Bäume betrachtet werden, aber ohne SNARKing praktikabler (wegen der geringeren Datenkosten) und billiger mit SNARKing (wegen der niedrigeren Beweiskosten).
Der größte Vorteil von Verkle-Bäumen ist die Möglichkeit, Datenstrukturen zu harmonisieren: Verkle-Proofs können direkt über dem L1- oder L2-Zustand verwendet werden, ohne Überlagerungsstrukturen und mit genau demselben Mechanismus für L1 und L2. Sobald Quantencomputer ein Problem darstellen oder der Nachweis erbracht ist, dass Merkle-Zweige effizient genug sind, könnten Verkle-Bäume an Ort und Stelle durch einen binären Hash-Baum mit einer geeigneten SNARK-freundlichen Hash-Funktion ersetzt werden.
Wenn N Benutzer N Transaktionen (oder realistischer, N ERC-4337 UserOperations) durchführen, die N Cross-Chain-Behauptungen beweisen müssen, können wir eine Menge Gas sparen, indem wir diese Beweise aggregieren: Der Builder, der diese Transaktionen zu einem Block oder Bündel kombinieren würde, der in einen Block geht, kann einen einzigen Beweis erstellen, der alle diese Behauptungen gleichzeitig beweist.
Dies könnte bedeuten:
In allen drei Fällen würden die Proofs jeweils nur ein paar hunderttausend Gas kosten. Der Ersteller müsste eine davon auf jeder L2 für die Benutzer in dieser L2 erstellen. Damit dies nützlich ist, muss das Schema als Ganzes so weit genutzt werden, dass es sehr oft mindestens ein paar Transaktionen innerhalb desselben Blocks auf mehreren großen L2s gibt.
Wenn ZK-SNARKs verwendet werden, sind die Hauptgrenzkosten einfach die "Geschäftslogik" der Nummernweitergabe zwischen den Verträgen, also vielleicht ein paar tausend L2-Gas pro Benutzer. Wenn KZG-Multi-Proofs verwendet werden, müsste der Prüfer 48 Gas für jeden Keystore-haltenden L2 hinzufügen, der innerhalb dieses Blocks verwendet wird, so dass die Grenzkosten des Schemas pro Benutzer weitere ~800 L1-Gas pro L2 (nicht pro Benutzer) hinzufügen würden. Diese Kosten sind jedoch viel niedriger als die Kosten für die Nicht-Aggregation, die unweigerlich über 10.000 L1-Gas und Hunderttausende von L2-Gas pro Benutzer mit sich bringen. Für Verkle-Bäume können Sie entweder direkt Verkle-Multi-Proofs verwenden, indem Sie etwa 100-200 Bytes pro Benutzer hinzufügen, oder Sie können einen ZK-SNARK aus einem Verkle-Multi-Proof erstellen, der ähnliche Kosten wie ZK-SNARKs von Merkle-Zweigen hat, aber deutlich billiger zu beweisen ist.
Aus Sicht der Implementierung ist es wahrscheinlich am besten, wenn Bundler Cross-Chain-Proofs über den ERC-4337-Kontoabstraktionsstandard aggregieren. ERC-4337 verfügt bereits über einen Mechanismus, mit dem Entwickler Teile von UserOperations auf benutzerdefinierte Weise aggregieren können. Es gibt sogar eine <a href="https://hackmd.io/@voltrevo/BJ0QBy3zi">Implementierung für die BLS-Signaturaggregation, die die Gaskosten auf L2 um das 1,5- bis 3-fache senken könnte, je nachdem, welche anderen Formen der Kompression enthalten sind.
Diagramm aus einem <a href="https://hackmd.io/@voltrevo/BJ0QBy3zi">BLS-Wallet-Implementierungsbeitrag, der den Workflow von BLS-aggregierten Signaturen in einer früheren Version von ERC-4337 zeigt. Der Workflow zum Aggregieren von Cross-Chain-Proofs wird wahrscheinlich sehr ähnlich aussehen.
Eine letzte Möglichkeit, die nur für L2 verwendet werden kann, die L1 liest (und nicht L1, die L2 liest), besteht darin, L2s so zu modifizieren, dass sie statische Aufrufe von Kontrakten auf L1 direkt ausführen können.
Dies kann mit einem Opcode oder einem Vorkompilat erfolgen, das Anrufe in L1 ermöglicht, wobei Sie die Zieladresse, Gas und Anrufdaten angeben, und es gibt die Ausgabe zurück, obwohl diese Aufrufe statische Aufrufe sind, können sie keinen L1-Zustand ändern. L2s müssen L1 bereits kennen, um Einlagen zu verarbeiten, also gibt es nichts Grundsätzliches, was die Implementierung einer solchen Sache verhindert; Es handelt sich hauptsächlich um eine technische Herausforderung bei der Implementierung (siehe: diese Ausschreibung von Optimism zur Unterstützung statischer Aufrufe in L1).
Beachten Sie, dass, wenn sich der Keystore auf L1 befindet und L2s die statische Anruffunktion von L1 integrieren, überhaupt keine Nachweise erforderlich sind! Wenn L2s jedoch keine statischen L1-Aufrufe integrieren oder wenn sich der Keystore auf L2 befindet (was möglicherweise irgendwann der Fall sein muss, wenn L1 für Benutzer zu teuer wird, um es auch nur ein bisschen zu verwenden), dann sind Nachweise erforderlich.
Alle oben genannten Schemata erfordern, dass L2 entweder auf den aktuellen L1-Statusstamm oder auf den gesamten aktuellen L1-Status zugreift. Glücklicherweise verfügen alle L2s bereits über einige Funktionen, um auf den aktuellen L1-Status zuzugreifen. Dies liegt daran, dass sie eine solche Funktionalität benötigen, um Nachrichten zu verarbeiten, die von L1 bis L2 eingehen, insbesondere Einzahlungen.
Und tatsächlich, wenn ein L2 eine Einzahlungsfunktion hat, dann können Sie dieses L2 unverändert verwenden, um L1-Zustandswurzeln in einen Vertrag auf L2 zu verschieben: Lassen Sie einfach einen Vertrag auf L1 den BLOCKHASH-Opcode aufrufen und übergeben Sie ihn als Einzahlungsnachricht an L2. Der vollständige Blockheader kann auf der L2-Seite empfangen und sein Zustandsstamm extrahiert werden. Es wäre jedoch viel besser, wenn jede L2 eine explizite Möglichkeit hätte, entweder direkt auf den vollständigen aktuellen L1-Status oder auf die aktuellen L1-Statusstämme zuzugreifen.
Die größte Herausforderung bei der Optimierung der Art und Weise, wie L2s aktuelle L1-Zustandswurzeln empfangen, besteht darin, gleichzeitig Sicherheit und niedrige Latenz zu erreichen:
Zusätzlich in die entgegengesetzte Richtung (L1s, die L2 liest):
Einige dieser Geschwindigkeiten für vertrauenswürdige Cross-Chain-Operationen sind für viele DeFi-Anwendungsfälle inakzeptabel langsam. In diesen Fällen benötigen Sie schnellere Bridges mit unvollkommeneren Sicherheitsmodellen. Für den Anwendungsfall der Aktualisierung von Wallet-Schlüsseln sind längere Verzögerungen jedoch akzeptabler: Sie verzögern Transaktionen nicht um Stunden, sondern um Schlüsseländerungen. Sie müssen nur die alten Schlüssel länger aufbewahren. Wenn Sie Schlüssel ändern, weil Schlüssel gestohlen wurden, haben Sie eine erhebliche Anfälligkeit, die jedoch gemildert werden kann, z. durch Wallets mit einer Freeze-Funktion.
Letztendlich besteht die beste Lösung zur Minimierung der Latenz darin, dass L2s das direkte Lesen von L1-Zustandswurzeln auf optimale Weise implementiert, wobei jeder L2-Block (oder das Zustandsstammberechnungsprotokoll) einen Zeiger auf den letzten L1-Block enthält, sodass L2 ebenfalls zurückkehren kann, wenn L1 zurückgesetzt wird. Keystore-Verträge sollten entweder im Mainnet oder auf L2-Verträgen platziert werden, die ZK-Rollups sind und sich daher schnell an L1 binden können.
Blöcke der L2-Kette können nicht nur von vorherigen L2-Blöcken, sondern auch von einem L1-Block abhängig sein. Wenn L1 über einen solchen Link hinaus zurückkehrt, wird auch L2 zurückgesetzt. Es ist erwähnenswert, dass dies auch die Art und Weise ist, wie eine frühere Version von Sharding (vor Dank) funktionieren sollte. Code finden Sie hier .
Überraschenderweise nicht so sehr. Es muss eigentlich nicht einmal ein Rollup sein: Wenn es sich um ein L3 oder ein Validium handelt, dann ist es in Ordnung, Wallets dort zu halten, solange Sie Keystores entweder auf L1 oder auf einem ZK-Rollup halten. Was Sie brauchen, ist, dass die Chain direkten Zugang zu den Wurzeln des Ethereum-Staates hat und ein technisches und soziales Engagement, um bereit zu sein, sich neu zu organisieren, wenn Ethereum neu organisiert wird, und eine Hard Fork, wenn Ethereum hart abgespalten wird.
Ein interessantes Forschungsproblem besteht darin, herauszufinden, inwieweit es möglich ist, dass eine Kette diese Form der Verbindung mit mehreren anderen Ketten (z. Ethereum und Zcash). Es ist möglich, es naiv zu machen: Ihre Chain könnte sich darauf einigen, sich neu zu organisieren, wenn Ethereum oder Zcash reorganisiert werden (und eine Hard Fork, wenn Ethereum oder Zcash eine Hard Fork hat), aber dann haben Ihre Node-Betreiber und Ihre Community im Allgemeinen doppelt so viele technische und politische Abhängigkeiten. Daher könnte eine solche Technik verwendet werden, um eine Verbindung zu einigen anderen Ketten herzustellen, jedoch zu steigenden Kosten. Schemes, die auf ZK-Bridges basieren, haben attraktive technische Eigenschaften, aber sie haben die entscheidende Schwäche, dass sie nicht robust gegenüber 51%-Angriffen oder Hard Forks sind. Vielleicht gibt es cleverere Lösungen.
Im Idealfall wollen wir auch die Privatsphäre wahren. Wenn Sie viele Wallets haben, die vom selben Keystore verwaltet werden, möchten wir sicherstellen:
Dies führt zu einigen Problemen:
Mit SNARKs sind die Lösungen konzeptionell einfach: Beweise verbergen standardmäßig Informationen, und der Aggregator muss ein rekursives SNARK erzeugen, um die SNARKs zu beweisen.
Die größte Herausforderung dieses Ansatzes besteht heute darin, dass der Aggregator für die Aggregation ein rekursives SNARK erstellen muss, was derzeit recht langsam ist.
Mit KZG können wir <a href="https://notes.ethereum.org/@vbuterin/non_index_revealing_proof">this verwenden. Arbeit an nicht-index-offenbaren KZG-Beweisen (siehe auch: eine formalisiertere Version dieser Arbeit im Caulk-Papier ) als Ausgangspunkt. Die Aggregation von verblindeten Beweisen ist jedoch ein offenes Problem, das mehr Aufmerksamkeit erfordert.
Das direkte Lesen von L1 aus L2 bewahrt leider nicht die Privatsphäre, obwohl die Implementierung der Funktion zum direkten Lesen immer noch sehr nützlich ist, sowohl um die Latenz zu minimieren als auch wegen ihrer Nützlichkeit für andere Anwendungen.
Teilen
Nội dung
Besonderer Dank geht an Yoav Weiss, Dan Finlay, Martin Koppelmann und die Teams von Arbitrum, Optimism, Polygon, Scroll und SoulWallet für das Feedback und die Bewertung.
In diesem Beitrag über die drei Übergänge habe ich einige Hauptgründe skizziert, warum es wertvoll ist, explizit über L1 + Cross-L2-Unterstützung, Wallet-Sicherheit und Datenschutz als notwendige Grundfunktionen des Ökosystem-Stacks nachzudenken, anstatt jedes dieser Dinge als Addons zu erstellen, die von einzelnen Wallets separat gestaltet werden können.
Dieser Beitrag konzentriert sich direkt auf die technischen Aspekte eines bestimmten Teilproblems: Wie kann man es einfacher machen, L1 von L2, L2 von L1 oder L2 von einem anderen L2 zu lesen? Die Lösung dieses Problems ist entscheidend für die Implementierung einer Asset-/Keystore-Trennungsarchitektur, hat aber auch wertvolle Anwendungsfälle in anderen Bereichen, insbesondere die Optimierung zuverlässiger L2-übergreifender Aufrufe, einschließlich Anwendungsfällen wie dem Verschieben von Assets zwischen L1 und L2.
Sobald L2s mehr zum Mainstream werden, werden die Benutzer über Assets in mehreren L2s und möglicherweise auch über L1 verfügen. Sobald Smart-Contract-Wallets (Multisig, Social Recovery oder andere) zum Mainstream werden, werden sich die Schlüssel, die für den Zugriff auf ein Konto benötigt werden, im Laufe der Zeit ändern, und alte Schlüssel müssten nicht mehr gültig sein. Sobald beides geschieht, muss ein Benutzer eine Möglichkeit haben, die Schlüssel zu ändern, die für den Zugriff auf viele Konten an vielen verschiedenen Orten berechtigt sind, ohne eine extrem hohe Anzahl von Transaktionen durchzuführen.
Insbesondere brauchen wir eine Möglichkeit, mit kontrafaktischen Adressen umzugehen: Adressen, die noch in keiner Weise on-chain "registriert" wurden, die aber dennoch Gelder empfangen und sicher aufbewahren müssen. Wir alle sind auf kontrafaktische Adressen angewiesen: Wenn Sie Ethereum zum ersten Mal verwenden, können Sie eine ETH-Adresse generieren, mit der jemand Sie bezahlen kann, ohne die Adresse auf der Chain zu "registrieren" (was die Zahlung von Txfees erfordern würde und somit bereits einige ETH halten würde).
Bei EOAs beginnen alle Adressen als kontrafaktische Adressen. Mit Smart-Contract-Wallets sind kontrafaktische Adressen immer noch möglich, vor allem dank CREATE2, die es Ihnen ermöglicht, eine ETH-Adresse zu haben, die nur von einem Smart Contract gefüllt werden kann, dessen Code mit einem bestimmten Hash übereinstimmt.
EIP-1014 (CREATE2) Adressberechnungsalgorithmus.
Smart-Contract-Wallets bringen jedoch eine neue Herausforderung mit sich: die Möglichkeit, Zugangsschlüssel zu ändern. Die Adresse, bei der es sich um einen Hash des Initcodes handelt, kann nur den anfänglichen Verifizierungsschlüssel des Wallets enthalten. Der aktuelle Verifizierungsschlüssel wird im Speicher der Wallet gespeichert, aber dieser Speicherdatensatz wird nicht auf magische Weise an andere L2s weitergegeben.
Wenn ein Benutzer viele Adressen auf vielen L2s hat, einschließlich Adressen, die (weil sie kontrafaktisch sind) der L2, auf der er sich befindet, nicht kennt, dann scheint es nur eine Möglichkeit zu geben, Benutzern das Ändern ihrer Schlüssel zu ermöglichen: Asset-/Keystore-Trennungsarchitektur. Jeder Benutzer hat (i) einen "Keystore-Vertrag" (auf L1 oder auf einem bestimmten L2), der den Verifizierungsschlüssel für alle Wallets zusammen mit den Regeln für die Änderung des Schlüssels speichert, und (ii) "Wallet-Verträge" auf L1 und vielen L2s, die Cross-Chain lesen, um den Verifizierungsschlüssel zu erhalten.
Es gibt zwei Möglichkeiten, dies zu implementieren:
Um die volle Komplexität zu zeigen, untersuchen wir den schwierigsten Fall: Wenn sich der Keystore auf einem L2 und die Wallet auf einem anderen L2 befindet. Wenn sich entweder der Keystore oder die Wallet auf L1 befindet, wird nur die Hälfte dieses Designs benötigt.
Nehmen wir an, dass sich der Keystore auf Linea und die Wallet auf Kakarot befindet. Ein vollständiger Nachweis der Schlüssel zum Wallet besteht aus:
Hier gibt es zwei primäre knifflige Implementierungsfragen:
Es gibt fünf Hauptoptionen:
In Bezug auf den Infrastrukturaufwand und die Kosten für die Nutzer ordne ich sie grob wie folgt ein:
"Aggregation" bezieht sich auf die Idee, alle von Benutzern innerhalb jedes Blocks gelieferten Beweise zu einem großen Meta-Beweis zu aggregieren, der alle kombiniert. Dies ist für SNARKs und für KZG möglich, aber nicht für Merkle-Zweige (Sie können Merkle-Zweige ein wenig kombinieren, aber es spart Ihnen nur log(txs pro Block) / log (Gesamtzahl der Keystores), vielleicht 15-30% in der Praxis, also ist es die Kosten wahrscheinlich nicht wert).
Die Aggregation lohnt sich erst, wenn das Schema eine beträchtliche Anzahl von Benutzern hat, daher ist es realistischerweise in Ordnung, wenn eine Implementierung der Version 1 die Aggregation weglässt und für Version 2 implementiert.
Das ist einfach: Folgen Sie direkt dem Diagramm im vorherigen Abschnitt . Genauer gesagt würde jeder "Beweis" (unter der Annahme des maximalen Schwierigkeitsfalls des Beweises eines L2 in ein anderes L2) enthalten:
Leider sind Ethereum-Zustandsnachweise kompliziert, aber es gibt Bibliotheken, um sie zu verifizieren, und wenn Sie diese Bibliotheken verwenden, ist dieser Mechanismus nicht allzu kompliziert zu implementieren.
Das größere Problem sind die Kosten. Merkle-Beweise sind lang, und Patricia-Bäume sind leider ~3,9x länger als nötig (genau: ein idealer Merkle-Beweis für einen Baum, der N Objekte enthält, ist 32 log2(N)-Bytes lang, und da die Patricia-Bäume von Ethereum 16 Blätter pro Kind haben, sind die Beweise für diese Bäume 32 15 log16(N) ~= 125 log2(N) Bytes lang). In einem Staat mit etwa 250 Millionen (~2²⁸) Konten ergibt dies jeden Beweis 125 * 28 = 3500 Bytes oder etwa 56.000 Gas, zuzüglich zusätzlicher Kosten für die Dekodierung und Verifizierung von Hashes.
Zwei Proofs zusammen würden am Ende etwa 100.000 bis 150.000 Gas kosten (ohne Signaturprüfung, wenn diese pro Transaktion verwendet wird) - deutlich mehr als die derzeitige Basis von 21.000 Gas pro Transaktion. Die Diskrepanz wird jedoch noch größer, wenn der Beweis auf L2 verifiziert wird. Die Berechnung innerhalb eines L2 ist billig, da die Berechnung außerhalb der Kette und in einem Ökosystem mit viel weniger Knoten als L1 erfolgt. Die Daten hingegen müssen in L1 gebucht werden. Der Vergleich lautet also nicht 21000 Gas vs. 150.000 Gas; es sind 21.000 L2 Gas gegenüber 100.000 L1 Gas.
Wir können berechnen, was das bedeutet, indem wir uns Vergleiche zwischen den L1-Gaskosten und den L2-Gaskosten ansehen:
L1 ist derzeit etwa 15-25x teurer als L2 für einfache Sendungen und 20-50x teurer für Token-Swaps. Einfache Sendungen sind relativ datenintensiv, aber Swaps sind viel rechenintensiver. Daher sind Swaps ein besserer Maßstab für die Annäherung an die Kosten der L1-Berechnung im Vergleich zur L2-Berechnung. Wenn wir unter Berücksichtigung all dessen von einem 30-fachen Kostenverhältnis zwischen L1-Rechenkosten und L2-Rechenkosten ausgehen, scheint dies zu implizieren, dass das Platzieren eines Merkle-Proofs auf L2 das Äquivalent von vielleicht fünfzig regulären Transaktionen kostet.
Natürlich kann die Verwendung eines binären Merkle-Baums die Kosten um das ~4-fache senken, aber selbst dann werden die Kosten in den meisten Fällen zu hoch sein - und wenn wir bereit sind, das Opfer zu bringen, nicht mehr mit dem aktuellen hexaären Zustandsbaum von Ethereum kompatibel zu sein, können wir genauso gut nach noch besseren Optionen suchen.
Konzeptionell ist die Verwendung von ZK-SNARKs auch einfach zu verstehen: Sie ersetzen einfach die Merkle-Beweise im obigen Diagramm durch einen ZK-SNARK, der beweist, dass diese Merkle-Beweise existieren. Ein ZK-SNARK kostet ~400.000 Gas an Rechenleistung und etwa 400 Bytes (zum Vergleich: 21.000 Gas und 100 Byte für eine einfache Transaktion, in Zukunft reduzierbar auf ~25 Bytes mit Komprimierung). Aus rechnerischer Sicht kostet ein ZK-SNARK heute also das 19-fache der Kosten einer Basistransaktion, und aus Datensicht kostet ein ZK-SNARK heute 4x so viel wie eine Basistransaktion und 16-mal so viel wie eine Basistransaktion in der Zukunft.
Diese Zahlen sind eine massive Verbesserung gegenüber Merkle-Proofs, aber sie sind immer noch ziemlich teuer. Es gibt zwei Möglichkeiten, dies zu verbessern: (i) spezielle KZG-Beweise oder (ii) Aggregation, ähnlich der ERC-4337-Aggregation , aber mit ausgefeilterer Mathematik. Wir können uns mit beidem befassen.
Achtung, dieser Abschnitt ist viel mathematischer als andere Abschnitte. Das liegt daran, dass wir über Allzweckwerkzeuge hinausgehen und etwas Spezielles bauen, um billiger zu sein, also müssen wir viel mehr "unter die Haube" gehen. Wenn du keine tiefgründige Mathematik magst, springe direkt zum nächsten Abschnitt.
Zunächst eine Zusammenfassung der Funktionsweise der KZG-Verpflichtungen:
Einige wichtige Eigenschaften, die es zu verstehen gilt, sind:
Daher haben wir eine Struktur, in der wir einfach am Ende einer ständig wachsenden Liste Werte hinzufügen können, wenn auch mit einer bestimmten Größenbeschränkung (realistisch gesehen könnten Hunderte von Millionen lebensfähig sein). Wir verwenden dies dann als unsere Datenstruktur, um (i) eine Zusage für die Liste der Schlüssel auf jeder L2, die auf dieser L2 gespeichert und auf L1 gespiegelt wird, und (ii) eine Verpflichtung für die Liste der L2-Schlüsselzusagen zu verwalten, die auf der Ethereum-L1 gespeichert und auf jede L2 gespiegelt werden.
Die Verpflichtungen auf dem neuesten Stand zu halten, könnte entweder Teil der Kernlogik von L2 werden, oder sie könnte ohne Änderungen des L2-Kernprotokolls durch Ein- und Auszahlungsbrücken implementiert werden.
Ein vollständiger Nachweis würde daher Folgendes erfordern:
Es ist tatsächlich möglich, die beiden KZG-Beweise zu einem zusammenzuführen, so dass wir eine Gesamtgröße von nur 100 Bytes erhalten.
Beachten Sie eine Feinheit: Da es sich bei der Schlüsselliste um eine Liste und nicht um eine Schlüssel-Wert-Zuordnung wie beim Status handelt, muss die Schlüsselliste Positionen sequenziell zuweisen. Der Schlüsselverpflichtungsvertrag würde eine eigene interne Registrierung enthalten, die jeden Schlüsselspeicher einer ID zuordnet, und für jeden Schlüssel würde er hash (Schlüssel, Adresse des Schlüsselspeichers) anstelle des Schlüssels speichern, um anderen L2s eindeutig mitzuteilen, um welchen Schlüsselspeicher ein bestimmter Eintrag spricht.
Der Vorteil dieser Technik ist, dass sie auf L2 sehr gut funktioniert. Die Daten sind 100 Byte groß, ~4x kürzer als ein ZK-SNARK und waaaay kürzer als ein Merkle-Proof. Die Rechenkosten belaufen sich größtenteils auf eine Pairing-Prüfung der Größe 2 oder etwa 119.000 Gas. Auf L1 sind die Daten weniger wichtig als die Berechnung, und so ist KZG leider etwas teurer als Merkle-Beweise.
Bei Verkle-Bäumen geht es im Wesentlichen darum, KZG-Verpflichtungen (oder IPA-Verpflichtungen, die effizienter sein und einfachere Kryptografie verwenden können) übereinander zu stapeln: Um 2⁴⁸-Werte zu speichern, können Sie eine KZG-Verpflichtung zu einer Liste von 2²⁴-Werten eingehen, von denen jeder selbst eine KZG-Verpflichtung zu 2²⁴-Werten ist. Verkle-Bäume werden <a href="https://notes.ethereum.org/@vbuterin/verkle_tree_eip">stark für den Ethereum-Zustandsbaum in Betracht gezogen, da Verkle-Bäume verwendet werden können, um Schlüssel-Wert-Karten und nicht nur Listen zu speichern (im Grunde können Sie einen Baum der Größe 2²⁵⁶ erstellen, ihn aber leer beginnen und nur bestimmte Teile des Baums ausfüllen, wenn Sie sie tatsächlich füllen müssen).
Wie ein Verkle-Baum aussieht. In der Praxis können Sie jedem Knoten eine Breite von 256 == 2⁸ für IPA-basierte Bäume oder 2²⁴ für KZG-basierte Bäume zuweisen.
Die Nachweise in Verkle-Bäumen sind etwas länger als in KZG; Sie können einige hundert Byte lang sein. Sie sind auch schwer zu überprüfen, vor allem, wenn Sie versuchen, viele Beweise zu einem zu aggregieren.
Realistisch betrachtet sollten Verkle-Bäume als wie Merkle-Bäume betrachtet werden, aber ohne SNARKing praktikabler (wegen der geringeren Datenkosten) und billiger mit SNARKing (wegen der niedrigeren Beweiskosten).
Der größte Vorteil von Verkle-Bäumen ist die Möglichkeit, Datenstrukturen zu harmonisieren: Verkle-Proofs können direkt über dem L1- oder L2-Zustand verwendet werden, ohne Überlagerungsstrukturen und mit genau demselben Mechanismus für L1 und L2. Sobald Quantencomputer ein Problem darstellen oder der Nachweis erbracht ist, dass Merkle-Zweige effizient genug sind, könnten Verkle-Bäume an Ort und Stelle durch einen binären Hash-Baum mit einer geeigneten SNARK-freundlichen Hash-Funktion ersetzt werden.
Wenn N Benutzer N Transaktionen (oder realistischer, N ERC-4337 UserOperations) durchführen, die N Cross-Chain-Behauptungen beweisen müssen, können wir eine Menge Gas sparen, indem wir diese Beweise aggregieren: Der Builder, der diese Transaktionen zu einem Block oder Bündel kombinieren würde, der in einen Block geht, kann einen einzigen Beweis erstellen, der alle diese Behauptungen gleichzeitig beweist.
Dies könnte bedeuten:
In allen drei Fällen würden die Proofs jeweils nur ein paar hunderttausend Gas kosten. Der Ersteller müsste eine davon auf jeder L2 für die Benutzer in dieser L2 erstellen. Damit dies nützlich ist, muss das Schema als Ganzes so weit genutzt werden, dass es sehr oft mindestens ein paar Transaktionen innerhalb desselben Blocks auf mehreren großen L2s gibt.
Wenn ZK-SNARKs verwendet werden, sind die Hauptgrenzkosten einfach die "Geschäftslogik" der Nummernweitergabe zwischen den Verträgen, also vielleicht ein paar tausend L2-Gas pro Benutzer. Wenn KZG-Multi-Proofs verwendet werden, müsste der Prüfer 48 Gas für jeden Keystore-haltenden L2 hinzufügen, der innerhalb dieses Blocks verwendet wird, so dass die Grenzkosten des Schemas pro Benutzer weitere ~800 L1-Gas pro L2 (nicht pro Benutzer) hinzufügen würden. Diese Kosten sind jedoch viel niedriger als die Kosten für die Nicht-Aggregation, die unweigerlich über 10.000 L1-Gas und Hunderttausende von L2-Gas pro Benutzer mit sich bringen. Für Verkle-Bäume können Sie entweder direkt Verkle-Multi-Proofs verwenden, indem Sie etwa 100-200 Bytes pro Benutzer hinzufügen, oder Sie können einen ZK-SNARK aus einem Verkle-Multi-Proof erstellen, der ähnliche Kosten wie ZK-SNARKs von Merkle-Zweigen hat, aber deutlich billiger zu beweisen ist.
Aus Sicht der Implementierung ist es wahrscheinlich am besten, wenn Bundler Cross-Chain-Proofs über den ERC-4337-Kontoabstraktionsstandard aggregieren. ERC-4337 verfügt bereits über einen Mechanismus, mit dem Entwickler Teile von UserOperations auf benutzerdefinierte Weise aggregieren können. Es gibt sogar eine <a href="https://hackmd.io/@voltrevo/BJ0QBy3zi">Implementierung für die BLS-Signaturaggregation, die die Gaskosten auf L2 um das 1,5- bis 3-fache senken könnte, je nachdem, welche anderen Formen der Kompression enthalten sind.
Diagramm aus einem <a href="https://hackmd.io/@voltrevo/BJ0QBy3zi">BLS-Wallet-Implementierungsbeitrag, der den Workflow von BLS-aggregierten Signaturen in einer früheren Version von ERC-4337 zeigt. Der Workflow zum Aggregieren von Cross-Chain-Proofs wird wahrscheinlich sehr ähnlich aussehen.
Eine letzte Möglichkeit, die nur für L2 verwendet werden kann, die L1 liest (und nicht L1, die L2 liest), besteht darin, L2s so zu modifizieren, dass sie statische Aufrufe von Kontrakten auf L1 direkt ausführen können.
Dies kann mit einem Opcode oder einem Vorkompilat erfolgen, das Anrufe in L1 ermöglicht, wobei Sie die Zieladresse, Gas und Anrufdaten angeben, und es gibt die Ausgabe zurück, obwohl diese Aufrufe statische Aufrufe sind, können sie keinen L1-Zustand ändern. L2s müssen L1 bereits kennen, um Einlagen zu verarbeiten, also gibt es nichts Grundsätzliches, was die Implementierung einer solchen Sache verhindert; Es handelt sich hauptsächlich um eine technische Herausforderung bei der Implementierung (siehe: diese Ausschreibung von Optimism zur Unterstützung statischer Aufrufe in L1).
Beachten Sie, dass, wenn sich der Keystore auf L1 befindet und L2s die statische Anruffunktion von L1 integrieren, überhaupt keine Nachweise erforderlich sind! Wenn L2s jedoch keine statischen L1-Aufrufe integrieren oder wenn sich der Keystore auf L2 befindet (was möglicherweise irgendwann der Fall sein muss, wenn L1 für Benutzer zu teuer wird, um es auch nur ein bisschen zu verwenden), dann sind Nachweise erforderlich.
Alle oben genannten Schemata erfordern, dass L2 entweder auf den aktuellen L1-Statusstamm oder auf den gesamten aktuellen L1-Status zugreift. Glücklicherweise verfügen alle L2s bereits über einige Funktionen, um auf den aktuellen L1-Status zuzugreifen. Dies liegt daran, dass sie eine solche Funktionalität benötigen, um Nachrichten zu verarbeiten, die von L1 bis L2 eingehen, insbesondere Einzahlungen.
Und tatsächlich, wenn ein L2 eine Einzahlungsfunktion hat, dann können Sie dieses L2 unverändert verwenden, um L1-Zustandswurzeln in einen Vertrag auf L2 zu verschieben: Lassen Sie einfach einen Vertrag auf L1 den BLOCKHASH-Opcode aufrufen und übergeben Sie ihn als Einzahlungsnachricht an L2. Der vollständige Blockheader kann auf der L2-Seite empfangen und sein Zustandsstamm extrahiert werden. Es wäre jedoch viel besser, wenn jede L2 eine explizite Möglichkeit hätte, entweder direkt auf den vollständigen aktuellen L1-Status oder auf die aktuellen L1-Statusstämme zuzugreifen.
Die größte Herausforderung bei der Optimierung der Art und Weise, wie L2s aktuelle L1-Zustandswurzeln empfangen, besteht darin, gleichzeitig Sicherheit und niedrige Latenz zu erreichen:
Zusätzlich in die entgegengesetzte Richtung (L1s, die L2 liest):
Einige dieser Geschwindigkeiten für vertrauenswürdige Cross-Chain-Operationen sind für viele DeFi-Anwendungsfälle inakzeptabel langsam. In diesen Fällen benötigen Sie schnellere Bridges mit unvollkommeneren Sicherheitsmodellen. Für den Anwendungsfall der Aktualisierung von Wallet-Schlüsseln sind längere Verzögerungen jedoch akzeptabler: Sie verzögern Transaktionen nicht um Stunden, sondern um Schlüsseländerungen. Sie müssen nur die alten Schlüssel länger aufbewahren. Wenn Sie Schlüssel ändern, weil Schlüssel gestohlen wurden, haben Sie eine erhebliche Anfälligkeit, die jedoch gemildert werden kann, z. durch Wallets mit einer Freeze-Funktion.
Letztendlich besteht die beste Lösung zur Minimierung der Latenz darin, dass L2s das direkte Lesen von L1-Zustandswurzeln auf optimale Weise implementiert, wobei jeder L2-Block (oder das Zustandsstammberechnungsprotokoll) einen Zeiger auf den letzten L1-Block enthält, sodass L2 ebenfalls zurückkehren kann, wenn L1 zurückgesetzt wird. Keystore-Verträge sollten entweder im Mainnet oder auf L2-Verträgen platziert werden, die ZK-Rollups sind und sich daher schnell an L1 binden können.
Blöcke der L2-Kette können nicht nur von vorherigen L2-Blöcken, sondern auch von einem L1-Block abhängig sein. Wenn L1 über einen solchen Link hinaus zurückkehrt, wird auch L2 zurückgesetzt. Es ist erwähnenswert, dass dies auch die Art und Weise ist, wie eine frühere Version von Sharding (vor Dank) funktionieren sollte. Code finden Sie hier .
Überraschenderweise nicht so sehr. Es muss eigentlich nicht einmal ein Rollup sein: Wenn es sich um ein L3 oder ein Validium handelt, dann ist es in Ordnung, Wallets dort zu halten, solange Sie Keystores entweder auf L1 oder auf einem ZK-Rollup halten. Was Sie brauchen, ist, dass die Chain direkten Zugang zu den Wurzeln des Ethereum-Staates hat und ein technisches und soziales Engagement, um bereit zu sein, sich neu zu organisieren, wenn Ethereum neu organisiert wird, und eine Hard Fork, wenn Ethereum hart abgespalten wird.
Ein interessantes Forschungsproblem besteht darin, herauszufinden, inwieweit es möglich ist, dass eine Kette diese Form der Verbindung mit mehreren anderen Ketten (z. Ethereum und Zcash). Es ist möglich, es naiv zu machen: Ihre Chain könnte sich darauf einigen, sich neu zu organisieren, wenn Ethereum oder Zcash reorganisiert werden (und eine Hard Fork, wenn Ethereum oder Zcash eine Hard Fork hat), aber dann haben Ihre Node-Betreiber und Ihre Community im Allgemeinen doppelt so viele technische und politische Abhängigkeiten. Daher könnte eine solche Technik verwendet werden, um eine Verbindung zu einigen anderen Ketten herzustellen, jedoch zu steigenden Kosten. Schemes, die auf ZK-Bridges basieren, haben attraktive technische Eigenschaften, aber sie haben die entscheidende Schwäche, dass sie nicht robust gegenüber 51%-Angriffen oder Hard Forks sind. Vielleicht gibt es cleverere Lösungen.
Im Idealfall wollen wir auch die Privatsphäre wahren. Wenn Sie viele Wallets haben, die vom selben Keystore verwaltet werden, möchten wir sicherstellen:
Dies führt zu einigen Problemen:
Mit SNARKs sind die Lösungen konzeptionell einfach: Beweise verbergen standardmäßig Informationen, und der Aggregator muss ein rekursives SNARK erzeugen, um die SNARKs zu beweisen.
Die größte Herausforderung dieses Ansatzes besteht heute darin, dass der Aggregator für die Aggregation ein rekursives SNARK erstellen muss, was derzeit recht langsam ist.
Mit KZG können wir <a href="https://notes.ethereum.org/@vbuterin/non_index_revealing_proof">this verwenden. Arbeit an nicht-index-offenbaren KZG-Beweisen (siehe auch: eine formalisiertere Version dieser Arbeit im Caulk-Papier ) als Ausgangspunkt. Die Aggregation von verblindeten Beweisen ist jedoch ein offenes Problem, das mehr Aufmerksamkeit erfordert.
Das direkte Lesen von L1 aus L2 bewahrt leider nicht die Privatsphäre, obwohl die Implementierung der Funktion zum direkten Lesen immer noch sehr nützlich ist, sowohl um die Latenz zu minimieren als auch wegen ihrer Nützlichkeit für andere Anwendungen.