佛萨奇2.0原力元宇宙马蹄莲智能合约系统开发详情及原理

1.2. 智能合约的开发过程

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

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

  1. 智能合约中不要使用带有随机性的函数,以避免在不同的机器上合约执行结果不一致,从而导致交易无法达成共识,例如Golang常用的随机数函数包math/rand、获取系统时间的函数time.Now()和time.Date。
  2. 智能合约中不要使用全局变量、静态变量,需要将合约的函数设计成无状态的,每次运行结果具有确定性,不依赖于全局变量或者静态变最,避免在不同的节点运行结果不一致,从而无法达成共识。
  3. 智能合约中避免使用多线程(或者多协程),避免出现随机性,从而导致交易无法达成共识。
  4. 智能合约中状态数据key、field内容仅支持数字、字母以及._-。
  5. 使用Golang编写合约时,应避免在合约中捕获panic异常输出,合约进程如果panic,栈信息会自动输出到合约产生的log中去。
  6. 在安装CPP智能合约时,要求共识节点、非共识节点必须安装GCC。
  7. TinyGo对wasm的支持不太完善,对内存逃逸分析、GC等方面有不足之处,比较容易造成栈溢出。在开发合约时,应尽可能减少循环、内存申请等业务逻辑,使变量的栈内存地址在64K以内,要求tinygo version >= 0.17.0,推荐使用0.17.0。
  8. TinyGo对导入的包支持有限,请参考:https://tinygo.org/lang-support/stdlib/,对列表中显示已支持的包,实际测试发现支持的并不完整,会发生一些错误,需要在实际开发过程中进行测试检验。
  9. 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】

1.6. 合约和用户地址

计算方式

在区块链上,通常会有一个地址,作为用户或者合约在链上的唯一标识符。为了保证地址的唯一性,地址一般由哈希计算得到。一般来说,用户的地址根据公钥计算得到,而智能合约的地址由区块链自动生成。

在ChainMaker上,用户地址也是根据用户的公钥计算得到的,但合约地址,可以由链自动生成,也可以根据用户的合约名计算得到。且对于合约来说,ChainMaker支持合约名与合约地址两种方式调用。对于任意类型的合约,包括evm、wasmer、wxvm等等,ChainMaker部署合约时,都会将用户提供的合约名计算为合约地址,并在合约部署成功后将合地址放入contract对象内返回,用户反序列化contract对象就得到该合约的地址。

对于ChainMaker来说,当前支持以下三种地址类型:

  • CHAINMAKER 此地址格式为20字节数组,但一般会将其转换为可展示的16进制字符串,转换后长度为40字节,例如:ce244336a16f64c5b6b27feae28a5ebd270be8ee。CHAINMAKER对于公钥模式的用户来说,由于计算SKI稍显复杂,现已不推荐使用。
    • 用户地址——根据用户的SKI(SubjectKeyId)计算keccak256哈希,然后截取哈希值的后20字节,对外展示时,会再转换为十六进制字符串形式;
    • 合约地址——根据合约名计算keccak256哈希,然后截取哈希值的后20字节,对外展示时,会再转换为十六进制字符串形式。
  • ZXL 此地址类型,为至信链业务专用,不建议对外使用。ZXL的地址为20字节数组,转换为可展示的16进制字符串后,还会加一个字符串”ZX“作为前缀,长度变成了42字节,例如:ZXd37af1a7fc2076a03184de539d5be976bd5c0688
    • 用户地址——对用户的公钥序列化后,计算sm3哈希,然后截取哈希值的前20字节,对外展示时,会再转换为十六进制字符串形式,并添加”ZX“前缀;
    • 合约地址——根据合约名计算sm3哈希,然后截取哈希值的前20字节,对外展示时,会再转换为十六进制字符串形式,并添加”ZX“前缀。

    ZXL与CHAINMAKER的主要区别是哈希算法不同,ZXL是sm3,CHAINMAKER是keccak256,另外,对于用户地址来说,计算所用的参数也不同,ZXL为序列化后的公钥,而CHAINMAKER为SKI,除此之外ZXL地址有”ZX前缀“。

  • ETHEREUM 此地址格式也是20字节数组,转换为可展示的16进制字符串后,一般会加一个”0x“前缀,长度也变成了42字节,例如:0x7cf146966856b4899b4f25f169d81176d0942050,但”0x“前缀非必须,可加可不加。
    • 用户地址——对用户公钥序列化后,计算keccak256哈希,然后截取哈希值的后20字节,对外展示时,会再转换为十六进制字符串形式;
    • 合约地址——根据合约名计算keccak256哈希,然后截取哈希值的后20字节,对外展示时,会再转换为十六进制字符串形式。

    ETHEREUM与CHAINMAKER非常相似,尤其对于合约地址,两者的参数和哈希算法都是相同的。但对于用户地址稍有不同,主要是地址的计算参数,ETHEREUM是序列化后的公钥,而CHAINMAKER为SKI,哈希算法仍然是相同的。 ETHEREUM地址类型的优点是兼容以太坊地址类型,而且,也是ChainMaker的默认地址类型。

配置

在ChainMaker内,地址类型可以通过配置文件chainconfig/bc.yml内的addr_type字段指定,配置为0,是CHAINMAKER类型,1为ZXL类型,2为EHEREUM类型,默认配置类型为2,如下所示。

chainconfig/bc.yml配置地址类型的片段

......
# 虚拟机配置
vm:
  addr_type: 2 #0:chainmaker, 1:zxl, 2:ethereum
  # 虚拟机支持列表
  support_list:
......

计算接口

对于地址的计算,ChainMaker为开发者提供了统一的计算接口,这些接口统一放在了utils模块下的address.go原文件内(gitlab链接:https://git.chainmaker.org.cn/chainmaker/utils/-/blob/master/address.go),开发者可通过导入该模块,并调用对应的接口计算地址,以保证接口计算的一致性。以下表格为地址计算接口展示。

相关文章

学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习...
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面...
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生...
Can’t connect to local MySQL server through socket \'/v...
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 ...
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服...