
In diesem Artikel werden zwei Beispiele zum Schreiben eines intelligenten Vertrags in C ++ mit
WASM basierend auf dem Ontology-Blockchain-Netzwerk vorgestellt. Heute, nach mehreren Monaten stabilen Betriebs im Testmodus, hat
Ontology WASM im Hauptnetzwerk
gestartet , mit dem dApp-Verträge mit komplexer Geschäftslogik schmerzlos und zu geringeren Kosten in die Blockchain übertragen werden können, wodurch das dApp-Ökosystem erheblich bereichert wird.
Ontology Wasm unterstützt auch die Erstellung intelligenter Verträge in der Sprache Rust. Sie können hier darüber lesen.
Im Folgenden finden Sie zwei Beispiele für einen intelligenten Vertrag: Schreiben Sie zunächst „Hallo Welt!“. und erstellen Sie dann einen virtuellen Geldumschlag, der als Geschenk an einen Freund gesendet werden kann.
Entwicklung eines WASM-Vertrags mit C ++
Beispiel 1. Hallo Welt
Beginnen wir mit Hello World:
#include<ontiolib/ontio.hpp> #include<stdio.h> using namespace ontio; class hello:public contract { public: using contract::contract: void sayHello(){ printf("hello world!"); } }; ONTIO_DISPATCH(hello, (sayHello));
Vertragserstellung
Der
Ontology Wasm CDT- Compiler enthält einen Einstiegspunkt und
Analyseparameter , sodass Entwickler keine Eingabemethoden neu definieren müssen. Um die Logik des Dienstes zu schreiben, können Sie außerdem API-Methoden eines intelligenten Vertrags aufrufen.
ONTIO_DISPATCH(hello, (sayHello));
Im obigen Beispiel unterstützen wir bisher nur sayHello:
printf("hello world!");
"Hallo Welt!" wird im Debug-Knotenprotokoll angezeigt. Wenn Sie einen Smart-Vertrag direkt schreiben, kann printf nur zum Debuggen verwendet werden, da der Smart-Vertrag selbst mehr Funktionsbefehle enthält.
Intelligente Vertrags-API
Ontology Wasm bietet die folgenden APIs für die Interaktion mit der Server-Blockchain:

Beispiel 2: Geldumschlag
Schauen wir uns nun ein komplexeres Beispiel mit der Wasm Smart Contract API an.
In diesem Beispiel schreiben wir einen virtuellen Geldumschlag. Ein Analogon zum roten Umschlag (Hongbao) ist eine beliebte Funktion des chinesischen Boten Wechat, mit der Sie in einem Chat Geld an Freunde senden können. Der Benutzer erhält eine Nachricht in Form eines roten Umschlags, öffnet sie und das Geld wird automatisch dem Kontostand gutgeschrieben.
Im Rahmen eines intelligenten Vertrags können Benutzer diesen Vertrag verwenden, um ONT-, ONG- oder OEP-4-Token mithilfe virtueller Geldumschläge an ihre Freunde zu senden, die dann Token in ihre Blockchain-Brieftaschen übertragen können.
Vorbereitung zum Erstellen eines Vertrags
Erstellen Sie zunächst die Quellvertragsdatei und nennen Sie sie redEnvelope.cpp. Als nächstes benötigen wir drei APIs für diesen Vertrag:
- createRedEnvelope : Erstellen Sie einen Geldumschlag
- queryEnvelope : Umschlaginformationen anfordern
- ClaimEnvelope : Öffnen Sie einen Umschlag und erhalten Sie Geld
#include<ontiolib/ontio.hpp> using namespace ontio; class redEnvlope: public contract{ } ONTIO_DISPATCH(redEnvlope, (createRedEnvlope)(queryEnvlope)(claimEnvelope));
Jetzt müssen wir den Schlüsselwert speichern. In einem intelligenten Vertrag werden die Daten im Kontext des Vertrags als Schlüsselwert gespeichert, und wir müssen den KEY-Daten für eine nachfolgende Anforderung ein Präfix hinzufügen.
Im Folgenden definieren wir drei Präfixe, die wir verwenden werden:
std::string rePrefix = "RE_PREFIX_"; std::string sentPrefix = "SENT_COUNT_"; std::string claimPrefix = "CLAIM_PREFIX_";
Da der Vertrag beide Ontologie-Token - ONT und ONG - unterstützt, können wir deren Vertragsadresse im Voraus bestimmen. Im Gegensatz zu einem Standard-Smart-Vertrag ist die eigene Vertragsadresse von Ontology festgelegt und wird nicht aus dem Hash des Vertrags abgeleitet.
address ONTAddress = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; address ONGAddress = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2};
Als Nächstes müssen Sie Informationen zum verwendeten Token im Vertrag speichern: die Adresse des Vertragstokens, den Gesamtbetrag des Umschlags und die Anzahl der Umschläge.
struct receiveRecord{ address account;
Das Folgende ist die Makrooperation, die vom Ontology Wasm CDT definiert wird und für die Serialisierung vor der Datenstrukturierung verwendet wird.
ONTLIB_SERIALIZE(receiveRecord,(account)(amount))
Umschlag erstellen
Nachdem wir die erforderlichen Vorbereitungen getroffen haben, werden wir mit der Entwicklung der API-Logik beginnen.
1. Beim Erstellen eines Geldumschlags müssen die Adresse des Eigentümers, die Anzahl und Anzahl der Umschläge sowie die Adresse des Tokens angegeben werden:
bool createRedEnvlope(address owner,asset packcount, asset amount,address tokenAddr ){ return true; }
2. Überprüfen Sie die Unterschrift des Eigentümers. Andernfalls wird ein Rollback (Rollback der Transaktion) durchgeführt und Folgendes beendet:
ontio_assert(check_witness(owner),"checkwitness failed");
Hinweis : ontio_assert (expr, errormsg): false expr gibt einen Fehler zurück und beendet den Vertrag.
3. Wenn ein ONT-Token in einem Umschlag verwendet wird, ist es wichtig zu beachten, dass ONT nicht fragmentiert ist (mindestens 1 ONT). Dann muss der Gesamtbetrag des Geldumschlags größer oder gleich der Anzahl der Token sein, um sicherzustellen, dass jeder Umschlag mindestens 1 ONT enthält:
if (isONTToken(tokenAddr)){ ontio_assert(amount >= packcount,"ont amount should greater than packcount"); }
4. Als nächstes bestimmen wir für den Inhaber des Umschlags die Gesamtzahl der Geldumschläge, die er sendet:
key sentkey = make_key(sentPrefix,owner.tohexstring()); asset sentcount = 0; storage_get(sentkey,sentcount); sentcount += 1; storage_put(sentkey,sentcount);
5. Generieren Sie den Hash des Umschlags - die Kennung, die diesen Umschlag kennzeichnet:
H256 hash ; hash256(make_key(owner,sentcount),hash) ; key rekey = make_key(rePrefix,hash256ToHexstring(hash));
6. Wir werden die Token in den Vertrag übersetzen. Wir ermitteln die Adresse des Vertrags, der gerade ausgeführt wird, mit dem Befehl self_address (). Anschließend übertragen wir die zugewiesene Anzahl von Token basierend auf der Art der Token in den Vertrag:
address selfaddr = self_address(); if (isONTToken(tokenAddr)){ bool result = ont::transfer(owner,selfaddr ,amount); ontio_assert(result,"transfer native token failed!"); }else if (isONGToken(tokenAddr)){ bool result = ong::transfer(owner,selfaddr ,amount); ontio_assert(result,"transfer native token failed!"); }else{ std::vector<char> params = pack(std::string("transfer"),owner,selfaddr,amount); bool res; call_contract(tokenAddr,params, res ); ontio_assert(res,"transfer oep4 token failed!"); }
Hinweis 1: Für ONT und ONG bietet Ontology Wasm CDT die ont :: transfer-API zum Übertragen von Token. OEP-4-Token müssen mit der herkömmlichen vertragsübergreifenden Anrufmethode gesendet werden.
Hinweis 2: Wie eine normale Brieftaschenadresse kann die Vertragsadresse jede Art von Token akzeptieren. Die Vertragsadresse wird jedoch durch einen kompilierten binären Hash generiert und verfügt daher nicht über einen entsprechenden privaten Schlüssel und kann keine Vertragstoken verwenden. Wenn Sie keinen privaten Schlüssel eingerichtet haben, können Sie diese Token nicht verwalten.
7. Speichern Sie die Informationen zum Vertrag im Data Warehouse:
struct envlopeStruct es ; es.tokenAddress = tokenAddr; es.totalAmount = amount; es.totalPackageCount = packcount; es.remainAmount = amount; es.remainPackageCount = packcount; es.records = {}; storage_put(rekey, es);
8. Senden Sie eine Benachrichtigung über die Erstellung des Umschlags. Dies ist ein asynchroner Prozess zum Aufrufen eines intelligenten Vertrags. Der Vertrag sendet auch eine Benachrichtigung über das Ergebnis der Ausführung. Das Ausführungsformat kann vom Vertragsautor festgelegt werden.
char buffer [100]; sprintf(buffer, "{\"states\":[\"%s\", \"%s\", \"%s\"]}","createEnvlope",owner.tohexstring().c_str(),hash256ToHexstring(hash).c_str()); notify(buffer); return true;
Hurra, der Geldumschlag ist fast fertig. Lassen Sie uns nun sehen, wie Sie Umschlaginformationen anfordern.
Abfrageumschlag (Abfrage
Die Logik der Anforderung ist recht einfach. Sie müssen nur die Informationen und das Format aus dem Datenspeicher abrufen und dann Folgendes ausgeben:
std::string queryEnvlope(std::string hash){ key rekey = make_key(rePrefix,hash); struct envlopeStruct es; storage_get(rekey,es); return formatEnvlope(es); }
Hinweis: Bei schreibgeschützten intelligenten Vertragsvorgängen (z. B. Abfragen) können Sie das Ergebnis vor der Ausführung überprüfen. Im Gegensatz zu einem regulären Vertragsanruf erfordert Pre-Exec keine Brieftaschensignatur und daher keine Provision in ONG. Anschließend können andere Benutzer den Umschlag beantragen, wenn sie über einen Umschlag-Hash (Umschlag-ID) verfügen.
Umschlag empfangen
Zu diesem Zeitpunkt haben wir bereits erfolgreich Token an einen intelligenten Vertrag übertragen. Damit Ihre Freunde erfolgreich einen Anteil am Umschlag beanspruchen können, müssen Sie ihnen die Umschlagkennung (Hash) senden.
1. Um einen Umschlag zu erhalten, müssen Sie die Adresse Ihres Kontos und den Hash des Umschlags eingeben:
bool claimEnvlope(address account, std::string hash){ return true; }
2. Als Nächstes überprüft der Vertrag die Unterschrift Ihres Kontos, um sicherzustellen, dass Sie dessen Eigentümer sind. Jedes Konto kann nur einmal einen Umschlag beantragen:
ontio_assert(check_witness(account),"checkwitness failed"); key claimkey = make_key(claimPrefix,hash,account); asset claimed = 0 ; storage_get(claimkey,claimed); ontio_assert(claimed == 0,"you have claimed this envlope!");
3. Überprüfen Sie, ob der Umschlag gemäß den vom Geschäft empfangenen Hash-Informationen empfangen wurde:
key rekey = make_key(rePrefix,hash); struct envlopeStruct es; storage_get(rekey,es); ontio_assert(es.remainAmount > 0, "the envlope has been claimed over!"); ontio_assert(es.remainPackageCount > 0, "the envlope has been claimed over!");
4. Erstellen eines Anspruchsdatensatzes:
struct receiveRecord record ; record.account = account; asset claimAmount = 0;
5. Berechnung des Betrags für jeden Umschlagantragsteller.
Für den letzten Teilnehmer wird der Betrag des Restbetrags bestimmt, für jeden anderen wird der deklarierte Betrag durch eine Zufallszahl bestimmt, die aus dem Hash des aktuellen Blocks und den aktuellen Informationen über den Umschlag berechnet wird:
if (es.remainPackageCount == 1){ claimAmount = es.remainAmount; record.amount = claimAmount; }else{ H256 random = current_blockhash() ; char part[8]; memcpy(part,&random,8); uint64_t random_num = *(uint64_t*)part; uint32_t percent = random_num % 100 + 1; claimAmount = es.remainAmount * percent / 100;
6. Gutschrift von Geldern
Der entsprechende Betrag an Token wird gemäß dem Berechnungsergebnis auf das Konto der Umschlagantragsteller überwiesen:
address selfaddr = self_address(); if (isONTToken(es.tokenAddress)){ bool result = ont::transfer(selfaddr,account ,claimAmount); ontio_assert(result,"transfer ont token failed!"); } else if (isONGToken(es.tokenAddress)){ bool result = ong::transfer(selfaddr,account ,claimAmount); ontio_assert(result,"transfer ong token failed!"); } else{ std::vector<char> params = pack(std::string("transfer"),selfaddr,account,claimAmount); bool res = false; call_contract(es.tokenAddress,params, res ); ontio_assert(res,"transfer oep4 token failed!"); }
7. Wir werden Informationen über den Erhalt von Geldern und aktualisierte Informationen über den Umschlag im Tresor aufschreiben und eine Benachrichtigung über die Vertragserfüllung senden:
storage_put(claimkey,claimAmount); storage_put(rekey,es); char buffer [100]; std::sprintf(buffer, "{\"states\":[\"%s\",\"%s\",\"%s\",\"%lld\"]}","claimEnvlope",hash.c_str(),account.tohexstring().c_str(),claimAmount); notify(buffer); return true;
Wie oben erwähnt, kann dieser Vertrag über die ClaimEnvelope-API Token aus dem Vertrag senden. Dies gewährleistet die Sicherheit von Token, während sie sich im Umschlag befinden, da niemand Vermögenswerte abheben kann, ohne die erforderlichen Anforderungen zu erfüllen.
Fertig Sie haben Ihren ersten intelligenten Vertrag geschrieben. Den vollständigen Vertragscode finden Sie auf GitHub
hier .
Vertragstests
Es gibt zwei Möglichkeiten, einen Vertrag zu überprüfen:
- Verwenden Sie CLI
- Verwenden Sie das Golang SDK
Fazit
In diesem Artikel haben wir darüber gesprochen, wie ein intelligenter Vertrag für Ontolgy Wasm mithilfe der Blockchain-API erstellt wird. Es bleibt das Datenschutzproblem zu lösen, damit aus dem intelligenten Vertrag ein vollwertiges Produkt wird. In dieser Phase des Codes kann jeder einen Hash des roten Umschlags erhalten, indem er die Aufzeichnungen des Vertrags verfolgt. Dies bedeutet, dass jeder einen Anteil am Umschlag beanspruchen kann. Dieses Problem kann einfach gelöst werden - wir definieren eine Liste von Konten, die für einen Umschlag gelten können, wenn dieser erstellt wird. Auf Wunsch kann diese Funktion auch getestet werden.
Holen Sie sich ein Ontologie-
Stipendium für die dApp-Entwicklung ab 20.000 US-Dollar
Bewerben Sie sich für das Ontology Student Talent Program
Bist du ein Entwickler? Treten Sie unserer Tech-Community auf
Discord bei . Besuchen Sie auch
das Developer Center auf unserer Website, wo Sie Entwicklertools, Dokumentationen und vieles mehr finden.
Ontologie