如何在本体网络上编写WebAssembly智能合约? 第 1 部分:生锈

如何在本体网络上编写WebAssembly智能合约? 第 1 部分:生锈

本体Wasm技术降低了将具有复杂业务逻辑的dApp智能合约迁移到区块链的成本,从而极大地丰富了dApp生态。

现在 本体 Wasm 同时支持 Rust 和 C++ 开发。 Rust语言对Wasm的支持更好,生成的字节码更简单,可以进一步降低合约调用的成本。 所以, 如何使用Rust在本体网络上开发合约?

使用 Rust 开发 WASM 合约

创建合约

货物 是一款不错的Rust开发项目创建和包管理工具,帮助开发者更好的组织代码和第三方库的交互。 要创建新的 Ontology Wasm 合约,只需运行以下命令:

如何在本体网络上编写WebAssembly智能合约? 第 1 部分:生锈

它生成的项目结构:

如何在本体网络上编写WebAssembly智能合约? 第 1 部分:生锈

Cargo.toml文件用于设置项目基本信息和依赖库信息。 文件的 [lib] 部分必须设置为 crate-type = ["cdylib"]。 lib.rs 文件用于编写合约逻辑代码。 此外,还需要在 Cargo.toml 配置文件的 [dependencies] 部分添加依赖参数:

如何在本体网络上编写WebAssembly智能合约? 第 1 部分:生锈

通过这种依赖,开发者可以调用与本体区块链交互的接口和序列化参数等工具。

合约录入功能

每个程序都有一个input函数,比如我们平时看到的main函数,但是合约没有main函数。 当使用 Rust 开发 Wasm 合约时,默认的 invoke 函数被用作输入函数来使用合约。 在将 Rust 源代码编译成虚拟机可以执行的字节码时,Rust 中的函数名称会不清楚。 为了防止编译器产生冗余代码,减少合约的大小,invoke函数添加了#[no_mangle]注解。

invoke函数是如何获取参数来执行交易的?

ontio_std 库提供了一个 runtime::input() 函数来获取执行交易的参数。 开发人员可以使用 ZeroCopySource 反序列化生成的字节数组。 其中读取的第一个字节数组是调用方法的名称,后面是方法参数。

合约执行的结果如何返回?

ontio_std 库提供的 runtime::ret 函数返回方法执行的结果。

完成的调用函数如下所示:

如何在本体网络上编写WebAssembly智能合约? 第 1 部分:生锈

序列化和反序列化合约数据

在开发合约的过程中,开发者总是会遇到序列化和反序列化的问题,具体来说就是如何在数据库中存储一个struct数据类型,以及如何反序列化从数据库读取的一个byte数组得到一个struct数据类型。

ontio_std 库为数据序列化和反序列化提供解码器和编码器接口。 结构的字段还实现了解码器和编码器接口,以便可以对结构进行序列化和反序列化。 序列化各种数据类型时,需要 Sink 类的实例。 Sink类的一个实例有一个set-type字段buf,存放的是byte类型的数据,所有序列化后的数据都存放在buf中。

对于固定长度的数据(如:byte、u16、u32、u64等),直接将数据转为byte数组,然后存入buf; 对于非固定长度的数据,必须先序列化length,再序列化Ddata(例如未知大小的无符号整数,包括u16、u32或u64等)。

反序列化恰恰相反。 对于每一种序列化方法,都有一种对应的反序列化方法。 反序列化需要使用 Source 类的实例。 此类实例有两个字段 buf 和 pos。 buf用来存放要反序列化的数据,pos用来存放当前读取的位置。 读取某类数据时,如果知道长度,可以直接读取,对于未知长度的数据,先读取长度,再读取内容。

访问和更新链中数据

本体-wasm-cdt-rust - 封装了一个对链中数据进行操作的操作方法,方便开发者实现对链中数据的增删改查操作,如下:

  • 数据库::获取(键) - 用于向链上请求数据,key请求AsRef接口的实现;
  • 数据库::放(键,值) - 用于在网络上存储数据。 Key请求AsRef接口的实现,value请求Encoder接口的实现;
  • 数据库::删除(键) - 用于从链中移除数据,key请求AsRef接口的实现。

合同测试

当合约的方法实现时,我们需要访问链上的数据,需要合适的虚拟机来执行合约的字节码,所以一般需要将合约部署在链上进行测试。 但是这种测试方法是有问题的。 为了方便开发者测试合约,ontio_std 库提供了一个 mock 模块用于测试。 该模块提供了电路中数据的模拟,方便开发者对合约中的方法进行单元测试。 具体例子可以看 这里.

合约调试

console::debug(msg) 在调试合约时显示调试信息。 msg 信息将添加到节点日志文件中。 前提条件是在本地本体测试节点运行时将日志文件级别设置为调试模式。

runtime::notify(msg) 在调试合约时输出适当的调试信息。 此方法将存储输入到链中的信息,并且可以使用 getSmartCodeEvent 方法从链中查询。

该文章由 Hashrate&Shares 的编辑特别为 OntologyRussia 翻译。 单击

你是开发者吗? 加入我们的技术社区 Discord. 另外,看看 开发者中心 在我们的网站上,您可以在其中找到开发人员工具、文档等。

本体论

来源: habr.com

添加评论