本体技术视点 | 使用C++进行Wasm合约开发

Ontology Wasm 自从上线测试网以来便受到了社区开发人员的极大关注。Ontology Wasm 的上线将使得业务逻辑复杂的 dApp 合约上链成本降低,极大丰富 dApp 生态。在进行 Ontology Wasm 合约开发时,开发者不仅可以使用 Rust,还可以使用 C++ 作为合约开发语言。本期我们将通过两个简单的示例来示范如何使用 C++ 进行Ontology Wasm 合约开发。

本体技术视点 | 使用C++进行Wasm合约开发

Ontology Wasm 自从上线测试网以来便受到了社区开发人员的极大关注。Ontology Wasm 的上线将使得业务逻辑复杂的 dApp 合约上链成本降低,极大丰富 dApp 生态。在进行 Ontology Wasm 合约开发时,开发者不仅可以使用 Rust,还可以使用 C++ 作为合约开发语言。本期我们将通过两个简单的示例来示范如何使用 C++ 进行Ontology Wasm 合约开发。

本体技术视点 | 使用C++进行Wasm合约开发

一、Hello World

按照惯例,我们还是从一个 Hello world 开始本体技术视点 | 使用C++进行Wasm合约开发

1.1 合约入口

本体技术视点 | 使用C++进行Wasm合约开发

在上面的例子中, 我们暂时只支持 sayHello 这个方法:本体技术视点 | 使用C++进行Wasm合约开发这个“Hello world!”会在节点的日志中以调试信息打印出来。在实际的应用中, printf 只能用作调试的目的, 一个实际的智能合约,需要实现更多更复杂的功能。

1.2 智能合约 API

Ontology Wasm 提供如下 API 与区块链的底层进行交互:

本体技术视点 | 使用C++进行Wasm合约开发

二、红包合约

下面我们通过一个更加复杂的例子来演示如何通过这些 API 来开发一个完整的 Wasm 智能合约。

很多情况下我们都会通过各种 App,如微信等聊天工具发红包。我们可以给朋友发送红包,也可以抢其他人发送的红包,收到的钱会记入到个人微信账户中。

类似于微信的流程,我们将尝试创建一个智能合约。用户使用该合约,可以发送 ONT,ONG 或者是标准的 OEP-4的 Token 资产红包给他的朋友们,而朋友们抢到的红包可以直接转入到他们的钱包账户中。

2.1 创建合约

首先,我们需要新建合约的源文件,暂且命名为 redEnvelope.cpp。这个合约我们需要三个接口:

  •  createRedEnvelope: 创建红包

  •  queryEnvelope: 查询红包信息

  •  claimEnvelope: 抢红包

本体技术视点 | 使用C++进行Wasm合约开发

我们需要在存储中保存一些关键的数据。在智能合约中, 数据以 KV 的形式保存在该合约的上下文空间中,这些数据的 KEY 需要设置前缀以便于后面的查询。下面定义了三个不同的前缀供使用:

本体技术视点 | 使用C++进行Wasm合约开发

因为我们的合约支持 ONT 和 ONG 这两种 Ontology 的原生资产, 我们可以预先定义好这两种资产的合约地址。不同于标准的智能合约, Ontology 原生合约(native contract)的合约地址是固定的,而不是根据合约代码的 hash 计算而来的。

本体技术视点 | 使用C++进行Wasm合约开发

我们需要在合约中保存红包的信息, 如红包的资产信息(token 的合约地址, 红包的总金额, 红包的个数等等)。

本体技术视点 | 使用C++进行Wasm合约开发

其中,

本体技术视点 | 使用C++进行Wasm合约开发

是由 Ontology Wasm CDT 定义的宏操作,用于在将 struct 存储前进行序列化的操作。

2.2 创建红包

准备工作差不多了,下面我们开始开发具体的接口逻辑。1. 创建红包需要指定创建者地址, 红包数量, 红包金额和资产的合约地址:本体技术视点 | 使用C++进行Wasm合约开发2. 检查是否有创建者的签名, 否则交易回滚退出:

本体技术视点 | 使用C++进行Wasm合约开发

3. 如果红包资产是 ONT,由于 ONT 的不可分割性(最小为1个 ONT), 红包的金额要大于或等于红包的数量,保证每个红包最少有1个 ONT:

本体技术视点 | 使用C++进行Wasm合约开发

4. 对于每个红包的创建者,我们需要记录一下他发送红包的总数量:

本体技术视点 | 使用C++进行Wasm合约开发

5. 生成红包 hash, 这个 hash 就是之后标识这个红包的唯一 ID:

本体技术视点 | 使用C++进行Wasm合约开发

6. 根据 token 资产的类型,将资产转入合约中,self_address()可以取得当前执行的合约地址, 我们根据用户输入的 token 类型,将指定数量的 token 转入合约:

本体技术视点 | 使用C++进行Wasm合约开发

7. 将合约的信息保存在存储中:

本体技术视点 | 使用C++进行Wasm合约开发

8. 发送创建红包的事件。对于智能合约的调用是一个异步的过程,合约会在执行成功后发送一个事件来通知客户端执行结果,这个事件的格式可以由合约的编写者来指定。

本体技术视点 | 使用C++进行Wasm合约开发

一个简单的红包就创建完成了, 下一步我们需要实现如何查询这个红包的信息.

2.3 查询红包

查询红包的逻辑非常简单, 只需要将存储中的红包信息取出并格式化返回即可:本体技术视点 | 使用C++进行Wasm合约开发

2.4 领取红包

我们已经把资产成功地转入到智能合约中了, 接下来就可以把这个红包的 ID 发送给你的朋友们让他们去抢红包了。

1. 领取红包需要输入领取人的账户和红包的hash:

本体技术视点 | 使用C++进行Wasm合约开发

2. 同样, 我们需要验证领取账户的签名, 不允许替其他人抢红包, 而且每个账户每个红包只能抢一次:

本体技术视点 | 使用C++进行Wasm合约开发3. 按照 hash 从存储中取出红包的信息, 判断这个红包是否没有被抢完:

本体技术视点 | 使用C++进行Wasm合约开发

4. 新建一条领取的记录:

本体技术视点 | 使用C++进行Wasm合约开发

5. 计算本次领取红包的资产数量。如果是最后一个红包, 数量为剩余的金额, 否则根据当前区块 hash 计算随机数,确定本次领取的数量, 并更新红包信息:

本体技术视点 | 使用C++进行Wasm合约开发

6. 根据计算结果, 将对应资产从合约中转到领取的账户:

本体技术视点 | 使用C++进行Wasm合约开发

7. 记录领取的信息, 将更新后的红包信息写回存储并发送通知事件:

本体技术视点 | 使用C++进行Wasm合约开发

如前面所说,这个合约只能通过 claimEnvelope 这个接口将资产转出合约。所以,合约中的资产是安全的,任何人都无法随意的取走里面的资产。至此, 一个简单的红包合约逻辑完成, 完整的合约代码如下:https://github.com/JasonZhouPW/pubdocs/blob/master/redEnvelope.cpp

2.5 合约测试

合约测试可以有两种方法:

  1. 使用 CLI

    请参考:https://github.com/ontio/ontology-wasm-cdt-cpp/blob/master/How_To_Run_ontologywasm_node.md

  2. 使用 Golang SDK

    请参考:https://github.com/ontio/ontology-wasm-cdt-cpp/blob/master/example/other/main.go

三、总结

本示例只是为了展示如何编写一个完整的 Ontology Wasm 智能合约, 如何通过调用 API 和底层的区块链进行交互。如果要作为正式的产品, 还需要解决红包的隐私问题: 所有人都可以通过监控合约的事件来取得红包的 hash, 意味着每个人都可以抢这个红包。一种比较简单的解决方法,就是在创建红包时指定哪些账户能够领取。如果有兴趣, 您也可以尝试修改测试一下。

Ontology 作为领先公链,率先支持 Wasm 合约,为 Wasm 技术的成熟贡献自己的一份力量。我们欢迎更多的 Wasm 技术爱好者加入本体开发社区,共同打造技术生态。

*详细代码信息可能显示不全,可参考:https://mp.weixin.qq.com/s/LlvuX4NzZackasuvQyBDlg

生成图片
7

发表评论

本体技术视点 | 使用C++进行Wasm合约开发

星期四 2019-08-29 16:54:53

本体技术视点 | 使用C++进行Wasm合约开发

Ontology Wasm 自从上线测试网以来便受到了社区开发人员的极大关注。Ontology Wasm 的上线将使得业务逻辑复杂的 dApp 合约上链成本降低,极大丰富 dApp 生态。在进行 Ontology Wasm 合约开发时,开发者不仅可以使用 Rust,还可以使用 C++ 作为合约开发语言。本期我们将通过两个简单的示例来示范如何使用 C++ 进行Ontology Wasm 合约开发。

本体技术视点 | 使用C++进行Wasm合约开发

一、Hello World

按照惯例,我们还是从一个 Hello world 开始本体技术视点 | 使用C++进行Wasm合约开发

1.1 合约入口

本体技术视点 | 使用C++进行Wasm合约开发

在上面的例子中, 我们暂时只支持 sayHello 这个方法:本体技术视点 | 使用C++进行Wasm合约开发这个“Hello world!”会在节点的日志中以调试信息打印出来。在实际的应用中, printf 只能用作调试的目的, 一个实际的智能合约,需要实现更多更复杂的功能。

1.2 智能合约 API

Ontology Wasm 提供如下 API 与区块链的底层进行交互:

本体技术视点 | 使用C++进行Wasm合约开发

二、红包合约

下面我们通过一个更加复杂的例子来演示如何通过这些 API 来开发一个完整的 Wasm 智能合约。

很多情况下我们都会通过各种 App,如微信等聊天工具发红包。我们可以给朋友发送红包,也可以抢其他人发送的红包,收到的钱会记入到个人微信账户中。

类似于微信的流程,我们将尝试创建一个智能合约。用户使用该合约,可以发送 ONT,ONG 或者是标准的 OEP-4的 Token 资产红包给他的朋友们,而朋友们抢到的红包可以直接转入到他们的钱包账户中。

2.1 创建合约

首先,我们需要新建合约的源文件,暂且命名为 redEnvelope.cpp。这个合约我们需要三个接口:

  •  createRedEnvelope: 创建红包

  •  queryEnvelope: 查询红包信息

  •  claimEnvelope: 抢红包

本体技术视点 | 使用C++进行Wasm合约开发

我们需要在存储中保存一些关键的数据。在智能合约中, 数据以 KV 的形式保存在该合约的上下文空间中,这些数据的 KEY 需要设置前缀以便于后面的查询。下面定义了三个不同的前缀供使用:

本体技术视点 | 使用C++进行Wasm合约开发

因为我们的合约支持 ONT 和 ONG 这两种 Ontology 的原生资产, 我们可以预先定义好这两种资产的合约地址。不同于标准的智能合约, Ontology 原生合约(native contract)的合约地址是固定的,而不是根据合约代码的 hash 计算而来的。

本体技术视点 | 使用C++进行Wasm合约开发

我们需要在合约中保存红包的信息, 如红包的资产信息(token 的合约地址, 红包的总金额, 红包的个数等等)。

本体技术视点 | 使用C++进行Wasm合约开发

其中,

本体技术视点 | 使用C++进行Wasm合约开发

是由 Ontology Wasm CDT 定义的宏操作,用于在将 struct 存储前进行序列化的操作。

2.2 创建红包

准备工作差不多了,下面我们开始开发具体的接口逻辑。1. 创建红包需要指定创建者地址, 红包数量, 红包金额和资产的合约地址:本体技术视点 | 使用C++进行Wasm合约开发2. 检查是否有创建者的签名, 否则交易回滚退出:

本体技术视点 | 使用C++进行Wasm合约开发

3. 如果红包资产是 ONT,由于 ONT 的不可分割性(最小为1个 ONT), 红包的金额要大于或等于红包的数量,保证每个红包最少有1个 ONT:

本体技术视点 | 使用C++进行Wasm合约开发

4. 对于每个红包的创建者,我们需要记录一下他发送红包的总数量:

本体技术视点 | 使用C++进行Wasm合约开发

5. 生成红包 hash, 这个 hash 就是之后标识这个红包的唯一 ID:

本体技术视点 | 使用C++进行Wasm合约开发

6. 根据 token 资产的类型,将资产转入合约中,self_address()可以取得当前执行的合约地址, 我们根据用户输入的 token 类型,将指定数量的 token 转入合约:

本体技术视点 | 使用C++进行Wasm合约开发

7. 将合约的信息保存在存储中:

本体技术视点 | 使用C++进行Wasm合约开发

8. 发送创建红包的事件。对于智能合约的调用是一个异步的过程,合约会在执行成功后发送一个事件来通知客户端执行结果,这个事件的格式可以由合约的编写者来指定。

本体技术视点 | 使用C++进行Wasm合约开发

一个简单的红包就创建完成了, 下一步我们需要实现如何查询这个红包的信息.

2.3 查询红包

查询红包的逻辑非常简单, 只需要将存储中的红包信息取出并格式化返回即可:本体技术视点 | 使用C++进行Wasm合约开发

2.4 领取红包

我们已经把资产成功地转入到智能合约中了, 接下来就可以把这个红包的 ID 发送给你的朋友们让他们去抢红包了。

1. 领取红包需要输入领取人的账户和红包的hash:

本体技术视点 | 使用C++进行Wasm合约开发

2. 同样, 我们需要验证领取账户的签名, 不允许替其他人抢红包, 而且每个账户每个红包只能抢一次:

本体技术视点 | 使用C++进行Wasm合约开发3. 按照 hash 从存储中取出红包的信息, 判断这个红包是否没有被抢完:

本体技术视点 | 使用C++进行Wasm合约开发

4. 新建一条领取的记录:

本体技术视点 | 使用C++进行Wasm合约开发

5. 计算本次领取红包的资产数量。如果是最后一个红包, 数量为剩余的金额, 否则根据当前区块 hash 计算随机数,确定本次领取的数量, 并更新红包信息:

本体技术视点 | 使用C++进行Wasm合约开发

6. 根据计算结果, 将对应资产从合约中转到领取的账户:

本体技术视点 | 使用C++进行Wasm合约开发

7. 记录领取的信息, 将更新后的红包信息写回存储并发送通知事件:

本体技术视点 | 使用C++进行Wasm合约开发

如前面所说,这个合约只能通过 claimEnvelope 这个接口将资产转出合约。所以,合约中的资产是安全的,任何人都无法随意的取走里面的资产。至此, 一个简单的红包合约逻辑完成, 完整的合约代码如下:https://github.com/JasonZhouPW/pubdocs/blob/master/redEnvelope.cpp

2.5 合约测试

合约测试可以有两种方法:

  1. 使用 CLI

    请参考:https://github.com/ontio/ontology-wasm-cdt-cpp/blob/master/How_To_Run_ontologywasm_node.md

  2. 使用 Golang SDK

    请参考:https://github.com/ontio/ontology-wasm-cdt-cpp/blob/master/example/other/main.go

三、总结

本示例只是为了展示如何编写一个完整的 Ontology Wasm 智能合约, 如何通过调用 API 和底层的区块链进行交互。如果要作为正式的产品, 还需要解决红包的隐私问题: 所有人都可以通过监控合约的事件来取得红包的 hash, 意味着每个人都可以抢这个红包。一种比较简单的解决方法,就是在创建红包时指定哪些账户能够领取。如果有兴趣, 您也可以尝试修改测试一下。

Ontology 作为领先公链,率先支持 Wasm 合约,为 Wasm 技术的成熟贡献自己的一份力量。我们欢迎更多的 Wasm 技术爱好者加入本体开发社区,共同打造技术生态。

*详细代码信息可能显示不全,可参考:https://mp.weixin.qq.com/s/LlvuX4NzZackasuvQyBDlg