Como escrever um contrato inteligente para o WebAssembly em uma rede Ontology? Parte 1: Ferrugem

imagem

A tecnologia Ontology Wasm reduz o custo de transferência de contratos inteligentes do dApp com lógica de negócios complexa para o blockchain, enriquecendo muito o ecossistema do dApp.

Atualmente, o Ontology Wasm suporta simultaneamente o desenvolvimento de Rust e C ++ . O Rust suporta o Wasm melhor e o bytecode gerado é mais simples, o que pode reduzir ainda mais o custo das chamadas de contrato. Então, como usar o Rust para desenvolver um contrato na rede Ontology?

Desenvolvimento de contrato WASM com Rust


Criação de contrato


O Cargo é uma boa ferramenta para criar projetos e gerenciar pacotes ao desenvolver programas no Rust, o que ajuda os desenvolvedores a organizar melhor a interação do código e das bibliotecas de terceiros. Para criar um novo contrato do Ontology Wasm, basta executar o seguinte comando:

imagem

A estrutura do projeto que ele gera:

imagem

O arquivo Cargo.toml é usado para configurar informações básicas do projeto e informações da biblioteca dependente. A seção [lib] no arquivo deve ser configurada para crate-type = [“cdylib”]. O arquivo lib.rs é usado para escrever o código lógico do contrato. Além disso, você precisa adicionar parâmetros de dependência à seção [dependencies] do arquivo de configuração Cargo.toml:

imagem

Com essa dependência, os desenvolvedores podem chamar interfaces que interagem com o blockchain da Ontology e ferramentas como o parâmetro de serialização.

Função de entrada de contrato


Cada programa tem uma função de entrada, como uma função principal, que normalmente vemos, mas o contrato não tem uma função principal. Quando um contrato Wasm é desenvolvido usando o Rust, a invocação é usada por padrão como uma função de entrada para usar o contrato. Um nome de função no Rust não ficará claro ao compilar o código-fonte do Rust no bytecode que uma máquina virtual pode executar. Para alertar o compilador contra a geração de código redundante e reduzir o tamanho do contrato, a função invoke adiciona a anotação # [no_mangle].

Como a chamada obtém parâmetros para executar uma transação?


A biblioteca ontio_std fornece a função runtime :: input () para obter os parâmetros para a transação. Os desenvolvedores podem usar ZeroCopySource para desserializar a matriz de bytes resultante. Na qual a primeira matriz de bytes lida é o nome do método de chamada, seguido pelos parâmetros do método.

Como o resultado do contrato é devolvido?


A função runtime :: ret, fornecida pela biblioteca ontio_std, retorna o resultado do método.

A função de chamada final é a seguinte:

imagem

Serialização e desserialização de dados do contrato


No processo de desenvolvimento de contratos, os desenvolvedores sempre encontram problemas de serialização e desserialização e, especificamente, como salvar o tipo de estrutura dos dados no banco de dados e como byte bytes de leitura de matriz do banco de dados para desserializar para obter o tipo de estrutura dos dados.

A biblioteca ontio_std fornece interfaces de decodificador e codificador para serializar e desserializar dados. Os campos da estrutura struct também implementam as interfaces do decodificador e do codificador, para que a estrutura possa ser serializada e desserializada. Instâncias de coletor são necessárias ao serializar vários tipos de dados. Uma instância da classe Sink possui um campo do tipo conjunto buf, que armazena os dados do tipo byte e todos os dados serializados são armazenados no buf.
Para dados com um comprimento fixo (por exemplo: byte, u16, u32, u64 etc.), os dados são convertidos diretamente em uma matriz de bytes e armazenados em buf; para dados de comprimento não fixo, primeiro é necessário serializar o comprimento e, em seguida, D \ data (por exemplo, números inteiros não assinados de tamanho desconhecido, incluindo u16, u32 ou u64, etc.).

A desserialização é exatamente o oposto. Para cada método de serialização, existe um método de desserialização correspondente. A desserialização requer o uso de instâncias da classe Source. Essa instância de classe possui dois campos buf e pos. Buf é usado para armazenar dados a serem desserializados, e pos é usado para armazenar a posição atual de leitura. Quando um tipo de dados específico é lido, se você souber seu comprimento, poderá lê-lo diretamente, para dados de comprimento desconhecido - primeiro leia o comprimento e depois o conteúdo.

Acesse e atualize dados na cadeia


Ontology-wasm-cdt-rust - encapsulou um método operacional de trabalhar com dados em uma cadeia, o que é conveniente para os desenvolvedores implementarem operações como adicionar, excluir, alterar e consultar dados em uma cadeia da seguinte maneira:

  • database :: get (key) - usado para solicitar dados da cadeia, e key solicita a implementação da interface AsRef;
  • database :: put (key, value) - usado para armazenar dados na rede. Key solicita a execução da interface AsRef, e value solicita a implementação da interface Encoder;
  • database :: delete (key) - usado para remover dados da cadeia, e key solicita a implementação da interface AsRef.

Teste de contrato


Quando os métodos do contrato são implementados, precisamos acessar os dados no circuito e precisamos da máquina virtual apropriada para executar o bytecode do contrato, portanto, como regra, é necessário implantar o contrato na cadeia para teste. Mas esse método de teste é problemático. Para facilitar os contratos de teste para desenvolvedores, a biblioteca ontio_std fornece um módulo simulado para teste. Este módulo fornece simulação de dados em um circuito, facilitando para os desenvolvedores a unidade de métodos de teste em um contrato. Exemplos específicos podem ser encontrados aqui .

Depuração de contrato


console :: debug (msg) imprime informações de depuração enquanto depura um contrato. As informações da mensagem serão inseridas no arquivo de log do nó. Um pré-requisito é definir o nível do arquivo de log no modo de depuração quando o nó de teste Ontology local estiver em execução.

runtime :: notify (msg) exibe as informações de depuração apropriadas durante a depuração do contrato. Este método salvará as informações inseridas no circuito e pode ser solicitado a partir do circuito usando o método getSmartCodeEvent.



O artigo foi traduzido por Hashrate & Shares especificamente para OntologyRussia. clique

Você é desenvolvedor? Participe da nossa comunidade de tecnologia no Discord . Além disso, dê uma olhada no Developer Center em nosso site, onde você pode encontrar ferramentas, documentação e muito mais para desenvolvedores.

Ontologia


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


All Articles