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

1.1 智能合约简介

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

智能合约类型根据使用的运行时类型,整体上可以分为SolidityJavaScriptVM运行的合约二个大类。JavaScriptVM可将代码直接翻译成二进制机器码在物理机上执行,执行效率高,而且是一种可移植、加载高效、平台无关的字节码格式,能在平台上以接近原生的速度执行程序,这两项技术可以为JavaScriptVM 提供良好的基础功能支撑。Solidtiy合约和以太坊类似,先编译成Solidity字节码,然后再进行部署和调用。二种类型合约的执行原理如下图:

image-20221219205857431

JavaScriptVM合约执行流程

image-20221219205857431

EVM合约执行流程

1.2 智能合约的开发过程

智能合约的开发需要经过选择开发语言、开发工具、编写合逻辑代码、编译合约、部署合约和调用合约几个过程。

1.3 智能合约开发注意事项

  1. 智能合约中不要使用带有随机性的函数,以避免在不同的机器上合约执行结果不一致,从而导致交易无法达成共识。

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

  3. 智能合约中不要使用全局变量、静态变量,需要将合约的函数设计成无状态的,每次运行结果具有确定性,不依赖于全局变量或者静态变量,避免在不同的节点运行结果不一致,从而无法达成共识。

1.4 数据处理注意事项

数组处理

Chain对象方法中Chain.store(key,value)的功能是向DB中保存一条数据。其中key的最大长度是1024Byte,value的最大长度是256KB,超过最大长度会写失败、报错。

超过长度限制的情况常出现在合约中数组,场景如下

//合约中定义了如下结构 
Json::value record{count:0,index:[]};
func addRecord(){
	record[index][index.size] = "new record";
	Chain.store("record",record.toFastString());
}

函数addRecord会增加index的记录并保存,当index的长度超过256KB时,Chain.store语句会报错。

建议的处理方式是用多个大小固定的数组来代替一个持续增长的大数组。

循环处理

虚拟机在执行合约的函数时,有步长限制,最大1024。每一次Chain或者utils的对象方法的调用步长加1,因此当一个函数中调用了Chain的对象方法超过1024次时,函数会因为超过步长限制而执行失败。

通常出现在循环调用中,场景如下

func getRecord(){
	for(i=0; i < 5000; i++){
		Chain.load(i,value);
	}
}

函数getRecord()中通过一个循环来调用Chain.load,当循环次数大于1024时函数报错。

建议的处理是,如果循环的长度会超过步长限制,需要修改函数的逻辑。

递归调用处理

星火链合约函数调用递归深度最大为4层。即合约A–>合约B–>合约C–>合约D时交易正常执行,超过调用步长是则执行失败。