1. 长安链智能合约开发整体介绍

1.1. 长安链智能合约简介

“长安链·ChainMaker”智能合约是运行在长安链上的一组“动态代码”。可以认为它是长安链上承载具体业务场景和逻辑的软件实现,特点是以长安链为执行的输入和输出环境,可以动态地部署和使用。目前长安链已经支持使用Golang、Rust、Solidity、TinyGo、C++进行智能合约开发,很快将支持Java。本章节将介绍各种语言合约的编写环境、编写、编译以及部署等相关知识。

“长安链·ChainMaker”的智能合约类型根据使用的运行时类型,整体上可以分为Wasm、Solidity和基于Docker运行的合约三个大类,其中Wasm类型的合约包含Rust、TinyGo和C++三种开发语言,这一类型的合约需要先将智能合约使用对应的工具编译成Wasm文件,然后进行部署和调用;Solidtiy合约和以太坊类似,先编译成Solidity字节码,然后再进行部署和调用;基于Docker类型的合约包括Golang和Java语言合约(Java语言的合约支持在开发中,后续可能会扩展更多其他合约语言),Go合约直接编译成平台机器码压缩后进行部署和调用,Java类型的合约也是编译成Java字节码进行部署和调用。三种类型合约的执行原理如下图:

“长安链·ChainMaker”官方当前推荐的合约编程语言依次为Golang、Rust、Solidity、TinyGo和C++。其中Golang合约编程限制少(除开发注意事项中的限制外,可以使用所有Go语言的特性),运行时环境DockerGo虚拟机也是长安链自研的支持微服务化部署的高性能虚拟机,为第一推荐编程语言。

1.2. 智能合约的开发过程

“长安链·ChainMaker”智能合约的开发需要经过选择开发语言、开发工具、编写合逻辑代码、编译合约、部署合约和调用合约几个过程,长安链提供了整套合约开发过程推荐的工具,如下图所示:

1.3. 智能合约开发注意事项

1.3.1. 通用部分

  1. 智能合约中不要使用带有随机性的函数,以避免在不同的机器上合约执行结果不一致,从而导致交易无法达成共识,例如Golang常用的随机数函数包math/rand、获取系统时间的函数time.Now()和time.Date。

  2. 智能合约中不要使用全局变量、静态变量,同一合约进程会执行多次交易,可能造成变量污染,全局变量对后续交易造成影响。需要将合约的函数设计成无状态的,每次运行结果具有确定性,不依赖于全局变量或者静态变量。

  3. 智能合约中不要使用变量地址作为Key或value进行存储,不能包含成员变量,否则会引入随机性,导致无法共识。

  4. 智能合约不能读写文件,否则可能造成无法共识。

  5. 智能合约不能调用网络相关功能,否则可能造成无法共识。

  6. 智能合约中避免使用多线程(或者多协程),避免出现随机性,从而导致交易无法达成共识。

  7. 智能合约中状态数据key、field内容仅支持数字、字母以及._-。

  8. 使用Golang编写合约时,应避免在合约中捕获panic异常输出,合约进程如果panic,栈信息会自动输出到合约产生的log中去。

  9. 状态数据key、filed 字符串长度限制为1024,超出该长度将存储失败。

  10. 合约中使用map作为迭代器,由于map是无序的,遍历可能会引入随机因素,可以使用有序的迭代器代替map,或二次确认使用map未带来随机因素。

  11. 合约中应谨慎使用密码学函数:不使用对称加解密,避免密钥泄漏;不使用非对称加密函数,避免随机性;不使用非对称解密函数,避免私钥泄漏;不使用签名函数,避免私钥泄漏。可使用的是验签。

1.3.2. Golang部分

  1. 合约必须包含InitContract函数,否则合约无法安装。

  2. 合约必须包含UpgradeContract函数,否则合约无法升级。

1.3.3. CPP部分

  1. 在安装CPP智能合约时,要求共识节点、非共识节点必须安装GCC。

1.3.4. TinyGo部分

  1. TinyGo对wasm的支持不太完善,对内存逃逸分析、GC等方面有不足之处,比较容易造成栈溢出。在开发合约时,应尽可能减少循环、内存申请等业务逻辑,使变量的栈内存地址在64K以内,要求tinygo version >= 0.17.0,推荐使用0.17.0。

  2. TinyGo对导入的包支持有限,请参考:https://tinygo.org/lang-support/stdlib/,对列表中显示已支持的包,实际测试发现支持的并不完整,会发生一些错误,需要在实际开发过程中进行测试检验。

  3. TinyGo引擎不支持fmtstrconv包。

1.4. 智能合约开发语言和虚拟机

“长安链·ChainMaker”目前已经支持使用Golang、Rust、Solidity、TinyGo、C++进行智能合约开发,每种开发语言实现的合约由不同的虚拟机执行,在将合约发布到链上时通过Runtime Type来指定虚拟机类型,语言和类型的对应关系如下:

语言 类型
系统合约 RuntimeType_NATIVE = 1
Rust RuntimeType_WASMER = 2
C++ RuntimeType_WXVM = 3
TinyGo RuntimeType_GASM = 4
Solidity RuntimeType_EVM = 5
Golang RuntimeType_DOCKER_GO = 6

1.5. 智能合约生命周期

长安链对智能合约有完善的生命周期管理,包括合约部署、升级、 合约可以使用命令行工具安装、调用、查询合约,请参看:【命令行工具】,也可使用SDK进行合约的安装、调用、查询,请参看:【SDK】