Warnung
Diese Kiste wurde archiviert. Die Entwicklung wurde in das zksync-crypto-Repository verschoben. Bitte verwenden Sie es stattdessen.
zkSync Era ist ein Layer-2-Rollup, das wissensfreie Beweise verwendet, um Ethereum zu skalieren, ohne Kompromisse bei der Sicherheit oder Dezentralisierung einzugehen. Da es EVM-kompatibel (Solidity/Vyper) ist, können 99 % der Ethereum-Projekte ohne Umgestaltung oder erneute Prüfung einer einzigen Codezeile erneut bereitgestellt werden. zkSync Era verwendet außerdem einen LLVM-basierten Compiler, der es Entwicklern letztendlich ermöglichen wird, intelligente Verträge in C++, Rust und anderen gängigen Sprachen zu schreiben.
Der Zweck dieser Bibliothek besteht darin, mit einer sehr spezifischen Arithmetisierung mit zusätzlichen Annahmen über die Feldgröße zu arbeiten. Grob gesagt erwarten wir einen Körper F
mit |F| ~ 64 Bit (die Größe eines Maschinenworts) (die Annahme über die Feldgröße ist für die Strategie der Arithmetisierung und Gatterplatzierung nicht wichtig, wird aber in Gadget-Implementierungen für bestimmte Funktionen geltend gemacht, die auf einer bestimmten Feldgröße basieren).
Das System verfügt über eine Hierarchie aus logischen Funktionen (Gadgets), Gattern (Entitäten, die sich selbst in die Spur einschreiben können) und Auswertern (Beziehungen zwischen Polynomen). Evaluatoren werden in Form eines Merkmals geschrieben, das es uns später ermöglicht, automatisch Funktionen zu erstellen, um die Erfüllbarkeit zu überprüfen und Beweise zu berechnen sowie einfache und rekursive Verifizierer zu synthetisieren. An Gates sind zusätzliche Werkzeuge angebracht, die es den Gates selbst ermöglichen, die Logik zu verfolgen, wo sie in der Spur platziert werden sollen. Beachten Sie, dass wir uns auf die Kopierbeschränkungen von Plonk verlassen und an den kopierbaren logischen Einheiten von „Variablen“ arbeiten, um eine endgültige beweisbare Aussage zu verfassen. Das System ist nicht für die AIR-Arithmetisierung vorgesehen und erlaubt nicht das Ausdrücken von Einschränkungen, die sich über mehrere Zeilen der Ablaufverfolgung erstrecken.
Im Allgemeinen beschränkt die Ablaufverfolgung nur wenige Spaltenvarianten. Die Haupttrennung besteht zwischen:
Darüber hinaus können Sie mit der Ablaufverfolgung ein Suchargument hinzufügen, das entweder spezielle Spalten zur Aufnahme der Einträge der Suchtabellen oder einfach allgemeine Spalten verwenden kann. Tabellen werden derzeit nur als ein Satz von Polynomen codiert, daher muss die Gesamtlänge der Spur größer sein als die Gesamtzahl der Einträge in den Tabellen.
Beachten Sie, dass jedes „Gate“ (als Rust-Typ) einzigartig ist und ein Gate daher nur in Spezial- oder Allzweckspalten platziert werden kann, nicht jedoch in beiden. Wenn man eine solche Funktionalität benötigt, ist es möglich, einen neuen Wrapper zu erstellen.
Logische Funktionen höherer Ebene (wie boolesche Zerlegungen, Bereichsprüfungen, Nullprüfungen usw.) werden verwendet, um eine Schaltung intern auf unterschiedliche Weise einzuschreiben, je nachdem, ob einige Gatter in der jeweiligen Instanz des CS zulässig sind oder nicht. Instanzen des CS mit unterschiedlichen Gattersätzen werden aus der Rust-Perspektive als ein anderer Typ betrachtet, und wir verlassen uns auf einige Inlining-/konstante Prop-/Compiler-Arbeiten, um die Verzweigung in statische Sprünge zu reduzieren.
|F|
und daher müssen wir Argumente wiederholen), aber dies wird geändert, sodass wir zum Erweiterungsfeld als wechseln so schnell wie möglich, nachdem Sie sich an den Zeugen gebunden haben, um eine ziemlich „große“ Chance zu vermeiden, Nullen im Nenner zu erhalten. Die Auswirkung auf den Rechenaufwand beim Beweisen ist vernachlässigbar Wir verwenden ein Suchargument, das über die Beziehungen sum_i selector(x_i) / (witness(x_i) + beta) == sum_i multiplicity(x_i) / (table(x_i) + beta)
erzwungen wird, wobei eine Suche über spezialisierte Spalten selector(x_i)
erfolgt selector(x_i)
ist nur eine Identität. Wir kodieren die Tabellen auch nicht als Polynom kleineren Grades, um Prüfungen zusätzlicher Gradgrenzen zu vermeiden, sondern füllen sie stattdessen mit Nullen auf. Beachten Sie, dass Tabelleneinträge niemals ein Element von (0,0,...,0)
enthalten, da wir bei mehreren Tabellen (auch wenn nur eine Tabelle verwendet wird) separate ID-Spalten für Tabellentypen und eine ID verwenden So beginnt dies mit 1.
Ein nettes Merkmal eines Sucharguments wie diesem besteht darin, dass wir aufgrund seiner additiven Natur, wenn wir mehrere witness
in derselben Tabelle nachschlagen, das Argument für jedes (Tupel) Polynom(e) wiederholen müssen (was erforderlich wäre). eine separate Multiplizitätsspalte sowie später einige Zwischenpolynome), können wir Multiplizitäten „addieren“ und das Argument in etwas wie sum_i selector_0(x_i) / (witness_0(x_i) + beta) + sum_i selector_1(x_i) / (witness_1(x_i) + beta) == sum_i total_multiplicity(x_i) / (table(x_i) + beta)
umwandeln sum_i selector_0(x_i) / (witness_0(x_i) + beta) + sum_i selector_1(x_i) / (witness_1(x_i) + beta) == sum_i total_multiplicity(x_i) / (table(x_i) + beta)
, also die Gesamtkosten einer Suche ist nur 1 Multiplizitätsspalte und 2 (zeugenbezogene) + 1 (tabellenbezogene) zu kodierende Zwischenpolynome die Links- und Rechtsbeziehungen auf den Wurzeln der Einheit.
Die Richtigkeit dieses Arguments ist klar. Aus Gründen der Solidität verwenden wir das ursprüngliche Argument wie im Artikel „Cached quotients for fast lookups“, Lemma 2.4. Wir müssen zeigen, dass es ausreicht, sich auf die total_multiplicity
und nicht auf die Multiplizitäten von witness_0
und witness_1
separat festzulegen.
Angenommen, die Gleichung sum_i selector_0(x_i) / (witness_0(x_i) + X) + sum_i selector_1(x_i) / (witness_1(x_i) + X) == sum_i total_multiplicity(x_i) / (table(x_i) + X)
gilt. Wir müssen zeigen, dass witness_0
und witness_1
in der Tabelle t
enthalten sind. Sei f = (witness_0 | witness_1)
, eine Verkettung der Werte. Die obige Gleichung impliziert sum_i selector_i / (f_i + X i
sum_i selector_i / (f_i + X) == sum_i total_multiplicity_i / (t_i + X)
Nach Lemma 2.4 erhalten wir f subset t
: „Teilmenge“ in dem Sinne, dass jede Koordinate des Vektors f
eine Koordinate von t
ist. Insbesondere witness_0, witness_1 subset f subset t
.
Beachten Sie, dass das Argument auch für mehrere witness_i
gilt. Der Rest des Aussagekraftarguments folgt für ein gewähltes beta
direkt wie in der obigen Arbeit.
2^-40
, 0
im Nenner zu erhalten, akzeptabel ist Es gibt Benchmarks für 8 KB SHA256, die unserer Meinung nach eine einigermaßen optimale Konfiguration von Gattern + Tabellen für die SHA256-Schaltung verwenden. Beachten Sie, dass wir, obwohl der Beweiser ziemlich schnell ist, die FFT nicht richtig optimiert haben und immer noch Poseidon (nicht Poseidon2) für Konfigurationen verwenden, bei denen wir erwarten, dass der Beweis für die Rekursion verwendet wird. Mit den beiden Skripten sha256_bench_recursive.sh
und sha256_bench_non_recursive.sh
können Sie die entsprechenden Tests ausführen (unabhängig davon, ob der Beweis in der Rekursion verwendet werden soll oder nicht). Sie sollten nach der Zeile Proving is done, taken ...
suchen, um die Prüfzeit anzuzeigen , weil der Prüfer, der danach ausgeführt wird, ziemlich ausführlich ist. Diese Benchmarks verwenden einen LDE-Faktor von 8, obwohl alle unsere Einschränkungen den Grad 4 oder weniger haben – es handelt sich jedoch um einen Parameter, der in einigen anderen öffentlichen Benchmarks verwendet wird. Wir verwenden PoW in diesen Beweisen auch nicht, da PoW für 20 Bit vernachlässigbar ist (30 ms) und wir PoW über algebraische Hashes noch nicht unterstützen (diese sind jedoch nur ~2x langsamer, also ebenfalls vernachlässigbar). Die Sicherheitsstufe beträgt ungefähr 100
Bit, aber die FRI-Stabilität kann durch eine Erhöhung der Anzahl der Abfragen gesteigert werden, und eine Erhöhung der Anzahl der Abfragen erhöht nicht die Prüfzeit (nicht zu verwechseln mit einer Änderung der FRI-Rate). Die Trace-Länge beträgt 2^16
und es werden 60 allgemeine Spalten und 8 Suchargumente mit der Breite 4 verwendet.
Hinweis: Benchmarks versuchen lediglich, zum nativen Arch zu kompilieren, und derzeit wird normalerweise nur der AArch64-Arch (sprich Apple M1) durchgehend getestet. x86-64-Arithmetikimplementierungen wurden auf Gültigkeit getestet, jedoch nicht durchgängig in vollständigen Beweisen. Beachten Sie, dass die maximale Leistung von x86-64 zusätzlich zu cpu = native
zusätzliche Compiler-Feature-Flags erfordert (AVX512-Satz wird vom Rust-Compiler nicht verwendet, selbst auf nativen CPUs).
Der Boojum-Prüfer wird unter den Bedingungen von beiden vertrieben
nach Ihrer Wahl.
zkSync Era hat viele Tests und Audits durchlaufen. Obwohl es live ist, befindet es sich noch im Alpha-Stadium und wird weitere Audits und Bug-Bounty-Programme durchlaufen. Wir würden gerne die Gedanken und Vorschläge unserer Community dazu hören! Es ist wichtig anzumerken, dass eine heutige Abzweigung möglicherweise dazu führen kann, dass wichtige Sicherheitsupdates, wichtige Funktionen und Leistungsverbesserungen verpasst werden.
Diese Software enthält Komponenten von Drittanbietern. Eine vollständige Liste dieser Komponenten und ihrer Lizenzen finden Sie in der Datei MITTEILUNGEN VON DRITTANBIETERN.