Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache

Als nächstes werden wir die Hauptmerkmale der Move-Sprache im Detail betrachten und was ihre Hauptunterschiede zu einer anderen, bereits beliebten Sprache für Smart Contracts sind – Solidity (auf der Ethereum-Plattform). Das Material basiert auf der Untersuchung eines online verfügbaren 26-seitigen Whitepapers.

Einführung

Move ist eine ausführbare Bytecode-Sprache, die zur Ausführung von Benutzertransaktionen und Smart Contracts verwendet wird. Achten Sie auf zwei Punkte:

  1. Während Move eine Bytecode-Sprache ist, die direkt auf der virtuellen Move-Maschine ausgeführt werden kann, ist Solidity (die intelligente Vertragssprache auf Ethereum) eine höhere Sprache, die zunächst in Bytecode kompiliert wird, bevor sie auf der EVM (Ethereum Virtual Machine) ausgeführt wird. ).
  2. Move kann nicht nur zur Implementierung von Smart Contracts, sondern auch für Benutzertransaktionen verwendet werden (dazu später mehr), während Solidity nur eine Sprache für Smart Contracts ist.


Die Übersetzung wurde vom INDEX-Protokoll-Projektteam durchgeführt. Wir haben bereits übersetzt umfangreiches Material, das das Libra-Projekt beschreibt, jetzt ist es an der Zeit, einen genaueren Blick auf die Move-Sprache zu werfen. Die Übersetzung erfolgte gemeinsam mit dem Habrauser coolsiu

Ein Hauptmerkmal von Move ist die Möglichkeit, benutzerdefinierte Ressourcentypen mit einer auf linearer Logik basierenden Semantik zu definieren: Eine Ressource kann niemals kopiert oder implizit gelöscht, sondern nur verschoben werden. Funktionell ähnelt dies den Fähigkeiten der Rust-Sprache. Werte in Rust können jeweils nur einem Namen zugewiesen werden. Wenn Sie einen Wert einem anderen Namen zuweisen, ist er unter dem vorherigen Namen nicht mehr verfügbar.

Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache

Das folgende Codefragment löst beispielsweise einen Fehler aus: Verwendung des verschobenen Werts „x“. Dies liegt daran, dass Rust keine Garbage Collection hat. Wenn Variablen den Gültigkeitsbereich verlassen, wird auch der Speicher freigegeben, auf den sie verweisen. Vereinfacht gesagt kann es nur einen „Eigentümer“ der Daten geben. In diesem Beispiel x ist der ursprüngliche Besitzer und dann y wird neuer Eigentümer. Lesen Sie hier mehr über dieses Verhalten..

Darstellung digitaler Assets in offenen Systemen

Es gibt zwei Eigenschaften physischer Vermögenswerte, die sich nur schwer digital darstellen lassen:

  • Rarität (Knappheit, im Original - Knappheit). Die Anzahl der Vermögenswerte (Emissionen) im System muss kontrolliert werden. Die Vervielfältigung bestehender Vermögenswerte muss verboten werden, und die Schaffung neuer Vermögenswerte ist eine privilegierte Operation.
  • Zugangskontrolle. Der Systemteilnehmer muss in der Lage sein, Vermögenswerte durch Zugriffskontrollrichtlinien zu schützen.

Diese beiden Eigenschaften, die für physische Vermögenswerte selbstverständlich sind, müssen auch für digitale Objekte umgesetzt werden, wenn wir sie als Vermögenswerte betrachten wollen. Beispielsweise ist ein seltenes Metall von Natur aus knapp und nur Sie haben Zugriff darauf (z. B. wenn Sie es in den Händen halten) und können es verkaufen oder ausgeben.

Um zu veranschaulichen, wie wir zu diesen beiden Eigenschaften gekommen sind, beginnen wir mit den folgenden Sätzen:

Vorschlag Nr. 1: Die einfachste Regel ohne Knappheit und Zugangskontrolle

Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache

  • G[K]:=n bezeichnet die Aktualisierung einer per Schlüssel verfügbaren Nummer К im globalen Zustand der Blockchain der neue Wert n.
  • Transaktion ⟨Alice, 100⟩ bedeutet, Alices Kontostand auf 100 zu setzen.

Die obige Lösung weist mehrere schwerwiegende Probleme auf:

  • Alice kann durch einfaches Senden unbegrenzt Münzen erhalten Transaktion ⟨Alice, 100⟩.
  • Die Münzen, die Alice an Bob sendet, sind nutzlos, da Bob sich mit derselben Technik eine unbegrenzte Anzahl Münzen senden könnte.

Vorschlag Nr. 2: Berücksichtigen Sie das Defizit

Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache

Jetzt beobachten wir die Situation, um die Anzahl der Münzen zu ermitteln Ka war mindestens gleich n vor der Überweisungstransaktion. Obwohl dadurch das Knappheitsproblem gelöst wird, gibt es jedoch keine Informationen darüber, wer Alice-Münzen senden kann (derzeit kann dies jeder tun, solange Sie nicht gegen die Mengenbegrenzungsregel verstoßen).

Vorschlag Nr. 3: Knappheit und Zugangskontrolle kombinieren

Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache

Wir lösen dieses Problem mithilfe eines digitalen Signaturmechanismus überprüfen_sig bevor sie den Kontostand überprüft, was bedeutet, dass Alice ihren privaten Schlüssel verwendet, um die Transaktion zu signieren und zu bestätigen, dass sie die Besitzerin ihrer Coins ist.

Blockchain-Programmiersprachen

Bestehende Blockchain-Sprachen stehen vor den folgenden Problemen (die alle in Move gelöst wurden). Leider bezieht sich der Autor des Artikels in seinen Vergleichen nur auf Ethereum, sodass man sie nur in diesem Zusammenhang betrachten sollte. Die meisten der folgenden Probleme werden beispielsweise auch in EOS gelöst)):

Indirekte Vermögensdarstellung. Ein Asset wird mit einer Ganzzahl codiert, aber ein ganzzahliger Wert ist nicht dasselbe wie ein Asset. Tatsächlich gibt es keinen Typ oder Wert, der Bitcoin/Ether/<Any Coin> darstellt! Dies macht es schwierig und fehleranfällig, Programme zu schreiben, die Assets verwenden. Muster wie die Übergabe von Assets an/von Prozeduren oder das Speichern von Assets in Strukturen erfordern besondere Unterstützung durch die Sprache.

Das Defizit vergrößert sich nicht. Sprache ist nur ein knappes Gut. Darüber hinaus sind die Mittel zum Schutz vor Defiziten direkt in der Semantik der Sprache verankert. Wenn ein Entwickler ein benutzerdefiniertes Asset erstellen möchte, muss er alle Aspekte der Ressource selbst sorgfältig kontrollieren. Genau das sind die Probleme mit den Smart Contracts von Ethereum.

Benutzer geben ihre Vermögenswerte, ERC-20-Token, aus und verwenden dabei Ganzzahlen, um sowohl den Wert als auch das Gesamtangebot zu bestimmen. Bei der Erstellung neuer Token muss der Smart-Contract-Code selbstständig prüfen, ob die Ausgaberegeln eingehalten werden. Darüber hinaus führt die indirekte Darstellung von Vermögenswerten teilweise zu schwerwiegenden Fehlern – Doppelspurigkeiten, doppelte Ausgaben oder sogar der vollständige Verlust von Vermögenswerten.

Mangel an flexibler Zugangskontrolle. Die einzige derzeit gültige Zugriffskontrollrichtlinie ist ein Signaturschema mit asymmetrischer Kryptografie. Wie der Knappheitsschutz ist auch die Zugangskontrollpolitik tief in der Semantik der Sprache verankert. Aber wie man die Sprache erweitert, damit Programmierer ihre eigenen Zugriffskontrollrichtlinien definieren können, ist oft eine nicht triviale Aufgabe.

Dies gilt auch für Ethereum, wo Smart Contracts keine native Kryptografieunterstützung für die Zugriffskontrolle bieten. Entwickler müssen die Zugriffskontrolle manuell festlegen, beispielsweise mit dem Modifikator onlyOwner.

Obwohl ich ein großer Fan von Ethereum bin, glaube ich, dass Asset-Eigenschaften aus Sicherheitsgründen nativ von der Sprache unterstützt werden sollten. Insbesondere die Übergabe von Ether an einen Smart Contract ermöglicht den dynamischen Versand, wodurch eine neue Klasse von Fehlern entstanden ist, die als Re-Entrance-Schwachstellen bekannt sind. Dynamischer Versand bedeutet hier, dass die Codeausführungslogik zur Laufzeit (dynamisch) und nicht zur Kompilierungszeit (statisch) bestimmt wird.

Wenn also in Solidity Vertrag A eine Funktion in Vertrag B aufruft, führt Vertrag B möglicherweise Code aus, der vom Entwickler von Vertrag A nicht vorgesehen war, was dazu führen kann Sicherheitslücken beim Wiedereintritt (Vertrag A fungiert versehentlich als Vertrag B, um Geld abzuheben, bevor der Saldo tatsächlich vom Konto abgebucht wird).

Grundlagen des Move-Sprachdesigns

Ressourcen erster Ordnung

Auf hoher Ebene ist die Interaktion zwischen Modulen/Ressourcen/Prozeduren in der Move-Sprache den Beziehungen zwischen Klassen/Objekten und Methoden in OOP-Sprachen sehr ähnlich.
Module in Move ähneln Smart Contracts in anderen Blockchains. Das Modul deklariert Ressourcentypen und Prozeduren, die Regeln zum Erstellen, Zerstören und Aktualisieren deklarierter Ressourcen festlegen. Aber das sind alles nur Konventionen („Jargon“) in Move. Wir werden diesen Punkt etwas später veranschaulichen.

Flexibilität

Move verleiht Libra durch Skripting mehr Flexibilität. Jede Transaktion in Libra umfasst ein Skript, das eigentlich den Hauptvorgang der Transaktion darstellt. Das Skript kann entweder eine bestimmte Aktion ausführen, beispielsweise Zahlungen an eine bestimmte Empfängerliste leisten, oder andere Ressourcen wiederverwenden, beispielsweise durch Aufrufen einer Prozedur, die eine gemeinsame Logik definiert. Aus diesem Grund bieten Move-Transaktionsskripte viel Flexibilität. Ein Skript kann sowohl einmalige als auch wiederkehrende Verhaltensweisen verwenden, während Ethereum nur wiederkehrende Skripte ausführen kann (Aufruf einer einzelnen Smart-Contract-Methode). Der Grund für die Bezeichnung „wiederholt“ liegt darin, dass Smart-Contract-Funktionen mehrfach ausgeführt werden können. (Notiz: Der Punkt hier ist sehr subtil. Einerseits existieren auch in Bitcoin Transaktionsskripte in Form von Pseudo-Bytecode. Andererseits erweitert Move, soweit ich es verstehe, diese Sprache tatsächlich auf das Niveau einer vollwertigen intelligenten Vertragssprache).

Sicherheit

Das Format der ausführbaren Move-Datei ist Bytecode, der einerseits eine höhere Programmiersprache als Assembler, aber eine niedrigere Programmiersprache als der Quellcode ist. Der Bytecode wird zur Laufzeit (on-chain) mithilfe eines Bytecode-Verifizierers auf Ressourcen, Typen und Speichersicherheit überprüft und dann vom Interpreter ausgeführt. Dieser Ansatz ermöglicht es Move, die Sicherheit des Quellcodes bereitzustellen, jedoch ohne den Kompilierungsprozess und die Notwendigkeit, dem System einen Compiler hinzuzufügen. Move zu einer Bytecode-Sprache zu machen, ist eine wirklich gute Idee. Es muss nicht aus dem Quellcode kompiliert werden, da im Fall von Solidity keine Angst vor möglichen Ausfällen oder Angriffen auf die Compiler-Infrastruktur besteht.

Überprüfbarkeit

Unser Ziel ist es, die Überprüfungen so einfach wie möglich zu gestalten, da alles in der Kette erfolgt (Hinweis: online, während der Ausführung jeder Transaktion, sodass jede Verzögerung das gesamte Netzwerk verlangsamt), jedoch ist das Sprachdesign zunächst bereit für die Verwendung statischer Off-Chain-Verifizierungstools. Obwohl dies vorzuziehen ist, wurde die Entwicklung von Verifizierungstools (als separates Toolkit) vorerst auf die Zukunft verschoben und jetzt wird nur die dynamische Verifizierung zur Laufzeit (in der Kette) unterstützt.

Modularität

Move-Module bieten Datenabstraktion und lokalisieren kritische Ressourcenvorgänge. Die vom Modul bereitgestellte Kapselung stellt in Kombination mit dem durch das Move-Typsystem bereitgestellten Schutz sicher, dass für Modultypen festgelegte Eigenschaften nicht durch Code außerhalb des Moduls verletzt werden können. Dabei handelt es sich um ein durchdachtes Abstraktionsdesign, d. h. die Daten innerhalb des Vertrags können nur im Rahmen der Vertragsabwicklung geändert werden, nicht jedoch von außen.

Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache

Übersicht verschieben

Das Beispiel eines Transaktionsskripts zeigt, dass böswillige oder unvorsichtige Aktionen eines Programmierers außerhalb des Moduls die Sicherheit der Modulressourcen nicht gefährden können. Als Nächstes schauen wir uns Beispiele dafür an, wie Module, Ressourcen und Verfahren zum Programmieren der Libra-Blockchain verwendet werden.

Peer-to-Peer-Zahlungen

Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache

Die im Betrag angegebene Anzahl an Coins wird vom Guthaben des Absenders an den Empfänger übertragen.
Hier gibt es ein paar Neuerungen (rot hervorgehoben):

  • 0x0: Adresse des Kontos, in dem das Modul gespeichert ist
  • Währung: Modulname
  • Münze: Ressourcentyp
  • Der von der Prozedur zurückgegebene Münzwert ist ein Ressourcenwert vom Typ 0x0.Currency.Coin
  • bewegen(): Wert kann nicht erneut verwendet werden
  • copy (): Wert kann später verwendet werden

Schauen wir uns den Code an: Im ersten Schritt ruft der Absender eine Prozedur mit dem Namen auf zurückziehen_vom_sender von einem Modul, das in gespeichert ist 0x0.Währung. Im zweiten Schritt überweist der Sender das Geld an den Empfänger, indem er den Wert der Münzressource in den Einzahlungsvorgang des Moduls überführt 0x0.Währung.

Hier sind drei Beispiele für Fehler im Code, die durch Prüfungen zurückgewiesen werden:
Doppelte Mittel durch Änderung des Anrufs bewegen (Münze) auf Kopie (Münze). Ressourcen können nur verschoben werden. Der Versuch, die Menge einer Ressource zu verdoppeln (z. B. durch Aufrufen von Kopie (Münze) im Beispiel oben) führt zu einem Fehler bei der Bytecode-Überprüfung.

Wiederverwendung von Mitteln durch Angabe bewegen (Münze) дважды . Eine Zeile hinzufügen 0x0.Currency.deposit(copy(some_other_payee), move(coin)) Das obige Beispiel ermöglicht es dem Absender, die Münzen zweimal „auszugeben“ – das erste Mal beim Zahlungsempfänger und das zweite Mal beim Zahlungsempfänger some_other_payee. Dies ist ein unerwünschtes Verhalten, das bei einem physischen Vermögenswert nicht möglich ist. Glücklicherweise wird Move dieses Programm ablehnen.

Geldverlust durch Ablehnung bewegen (Münze). Wenn Sie die Ressource nicht verschieben (z. B. durch Löschen der Zeile mit bewegen (Münze)), wird ein Bytecode-Überprüfungsfehler ausgelöst. Dies schützt Move-Programmierer vor versehentlichem oder böswilligem Verlust von Geldern.

Währungsmodul

Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache

Jedes Konto kann 0 oder mehr Module (dargestellt als Kästchen) und einen oder mehrere Ressourcenwerte (dargestellt als Zylinder) enthalten. Zum Beispiel ein Konto bei 0x0 enthält Modul 0x0.Währung und ein Ressourcenwert vom Typ 0x0.Currency.Coin. Konto unter Adresse 0x1 verfügt über zwei Ressourcen und ein Modul; Konto unter Adresse 0x2 hat zwei Module und einen Ressourcenwert.

Einige Momente:

  • Das Transaktionsskript ist atomar – entweder vollständig ausgeführt oder überhaupt nicht.
  • Ein Modul ist ein langlebiger Code, der weltweit verfügbar ist.
  • Der globale Status ist als Hash-Tabelle strukturiert, wobei die Kontoadresse der Schlüssel ist
  • Konten können nicht mehr als einen Ressourcenwert eines bestimmten Typs und nicht mehr als ein Modul mit einem bestimmten Namen (ein Konto unter) enthalten 0x0 darf keine zusätzliche Ressource enthalten 0x0.Currency.Coin oder ein anderes Modul namens Währung)
  • Die Adresse des deklarierten Moduls ist Teil des Typs (0x0.Currency.Coin и 0x1.Currency.Coin sind separate Typen, die nicht austauschbar verwendet werden können)
  • Programmierer können mehrere Instanzen eines bestimmten Ressourcentyps in einem Konto speichern, indem sie ihre benutzerdefinierte Ressource definieren – (Ressource TwoCoins {c1: 0x0.Currency.Coin, c2: 0x0.Currency.Coin})
  • Sie können ohne Konflikt auf eine Ressource mit ihrem Namen verweisen, Sie können beispielsweise auf zwei Ressourcen verweisen, indem Sie verwenden TwoCoins.c1 и TwoCoins.c2.

Deklaration der Münzressourcen

Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache
Benanntes Modul Währung und ein Ressourcentyp mit dem Namen Münze

Einige Momente:

  • Münze ist eine Struktur mit einem Feld vom Typ u64 (64-Bit-Ganzzahl ohne Vorzeichen)
  • Nur Modulprozeduren Währung kann Werte vom Typ erstellen oder zerstören Münze.
  • Andere Module und Skripte können das Wertfeld nur über die vom Modul bereitgestellten öffentlichen Prozeduren schreiben oder darauf verweisen.

Umsetzung der Anzahlung

Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache

Dieses Verfahren akzeptiert eine Ressource Münze als Eingabe und verkettet es mit einer Ressource Münzeim Konto des Empfängers gespeichert:

  1. Zerstören der Eingaberessource Coin und Schreiben ihres Wertes.
  2. Empfangen eines Links zu einer einzigartigen Coin-Ressource, die im Konto des Empfängers gespeichert ist.
  3. Ändern des Werts der Anzahl der Münzen um den Wert, der beim Aufruf der Prozedur im Parameter übergeben wurde.

Einige Momente:

  • Auspacken, AusleihenGlobal - Integrierte Prozeduren
  • Auspacken Dies ist die einzige Möglichkeit, eine Ressource vom Typ T zu löschen. Die Prozedur nimmt eine Ressource als Eingabe, zerstört sie und gibt den Wert zurück, der den Feldern der Ressource zugeordnet ist.
  • BorrowGlobal Nimmt eine Adresse als Eingabe und gibt einen Verweis auf eine eindeutige Instanz von T zurück, die von dieser Adresse veröffentlicht (im Besitz) wird
  • &mut Münze Dies ist ein Link zu einer Ressource Münze

Implementierung von „retract_from_sender“.

Tauchen Sie ein in Move – Facebooks Libra-Blockchain-Programmiersprache

Dieses Verfahren:

  1. Ruft einen Link zu einer eindeutigen Ressource ab Münze, verknüpft mit dem Konto des Absenders
  2. Verringert den Wert einer Ressource Münze per Referenz für den angegebenen Betrag
  3. Erstellt eine neue Ressource und gibt sie zurück Münze mit aktualisiertem Kontostand.

Einige Momente:

  • Deposit kann von jedem aufgerufen werden, aber zurückziehen_vom_sender hat nur Zugriff auf die Coins des aufrufenden Kontos
  • GetTxnSenderAddress ähnlich zu msg.sender in Solidität
  • AblehnenEs sei denn ähnlich zu erfordern in Solidität. Wenn diese Prüfung fehlschlägt, wird die Transaktion gestoppt und alle Änderungen werden rückgängig gemacht.
  • Pack Es handelt sich außerdem um eine integrierte Prozedur, die eine neue Ressource vom Typ T erstellt.
  • Ebenso gut wie Auspacken, Pack kann nur innerhalb des Moduls aufgerufen werden, in dem die Ressource deklariert ist T

Abschluss

Wir haben die Hauptmerkmale der Move-Sprache untersucht, sie mit Ethereum verglichen und uns auch mit der grundlegenden Syntax von Skripten vertraut gemacht. Abschließend empfehle ich dringend, einen Blick darauf zu werfen Original-Whitepaper. Es enthält viele Details zu den Designprinzipien von Programmiersprachen sowie viele nützliche Links.

Source: habr.com

Kommentar hinzufügen