In den letzten zwei Wochen haben unser führender C ++ – Entwickler Gavin Wood und ich viel Zeit damit verbracht, die lokale Ethereum -Community in San Francisco und das Silicon Valley zu treffen. Wir waren sehr gespannt auf ein so großes Interesse an unserem Projekt und die Tatsache, dass wir nach nur zwei Monaten eine Meetup -Gruppe haben, die jede Woche zusammenkommt, genau wie das Bitcoin -Meetup, wobei jedes Mal über dreißig Menschen anwesend sind. Die Menschen in der Gemeinde nehmen es auf sich, Bildungsvideos zu machen, Veranstaltungen zu organisieren und mit Verträgen zu experimentieren, und eine Person beginnt sogar unabhängig davon, eine Implementierung von Ethereum in Node.js. Gleichzeitig hatten wir jedoch die Möglichkeit, uns die Ethereum -Protokolle noch einmal anzusehen, zu sehen, wo die Dinge noch unvollkommen sind, und sich auf eine große Reihe von Änderungen einigen, die in die POC 3.5 -Kunden integriert werden, wahrscheinlich nur mit minimaler Modifikation.
Transaktionen als Schließungen
In ES1 und ES2 hatte der MKTX-Opcode, mit dem Verträge Transaktionen gesendet wurden, die andere Verträge auslösen, ein sehr nicht intuitives Merkmal: Obwohl man von Natur aus erwarten würde, dass MKTX wie ein Funktionsanruf ist, die gesamte Transaktion sofort verarbeitet und dann mit dem Rest des Codes in Wirklichkeit, in Wirklichkeit MKTX, arbeitete MKTX nicht so. Stattdessen wird die Ausführung des Anrufs gegen Ende verschoben – als MKTX aufgerufen wurde, würde eine neue Transaktion an die Vorderseite des Transaktionsstapels des Blocks gedrückt, und wenn die Ausführung der ersten Transaktion die Ausführung der zweiten Transaktion beendet. Zum Beispiel ist dies etwas, das Sie erwarten könnten:
x = array () x[0] = “George” x[1] = Mypubkey
MKTX (Namecoin, 10^20, x, 2)
Wenn Vertrag.Storage (Namecoin)[“george”] == mypubkey: Registrierung_Successful = 1 sonst: Registrierung_SUCCESFUL = 0
// mehr Sachen machen …
Verwenden Sie den Namecoin -Vertrag, um „George“ zu registrieren, und verwenden Sie dann den Extro -Opcode, um festzustellen, ob die Registrierung erfolgreich ist. Dies scheint, als sollte es funktionieren. Natürlich nicht.
In EVM3 (nicht mehr ES3) beheben wir dieses Problem. Wir tun dies, indem wir eine Idee von ES2 nehmen – ein Konzept aus wiederverwendbarem Code, Funktionen und Softwarebibliotheken und einer Idee von ES1 erstellen – es einfach hält, indem Sie den Code als sequentielle Anweisungen im Zustand beibehalten und die beiden zu einem Konzept von „Nachrichtenaufrufen“ zusammenführen. Ein Nachrichtenaufruf ist ein Vorgang, der aus einem Vertrag ausgeführt wird, der eine Zieladresse, einen Ätherwert und einige Daten als Eingabe annimmt und den Vertrag mit diesem Etherwert und den Daten aufruft, aber im Gegensatz zu einer Transaktion Daten als Ausgabe zurückgibt. Es gibt daher auch einen neuen Return -Opcode, mit dem die Vertragsausführung Daten zurückgibt.
Mit diesem System können Verträge jetzt viel leistungsfähiger sein. Verträge der traditionellen Sorte, die bestimmte Daten beim Empfang von Nachrichtenaufrufen ausführen, können weiterhin vorhanden sein. Aber jetzt werden jedoch auch zwei andere Designmuster möglich. Erstens kann man jetzt einen proprietären Datenfeed -Vertrag erstellen. Zum Beispiel kann Bloomberg einen Vertrag veröffentlichen, in den sie verschiedene Vermögenspreise und andere Marktdaten vorantreiben, und in ihren Vertrag eine API einbeziehen, die die internen Daten zurückgibt, solange der eingehende Nachrichtenaufruf mindestens 1 Finney zusammen mit ihr sendet. Die Gebühr kann nicht zu hoch sein; Andernfalls sind Verträge, die Daten aus dem Bloomberg -Vertrag einmal pro Block abrufen und dann einen billigeren Durchgang liefern, rentabel. Selbst mit Gebühren entspricht möglicherweise dem Wert einer Viertel einer Transaktionsgebühr, dass ein solches Geschäft mit Datenfressen sehr rentabel ist. Der Extro -Opcode wird entfernt, um diese Funktionalität zu erleichtern, dh. Verträge sind jetzt im Inneren des Systems undurchsichtig, obwohl man von außen offensichtlich einfach den Merkle -Baum betrachten kann.
Zweitens ist es möglich, Verträge zu erstellen, die Funktionen darstellen. Zum Beispiel kann man einen SHA256 -Vertrag oder einen ECMUL -Vertrag haben, um diese jeweiligen Funktionen zu berechnen. Es gibt ein Problem damit: Zwanzig Bytes, um die Adresse zu speichern, um eine bestimmte Funktion aufzurufen, kann ein bisschen viel sein. Dies kann jedoch gelöst werden, indem ein „STDLIB“ -Vertrag erstellt wird, der einige hundert Klauseln für gemeinsame Funktionen enthält, und Verträge können die Adresse dieses Vertrags einmal als Variable speichern und dann einfach als „x“ auf sie zugreifen (technisch gesehen „Push 0 MLOAD“). Dies ist die EVM3 -Methode, um die andere Hauptidee von ES2, dem Konzept der Standardbibliotheken, zu integrieren.
Äther und Gas
Eine weitere wichtige Änderung ist Folgendes: Verträge zahlen nicht mehr für die Vertragsausführung, Transaktionen. Wenn Sie eine Transaktion senden, müssen Sie jetzt eine Basisfee und eine maximale Anzahl von Schritten einfügen, für die Sie bereit sind, zu bezahlen. Zu Beginn der Transaktionsausführung wird die von den Maxsteps multiplizierte Basefire sofort von Ihrem Gleichgewicht abzugiert. Ein neuer Zähler wird dann instanziiert, genannt Gas, der mit der Anzahl der Schritte beginnt, die Sie hinterlassen haben. Dann beginnt die Transaktionsausführung wie zuvor. Jeder Schritt kostet 1 Gas, und die Ausführung wird fortgesetzt, bis entweder auf natürliche Weise angehalten wird. Zu diesem Zeitpunkt wird alle verbleibenden Gaszeiten der bereitgestellten Basisfee an den Absender zurückgegeben, oder die Ausführung hat das Gas aus. In diesem Fall wird die gesamte Ausführung zurückgekehrt, die gesamte Gebühr wird jedoch noch gezahlt.
Dieser Ansatz hat zwei wichtige Vorteile. Erstens ermöglicht es Bergleuten, die maximale Gasmenge, die eine Transaktion verbraucht, im Voraus zu wissen. Zweitens und viel wichtiger ist, dass Vertragsautoren viel weniger Zeit damit verbringen können, den Vertrag gegen Dummy -Transaktionen „vertretbar“ zu machen, die versuchen, den Vertrag zu sabotieren, indem er ihn zur Zahlung der Gebühren zwingt. Betrachten Sie beispielsweise die alte 5-Zeilen-Namenscoin:
Wenn tx.value
Zwei Zeilen, keine Schecks. Viel einfacher. Konzentrieren Sie sich auf die Logik, nicht auf die Protokolldetails. Die Hauptschwäche des Ansatzes besteht darin, dass Sie, wenn Sie eine Transaktion an einen Vertrag senden, vorhanden sind, wie lange die Ausführung eine angemessene Obergrenze festlegt (oder zumindest eine angemessene Obergrenze, die Sie zu zahlen bereit sind), und der Vertrag hat die Befugnis, in eine unendliche Runde zu gelangen, das gesamte Gas zu verbrauchen und Sie zu zwingen, Ihre Gebühr ohne Wirkung zu zahlen. Dies ist jedoch wohl ein Nicht-identifiziertes; Wenn Sie eine Transaktion an jemanden senden, vertrauen Sie ihm bereits implizit, dass er das Geld nicht in einen Graben werfen (oder zumindest nicht beschweren, wenn sie es tun), und es liegt an dem Vertrag, angemessen zu sein. Verträge können sogar ein Flag enthalten, in dem angegeben ist, wie viel Gas sie erwarten (ich nominiere hiermit die Vorbereitung „Push 4 JMP“ in den Ausführungscode als freiwilligen Standard).
Es gibt eine wichtige Erweiterung dieser Idee, die für das Konzept der Nachrichtenanrufe gilt: Wenn ein Vertrag einen Nachrichtenaufruf tätigt, gibt der Vertrag auch die Höhe des Gas an, den der Vertrag am anderen Ende des Anrufs verwenden muss. So wie auf der obersten Ebene der Empfangsvertrag entweder rechtzeitig abgeschlossen oder das Gas ausgeht. Zu diesem Zeitpunkt wird die Ausführung zum Beginn des Anrufs zurückgekehrt, aber das Gas wird weiterhin verbraucht. Alternativ können Verträge in die Gasfelder eine Null aufnehmen. In diesem Fall vertrauen sie dem Untervertrag mit allen verbleibenden Gas. Der Hauptgrund, warum dies notwendig ist, ist, dass automatische Verträge und von Menschen kontrollierte Verträge miteinander interagieren. Wenn nur die Option, einen Vertrag mit allen verbleibenden Gas anzurufen, verfügbar wäre, könnten automatische Verträge keine von Menschen kontrollierten Verträgen verwenden, ohne ihren Eigentümern absolut zu vertrauen. Dies würde M-of-N-Daten-Feed-Anwendungen im Wesentlichen nicht lebensfähig machen. Auf der anderen Seite wird die Schwäche eingeführt, die die Ausführungsmaschine benötigt, um die Möglichkeit zu geben, zu bestimmten vorherigen Punkten zurückzukehren (insbesondere den Beginn eines Nachrichtenaufrufs).
Der neue Terminologiehandbuch
Bei all den neuen Konzepten, die wir eingeführt haben, haben wir einige neue Begriffe, die wir verwenden werden, standardisiert. Hoffentlich hilft dies dabei, die Diskussion zu den verschiedenen Themen zu beseitigen.
- Externer Schauspieler: Eine Person oder eine andere Entität, die in der Lage ist, mit einem Ethereum -Knoten, aber außerhalb der Welt von Ethereum, zu verknüpfen. Es kann mit Ethereum interagieren, indem signierte Transaktionen abgelagert und die Blockkette und den zugehörigen Zustand inspiziert werden. Hat einen (oder mehr) intrinsischen Konten.
- Adresse: Ein 160-Bit-Code, der zur Identifizierung von Konten verwendet wird.
- Konto: Konten haben einen intrinsischen Saldo und eine Transaktionszahl im Rahmen des Ethereum -Staates. Sie sind entweder externer Akteure oder intrinsisch (als Insentität) ein autonomes Objekt innerhalb von Ethereum. Wenn ein Konto ein autonomes Objekt identifiziert, führt Ethereum auch einen speziellen Speicher für dieses Konto bei. Jedes Konto hat eine einzige Adresse, die sie identifiziert.
- Transaktion: Ein Datenstück, das von einem externen Schauspieler signiert wurde. Es repräsentiert entweder eine Nachricht oder ein neues autonomes Objekt. Transaktionen werden in jedem Block der Blockkette aufgezeichnet.
- Autonomes Objekt: Ein virtuelles Objekt existiert nur im hypothetischen Zustand von Ethereum. Hat eine intrinsische Adresse. Nur als Zustand der Speicherkomponente der VM eingebaut.
- Speicherzustand: Die Informationen zu einem bestimmten autonomen Objekt, das zwischen den Zeiten, in denen es ausgeführt wird, aufrechterhalten wird.
- Nachricht: Daten (als Reihe von Bytes) und Wert (als Ether angegeben), die auf eine vollkommen vertrauenswürdige Weise zwischen zwei Konten übergeben werden, entweder durch den deterministischen Betrieb eines autonomen Objekts oder die kryptografisch sichere Signatur der Transaktion.
- Nachrichtenanruf: Die Akt der Übergabe einer Nachricht von einem Konto an einen anderen. Wenn das Zielkonto ein autonomes Objekt ist, wird die VM mit dem Zustand des Objekts und der Nachricht gestartet. Wenn der Nachrichtensender ein autonomes Objekt ist, übergibt der Anruf alle Daten, die aus der VM -Operation zurückgegeben wurden.
- Gas: Die grundlegende Netzwerkkosteneinheit. Ausschließlich von Ether (ab POC-3.5) bezahlt, die nach Bedarf frei zu und von Gas umgewandelt wird. Gas existiert nicht außerhalb der internen Ethereum -Rechenmotor. Der Preis wird durch die Transaktion festgelegt und die Bergleute können Transaktionen ignorieren, deren Gaspreis zu niedrig ist.
Langzeitansicht
Bald werden wir eine vollständige formale Spezifikation der oben genannten Änderungen veröffentlichen, einschließlich einer neuen Version des Whitepaper, die alle diese Änderungen berücksichtigt, sowie eine neue Version des Kunden, die es implementiert. Später werden wahrscheinlich weitere Änderungen an der EVM vorgenommen, aber die ETH-Hll wird so wenig wie möglich verändert. Daher ist es absolut sicher, jetzt Verträge in ETH-HLL zu schreiben, und sie werden auch dann weiter funktionieren, wenn sich die Sprache ändert.
Wir haben immer noch keine endgültige Vorstellung davon, wie wir mit obligatorischen Gebühren umgehen werden. Der aktuelle Stop-Gap-Ansatz besteht nun darin, eine Blocklimit von 1000000 Operationen (dh Gas ausgegeben) pro Block zu haben. Wirtschaftlich sind eine obligatorische Gebühr und eine obligatorische Blockgrenze im Wesentlichen gleichwertig. Die Blocklimit ist jedoch etwas generischer und ermöglicht theoretisch eine begrenzte Anzahl von Transaktionen kostenlos. Es wird einen Blog -Beitrag geben, der in Kürze unsere neuesten Gedanken zum Gebührenproblem abdeckt. Die andere Idee, die ich hatte, kann auch später implementiert werden.
Langfristig, vielleicht sogar über Ethereum 1.0, ist vielleicht der Heilige Gral die letzten beiden „intrinsischen“ Teile des Systems an, und prüfen Sie, ob wir sie auch in Verträge verwandeln können: Äther und ECDSA. In einem solchen System wäre Ether immer noch die privilegierte Währung im System; Das aktuelle Denken ist, dass wir den Äther-Vertrag in den Index „1“ einleiten werden, sodass es neunzehn weniger Bytes braucht, um ihn zu verwenden. Die Ausführungsmaschine wird jedoch einfacher, da es kein Konzept mehr gibt. Stattdessen würde alles über Verträge und Nachrichtenaufrufe. Ein weiterer interessanter Vorteil ist, dass es sich um ein E-CDSA handelt. NTRU oder LAMPORT -Vertrag stattdessen ist ein Nachteil, dass ohne Währung, die auf Protokollebene intrinsisch ist, nicht möglich ist.

