Come scrivere un contratto intelligente su WebAssembly nella rete Ontology? Parte 1: Rust

Come scrivere un contratto intelligente su WebAssembly nella rete Ontology? Parte 1: Rust

La tecnologia Ontology Wasm riduce il costo di trasferimento dei contratti smart dApp con logiche di business complesse sulla blockchain, arricchendo così notevolmente l'ecosistema dApp.

Attualmente Ontology Wasm supporta simultaneamente lo sviluppo sia in Rust che in C++. Il linguaggio Rust offre un migliore supporto per Wasm, e il bytecode generato è più semplice, il che può ulteriormente ridurre i costi delle chiamate ai contratti. Quindi, come utilizzare Rust per sviluppare un contratto sulla rete Ontology?

Sviluppo di un contratto WASM usando Rust

Creare un contratto

Cargo è un buon strumento per creare progetti e gestire pacchetti durante lo sviluppo di programmi in Rust, che aiuta gli sviluppatori a organizzare meglio l'interazione tra il codice e le librerie esterne. Per creare un nuovo contratto Ontology Wasm, basta eseguire il seguente comando:

Come scrivere un contratto intelligente su WebAssembly nella rete Ontology? Parte 1: Rust

La struttura del progetto che genera:

Come scrivere un contratto intelligente su WebAssembly nella rete Ontology? Parte 1: Rust

Il file Cargo.toml viene utilizzato per configurare le informazioni di base del progetto e le informazioni delle librerie dipendenti. La sezione [lib] nel file deve essere impostata su crate-type = ["cdylib"]. Il file lib.rs è utilizzato per scrivere la logica del contratto. Inoltre, è necessario aggiungere i parametri delle dipendenze nella sezione [dependencies] del file di configurazione Cargo.toml:

Come scrivere un contratto intelligente su WebAssembly nella rete Ontology? Parte 1: Rust

Con questa dipendenza, gli sviluppatori possono chiamare interfacce che interagiscono con la blockchain Ontology e strumenti come i parametri di serializzazione.

Funzione di input del contratto

Ogni programma ha una funzione di input, come ad esempio la funzione main che vediamo di solito, ma un contratto non ha una funzione main. Quando si sviluppa un contratto Wasm utilizzando Rust, la funzione invoke è utilizzata di default come funzione di input per l'uso del contratto. Il nome della funzione in Rust sarà poco chiaro durante la compilazione del codice sorgente Rust in bytecode, che può essere eseguito dalla macchina virtuale. Per avvisare il compilatore di non generare codice ridondante e ridurre la dimensione del contratto, la funzione invoke aggiunge l'annotazione #[no_mangle].

Come ottiene la funzione invoke i parametri per eseguire la transazione?

La libreria ontio_std fornisce la funzione runtime::input() per ottenere i parametri necessari all'esecuzione di una transazione. Gli sviluppatori possono utilizzare ZeroCopySource per deserializzare l'array di byte ottenuto, in cui il primo array di byte letto è il nome del metodo invoke, seguito dai parametri del metodo.

Come viene restituito il risultato dell'esecuzione del contratto?

La funzione runtime::ret, fornita dalla libreria ontio_std, restituisce il risultato dell'esecuzione del metodo.

La funzione invoke completata appare come segue:

Come scrivere un contratto intelligente su WebAssembly nella rete Ontology? Parte 1: Rust

Serializzazione e deserializzazione dei dati del contratto

Durante lo sviluppo dei contratti, gli sviluppatori si imbattono sempre in problemi di serializzazione e deserializzazione, in particolare su come memorizzare il tipo di dato struct nel database e come deserializzare un array di byte letto dal database per ottenere il tipo di dato struct.

La libreria ontio_std offre interfacce per il codificatore e il decodificatore per la serializzazione e la deserializzazione dei dati. I campi della struttura struct implementano anche interfacce per il decodificatore e il codificatore, in modo che la struttura possa essere serializzata e deserializzata. Le istanze della classe Sink sono necessarie quando vengono serializzati diversi tipi di dati. Un'istanza della classe Sink ha un campo buf di tipo set che memorizza i dati di tipo byte, mentre tutti i dati serializzati vengono memorizzati in buf.

Per i dati a lunghezza fissa (ad esempio: byte, u16, u32, u64, ecc.) i dati vengono direttamente convertiti in un array di byte e poi memorizzati in buf; per i dati a lunghezza variabile, è prima necessario serializzare la lunghezza e poi i dati (ad esempio numeri interi senza segno di dimensione sconosciuta, inclusi u16, u32 o u64, ecc.).

La deserializzazione è l'opposto diretto. Per ogni metodo di serializzazione esiste un metodo di deserializzazione corrispondente. La deserializzazione richiede l'uso di istanze della classe Source. Questa istanza ha due campi buf e pos. Buf viene utilizzato per memorizzare i dati che verranno deserializzati, mentre pos viene utilizzato per memorizzare la posizione attuale di lettura. Quando si legge un tipo di dato specifico, se si conosce la lunghezza, è possibile leggerlo direttamente; per dati di lunghezza sconosciuta, prima leggere la lunghezza e poi il contenuto.

Accesso e aggiornamento dei dati sulla catena

Ontology-wasm-cdt-rust — ha incapsulato il metodo operativo per lavorare con i dati nella blockchain, che è comodo per gli sviluppatori per implementare operazioni come l'aggiunta, la rimozione, la modifica e la richiesta di dati nella blockchain nel seguente modo:

  • database::get(key) — è utilizzato per richiedere dati dalla blockchain, mentre key richiede l'implementazione dell'interfaccia AsRef;
  • database::put(key, value) — è utilizzato per memorizzare dati nella rete. Key richiede l'esecuzione dell'interfaccia AsRef, e value richiede l'implementazione dell'interfaccia Encoder;
  • database::delete(key) — è utilizzato per rimuovere dati dalla blockchain, e key richiede l'implementazione dell'interfaccia AsRef.

Test di contratto

Quando vengono implementati i metodi di contratto, abbiamo bisogno di accesso ai dati nella blockchain e abbiamo bisogno della macchina virtuale appropriata per eseguire il bytecode del contratto, quindi di solito è necessario distribuire il contratto nella blockchain per il test. Ma questo metodo di test presenta delle problematiche. Per facilitare il testing dei contratti per gli sviluppatori, la libreria ontio_std fornisce un modulo mock per il testing. Questo modulo simula i dati nella blockchain, rendendo più facile per gli sviluppatori eseguire test unitari sui metodi nel contratto. Esempi concreti possono essere trovati. qui.

Debugging del contratto

console::debug(msg) stampa informazioni di debug durante il debugging del contratto. Le informazioni msg verranno registrate nel file di log del nodo. È requisito fondamentale impostare il livello del file di log in modalità debug quando è in esecuzione un nodo di test locale di Ontology.

runtime::notify(msg) stampa informazioni di debug pertinenti durante il debugging del contratto. Questo metodo salverà le informazioni inserite nella blockchain e può essere richiesto dalla blockchain utilizzando il metodo getSmartCodeEvent.

L'articolo è stato tradotto dalla redazione di Hashrate&Shares specificamente per OntologyRussia. clicca

Sei uno sviluppatore? Unisciti alla nostra comunità tecnica su Discord. Inoltre, dai un'occhiata al Centro sviluppatori sul nostro sito, dove puoi trovare strumenti per sviluppatori, documentazione e molto altro.

Ontology

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster