¿Cómo escribir un contrato inteligente para WebAssembly en una red Ontology? Parte 1: óxido

imagen

La tecnología Ontology Wasm reduce el costo de transferir contratos inteligentes de dApp con una lógica empresarial compleja a la cadena de bloques, lo que enriquece enormemente el ecosistema de dApp.

Actualmente, Ontology Wasm soporta simultáneamente el desarrollo de Rust y C ++ . Rust admite Wasm mejor, y el bytecode generado es más simple, lo que puede reducir aún más el costo de las llamadas de contrato. Entonces, ¿cómo usar Rust para desarrollar un contrato en la red de Ontología?

Desarrollo del contrato WASM con Rust


Creación de contrato


Cargo es una buena herramienta para crear proyectos y administrar paquetes al desarrollar programas en Rust, lo que ayuda a los desarrolladores a organizar mejor la interacción del código y las bibliotecas de terceros. Para crear un nuevo contrato de Ontology Wasm, simplemente ejecute el siguiente comando:

imagen

La estructura del proyecto que genera:

imagen

El archivo Cargo.toml se usa para configurar la información básica del proyecto y la información de la biblioteca dependiente. La sección [lib] en el archivo debe establecerse en crate-type = ["cdylib"]. El archivo lib.rs se usa para escribir código lógico de contrato. Además, debe agregar parámetros de dependencia a la sección [dependencias] del archivo de configuración Cargo.toml:

imagen

Con esta dependencia, los desarrolladores pueden invocar interfaces que interactúan con la cadena de bloques de Ontology y herramientas como el parámetro de serialización.

Función de entrada de contrato


Cada programa tiene una función de entrada, como una función principal, que generalmente vemos, pero el contrato no tiene una función principal. Cuando se desarrolla un contrato Wasm usando Rust, la invocación se usa por defecto como una función de entrada para usar el contrato. El nombre de una función en Rust no estará claro al compilar el código fuente de Rust en bytecode que una máquina virtual puede ejecutar. Para advertir al compilador contra la generación de código redundante y reducir el tamaño del contrato, la función de invocación agrega la anotación # [no_mangle].

¿Cómo invoca obtener parámetros para ejecutar una transacción?


La biblioteca ontio_std proporciona la función runtime :: input () para obtener los parámetros para la transacción. Los desarrolladores pueden usar ZeroCopySource para deserializar la matriz de bytes resultante. En el que la primera lectura de la matriz de bytes es el nombre del método invoke, seguido de los parámetros del método.

¿Cómo se devuelve el resultado del contrato?


La función runtime :: ret, proporcionada por la biblioteca ontio_std, devuelve el resultado del método.

La función de invocación finalizada es la siguiente:

imagen

Serialización y deserialización de los datos del contrato.


En el proceso de desarrollar contratos, los desarrolladores siempre encuentran problemas de serialización y deserialización, y específicamente cómo guardar el tipo de estructura de los datos en la base de datos y cómo bytear los bytes de lectura de la matriz de la base de datos para deserializarlos para obtener el tipo de estructura de los datos.

La biblioteca ontio_std proporciona interfaces de decodificador y codificador para serializar y deserializar datos. Los campos de la estructura de estructura también implementan las interfaces del decodificador y el codificador, de modo que la estructura puede ser serializada y deserializada. Se requieren instancias de sumidero cuando se serializan varios tipos de datos. Una instancia de la clase Sink tiene un buf de campo de tipo conjunto, que almacena los datos de tipo byte, y todos los datos serializados se almacenan en buf.
Para datos con una longitud fija (por ejemplo: byte, u16, u32, u64, etc.), los datos se convierten directamente a una matriz de bytes y luego se almacenan en buf; para datos de longitud no fija, primero debe serializar la longitud y luego D \ data (por ejemplo, enteros sin signo de tamaño desconocido, incluidos u16, u32 o u64, etc.).

La deserialización es exactamente lo contrario. Para cada método de serialización, hay un método de deserialización correspondiente. La deserialización requiere el uso de instancias de la clase Source. Esta instancia de clase tiene dos campos buf y pos. Buf se usa para almacenar datos para ser deserializados, y pos se usa para almacenar la posición de lectura actual. Cuando se lee un tipo de datos en particular, si conoce su longitud, puede leerlo directamente, para datos de longitud desconocida: primero lea la longitud y luego lea el contenido.

Acceda y actualice datos en la cadena


Ontology-wasm-cdt-rust : encapsuló un método operativo para trabajar con datos en una cadena, que es conveniente para que los desarrolladores implementen operaciones como agregar, eliminar, cambiar y consultar datos en una cadena de la siguiente manera:

  • database :: get (key) : se utiliza para solicitar datos de la cadena y key solicita la implementación de la interfaz AsRef;
  • database :: put (clave, valor) : se usa para almacenar datos en la red. Key solicita la ejecución de la interfaz AsRef, y value solicita la implementación de la interfaz Encoder;
  • database :: delete (key) : se utiliza para eliminar datos de la cadena y Key solicita la implementación de la interfaz AsRef.

Prueba de contrato


Cuando se implementan los métodos del contrato, necesitamos acceso a los datos en el circuito y necesitamos la máquina virtual adecuada para ejecutar el código de bytes del contrato, por lo que, por regla general, es necesario implementar el contrato en la cadena para la prueba. Pero tal método de prueba es problemático. Para facilitar la prueba de los contratos para los desarrolladores, la biblioteca ontio_std proporciona un módulo simulado para la prueba. Este módulo proporciona simulación de datos en un circuito, lo que facilita a los desarrolladores unir los métodos de prueba en un contrato. Ejemplos específicos se pueden encontrar aquí .

Depuración de contratos


console :: debug (msg) imprime información de depuración mientras depura un contrato. La información del mensaje se ingresará en el archivo de registro del nodo. Un requisito previo es establecer el nivel del archivo de registro en modo de depuración cuando se ejecuta el nodo de prueba de Ontology local.

runtime :: notify (msg) muestra la información de depuración adecuada al depurar el contrato. Este método guardará la información ingresada en el circuito y puede solicitarse desde el circuito utilizando el método getSmartCodeEvent.



El artículo fue traducido por Hashrate & Shares específicamente para OntologyRussia. haga clic

¿Eres desarrollador? Únete a nuestra comunidad tecnológica en Discord . Además, eche un vistazo al Centro de desarrolladores en nuestro sitio web, donde puede encontrar herramientas para desarrolladores, documentación y mucho más.

Ontología


Source: https://habr.com/ru/post/471878/


All Articles