本体技术视点 | 想用Wasm开发dApp?你不得不读的入门教程(1)

Ontology Wasm 自从上线测试网以来,得到了社区开发人员的极大关注。同时,Ontology Wasm 也即将上线主网。我们知道,Ontology Wasm 合约支持 Rust 和 C++ 语言开发。在前面的技术视点文章中,我们曾经介绍过如何用 C++ 来实现一个简单的红包合约帮助开发者了解如何采用 C++ 语言来在 Ontology 上进行合约开发。另外,我们也简单介绍过使用 Rust 语言的开发注意事项。
在此次的技术视点以及以后的相关系列文章中,我们将会详细介绍如何使用 Rust 语言开发 Ontology Wasm 合约。本次技术视点中,我们将简单介绍如何进行相关环境搭建和使用合约模板来进行开发。
图 | 网络

一、环境搭建

为了提高开发的效率,建议在开发合约之前,先准备好如下的开发环境。

  • Rust 开发环境(必须)

  • 集成开发环境(推荐)

  • 本地 Wasm 合约测试节点(推荐)

这里需要注意的一点是:本地测试节点的搭建可以方便合约测试。同时,可以通过在合约中添加 debug 信息,在节点日志中监控合约运行信息。当然,如果觉得自己搭建测试节点较复杂,我们也可以使用 Ontology 测试网来进行合约测试。

1.1 Rust 开发环境搭建

Rust 开发环境可以通过以下几步来完成:

  1. 安装 rustup。如果是 Linux、Mac OS 以及其它类 Unix 系统可以直接执行下面的命令,并根据屏幕上的提示进行操作。

curl https://sh.rustup.rs -sSf | sh

如果是 Windows 等系统,请访问官网下载合适的版本进行安装。

  1. 安装 rust 编译器。

安装完 rustup 后可以通过以下命令安装 rust 编译器:


rustup install nightly

同时,设置默认的编译版本为 nightly:


rustup default nightly
  1. 安装 Wasm32 编译目标。

开发者可以通过以下命令安装 Wasm32 编译目标:


rustup target add wasm32-unknown-unknown
  1. 安装ontio-wasm-build工具。
    我们使用cargo工具把合约编译成 Wasm 字节码时,生成的文件会比较大,ontio-wasm-build可以优化字节码,从而减小合约文件大小,将合约部署到链上之前,必须通过该工具进行合约的优化与检查。
    具体安装方法如下:

cargo install --git=https://github.com/ontio/ontio-wasm-build

1.2 安装集成开发环境

集成开发环境 IDE 和编辑工具有很多种选择,比如 Clion、IntelliJ 以及 vim 等。其中, Clion 是一款功能强大的 C/C++/Rust 开发工具,支持单步调式,方便 Wasm 合约本地调试。开发者可以选择自己喜欢的 IDE 或编辑工具来进行开发。

1.3 本地测试节点搭建

该部分请参考 Ontology 官方文档:本地测试节点环境搭建。

注意:就像在前面强调过的一样,编译好的可执行文件在启动时,请设置日志级别为 debug 模式。该模式下,开发者可以十分方便地查看合约运行的 debug 信息。

二、使用合约模板开发 Wasm 合约

使用 Rust 开发的合约源代码要想在 Ontology 链上运行,要经过以下步骤:

  1. 需要先将源码编译成 Wasm 字节码。

  2. 使用 ontio-wasm-build 工具优化一下 Wasm 字节码。

  3. 将优化后的 Wasm 字节码部署到链上。

  4. 进行合约中方法的调用。

下面这是一个简单的使用合约模板开发 Wasm 合约的例子,以此来介绍一下上述整个流程。

2.1 取得 Wasm 合约模板

为了方便开发者入手 Ontology Wasm 合约开发,我们提供了一个合约模板(Rust 版),开发者仅需 clone 该代码,然后添加自己的合约逻辑即可。

git clone https://github.com/ontio/rust-wasm-contract-template.git

目录结构如下所示:


.
├── .cargo
│   └── config
├── Cargo.toml
├── build.sh
└── src
    └── lib.rs

我们对其中一些文件进行说明:

.cargo文件夹下面的config文件中配置了合约编译时的一些配置信息, config文件内容如下:

[target.wasm32-unknown-unknown]
rustflags = [
"-C", "link-args=-z stack-size=32768"
]

[target.wasm32-unknown-unknown]表示编译目标, rustflags 配置了编译的链接参数,此处设置了默认的栈大小为32768,即32 kb,合约在运行的过程中可以使用的栈的最大值。

Cargo.toml文件是合约的一些基本配置信息,其内容如下:

[package]
name = "rust-wasm-contract-template"
version = "0.1.0"
authors = ["name <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib"] #Compile as a dynamic link library

[dependencies]
ontio-std = {git = "https://github.com/ontio/ontology-wasm-cdt-rust"}

[features]
mock = ["ontio-std/mock"]

其中,在[lib]配置模块中, crate-type = [“cdylib”] 表示将项目编译动态链接库,用于被其他语言调用。
[dependencies]用于配置项目依赖信息,这里引入了 Ontology Wasm 合约开发需要的ontio-std库。
[features]用于开启一些不稳定特性,只可在 nightly 版的编译器中使用。
build.sh文件里面封装好了编译合约和优化合约的功能,待合约开发完成后,执行该脚本会将优化后的合约字节码放到output目录下面。
src/lib.rs用于编写合约逻辑代码,合约模板里面的代码如下:

#![no_std]
use ontio_std::runtime;

#[no_mangle]
fn invoke() {
runtime::ret(b"hello");
}

该合约模板实现了一个简单的返回 hello 功能。对于该模板的一些简单说明如下:
#![no_std] 表示屏蔽 rust std 库中的接口,但是开发者可以调用 rust core 库中的 api。
#[no_mangle]表示在编译成wasm字节码时候,将 invoke 函数导出,invoke 函数是 Ontology Wasm 合约的入口函数,需要将其导出。
runtime模块封装了合约与链交互的接口,runtime::ret()用于将合约执行的结果返回给调用方。

2.2 编译合约

开发者可以直接执行build.sh脚本即可实现合约编译和合约字节码优化。

./build.sh

如果在执行的过程中出现如下权限错误:

-bash: ./build.sh: Permission denied

那么,可以先给该文件可执行权限:

sudo chmod +x ./build.sh

执行成功后,会在当前目录下生成output目录。output 的目录结构如下:

├── output
│   ├── rust_wasm_contract_template.wasm
│   └── rust_wasm_contract_template.wasm.str

其中, rust_wasm_contract_template.wasm是我们编译合约源代码生成的 Wasm 字节码文件。rust_wasm_contract_template.wasm.str是 Wasm 字节码的 hex 编码格式的文件。

2.3 部署合约

编译好的 Wasm 合约需要部署到链上才能运行。我们可以将上面的合约字节码文件部署到测试网,或者本地测试节点,下面以部署到本地测试网为例:

首先,启动本地测试节点,在启动之前,我们需要先生成钱包文件:

./ontology account add

上面命令在执行的过程中用默认配置即可,再执行下面的命令启动本地测试节点:

./ontology --testmode --loglevel 1
--loglevel 1 表示节点的日志级别是debug,测试合约中如果有 debug 信息,会在节点日志中显示出来。
然后,打开另外一个终端窗口,进行合约部署。
$ ./ontology contract deploy --vmtype 3 --code ./rust_wasm_contract_template.wasm.str --name helloworld --author "author" --email "email" --desc "desc" --gaslimit 22200000
Password:
Deploy contract:
  Contract Address:0be3df2e320f86f55709806425dc1f0b91966634
  TxHash:bd83f796bfd79bbb2546978ebd02d5ff3a54c2a4a6550d484689f627513f5770

Tip:
  Using './ontology info status bd83f796bfd79bbb2546978ebd02d5ff3a54c2a4a6550d484689f627513f5770' to query transaction status.

如果出现 gaslimit 不够的错误信息,请设置更大的 gaslimit 参数。

2.4 测试合约
现在我们来调用合约中的方法,执行如下的命令:

$ ./ontology contract invoke --address 0be3df2e320f86f55709806425dc1f0b91966634 --vmtype 3 --params '' --version 0 --prepare
Invoke:346696910b1fdc2564800957f5860f322edfe30b Params:null
Contract invoke successfully
  Gas limit:20000
  Return:68656c6c6f (raw value)

为了能够看到合约执行返回的结果,我们在命令后面加了–prepare标签,表示该交易是预执行交易。

可以看到,在命令行中,我们得到了68656c6c6f,这是预期结果hello的 hex 编码格式而已,我们仅需用 hex 解码即可得到预期结果。

三、结论

在本期技术视点中,我们简单介绍了使用 Rust 语言在 Ontology 上进行 Wasm 开发时,如何进行相关环境搭建和使用合约模板来进行开发。此外,支持 Ontology Wasm 合约部署和调用的新版 SmartX 正在开发中,即将上线。它的上线会大大方便开发者进行 Ontology Wasm 合约的部署以及相关函数的调用。
Ontology 作为领先公链,率先支持 Wasm 合约,为 Wasm 技术的成熟贡献力量。同时,我们也欢迎更多的 Wasm 技术爱好者加入本体开发社区,共同打造技术生态。

发布了125 篇原创文章 · 获赞 38 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ontologycoding/article/details/102587843