1.智能合约开发整体介绍
1.1 星火链虚拟机简介
星火链设计了统一的抽象智能合约引擎适配器,可以支持多种智能合约引擎同时运行在星火链节点上,支持多种引擎同时加载,以适配不同的智能合约编程环境。主要包含以下部分:
语言层:可以支持多种语言:如JavaScript、Solidity、C/C++(暂未上线);
编译层:针对不同的高级语言对接不同的不同类别的编译器,如solidity接入solc编译器、C/C++接入gcc编译器,编译单元将输入的高级智能合约语言通过编译适配器编译为字节码,不同高级智能合约语言输出不同后缀名的字节码文件,如solidity源文件.sol经过solc编译器接口编译后产生的字节码文件为sol的智能合约文件。编译适配接口接入不同的编译器单元,不同种类的智能合约经过适配接口后教育不同的编译器单元处理,输出不同的字节码文件。输出的字节码是编码后的数值常量、引用、指令等构成的序列,与特定机器代码无关,需要解释器转译后才能成为机器代码的中间代码。
引擎层:可以支持V8、EVM、WASM等智能合约引擎,以可插拔的方式实现,由于不同类型的合约包含了不同的字节码特征,可插拔虚拟机引擎接口通过对特征的识别,可以判断该段字节码需要使用哪种虚拟机进行执行,选择对应虚拟机后加载字节码,解析字节码,然后根据指令去执行对应的函数功能。
实现层:分为验证、注入、解释、执行等模块,以支撑不同的智能合约引擎的实现。
1.2 星火链智能合约简介
目前星火链线上支持两种智能合约:
Solidity智能合约。星火链的
Solidity
合约基本上和以太坊的Solidity
合约保持一致,有一些地方由于“许可公有”的特性会和以太坊有一定的差异。JavaScript智能合约。星火链的
Javascript
合约是执行在集成到星火链的优化的V8虚拟机引擎上的,基本支持Javascript的原生语法,有些语法特性为了适配区块链的特性做了增删。
Solidity
合约的生态工具更加完善且性能更佳,官方推荐使用Solidity
智能合约。
1.3 星火链智能合约开发建议
逻辑与数据分离。
从业务视角来看,智能合约只需要做两件事,一是定义数据的结果和读写方式,二是处理数据并对外提供服务接口。为了更好的做好模块抽象和合约结构分层,将业务控制逻辑和数据从合约代码层面做好分离,即将合约分为控制器合约与数据合约,被认为是比较好的设计模式。
控制器合约专注于对数据的逻辑处理和对外提供服务,通过访问数据合约获得数据,并对数据做逻辑处理,然后写回数据合约。
数据合约专注于数据结构定义与所存储数据的读写裸接口。
保持智能合约的简洁。
单个合约的行数建议控制在1000行以内。
确保合约逻辑简洁,只在系统中的去中心化部分使用智能合约实现。
对可能的错误有所准备。
可能存在交易执行超过1s甚至1分钟的情况。
合约可能存在bug或被攻击的情况,合约设计需要考虑冻结或暂停合约的开关。
合约可能会被其他人调用,如果合约的某个方法不希望其他人调用,需要在合约内做好权限控制。
1.4 星火链智能合约升级
星火链提供了合约升级方法,此方法是覆盖式升级,升级后合约地址不变,旧合约逻辑被覆盖。
如果需要保留旧合约的逻辑,可以参考以太坊的代理控制器合约模式,定义一个接口合约与应用程序交互,架构如下:
代理控制器合约定义智能合约对外接口,与应用程序交互。代理控制器合约调用控制器合约实现接口功能。
升级合约时,可以写一个新的合约,继承旧版本的控制器合约,并设置一个开关,调用升级后的控制器合约时,通过开关判断是执行新逻辑还是透传到旧的控制器合约。
在数据合约升级的场景,某些情况需要处理历史数据在新旧合约之间的迁移。新的数据合约中可以保持一个指向旧版本数据合约的合约地址,新版本数据合约保存的是增量的数据内容。这样设计简单灵活,但持续不断的版本升级会导致形成较长的链式逻辑关系,维护成本较高。