译者声明:本文内容为翻译ZILLIQA英文版白皮书,个人阐述均有注明。个人水平有限,如有错误,请不吝指正,谢谢!
第四部分 数据层
从广义上讲,数据层定义了构成ZILLIQA全局状态的数据。 通过扩展,它还定义了ZILLIQA中不同实体对象更新其全局状态所需的数据。
A. 账户、地址、状态
与以太坊一样,Zilliqa是一个基于帐户的系统。它的账户有两个类型:普通账户和合约账户。普通帐号是通过生成EC-Schnorr私钥来创建的,合约账户则是由其他账户生成的。
每个帐户都由一个地址标识,该地址根据其类型而有所不同。普通帐户的地址来源于帐户的私钥。假设一个私钥为sk,它对应的地址Anormal是一个160位的值,其计算公式是:
Anormal = LSB160(SHA3-256(PubKey(sk))),
其中,PubKey()函数 的参数是私钥sk,其返回的结果是公钥,此结果再作为参数进行SHA3-256计算,得到的哈希值再作为参数传给LSB160()计算,得到一个160位的值。合约帐户的地址是根据其创建者的地址和创建者帐户发送的交易数量计算的,即帐户nonce(如下所述)。
Acontract = LSB160(SHA3-256(address||nonce)),
上式中,address为创建者账户地址,nonce为创建者的nonce值。
不论是合约还是普通账户,都与一个帐户状态相关联。帐户状态是键值存储,包含以下键:
1. 账户nonce
Nonce 是一个64位的计数器,如果是普通帐户,它表示发送的交易数。如果是合约账户,它表示的是创建合约的数量。
2. 余额
余额是一个128位的非负数。当账户接收到其他账户发送过来的token后,余额就要增加接收的数目,如果是转出token给其他账户,余额就要减去转出的数量。
3. 代码哈希
这存储了合同代码的SHA3-256值,对于普通帐户,它是空字符串的SHA3-256值。
4. 存储根
每个帐户都有一个存储,它也是一个具有256位的键和256位的值的密钥值存储。存储根是表示此存储的SHA3-256哈希值。 例如,如果存储是树,则存储根是树根的哈希值。
ZILLIQA的全局状态是帐户地址和帐户状态之间的映射。 它使用类似于数据结构中的树的实现。
B. 交易
交易始终由普通帐户发起,并且它会更新ZILLIQA的全局状态。 每个交易都具有以下字段(这里的字段可能是代码中结构体的组成字段,故不翻译):
- version (32位) : 当前版本号
- nonce(64位) :交易的发送方发送的交易数
- to (160位) :交易的目标地址。如果该交易是生成一个新合约,那这个字段就是一个空字符串的SHA3-256哈希值的右边160位(低160位)。
- amount(128位) :交易的金额
- gas price(128位) : Gas被定义为计算的最小单位。Gas price 是发送方,为交易处理中产生的每一步计算,愿意支付的金额
- gas limit(128位) :本次交易花费的gas数量的上限
- code(不限大小) :一个可扩展的字节数组,特指合约代码。 它只存在于创建一个新的合约帐户的交易中。
- data(不限大小) : 一个可扩展的字节数组,特指处理交易的数据。仅当交易的目标地址调用合约时才存在。
- pubkey(264位) : EC-Schnorr公钥,用来验证签名的,也可以确定交易的发送地址。
- signature(512位):EC-Schnorr签名,在整个数据上的签名。
每个交易由交易ID唯一标识,此ID是交易数据的SHA3-256哈希值(不包括签名字段)。
c. 区块
ZILLIQA协议引入了两种类型的块(从而引入了两种区块链):交易块(TX-Block)和目录服务块(DS-Block)。 TX-Block包含用户发送的交易,而DS-Block包含有关参与共识协议的矿工的元数据。
1. 目录服务块(DS-Block,本译文中后面用DS块来表示)
一个DS块包含两个部分:区块头和签名。其区块头有如下字段:
- version(32位) : 当前版本号
- previous hash(256位):父块(前面一个区块)的SHA3-256哈希值
- pubkey(264位) : 在此区块头中完成了工作量证明的矿工的公钥
- difficulty(64位) : 由父块的难度和编号(这个编号我不确定是指谁的,但也无所谓)计算得出。它存储PoW难题的难度。
- number(256位) : 祖先块的数量。创世块的块号为0。
- timestamp(64位) : 创建此区块的Unix时间
- mixHash(256位) : 根据nonce计算的摘要,允许检测DoS攻击。
- nonce(64位的) : 工作量证明的计算结果
DS块的另一个部分——签名,包括两个部分:
- signature(512位) : 是DS节点对DS块头部的多重签名,基于EC-Schnorr。
- bitmap(1024位) : 它记录哪些DS节点参与了多重签名。我们用位数组B来表示bitmap, 当第i个节点在头部签名时,B[i]=1, 否则B[i]=0。
DS块来自于DS区块链。
2. 交易块(本译文中后面用TX块来表示)
之前提到过,DS块包含有关在交易上达成共识的DS节点的信息。TX块存储由DS节点达成共识的交易的信息。每个DS块都对应多个TX块。一个TX块包含头部、数据和签名三部分。
头部包含如下字段:
- type (8 bits): TX块有两种类型:微块(micro block, 值为0x00)和最终块(final block, 值为0x01)。详情会在第5部分D小节中介绍。
- version (32 bits): 当前版本号
- previous hash (256 bits): 父块的SHA3-256哈希值
- gas limit (128 bits) : 当前每个区块花费的gas的上限
- gas used (128 bits) : 此区块中所有交易所花费的gas总额
- number (256 bits) : 祖先块的数量。创世块的块号为0。
- timestamp (64 bits) : 此区块创建时的unix时间
- state root (256 bits) : 此区块所有的交易完成并确认之后,全局状态的SHA3-256 hash值。如果全局状态是以树的形式 存储,那么sate root就是树根的hash值。
- transaction root (256 bits): 此区块中所有交易的Merkle树根的哈希值
- tx hashes (each 256 bits) : 交易的哈希列表,交易的签名部分也被包括并计算。(译者注:这里应该是每一个包含了签名的完整交易数据的哈希值,这里是一个列表,与上面的transaction root代表一个整体不同)
- pubkey (264 bits) : 提出计划的领导者的EC-Schnorr公钥
- pubkey micro blocks (unlimited): 这是一个EC-Schnorr公钥的列表,每一项长264位,为每个交易的发起者的公钥。只有最终块才存在此字段
- parent block hash (256 bits) : 前一个最终块区块头部的哈希值
- parent ds hash (256 bits) : 前一个DS块的区块头的哈希值
- parent ds block number (256 bits): 前一个DS区块的编号
TX块的数据部分包含一系列的交易,它有如下字段:
- tx count (32 bits): 此区块的交易的总数量
- tx list (unlimited): 交易列表
TX块的签名部分,包含一个基于EC- Schnorr的多重签名,它主要包含两个字段:
- signature (512 bits): TX块的区块头中,一组节点的多重签名。签名由不同的节点集产生,取决于它是微块还是最终块。 关于签名的详情,会在本文后面的第五部分D单元阐述。
- bitmap (1024 bits): 它记录了哪些节点参与了多重签名。我们用数组B来表示bitmap, 如果第i个节点签名了,那么B[i]=1, 否则B[i]=0
最终块来自与交易区块链,交易链不包括微块。
------------------------------------------------------------------------------------完------------------------------------------------------------------------------------------------