zl程序教程

您现在的位置是:首页 >  Java

当前栏目

MetaForce佛萨奇开发案例,MetaForce佛萨奇2.0智能合约系统开发流程及源码

2023-02-18 16:30:25 时间

6. 使用C++进行智能合约开发

读者对象:本章节主要描述使用C++进行ChainMaker合约编写的方法,主要面向于使用C++进行ChainMaker的合约开发的开发者。

6.1. 环境依赖

操作系统

目前仅支持Linux和MAC系统。

软件依赖

软件依赖表如下:

名称

版本

描述

是否必须

GCC

7.3+

C编译器

依赖软件安装:

Mac:brew install gcc

Linux:

  • yum install gcc —— Ubuntu/Debian安装命令。
  • apt-get install gcc —— CentOS/Redhat安装命令。

长安链环境准备

准备一条支持WXVM的长安链,以及长安链CMC工具,用于将写编写好的合约,部署到链上进行测试。相关安装教程请详见:

6.2. 编写C++智能合约

6.2.1. 搭建开发环境

开发者可根据ChainMaker提供的SDK开发C++合约,C++合约的SDK工程下载地址为:chainmaker-contract-sdk-cpp

SDK下载完成后,开发者可根据自身习惯选择熟悉的C++编辑器或IDE。推荐使用CLion,CLion下载和安装请参见官网:https://www.jetbrains.com/clion/。

安装完成后,使用CLion打开SDK工程,通过编辑main.cc文件即可编辑自己的C++合约。

6.2.2. 代码编写规则

外部方法声明

只有声明为外部方法的函数,才可以(被用户或其他合约)从外部调用,否则,只能用于合约内部调用。外部方法声明规则如下:

  • WASM_EXPORT: 必须,暴露声明
  • void: 必须,无返回值
  • method_name(): 必须,暴露方法名称
// 示例
WASM_EXPORT void init_contract() {
    
}

强制声明外部方法

强制声明外部方法为合约必须提供且必须对外暴露的方法,有以下两个:

  • init_contract:创建合约会自动执行该方法,无需指定方法名。
  • upgrade: 升级合约会自动执行该方法,无需指定方法名。
// 在创建本合约时, 调用一次init方法. ChainMaker不允许用户直接调用该方法.
WASM_EXPORT void init_contract() {
    // 安装时的业务逻辑,可为空
    
}

// 在升级本合约时, 对于每一个升级的版本调用一次upgrade方法. ChainMaker不允许用户直接调用该方法.
WASM_EXPORT void upgrade() {
    // 升级时的业务逻辑,可为空
    
}

获取SDK 接口上下文

C++合约通过SDK接口上下文与链进行交互,具体信息可参考文章末尾[C++ SDK API描述](C++ SDK API描述)。

//获取SDK接口上下文
Context* ctx = context();

6.2.3. 合约示例源码展示

下文代码框内为一个C++编写的存证合约示例,该合约示例实现以下功能:

1、存储文件哈希、文件名称和该交易的ID;

2、通过文件哈希查询该条记录。

#include "chainmaker/chainmaker.h"

using namespace chainmaker;

class Counter : public Contract {
public:
    void init_contract() {}
    void upgrade() {}
    // 保存
    void save() {
        // 获取SDK 接口上下文
        Context* ctx = context();
        // 定义变量
        std::string time;
        std::string file_hash;
        std::string file_name;
        std::string tx_id;
		// 获取参数
        ctx->arg("time", time);
        ctx->arg("file_hash", file_hash);
        ctx->arg("file_name", file_name);
        ctx->arg("tx_id", tx_id);
        // 发送合约事件
        // 向topic:"topic_vx"发送2个event数据,file_hash,file_name
        ctx->emit_event("topic_vx",2,file_hash.c_str(),file_name.c_str());
		// 存储数据
        ctx->put_object("fact"+ file_hash,  tx_id+" "+time+" "+file_hash+" "+file_name);
        // 记录日志
        ctx->log("call save() result:" + tx_id+" "+time+" "+file_hash+" "+file_name);
        // 返回结果
        ctx->success(tx_id+" "+time+" "+file_hash+" "+file_name);
    }

    // 查询
    void find_by_file_hash() {
        // 获取SDK 接口上下文
    	Context* ctx = context();

		// 获取参数
        std::string file_hash;
        ctx->arg("file_hash", file_hash);
		
        // 查询数据
    	std::string value;
        ctx->get_object("fact"+ file_hash, &value);
        // 记录日志
        ctx->log("call find_by_file_hash()-" + file_hash + ",result:" + value);
        // 返回结果
        ctx->success(value);
    }

};

// 在创建本合约时, 调用一次init方法. ChainMaker不允许用户直接调用该方法.
WASM_EXPORT void init_contract() {
    Counter counter;
    counter.init_contract();
}

// 在升级本合约时, 对于每一个升级的版本调用一次upgrade方法. ChainMaker不允许用户直接调用该方法.
WASM_EXPORT void upgrade() {
    Counter counter;
    counter.upgrade();
}

WASM_EXPORT void save() {
    Counter counter;
    counter.save();
}

WASM_EXPORT void find_by_file_hash() {
    Counter counter;
    counter.find_by_file_hash();
}