Hoe schrijf je een WebAssembly smart contract op het Ontology-netwerk? Deel 1: Roest

Hoe schrijf je een WebAssembly smart contract op het Ontology-netwerk? Deel 1: Roest

Ontology Wasm-technologie verlaagt de kosten van het migreren van slimme dApp-contracten met complexe bedrijfslogica naar de blockchain, waardoor het dApp-ecosysteem enorm wordt verrijkt.

Nu Ontologie Wasm Ondersteunt tegelijkertijd zowel Rust- als C++-ontwikkeling. De Rust-taal ondersteunt Wasm beter en de gegenereerde bytecode is eenvoudiger, wat de kosten van contractoproepen verder kan verlagen. Dus, hoe Rust te gebruiken om een ​​contract op het Ontology-netwerk te ontwikkelen?

Een WASM-contract ontwikkelen met Rust

Maak een contract aan

Cargo is een goede tool voor projectcreatie en pakketbeheer voor Rust-ontwikkeling, die ontwikkelaars helpt de interactie van code en bibliotheken van derden beter te organiseren. Voer eenvoudig de volgende opdracht uit om een ​​nieuw Ontology Wasm-contract te maken:

Hoe schrijf je een WebAssembly smart contract op het Ontology-netwerk? Deel 1: Roest

De projectstructuur die het genereert:

Hoe schrijf je een WebAssembly smart contract op het Ontology-netwerk? Deel 1: Roest

Het bestand Cargo.toml wordt gebruikt om basisprojectinformatie en afhankelijke bibliotheekinformatie in te stellen. De sectie [lib] van het bestand moet worden ingesteld op krattype = ["cdylib"]. Het bestand lib.rs wordt gebruikt om de contractlogicacode te schrijven. Bovendien moet u afhankelijkheidsparameters toevoegen aan de sectie [dependencies] van het Cargo.toml-configuratiebestand:

Hoe schrijf je een WebAssembly smart contract op het Ontology-netwerk? Deel 1: Roest

Met deze afhankelijkheid kunnen ontwikkelaars interfaces aanroepen die interageren met de Ontology-blockchain en tools zoals de serialisatieparameter.

Functie voor het invoeren van contracten

Elk programma heeft een invoerfunctie, zoals de hoofdfunctie die we meestal zien, maar het contract heeft geen hoofdfunctie. Wanneer een Wasm-contract wordt ontwikkeld met Rust, wordt de standaardfunctie Invoke gebruikt als de invoerfunctie om het contract te gebruiken. De naam van een functie in Rust zal onduidelijk zijn bij het compileren van Rust-broncode in bytecode die kan worden uitgevoerd door een virtuele machine. Om te voorkomen dat de compiler overbodige code genereert en om de omvang van het contract te verkleinen, voegt de functie invoke de annotatie #[no_mangle] toe.

Hoe krijgt de invoke-functie parameters om een ​​transactie uit te voeren?

De ontio_std-bibliotheek biedt een runtime::input()-functie om de parameters op te halen om een ​​transactie uit te voeren. Ontwikkelaars kunnen ZeroCopySource gebruiken om de resulterende byte-array te deserialiseren. Waarin de eerste array van gelezen bytes de naam is van de invoke-methode, gevolgd door de methodeparameters.

Hoe wordt het resultaat van de uitvoering van het contract geretourneerd?

De functie runtime::ret die door de ontio_std-bibliotheek wordt geleverd, retourneert het resultaat van de uitvoering van een methode.

De voltooide invoke-functie ziet er als volgt uit:

Hoe schrijf je een WebAssembly smart contract op het Ontology-netwerk? Deel 1: Roest

Serialiseren en deserialiseren van contractgegevens

Tijdens het ontwikkelen van contracten komen ontwikkelaars altijd problemen tegen met serialisatie en deserialisatie, met name met het opslaan van een struct-gegevenstype in de database en het deserialiseren van een byte-array die uit de database is gelezen om een ​​struct-gegevenstype te krijgen.

De ontio_std-bibliotheek biedt decoder- en encoderinterfaces voor gegevensserialisatie en deserialisatie. De velden van een structuur implementeren ook de decoder- en encoderinterfaces, zodat de structuur kan worden geserialiseerd en gedeserialiseerd. Instanties van de klasse Sink zijn vereist wanneer verschillende gegevenstypen worden geserialiseerd. Een instantie van de Sink-klasse heeft een set-type veld buf waarin de gegevens van het bytetype worden opgeslagen, en alle geserialiseerde gegevens worden opgeslagen in buf.

Voor gegevens met een vaste lengte (bijv.: byte, u16, u32, u64, etc.) worden de gegevens direct geconverteerd naar een byte-array en vervolgens opgeslagen in buf; voor gegevens van niet-vaste lengte moet de lengte eerst worden geserialiseerd en vervolgens Ddata (bijvoorbeeld niet-ondertekende gehele getallen van onbekende grootte, waaronder u16, u32 of u64, enz.).

Deserialisatie is precies het tegenovergestelde. Voor elke serialisatiemethode is er een overeenkomstige deserialisatiemethode. Deserialisatie vereist het gebruik van instanties van de klasse Source. Deze klasse-instantie heeft twee velden buf en pos. Buf wordt gebruikt om de te deserialiseren gegevens op te slaan en pos wordt gebruikt om de huidige leespositie op te slaan. Wanneer een bepaald type gegevens wordt gelezen, kunt u, als u de lengte ervan kent, deze direct lezen, voor gegevens van onbekende lengte: lees eerst de lengte en lees dan de inhoud.

Toegang tot en actualisering van gegevens in de keten

ontologie-wasm-cdt-roest - een operationele methode ingekapseld voor het werken met gegevens in de keten, die handig is voor ontwikkelaars om bewerkingen zoals het toevoegen, verwijderen, wijzigen en opvragen van gegevens in de keten als volgt uit te voeren:

  • database::get(sleutel) - wordt gebruikt om gegevens uit de keten op te vragen, en sleutel vraagt ​​om de implementatie van de AsRef-interface;
  • database::put(sleutel, waarde) - gebruikt om gegevens op het netwerk op te slaan. Key vraagt ​​om de implementatie van de AsRef-interface en waarde vraagt ​​om de implementatie van de Encoder-interface;
  • database::verwijderen(sleutel) - wordt gebruikt om gegevens uit de keten te verwijderen, en sleutel vraagt ​​om de implementatie van de AsRef-interface.

Contract testen

Wanneer de methoden van een contract worden geïmplementeerd, hebben we toegang nodig tot de gegevens in de keten en hebben we een geschikte virtuele machine nodig om de bytecode van het contract uit te voeren, dus is het over het algemeen nodig om het contract in de keten in te zetten om te testen. Maar deze manier van testen is problematisch. Om het ontwikkelaars gemakkelijker te maken om contracten te testen, biedt de ontio_std-bibliotheek een proefmodule om te testen. Deze module biedt een simulatie van de gegevens in het circuit, waardoor het voor ontwikkelaars gemakkelijker wordt om de methoden in het contract te testen. Specifieke voorbeelden zijn te vinden hier.

Contractfoutopsporing

console::debug(msg) geeft debug-informatie weer tijdens het debuggen van een contract. De msg-informatie wordt toegevoegd aan het node-logbestand. Een vereiste is om het logboekbestandsniveau in te stellen op foutopsporingsmodus wanneer het lokale ontology-testknooppunt actief is.

runtime::notify(msg) voert de juiste debug-informatie uit terwijl het contract wordt gedebugd. Deze methode slaat de informatie op die in de keten is ingevoerd en kan uit de keten worden opgevraagd met behulp van de methode getSmartCodeEvent.

Het artikel is speciaal voor OntologyRussia vertaald door de redactie van Hashrate&Shares. schreeuw

Ben je een ontwikkelaar? Word lid van onze technische gemeenschap op Discord. Kijk ook eens naar Ontwikkelaarscentrum op onze website, waar u hulpprogramma's voor ontwikkelaars, documentatie en meer kunt vinden.

Ontologie

Bron: www.habr.com

Voeg een reactie