Move entstand in der Anfangsphase des Libra-Projekts im Jahr 2018 – die beiden Gründer von Mysten (Evan und ich) waren auch das Gründungsteam von Libra. Bevor wir uns entschieden, eine neue Sprache zu erstellen, untersuchte das frühe Libra-Team intensiv bestehende Anwendungsfälle und Sprachen für intelligente Verträge, um zu verstehen, was Entwickler tun wollten und wo bestehende Sprachen nicht lieferten. Das Hauptproblem, das wir entdeckt haben, ist, dass es bei intelligenten Verträgen ausschließlich um Vermögenswerte und Zugriffskontrolle geht, die frühen intelligenten Vertragssprachen jedoch keine Typ-/Wertdarstellung für beides hatten. Unsere Hypothese ist, dass wir die Sicherheit von Smart Contracts und die Produktivität von Smart Contract-Programmierern erheblich verbessern können, wenn wir erstklassige Abstraktionen für diese Schlüsselkonzepte bereitstellen – das richtige Vokabular für die jeweilige Aufgabe kann den entscheidenden Unterschied machen. Im Laufe der Jahre haben viele Menschen zum Design und zur Implementierung von Move beigetragen, während sich die Sprache von einer Schlüsselidee zu einer plattformunabhängigen intelligenten Vertragssprache mit dem kühnen Ziel entwickelte, das „JavaScript von web3“ zu werden.
Wir freuen uns, heute einen Meilenstein bei der Integration von Move und Sui bekannt geben zu können. Die Funktionalität von Sui Move ist vollständig, wird durch fortschrittliche Tools unterstützt und verfügt über umfangreiche Dokumentation und Beispiele, einschließlich der folgenden Abschnitte:
Eine Reihe von Tutorials zum Programmieren mit Sui Move-Objekten. Ein Entwicklungsdokument zu den Grundkenntnissen, Entwurfsmustern und Beispielen von Sui Move. Ein vom Mysten Move-Team entwickeltes VSCode-Erweiterungs-Plug-in, das Code-Analyse und Fehlerdiagnose unterstützt die Erstellung, Prüfung und Paketverwaltung von Move, Dokumentationserstellung und Move-Validator integriert mit sui CLI
Was Move einzigartig macht
Move ist eine plattformübergreifende eingebettete Sprache. Die Kernsyntax selbst ist sehr einfach: Sie verfügt über gemeinsame Konzepte wie Strukturen, Ganzzahlen und Adressen, aber keine Blockchain-spezifischen Konzepte wie Konten und Transaktionen, Zeit, Kryptographie usw. Diese Funktionen müssen von der in Move integrierten Blockchain-Plattform bereitgestellt werden. Wichtig ist, dass diese Blockchains keine eigenen Move-Forks erfordern – jede Plattform verwendet dieselbe virtuelle Move-Maschine, denselben Bytecode-Validator, denselben Compiler, denselben Validator, denselben Paketmanager und dieselbe CLI, baut jedoch auf Code auf diesen Kernkomponenten auf, um Blockchain-spezifische Funktionen hinzuzufügen . Diem war die erste Blockchain, die Move einbettete, und nachfolgende Move-basierte Blockchains (einschließlich 0L, StarCoin und Aptos) verwendeten größtenteils einen Ansatz im Diem-Stil. Während Move im Diem-Stil einige großartige Eigenschaften aufweist, erschweren sowohl die Berechtigungscharakteristik von Diem als auch bestimmte Implementierungsdetails der Diem-Blockchain (insbesondere das Speichermodell) die Implementierung einiger grundlegender Smart-Contract-Anwendungsfälle. Insbesondere die ursprünglichen Designs von Move and Diem stammen aus der Zeit vor der explosionsartigen Beliebtheit von NFTs und weisen einige Eigenheiten auf, die die Implementierung von NFT-bezogenen Anwendungsfällen besonders schwierig machen. In diesem Beitrag werden wir die Probleme mit der ursprünglichen Move-Einbettung im Diem-Stil anhand von drei solchen Beispielen demonstrieren und beschreiben, wie wir dieses Problem in Sui Move gelöst haben. Wir setzen ein gewisses Grundverständnis von Move voraus, hoffen aber, dass diese Kernpunkte für jeden mit Programmierkenntnissen verständlich sind.
Seidige Erfahrung bei der Erstellung von Assets im großen Maßstab
Die Möglichkeit, Assets in großen Mengen zu erstellen und zu verteilen, ist sowohl für das Onboarding als auch für die Einbindung von Web3-Benutzern von entscheidender Bedeutung. Vielleicht möchte ein Twitch-Streamer NFTs zum Gedenken verteilen, ein Entwickler möchte Tickets für ein besonderes Event verschicken oder ein Spieleentwickler möchte neue Gegenstände per Airdrop an alle Spieler verteilen. Hier ist ein (fehlgeschlagener) Versuch, Code für die Massenprägung von Vermögenswerten in Move im Diem-Stil zu schreiben. Dieser Code verwendet als Eingabe einen Vektor von Empfängeradressen, generiert für jeden Empfänger ein Asset und versucht, das Asset zu übertragen.
Bei einem Umzug im Diem-Stil wird der globale Speicher durch (Adresse, Typname)-Paare typisiert – das heißt, jede Adresse kann höchstens ein Asset eines bestimmten Typs speichern. Daher versucht move_to(receiverient, CoolAsset { ...}, das CoolAsset zu verschieben, indem es an der Adresse des Empfängers gespeichert wird. Dieser Code kann jedoch in der Zeile move_to(receiverient, ...) nicht kompiliert werden. Die Schlüsselfrage ist , in Bei einem Umzug im Diem-Stil können Sie keinen Wert vom Typ CoolAsset an eine Adresse A senden, es sei denn, eine Transaktion wird von einer anderen Adresse als A gesendet und der Eigentümer eines in A erstellten Kontos sendet eine Transaktion und entscheidet sich ausdrücklich für den Empfang von CoolAsset. Dies sind zwei Transaktionen, nur um einen Vermögenswert zu erhalten! Die Entscheidung, dies zu tun, ist für Diem sinnvoll, da es sich um ein autorisiertes System handelt, das die Erstellung von Konten sorgfältig einschränken und verhindern muss, dass Konten durch das Speichersystem eingeschränkt werden. Anstatt jedoch zu viele Assets für ein offenes System zu halten, das die Asset-Allokation als Onboarding-Mechanismus nutzen oder einfach nur den freien Fluss von Assets zwischen Benutzern zulassen möchte, wie dies bei Ethereum und ähnlichen Blockchains der Fall ist, ist es sehr begrenzt .
Der Code zum Implementieren derselben Funktion in Sui Move lautet wie folgt:
Der globale Speicher von Sui Move ist durch die Objekt-ID verschlüsselt. Jede Struktur mit Schlüssel-Wert-Paaren ist ein „Sui-Objekt“, das über ein weltweit eindeutiges ID-Feld verfügen muss. Sui Move führt ein Übertragungsprimitiv ein, das für jedes Sui-Objekt verwendet werden kann, anstatt die restriktive move_to-Struktur zu verwenden. Unter der Haube ordnet dieses Grundelement die ID einem CoolAsset im globalen Speicher zu und fügt Metadaten hinzu, um anzuzeigen, dass der Wert dem Empfänger gehört. Eine interessante Eigenschaft der Sui-Version von mass_mint ist, dass sie mit allen anderen Transaktionen ausgetauscht wird (einschließlich anderer Transaktionen, die mass_mint aufrufen!). Die Sui-Laufzeit wird dies bemerken und Transaktionen, die diese Funktion aufrufen, über den byzantinischen Konsens-Broadcast „Fast Path“ senden, der keinen Konsens erfordert. Solche Transaktionen können entweder festgeschrieben oder parallel ausgeführt werden. Dies erfordert keinen Aufwand seitens des Programmierers (er schreibt einfach den obigen Code und die Laufzeit erledigt den Rest). Vielleicht subtil ist dies bei der Diem-Variante dieses Codes nicht der Fall – obwohl der obige Code funktioniert, existiert er und guid::create-Aufrufe erzeugen Konfliktpunkte mit anderen Transaktionen, die GUIDs generieren oder Kontoressourcen berühren. In einigen Fällen ist es möglich, den Move-Code im Diem-Stil umzuschreiben, um das Argument zu vermeiden, aber viele der herkömmlichen Schreibweisen für Move im Diem-Stil bringen kleine Hindernisse mit sich, die die parallele Ausführung behindern.
Lokaler Vermögensbesitz und Übertragungen
Erweitern wir den Move-Code im Diem-Stil um eine Problemumgehung, die tatsächlich kompiliert und ausgeführt wird. Der übliche Weg, dies zu tun, ist das „Wrapper-Muster“: Da Bob das CoolAsset nicht direkt an Alices Adresse verschieben kann, bitten wir Alice, sich für den Empfang des CoolAsset zu entscheiden, indem wir zunächst einen Wrapper-Typ CoolAssetStore veröffentlichen, der einen Collection-Typ enthält (Tisch). Alice kann dies tun, indem sie die Funktion opt_in aufruft. Anschließend fügen wir Code hinzu, der es Bob ermöglicht, das CoolAsset von seinem CoolAssetStore in Alices CoolAssetStore zu verschieben. In diesem Code fügen wir eine zusätzliche Falte hinzu: Wir erlauben nur Übertragungen von CoolAssets, wenn diese vor mindestens 30 Tagen erstellt wurden. Diese Art von Richtlinie ist wichtig für YouTuber, die beispielsweise Spekulanten davon abhalten wollen, Veranstaltungstickets zu kaufen bzw. diese zu übertreiben, damit es für echte Fans einfacher ist, diese Tickets zu einem vernünftigen Preis zu bekommen.
Dieser Code ist gültig. Aber das ist ein ziemlich komplizierter Weg, die Aufgabe der Übertragung von Vermögenswerten von Alice auf Bob zu erfüllen! Werfen wir einen Blick auf eine andere Implementierung von Sui Move
Dieser Code ist viel kürzer. Hier ist vor allem zu beachten, dass cool_transfer eine Eingabefunktion ist (das heißt, sie kann direkt von der Sui-Laufzeit über eine Transaktion aufgerufen werden), sie verfügt jedoch über einen Parameter vom Typ CoolAsset als Eingabe. Das ist wiederum die Magie von Sui Runtime. Eine Transaktion enthält eine Reihe von Objekt-IDs, die sie bearbeiten möchte, und wenn Sui Runtime:
Analysieren Sie die ID in einen Objektwert (die Teile „borgen_global_mut“ und „table_remove“ im obigen Diem-Code sind nicht erforderlich). Überprüft, ob das Objekt dem Absender der Transaktion gehört (es macht den Abschnitt signer::address_of und den zugehörigen Code oben überflüssig). Dieser Teil ist besonders interessant und wir werden ihn bald erklären: In Sui ist die Überprüfung des sicheren Objektbesitzes Teil der Laufzeit. Überprüfen Sie den Typ des Objektwerts entsprechend dem Parametertyp der aufgerufenen Funktion cool_transfer zu cool_transfer. Parameter und rufen Sie die Funktion auf
Dies ermöglichte es den Programmierern von Sui Move, die Vorlage für den „Auszahlung“-Teil der Logik zu überspringen und direkt zum unterhaltsamen Teil zu springen: der Überprüfung der 30-Tage-Ablaufrichtlinie. Ebenso wird der Teil „Einzahlung“ mit der oben erläuterten Sui Move-Übertragungsstruktur erheblich vereinfacht. Schließlich besteht keine Notwendigkeit, einen Wrapper-Typ mit einer internen Sammlung wie CoolAssetStore einzuführen – der id-indizierte globale Sui-Speicher ermöglicht es einer Adresse, eine beliebige Anzahl von Werten eines bestimmten Typs zu speichern. Ein weiterer hervorzuhebender Unterschied besteht darin, dass cool_transfer im Diem-Stil fünf Abbruchmöglichkeiten bietet (d. h. fehlschlägt und dem Benutzer Benzin in Rechnung stellt, ohne die Übertragung abzuschließen), wohingegen cool_transfer bei Sui Move nur eine Abbruchmöglichkeit hat: bei Verstoß gegen die 30-Tage-Richtlinie. Die Auslagerung der Objektbesitzprüfungen in die Laufzeit ist ein großer Gewinn, nicht nur im Hinblick auf die Ergonomie, sondern auch im Hinblick auf die Sicherheit. Durch die Implementierung von Sicherheit auf Laufzeitebene werden Fehler bei der Implementierung dieser Prüfungen im Konstrukt verhindert (oder sie werden ganz vergessen!). Beachten Sie schließlich, dass die Einstiegspunkt-Funktionssignatur cool_transfer( asset: CoolAsset, ...) von Sui Move uns viele Informationen darüber liefert, was diese Funktion tun wird (sie ist undurchsichtiger als Funktionssignaturen im Diem-Stil). Wir können uns vorstellen, dass diese Funktion die Erlaubnis zum Übertragen von CoolAsset anfordert, während eine andere Funktion f(asset: &mut CoolAsset, ...) die Erlaubnis zum Schreiben (aber nicht zur Übertragung) von CoolAsset anfordert, und g(asset: &CoolAsset, ...) bittet lediglich um Leseerlaubnis.
Da diese Informationen direkt in der Funktionssignatur verfügbar sind (keine Ausführung oder statische Analyse erforderlich!), können sie direkt von Wallets und anderen Client-Tools verwendet werden. In Sui Wallet arbeiten wir an für Menschen lesbaren Signaturanfragen und nutzen diese strukturierten Funktionssignaturen, um Benutzern Berechtigungsaufforderungen im iOS/Android-Stil bereitzustellen. Das Wallet kann etwa sagen: „Für diese Transaktion ist die Erlaubnis erforderlich, Ihr CoolAsset zu lesen, in Ihre AssetCollection zu schreiben und Ihr ConcertTicket zu übertragen. Fortfahren?“
Von Menschen lesbare Signaturanfragen lösen einen groß angelegten Angriffsvektor, der auf vielen bestehenden Plattformen vorhanden ist, einschließlich derjenigen, die Move! im Diem-Stil verwenden, bei denen Wallet-Benutzer Transaktionen blind signieren müssen, ohne zu verstehen, welche Auswirkungen sie haben können. Wir glauben, dass es ein entscheidender Schritt ist, die Wallet-Erfahrung weniger riskant zu machen, um die allgemeine Einführung von Kryptowährungs-Wallets zu fördern, und haben Sui Move so konzipiert, dass dieses Ziel unterstützt wird, indem Funktionen wie für Menschen lesbare Signaturanfragen ermöglicht werden.
Bündeln Sie verschiedene Vermögenswerte
Betrachten wir abschließend ein Beispiel für die Bündelung verschiedener Arten von Vermögenswerten. Dies ist ein ziemlich häufiger Anwendungsfall: Programmierer möchten möglicherweise verschiedene Arten von NFTs in einer Sammlung bündeln, Artikel bündeln, um sie auf einem Marktplatz zu verkaufen, oder Anhänge zu vorhandenen Artikeln hinzufügen. Angenommen, wir haben die folgende Situation:
Alice definiert ein Charakterobjekt zur Verwendung im Spiel. Alice möchte die Dekoration ihres Charakters mit verschiedenen Arten von Zubehör von Drittanbietern unterstützen, die später erstellt werden. Jeder sollte in der Lage sein, ein Accessoire zu erstellen, aber der Besitzer eines Charakters sollte entscheiden, ob er ein Accessoire hinzufügt. Beim Übertragen eines Charakters sollten automatisch alle seine Accessoires übertragen werden.
Beginnen wir dieses Mal mit dem Code für Sui Move. Wir nutzen einen weiteren Aspekt der in die Sui-Laufzeit integrierten Objektbesitzfunktionalität: Ein Objekt kann einem anderen Objekt gehören. Jedes Objekt hat einen eindeutigen Besitzer, aber ein übergeordnetes Objekt kann beliebig viele untergeordnete Objekte haben. Die Beziehung zwischen übergeordnetem und untergeordnetem Objekt wird mithilfe der Funktion „transfer_to_object“ erstellt, die das zugeordnete Objekt der oben eingeführten Übertragungsfunktion ist.
In diesem Code enthält das Rollenmodul eine Accessorize-Funktion, mit der der Rollenbesitzer ein Zubehörobjekt beliebiger Art als untergeordnetes Objekt hinzufügen kann. Dadurch können Bob und Clarissa ihre eigenen Ornamenttypen mit unterschiedlichen Eigenschaften und Funktionen erstellen, die Alice nicht hat, sondern auf dem aufbauen, was Alice bereits getan hat. Beispielsweise kann Bobs Hemd nur dann ausgerüstet werden, wenn es die Lieblingsfarbe des Charakters hat, und Clarissas Schwert kann nur geführt werden, wenn der Charakter stark genug ist. Das Folgende ist eine praktische Demonstration von Diem-Stil-Move, aber keine davon war erfolgreich, das heißt, Diem-Stil-Move kann das obige Szenario nicht erreichen.
Es ist ersichtlich, dass die Probleme beim Diem-Stil-Move wie folgt sind
Es werden nur Sammlungen des gleichen Typs unterstützt (wie der erste Test zeigte), aber eine Beziehung zwischen Objekten kann nicht grundsätzlich nur durch „Einhüllen“ (d. h. Speichern eines Objekts in einem anderen Objekt) erreicht werden Die Sammlung von Objekten, die verpackt werden können, muss vordefiniert sein (wie im zweiten Versuch) oder vorübergehend hinzugefügt werden, und eine zusätzliche Objektzusammensetzung wird nicht unterstützt (wie im dritten Test).
Zusammenfassen
Sui ist die erste Plattform, die in der Verwendung von Move deutlich vom ursprünglichen Diem-Design abweicht. Eine Kombination zu entwerfen, die Move und die einzigartigen Fähigkeiten der Plattform voll ausnutzt, ist sowohl eine Kunst als auch eine Wissenschaft und erfordert ein tiefes Verständnis der Move-Sprache und der Fähigkeiten der zugrunde liegenden Blockchain. Wir sind sehr gespannt auf die Fortschritte, die Sui Move macht, und auf die neuen Anwendungsfälle, die es ermöglichen wird! „. [1] Ein weiteres Argument für eine Move-Richtlinie im Diem-Stil ist, dass „Sie sich anmelden müssen, bevor Sie einen bestimmten Asset-Typ erhalten können.“ Dies ist ein guter Mechanismus, um Spam zu verhindern. Wir denken jedoch an Spam-Prävention Da Spam auf der Anwendungsebene angesiedelt ist, müssen Benutzer keine Transaktionen senden, die echtes Geld kosten, um sich für den Empfang von Vermögenswerten zu entscheiden. Spam kann beispielsweise auf Wallet-Ebene mit umfangreichen benutzerdefinierten Richtlinien und automatisierten Spamfiltern leicht angegangen werden. .


