2.星火链开发入门(必读)
本节厘清几个星火链开发必须知道的入门概念和工具。
2.1 名词解释
星火令XHT
星火令是星火链的基础单位, 在星火链上发起的交易需要耗费星火令, 星火链上账户必须持有一定的星火令才能使用星火链功能。 星火令单位转换关系:
星火链智能合约
智能合约指的是部署在区块链上通过交易触发, 自动执行的代码逻辑,开发者能够利用星火链支持的编程语言,开发一个商业级别的智能合约。
目前星火链支持javascript
, solidity
两种语言的智能合约。solidity
合约的性能更佳,推荐使用solidity智能合约。
星火链SDK
星火链提供了基于多种语言的SDK Github链接, 用来方便开发者程序与链上交互。
SDK提供功能包括:
创建账户
查询指定账户的信息
查询交易信息
部署合约
调用合约
查询合约
区块链浏览器
区块链浏览器提供了对账户, 交易, 合约的查询和跟踪等功能, 可以节省开发者的大量时间和精力。 目前星火链体验网的浏览器地址为:
星火链RPC地址
主网: 尚未对外
2.2 开发基础
做星火链应用开发前, 需要了解下星火链的帐号, 交易和费用等基础机制。
帐号
也称账户,分为外部账户和合约账户。
外部账户是星火链的主体,是对现实社会中法人或自然人一种的映射。外部帐号的实质为通过非对称加密技术保护的一对公私钥, 拥有外部账户的用户可以使用其私钥对交易进行签名,并通过发送签名的交易来管理账户。
合约账号是由智能合约代码控制的账号,没有对应的公私钥,通过发送交易到合约账户,可以调用智能合约的函数或触发合约中的其他逻辑。
每个星火链帐号都会有以下几个属性
address
账户地址, 外部账户实质为公钥的编码转化的字符串,合约账户为按照一定规则生成的字符串。
nonce
每个账户从0开始的计数, 代表该账户发起的交易数量, 同时用来防止签名重放攻击。 当账号执行一笔交易入链后,无论交易成功还是失败, 账号的
nonce
就会加1。当使用账号发起交易时,需要指定该交易
nonce
,其值必须比当前账号的nonce
大1, 当一个账号被新建时,它的nonce
为0,关于nonce
使用可参照星火链进阶进阶使用-2.如何保障账号交易异步上链章节。contract
合约账户特有,外部账户没有该字段,可以标明一个帐户是否是智能合约帐户。
balance
账户余额, 注意:每个账户至少要保留
0.1XHT
余额。
交易 transaction
交易广义的定义,它是一个对账号进行一系列操作的组合。
星火链上的交易包含的主要元素如下:
sourceAddress
交易发出地址, 由该地址来支付本次交易耗费的星火令。
nonce
交易序号, 同一个
sourceAddress
下的所有交易必须具有唯一的nonce
序号, 并且交易只能按照nonce
从小到大按序入链, 中间不能有空。fee_limit
该交易的费用上限, 防止因为不可预知原因或者bug,导致交易耗费过多超出预期。
gas_price
交易的
gas
价格, 详细参见下节。operation
操作是交易中附带的具体动作,改变账号的原子单位。星火链支持多种不同类型的操作,一个交易,必定是包含了1个或多个操作。
交易的基本结构
{
"source_address":"xxxxxxxxxxx",//交易源账号,即交易的发起方
"nonce":2, //nonce值
"fee_limit" : 1000000, //愿为交易花费的手续费
"gas_price": 100,//gas价格,填默认的100即可
"ceil_ledger_seq": 100, //可选,区块高度限制, 如果大于0,则交易只有在该区块高度之前(包括该高度)才有效
"metadata":"0123456789abcdef", //可选,用户自定义给交易的备注,16进制格式
"operations":[
{
//根据不同的操作填写
},
{
//根据不同的操作填写
}
......
]
}
交易操作 operation
创建账号操作
账号为交易的主体,所有的交易必须通过账号发起执行。因此,在执行其他操作之前必须首先创建账号。创建账号操作由其他已存在的账号申请执行。第一个账号是在星火链启动时内置生成的,也被成为创世账号。
设置metadatas操作
metadatas
每个账户都有一个matadatas字段,是一个键值对数据库,可以存储额外的账户信息。
设置签名权重操作
设置账户拥有者和签名者在源账号下的权重。具体可以参见星火链进阶进阶使用-3.如何进行账号权限托管章节。
设置门限操作
设置源账号下各项操作的门限,如果交易中某项操作的权重没有达到该操作的门限值,该操作将被拒绝。具体可以参见星火链进阶进阶使用-3.如何进行账号权限托管章节。
调用合约操作
调用智能合约操作。
交易费用
为防止链上出现大量无效的交易,提高交易的上链成本,星火链设计为用户发送交易请求必须支付相应的星火令作为交易费用。具体见下节。
交易耗费计算和检查
星火链上的所有交易都需要耗费星火令, 耗费的计算公式为gas * gas_price
,单位为星火萤(glowstone
)。
名词解释:
gas
gas用来表示单个交易的计算成本, 对于javascript
合约, 每种交易类型的gas
耗费固定, 对于solidity
合约, 交易gas
耗费是实际执行的各个op(操作码)的gas
耗费之和。gas_price
gas_price
指用户愿意为每单位gas
支付的XHT
数量, 默认填100即可。 星火链上每个区块的交易打包时, 会根据gas_price
排序,gas_price
越高的交易会排在前面优先执行。 同时每笔交易在打包前, 会检查下账户费用是否满足以下条件:账户balance - 账户最低reserve_balance > fee_limit
账户balance - 账户最低reserve_balance > gas * gas_price
星火链上一笔交易星火令的扣除分为如下几个部分:
(操作的固定gas + 交易的字节花费的gas + 合约指令花费的gas) * gasprice
其中创建合约和升级合约的固定
gas = 1000000
, 其他操作的固定gas = 0
交易字节花费的
gas = 交易字节数 * 1 星火萤(glowstone)
Js
合约指令花费的gas
为0,solidity
指令花费的gas
和以太坊一致
注意:
对于javascript合约, 系统会提前根据交易类型计算需要gas, 如果账户余额不足, 交易提交失败不予入链。
交易哈希
交易上链后链上会计算一个交易的哈希值作为交易的唯一索引返回,交易上链结果需等交易打包区块后通过该交易哈希调用SDK交易查询接口确认。
签名信息
签名是指通过算法和私钥对交易数据进行加密确认并得到签名数据的过程。用户可以通过签名数据判断交易数据的完整性和正确性。
交易缓存队列
区块链网络内任意一个节点收到一笔交易请求后,首先会对交易进行合法性检查。如果检查合法,则将此交易请求广播给其他节点,并将此请求加入到交易缓存队列中。注意事项:
交易池中存在一笔完全相同的交易(交易
hash
)一致,则直接插入失败。某个源账户发的交易,
nonce
相同,其它参数存在差异(计算出的tx hash不同),则会比较两笔交易的gasprice
,如果B>=1.1A
,则用B交易替换A交易;如果B < 1.1A
,则提示Drop the transaction to...
如果提交到交易池的交易的nonce出现不连续,则交易不会被处理,直到超时丢弃为止。目前星火链默认交易池处理超时时间为
10
分钟,超时则丢弃所有超时交易,需重新发起交易。
交易的打包
系统依靠定时器每1s
发起一轮共识来打包用于生成新区块的交易。打包时,从交易缓存队列的头部开始有序抓取交易池的交易进行打包,星火链单笔交易最大1M, 一个区块最大容量为16M。
交易出块时间
星火链的出块时间会动态调整,一般情况下有交易时3秒
内,空块时1分钟
,遇到共识或者网络波动的情况下出块时间可能会稍微延长。
交易事务处理
同一笔交易中的多个操作,要么同时成功,要么同时失败,这被称为交易的原子性或者事务性。
交易事件tlog
tlog
是星火链JS虚拟机(JSVM
)日志基础设施提供的一个便利接口,提供的一种链内链外沟通的机制。类似于以太坊EVM
虚拟机中的Event
。
当合约调用tlog
时,会触发参数存储到交易的日志中,通过触发事件智能合约可以通知链外组件某个交易动作是否触发完成。
2.3 交易流程
组装交易对象
根据意愿组装交易对象Transaction
, 不同操作的交易有不同的数据结构。
序列化交易
很多地方都要用到序列化的功能。比如我们要对一笔交易签名,其实我们只能对字节串签名,这时就需要将交易序列化为字节串;还有我们需要存储交易,也需要序列化为字节流才能存储。我们选择了Google
的Protocol Buffer 3
协议进行序列化。由此我们的所有数据结构的定义都是用Protocol Bbuffer 3
定义的。Protocol Buffer 3
的优点是速度快,占用空间小,有多种语言支持。我们统一用SerializeAsString
表示对一个protocol buffer
对象的序列化操作。
签名交易
用私钥PrivateKey
对序列化后的交易transaction_blob
签名得到sign_data
。
提交交易
向星火链发送交易请求,触发交易的执行。
查询交易是否执行成功
用SDK 通过唯一的交易哈希查询交易状态以及交易回执。