Sie haben wahrscheinlich gehört, dass Telegram die Blockchain-Plattform von Ton starten wird . Aber Sie hätten die Nachricht verpassen können, dass Telegram vor nicht allzu langer Zeit einen Wettbewerb für die Implementierung eines oder mehrerer intelligenter Verträge für diese Plattform ausgeschrieben hat.
Das Serokell-Team mit langjähriger Erfahrung in der Entwicklung großer Blockchain-Projekte konnte sich nicht zurückhalten. Wir haben fünf Mitarbeiter an den Wettbewerb delegiert, die zwei Wochen später unter dem (un) bescheidenen Spitznamen Sexy Chameleon den ersten Platz belegten. In diesem Artikel werde ich darüber sprechen, wie es ihnen gelungen ist. Wir hoffen, dass Sie in den nächsten zehn Minuten mindestens eine interessante Geschichte lesen und maximal etwas Nützliches darin finden, das Sie in Ihrer Arbeit anwenden können.
Aber lassen Sie uns mit einem kleinen Eintauchen in den Kontext beginnen.
Wettbewerb und seine Bedingungen
Die Hauptaufgaben der Teilnehmer waren daher die Umsetzung eines oder mehrerer der vorgeschlagenen intelligenten Verträge sowie die Unterbreitung von Vorschlägen zur Verbesserung des TON-Ökosystems. Der Wettbewerb fand vom 24. September bis 15. Oktober statt und die Ergebnisse wurden erst am 15. November bekannt gegeben. Angesichts der Tatsache, dass es Telegram in dieser Zeit gelungen ist, die Ergebnisse von Wettbewerben über Design und Anwendungsentwicklung in C ++ durchzuführen und bekannt zu geben, um die Qualität von VoIP-Anrufen in Telegram zu testen und zu bewerten.
Wir haben zwei intelligente Verträge aus der von den Organisatoren vorgeschlagenen Liste ausgewählt. Für einen von ihnen verwendeten wir mit TON vertriebene Tools und den zweiten implementierten wir in einer neuen Sprache, die von unseren Ingenieuren speziell für TON entwickelt und in Haskell integriert wurde.
Die Wahl einer funktionalen Programmiersprache ist kein Zufall. In unserem Unternehmensblog sprechen wir oft darüber, warum wir die Komplexität funktionaler Sprachen für eine große Übertreibung halten und warum wir generell bevorzugen, dass sie objektorientiert sind. Übrigens enthält es auch das Original dieses Artikels .
Warum haben wir uns für eine Teilnahme entschieden?
Kurz gesagt, weil unsere Spezialisierung nicht standardmäßige und komplexe Projekte sind, die besondere Fähigkeiten erfordern und für die IT-Community häufig von wissenschaftlichem Wert sind. Wir unterstützen die Open-Source-Entwicklung nachdrücklich und beteiligen uns an deren Popularisierung sowie an der Zusammenarbeit mit führenden Universitäten in Russland auf dem Gebiet der Informatik und Mathematik.
Die interessanten Aufgaben des Wettbewerbs und die Beteiligung am Telegramm-Projekt, die wir so sehr geliebt haben, waren an sich schon eine hervorragende Motivation, aber der Preisfonds wurde zu einem zusätzlichen Anreiz. :)
TON Blockchain Research
Wir beobachten die neuen Entwicklungen in der Blockchain, der künstlichen Intelligenz und dem maschinellen Lernen genau und versuchen, in jedem Bereich, in dem wir arbeiten, eine wichtige Veröffentlichung zu verpassen. Daher war unser Team zu Beginn des Wettbewerbs bereits mit den Ideen aus dem TON-Whitepaper vertraut. Bevor wir jedoch mit der Arbeit mit TON begannen, haben wir die technische Dokumentation und den tatsächlichen Quellcode der Plattform nicht analysiert, sodass der erste Schritt ganz offensichtlich war - ein gründliches Studium der offiziellen Dokumentation auf der Website und im Projektarchiv .
Zu Beginn des Wettbewerbs war der Code bereits veröffentlicht worden. Um Zeit zu sparen, haben wir uns entschlossen, einen Leitfaden oder eine Zusammenfassung zu suchen, die von Benutzern geschrieben wurde. Leider ergab dies kein Ergebnis - abgesehen von den Anweisungen zum Erstellen der Plattform unter Ubuntu fanden wir keine anderen Materialien.
Die Dokumentation selbst wurde sorgfältig ausgearbeitet, war jedoch an einigen Stellen schwer zu lesen. Sehr oft mussten wir zu bestimmten Punkten zurückkehren und von allgemeinen Beschreibungen abstrakter Ideen zu einfachen Implementierungsdetails übergehen.
Es wäre einfacher, wenn die Spezifikation überhaupt keine detaillierte Beschreibung der Implementierung hätte. Informationen darüber, wie die virtuelle Maschine ihren Stack präsentiert, lenken Entwickler eher davon ab, intelligente Verträge für die TON-Plattform zu erstellen, als ihnen zu helfen.
Nix: ein Projekt bauen
Wir bei Serokell sind große Fans von Nix . Wir sammeln unsere Projekte für sie und stellen sie mit NixOps bereit , und NixOS ist auf allen unseren Servern installiert. Dank dessen sind alle unsere Builds reproduzierbar und funktionieren unter jedem Betriebssystem, auf dem Nix installiert werden kann.
Also haben wir Nix-Overlay mit einem Ausdruck zum Erstellen von TON erstellt . Das Kompilieren von TON ist so einfach wie möglich:
$ cd ~/.config/nixpkgs/overlays && git clone https://github.com/serokell/ton.nix $ cd /path/to/ton/repo && nix-shell [nix-shell]$ cmakeConfigurePhase && make
Beachten Sie, dass Sie keine Abhängigkeiten installieren müssen. Nix erledigt auf magische Weise alles für Sie, egal ob Sie NixOS, Ubuntu oder macOS verwenden.
Programmierung für TON
Der TON Network Smart-Vertragscode wird auf der TON Virtual Machine (TVM) ausgeführt. TVM ist komplizierter als die meisten anderen virtuellen Maschinen und verfügt über eine sehr interessante Funktionalität, z. B. kann es mit Fortsetzungen und Verknüpfungen zu Daten arbeiten .
Außerdem haben die TON-Jungs drei neue Programmiersprachen erstellt:
Fift ist eine universelle Stack-Programmiersprache, die an Forth erinnert. Seine überragende Fähigkeit ist die Fähigkeit, mit TVM zu interagieren.
FunC ist eine intelligente Vertragsprogrammiersprache, die C ähnelt und in eine andere Sprache kompiliert wurde - Fift Assembler.
Fift Assembler - Fift-Bibliothek zum Generieren von ausführbarem Binärcode für TVM. Fift Assembler fehlt ein Compiler. Es ist eine eingebettete domänenspezifische Sprache (eDSL) .
Unsere wettbewerbsfähigen Werke
Schließlich ist es Zeit, die Ergebnisse unserer Bemühungen zu betrachten.
Asynchroner Zahlungskanal
Zahlungskanal - ein intelligenter Vertrag, mit dem zwei Benutzer Zahlungen außerhalb der Blockchain senden können. Das spart nicht nur Geld (es gibt keine Provision), sondern auch Zeit (Sie müssen nicht warten, bis der nächste Block abgearbeitet ist). Zahlungen können beliebig klein sein und beliebig oft erfolgen. Gleichzeitig müssen sich die Parteien nicht gegenseitig vertrauen, da die Fairness der Endabrechnung durch einen klugen Vertrag gewährleistet ist.
Wir haben eine ziemlich einfache Lösung für das Problem gefunden. Zwei Teilnehmer können signierte Nachrichten austauschen, die jeweils zwei Nummern enthalten - den Gesamtbetrag, den jeder Teilnehmer bezahlt. Diese beiden Zahlen funktionieren wie Vektoruhren in traditionellen verteilten Systemen und legen die Reihenfolge der Transaktionen fest, in der sie "vorher geschehen" sind. Mit diesen Daten kann der Vertrag etwaige Konflikte lösen.
Um diese Idee umzusetzen, ist eine Nummer ausreichend, aber wir haben beide überlassen, da wir in der Lage waren, eine komfortablere Benutzeroberfläche zu erstellen. Außerdem haben wir beschlossen, in jede Nachricht einen Zahlungsbetrag aufzunehmen. Wenn die Nachricht aus irgendeinem Grund verloren geht, kann es sein, dass der Benutzer den Verlust nicht bemerkt, obwohl alle Beträge und die endgültige Berechnung korrekt sind.
Um unsere Idee zu testen, haben wir nach Beispielen für die Verwendung eines so einfachen und übersichtlichen Zahlungskanalprotokolls gesucht. Überraschenderweise fanden wir nur zwei:
- Beschreibung eines ähnlichen Ansatzes, nur für unidirektionalen Kanal.
- Ein Tutorial , das die gleiche Idee beschreibt wie wir, aber ohne viele wichtige Details zu erklären, wie die allgemeine Korrektheit und das Verfahren zur Lösung von Konflikten.
Es hat sich herausgestellt, dass es sinnvoll ist, unser Protokoll im Detail zu beschreiben und dabei besonders auf seine Richtigkeit zu achten. Nach mehreren Iterationen war die Spezifikation fertig, und jetzt können Sie sie auch ansehen.
Wir haben einen Vertrag für FunC implementiert und das Befehlszeilendienstprogramm für die Interaktion mit unserem Vertrag in Fift geschrieben, wie von den Organisatoren empfohlen. Wir könnten jede andere Sprache für unsere CLI wählen, aber es war interessant für uns, Fift auszuprobieren, um zu sehen, wie es sich in Aktion zeigt.
Ehrlich gesagt, nachdem wir mit Fift gearbeitet haben, sahen wir keinen guten Grund, diese Sprache populären und aktiv verwendeten Sprachen mit entwickelten Werkzeugen und Bibliotheken vorzuziehen. Das Programmieren in der Stack-Sprache ist ziemlich unangenehm, da Sie ständig im Auge behalten müssen, was sich auf dem Stack befindet, und der Compiler nicht hilft.
Daher ist die einzige unserer Meinung nach Rechtfertigung für die Existenz von Fift seine Rolle als Host-Sprache für den Fift-Assembler. Wäre es nicht besser, den TVM-Assembler in eine vorhandene Sprache einzubetten und keine neue Sprache für diesen Zweck zu entwickeln, im Wesentlichen den einzigen Zweck?
TVM Haskell eDSL
Jetzt ist es Zeit, über unseren zweiten intelligenten Vertrag zu sprechen. Wir haben beschlossen, eine Brieftasche mit mehreren Unterschriften zu entwickeln, aber es wäre zu langweilig, einen weiteren intelligenten Vertrag für FunC zu schreiben. Wir wollten etwas mehr Schwung hinzufügen, und es wurde unsere eigene Assemblersprache für TVM.
Wie Fift Assembler kann auch unsere neue Sprache eingebettet werden, aber anstelle von Fift haben wir Haskell als Host gewählt, wodurch wir das fortschrittliche Typsystem vollständig nutzen konnten. Wenn Sie mit intelligenten Verträgen arbeiten, bei denen selbst ein kleiner Fehler sehr teuer sein kann, ist die statische Eingabe unserer Meinung nach ein großer Vorteil.
Um zu demonstrieren, wie der in Haskell integrierte TVM-Assembler aussieht, haben wir eine Standardbrieftasche darauf implementiert. Hier sind ein paar Dinge, auf die Sie achten sollten:
- Dieser Vertrag besteht aus einer Funktion, aber Sie können so viel verwenden, wie Sie möchten. Wenn Sie eine neue Funktion in der Host-Sprache (dh in Haskell) definieren, können Sie mit unserem eDSL auswählen, ob diese Funktion in TVM in ein separates Unterprogramm umgewandelt oder nur an der Stelle des Anrufs integriert werden soll.
- Funktionen haben wie Haskell Typen, die beim Kompilieren überprüft werden. In unserem eDSL ist der Funktionseingabetyp der Typ des Stacks, den die Funktion erwartet, und der Ergebnistyp ist der Typ des Stacks, der nach dem Aufruf abgerufen wird.
- Der Code verfügt
stacktype
Anmerkungen zum stacktype
, die den erwarteten stacktype
Peer beschreiben. Im ursprünglichen Brieftaschenvertrag waren dies nur Kommentare, aber in unserer eDSL sind sie tatsächlich Teil des Codes und werden beim Kompilieren überprüft. Sie können als Dokumentation oder Anweisungen dienen, die dem Entwickler helfen, das Problem zu finden, wenn sich der Stapeltyp ändert, während sich der Code ändert. Derartige Annotationen wirken sich natürlich nicht auf die Laufzeitleistung aus, da für sie kein TVM-Code generiert wird. - Dies ist immer noch ein Prototyp, der in zwei Wochen geschrieben wurde, es bleibt also noch viel Arbeit am Projekt. Beispielsweise sollten alle Klasseninstanzen, die Sie im folgenden Code sehen, automatisch generiert werden.
So sieht die Implementierung von Multisig Wallet auf unserem eDSL aus:
main :: IO () main = putText $ pretty $ declProgram procedures methods where procedures = [ ("recv_external", decl recvExternal) , ("recv_internal", decl recvInternal) ] methods = [ ("seqno", declMethod getSeqno) ] data Storage = Storage { sCnt :: Word32 , sPubKey :: PublicKey } instance DecodeSlice Storage where type DecodeSliceFields Storage = [PublicKey, Word32] decodeFromSliceImpl = do decodeFromSliceImpl @Word32 decodeFromSliceImpl @PublicKey instance EncodeBuilder Storage where encodeToBuilder = do encodeToBuilder @Word32 encodeToBuilder @PublicKey data WalletError = SeqNoMismatch | SignatureMismatch deriving (Eq, Ord, Show, Generic) instance Exception WalletError instance Enum WalletError where toEnum 33 = SeqNoMismatch toEnum 34 = SignatureMismatch toEnum _ = error "Uknown MultiSigError id" fromEnum SeqNoMismatch = 33 fromEnum SignatureMismatch = 34 recvInternal :: '[Slice] :-> '[] recvInternal = drop recvExternal :: '[Slice] :-> '[] recvExternal = do decodeFromSlice @Signature dup preloadFromSlice @Word32 stacktype @[Word32, Slice, Signature]
In diesem Repository finden Sie den vollständigen Quellcode unseres eDSL und den Brieftaschenvertrag mit mehreren Unterschriften . Im Detail sprach unser Kollege George Agapov über die eingebauten Sprachen.
Schlussfolgerungen zum Wettbewerb und zur TON
Insgesamt dauerte unsere Arbeit 380 Stunden (zusammen mit dem Kennenlernen der Dokumentation, der Besprechungen und der Entwicklung selbst). Fünf Entwickler nahmen am Wettbewerb teil: STO, Teamleiter, Blockchain-Plattformspezialist und Haskell-Softwareentwickler.
Wir fanden die Ressourcen, um problemlos am Wettbewerb teilnehmen zu können, da der Geist des Hackathons, die enge Zusammenarbeit und die Notwendigkeit, schnell in Aspekte neuer Technologien einzutauchen, immer aufregend sind. Einige schlaflose Nächte, um bei begrenzten Ressourcen maximale Ergebnisse zu erzielen, werden durch unschätzbare Erfahrungen und exzellente Erinnerungen kompensiert. Darüber hinaus ist die Bearbeitung solcher Aufgaben immer ein guter Test für die Unternehmensprozesse, da es äußerst schwierig ist, ohne eine exzellent abgestimmte interne Interaktion wirklich anständige Ergebnisse zu erzielen.
Abgesehen von den Texten: Wir waren beeindruckt von der Menge an Arbeit, die das TON-Team geleistet hat. Sie haben es geschafft, ein komplexes, schönes und vor allem funktionierendes System aufzubauen. TON erwies sich als Plattform mit großem Potenzial. Damit sich dieses Ökosystem entwickeln kann, muss jedoch noch viel mehr getan werden, sowohl im Hinblick auf seine Verwendung in Blockchain-Projekten als auch im Hinblick auf die Verbesserung von Entwicklungswerkzeugen. Wir sind stolz, jetzt Teil dieses Prozesses zu sein.
Wenn Sie nach dem Lesen dieses Artikels noch Fragen oder Anregungen zur Anwendung von TON zur Lösung Ihrer Probleme haben, schreiben Sie uns - wir teilen gerne unsere Erfahrungen mit.