智能合约即链代码,是运行在区块链上的、特定条件下自动执行的代码逻辑,是用户利用区块链实现业务逻辑的重要途径。基于区块链特点,智能合约的运行结果是可信的,其结果是无法被伪造和篡改的。
智能合约的执行是要交付给平台来完成执行的,如以太坊,参与合约的双方要在平台上安装合约并托管执行。主流平台有自己的合约技术标准。如下
以太坊(Ethereum):ERC20、ERC721、ERC1400,合约语言solidity
https://ethereum.org/en/developers/docs/standards/tokens/erc-20/
超级账本(Hyperleger Fabric):CHAINCODE, 合约语言java/go/nodejs
https://github.com/hyperledger/fabric/blob/master/docs/source/smartcontract/smartcontract.md
波场(TRON): TRC20
https://tronprotocol.github.io/documentation-zh/contracts/trc20/
如何基于BCS快速开发智能合约
BCS是基于Fabric底层平台构建的baas平台,这里指的是Fabric的合约开发。
BCS提供了合约仓库,内置了常见领域的合约模板,用户可以根据自己的业务场景选择对应的模板,基于模板创建CloudIDE实例,在IDE上在线编辑后使用。
CloudIDE是面向云原生的轻量级WebIDE,通过浏览器访问即可实现云端开发环境获取、代码编写、编译调试、运行预览、命令行执行等能力,同时支持丰富的插件扩展。在BCS合约仓库中创建的实例已经内置了fabric sdk,用户可以直接对合约代码进行UT。
如下是一个golang工程的使用流程示例。
进入合约仓库中,可以点击合约模板的名称,会有该合约相关的接口介绍、适用场景、版本、开发语言等信息。
这里我们选择“数据上链存证和查询合约模板”,点击“使用”。
输入CloudIDE实例的名称和描述信息
启动实例加载
进入实例后可以看到对应模板代码。
我们可以在“合约IDE实例”中对已创建的示例进行生命周期管理。
开发
Fabric的链码要基于其提供的sdk中shim接口开发。Shim接口只有Init和Invoke两个函数,如下
实现了Init和Invoke两个接口的类即为一个合约类。
Init方法是chaincode的初始化方法,在链码初始化或升级时被调用,以便进行必要的应用状态的初始化。
比如当执行peer chaincode instantiate实例化chaincode的时候会调用该方法,同时-c 参数后面内容会作为参数传入Init方法中,以下面的实例化命令为例:
peer chaincode deploy -C mychannel -n simple -c '{"Args": ["init", "a","100", "b", "200"]}'
Invoke方法的主要作用是写入数据。在执行命令peer chaincode invoke的时候会调用这个方法,同时会把命令中-c后面的参数传入Invoke方法中。以下面的invoke命令为例:
peer chaincode invoke -C mychannel -n simple -c '{"Args": ["transfer", "a", "b", "10"]}'
两个接口都会传入一个stub对象ChaincodeStubInterface,该stub实现了和peer通信并操作账本的常用操作接口,常用的有GetState、PutState、DelState等接口。通过stub提供的丰富接口,开发者可以完成合约的开发。
这些接口可分为四类:账本状态交互API、交易信息相关API、参数读取API、其他API。
可以在IDE中点击shim.ChaincodeStubInterface类跳转其定义。
开发注意事项:
- 可选择使用链代码编辑器编写链代码:可实现对一些简单接口(PutState、stub.GetState和stub.DelState)的测试
- 防止出现panic后链码容器挂掉:在Invoke函数入口处添加defer语句时,出现panic异常,返回客户端。为避免链码容器挂掉重启,找不到日志,导致问题无法及时定位
- 分批次查询数据:链码查询功能的函数,不要在一次查询中返回过多的数据,因为这会导致资源占用过多,接口延时较长(例如超过30s,peer会中断任务),应预先估计数据量,分批次进行查询;修改或删除账本数据的链码时,同样也需要根据数据量大小确定是否采取分批次操作的方式处理。
- 合理使用索引(账本数据存储方式为CouchDB):对于CouchDB来说,使用索引功能,写入数据时会消耗时间,但可明显提高数据查询速度。因此可以根据业务需要,合理地在某些字段上建立索引
- 权限验证:对智能合约执行者的权限进行验证,防止无权限的用户执行链代码。如果业务上不要求确定的某个组织进行背书,为确保链代码上的数据不被任意组织恶意修改(自己安装非法链代码,操作数据等),建议至少两个或两个以上组织共同参与背书。
- 参数校验:参数(包括入参和代码中定义的各种参数)在使用前需对其个数、类型、长度、取值范围等做校验,验证其合法性,防止出现数组越界等问题。
- 逻辑处理:根据业务场景,合理处理函数的执行逻辑,如果出错需要打印日志,或者直接中断函数执行返回错误信息。
- 查看日志:开发时需要对业务逻辑复杂、容易出错的地方,使用fmt打印日志,便于调测。但是在开发调测结束后,需要将其删除,因为fmt会消耗时间和资源。
调测
可以使用launch.json配置调试器。
参考:https://support.huaweicloud.com/usermanual-cloudide/run_and_debug.html
通过在环境变量env字段中预置世界状态值和函数入参进行UT.
也可写对应的test文件进行UT。
安装、实例化
调试ok的代码可以下载到本地
在将下载的zip文件在链码管理器中进行安装
实例化
触发合约调用
合约实例化成功后,需要开发应用来触发合约逻辑。
具体使用方法可以参考https://support.huaweicloud.com/devg-bcs/bcs_devg_0006.html。
交易触发成功后,在区块链浏览器中可以看到具体的交易详情。