您的位置:首页 > 其它

预编译合约极速开发指南(附完整步骤+实操模板)

2019-04-26 17:19 459 查看
原文链接:https://my.oschina.net/u/4119053/blog/3042948

因预编译合约的使用方式与普通Solidity合约使用方式完全相同,该框架能做到在不改变客户端开发者体验的情况下,获得极高的运行速度,这对逻辑相对确定、追求高速度和并发能力的场景来说,可谓是屠龙刀一样的存在。

今天,我将以HelloWorld合约为例,为大家介绍如何使用预编译合约版本的HelloWorld。注意,本章内容需要你具备一定的C++开发经验,且详细阅读了《FISCO BCOS 2.0原理解析: 分布式存储架构设计》

下图所示5个步骤是开发预编译合约的必经之路,我将按步骤实现HelloWorld预编译合约,然后分别使用控制台、Solidity合约两种方式来调用HelloWorld预编译合约。

 

HelloWorld预编译合约开发

 

先来看一下我们想要实现的HelloWorld合约的Solidity版本。Solidity版本的HelloWorld,有一个成员name用于存储数据,两个接口get(),set(string)分别用于读取和设置该成员变量。

 

#step1#

定义HelloWorld接口

Solidity的接口调用都会被封装为一笔交易,其中,调用只读接口的交易不会被打包进区块,而写接口交易会被打包进区块中。由于底层需要根据交易数据中的ABI编码来判断调用的接口并解析参数,所以需要先把接口定义出来。

预编译合约的ABI接口规则与Solidity完全相同,定义预编译合约接口时,通常需要定义一个有相同接口的Solidity合约,这个合约称为预编译合约的接口合约。接口合约在调用预编译合约时需要使用。

 

#step2#

设计存储结构

预编译合约涉及存储操作时,需要确定存储的表信息(表名与表结构,存储数据在FISCO BCOS中会统一抽象为表结构)。这在之前的文章分布式存储架构设计有介绍。如果合约中不涉及变量存储,可以忽略该步骤。

对于HelloWorld,我们设计如下的表。该表只存储一对键值对,key字段为hello_key,value字段为hello_value 存储对应的字符串值,可以通过set(string)接口修改,通过get()接口获取。

 

#step3#

实现合约逻辑

实现新增合约的调用逻辑,需要新实现一个C++类,该类需要继承Precompiled类, 重载call函数, 在call函数中实现各个接口的调用行为。

call函数有三个参数,_context保存交易执行的上下文,_param是调用合约的参数信息,本次调用对应合约接口以及接口的参数可以从_param解析获取,_origin是交易发送者,用于权限控制。

接下来,我们在源码FISCO-BCOS/libprecompiled/extension目录下实现HelloWorldPrecompiled类,重载call函数,实现get()/set(string)两个接口。

 

接口注册:

 

创建表:

在call函数中添加打开表的逻辑

 

区分调用接口:

 

参数解析与返回:

调用合约时的参数包含在call函数的_param参数中,是按照Solidity ABI格式进行编码,使用dev::eth::ContractABI工具类可以进行参数的解析,同样接口返回时返回值也需要按照该编码格编码。

dev::eth::ContractABI类中我们需要使用abiIn/abiOut两个接口,前者用户参数的序列化,后者可以从序列化的数据中解析参数。

 

HelloWorldPrecompiled实现:

考虑手机上的阅读体验,我们分块介绍call接口内部实现并省略部分错误处理逻辑,详细代码实现可以参考FISCO BCOS 2.0文档使用手册->智能合约开发->预编译合约开发。可复制下列链接到网页中查看:

https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/manual/smart_contract.html#id2

get()接口实现

set接口实现

 

#step4#

分配并注册合约地址

FSICO BCOS 2.0执行交易时,根据合约地址区分是不是预编译合约,所以开发完预编译合约后,需要在底层注册为预编译合约注册地址。2.0版本地址空间划分如下:

用户分配地址空间为0x5001-0xffff,用户需要为新添加的预编译合约分配一个未使用的地址,预编译合约地址必须唯一, 不可冲突

开发者需要修改
FISCO-BCOS/cmake/templates/UserPrecompiled.h.in文件,在registerUserPrecompiled函数中注册HelloWorldPrecompiled合约的地址(要求v2.0.0-rc2以上版本),如下注册HelloWorldPrecompiled合约:

 

#step5#

编译源码

参考FISCO BCOS 2.0使用手册->获取可执行程序->源码编译。

https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/manual/get_executable.html

需要注意的是,实现的

HelloWorldPrecompiled.cpp

和HelloWorldPrecompiled.h

需要放置于

FISCO-BCOS/libprecompiled/extension目录下。

 

HelloWorld预编译合约调用

 

使用控制台调用HelloWorld预编译合约

在控制台solidity/contracts创建HelloWorldPrecompiled.sol文件,文件内容是HelloWorld预编译合约的接口声明,如下

pragma solidity ^0.4.24;
contract HelloWorldPrecompiled{
function get() public constant returns(string);
function set(string n);
}

使用编译出的二进制搭建节点后,部署控制台v1.0.2以上版本,然后执行下面语句即可调用

 

在Solidity中调用HelloWorld预编译合约

我们尝试在Solidity合约中创建预编译合约对象并调用其接口。在控制台solidity/contracts创建HelloWorldHelper.sol文件,文件内容如下

pragma solidity ^0.4.24;
import "./HelloWorldPrecompiled.sol";
contract HelloWorldHelper {
HelloWorldPrecompiled hello;
function HelloWorldHelper() {
// 调用HelloWorld预编译合约
hello = HelloWorldPrecompiled(0x5001);
}
function get() public constant returns(string) {
return hello.get();
}
function set(string m) {
hello.set(m);
}
}

 

部署HelloWorldHelper合约,然后调用HelloWorldHelper合约的接口,结果如下

到这里,就可以恭喜你顺滑地完成了HelloWorld预编译合约的开发,其他预编译合约的开发流程道理相通。

 

 

我们鼓励机构成员、开发者等社区伙伴参与开源共建事业,有你在一起,会更了不起。多样参与方式:

1 进入微信社群,随时随地与圈内最活跃、最顶尖的团队畅聊技术话题(进群请添加小助手微信,微信ID:fiscobcosfan);

2 订阅我们的公众号:“FISCO BCOS开源社区”,我们为你准备了开发资料库、最新FISCO BCOS动态、活动、大赛等信息;

3 来Meetup与开发团队面对面交流,FISCO BCOS正在全国举办巡回Meetup,深圳、北京、上海、成都……欢迎您公众号在菜单栏【找活动】中找到附近的Meetup,前往结识技术大咖,畅聊硬核技术;

4 参与代码贡献,您可以在Github提交Issue进行问题交流,欢迎向FISCO BCOS提交Pull Request,包括但不限于文档修改、修复发现的bug、提交新的功能特性。

代码贡献指引:

https://github.com/FISCO-BCOS/FISCO-BCOS/blob/master/docs/CONTRIBUTING_CN.md

 

本文首发于公众号【FISCO BCOS开源社区】,如转载请注明出处,原创不易,谢谢珍惜

转载于:https://my.oschina.net/u/4119053/blog/3042948

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: