Como escrever um contrato inteligente WebAssembly na rede Ontology? Parte 1: Ferrugem

Como escrever um contrato inteligente WebAssembly na rede Ontology? Parte 1: Ferrugem

A tecnologia Ontology Wasm reduz o custo de migração de contratos inteligentes dApp com lógica de negócios complexa para o blockchain, enriquecendo bastante o ecossistema dApp.

Agora Ontologia Wasm Simultaneamente, oferece suporte ao desenvolvimento em Rust e C++. A linguagem Rust suporta melhor o Wasm 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?

Desenvolvendo um contrato WASM com Rust

Criar um contrato

Carga é uma boa ferramenta de criação de projetos e gerenciamento de pacotes para desenvolvimento Rust, que ajuda os desenvolvedores a organizar melhor a interação de código e bibliotecas de terceiros. Para criar um novo contrato Ontology Wasm, basta executar o seguinte comando:

Como escrever um contrato inteligente WebAssembly na rede Ontology? Parte 1: Ferrugem

A estrutura do projeto que gera:

Como escrever um contrato inteligente WebAssembly na rede Ontology? Parte 1: Ferrugem

O arquivo Cargo.toml é usado para configurar informações básicas do projeto e informações da biblioteca dependente. A seção [lib] do arquivo deve ser definida como 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:

Como escrever um contrato inteligente WebAssembly na rede Ontology? Parte 1: Ferrugem

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

Função de entrada de contrato

Todo programa tem uma função de entrada, como a função principal que costumamos ver, mas o contrato não tem uma função principal. Quando um contrato Wasm é desenvolvido usando Rust, a função de chamada padrão é usada como a função de entrada para usar o contrato. O nome de uma função no Rust não ficará claro ao compilar o código-fonte Rust em bytecode que pode ser executado por uma máquina virtual. Para evitar que o compilador gere código redundante e reduza o tamanho do contrato, a função de chamada adiciona a anotação #[no_mangle].

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

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

Como é devolvido o resultado da execução do contrato?

A função runtime::ret fornecida pela biblioteca ontio_std retorna o resultado da execução de um método.

A função de chamada concluída se parece com isto:

Como escrever um contrato inteligente WebAssembly na rede Ontology? Parte 1: Ferrugem

Serializando e desserializando dados de contrato

No processo de desenvolvimento de contratos, os desenvolvedores sempre se deparam com problemas de serialização e desserialização, especificamente sobre como armazenar um tipo de dados struct no banco de dados e como desserializar uma matriz de bytes lida do banco de dados para obter um tipo de dados struct.

A biblioteca ontio_std fornece interfaces de decodificador e codificador para serialização e desserialização de dados. Os campos de uma struct também implementam as interfaces do decodificador e do codificador para que a estrutura possa ser serializada e desserializada. As instâncias da classe Sink são necessárias quando vários tipos de dados são serializados. Uma instância da classe Sink tem um campo de tipo definido buf que armazena os dados do tipo byte e todos os dados serializados são armazenados em buf.

Para dados de comprimento fixo (por exemplo: byte, u16, u32, u64, etc.), os dados são convertidos diretamente em uma matriz de bytes e, em seguida, armazenados em buf; para dados de comprimento não fixo, o comprimento deve ser serializado primeiro, depois Ddata (por exemplo, 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. Esta instância de classe tem dois campos buf e pos. Buf é usado para armazenar os dados a serem desserializados e pos é usado para armazenar a posição de leitura atual. Quando um determinado tipo de dados está sendo lido, se você souber seu comprimento, poderá lê-lo diretamente, para dados de comprimento desconhecido - leia primeiro o comprimento e depois leia o conteúdo.

Acessar e atualizar dados na cadeia

ontologia-wasm-cdt-ferrugem - encapsulado um método operacional para trabalhar com dados na cadeia, o que é conveniente para os desenvolvedores implementarem operações como adicionar, excluir, alterar e consultar dados na cadeia da seguinte forma:

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

Teste de contrato

Quando os métodos de um contrato são implementados, precisamos acessar os dados da cadeia e precisamos de uma máquina virtual apropriada para executar o bytecode do contrato; portanto, geralmente é necessário implantar o contrato na cadeia para teste. Mas esse método de teste é problemático. Para tornar mais fácil para os desenvolvedores testar contratos, a biblioteca ontio_std fornece um módulo simulado para teste. Este módulo fornece uma simulação dos dados no circuito, tornando mais fácil para os desenvolvedores testarem os métodos do contrato. Exemplos específicos podem ser encontrados aqui.

Depuração de contrato

console::debug(msg) exibe informações de depuração durante a depuração de um contrato. As informações da msg serão adicionadas ao arquivo de log do nó. Um pré-requisito é definir o nível do arquivo de log para o modo de depuração quando o nó de teste Ontology local estiver em execução.

runtime::notify(msg) gera as informações de depuração apropriadas enquanto o contrato está sendo depurado. Este método irá armazenar as informações inseridas na cadeia e pode ser consultado na cadeia usando o método getSmartCodeEvent.

O artigo foi traduzido pelos editores da Hashrate&Shares especialmente para a OntologyRussia. clique

Você é um desenvolvedor? Junte-se à nossa comunidade de tecnologia em Discord. Além disso, dê uma olhada Centro do Desenvolvedor em nosso site, onde você pode encontrar ferramentas para desenvolvedores, documentação e muito mais.

Ontologia

Fonte: habr.com

Adicionar um comentário