账本
账本、事实和状态
账本储存的其实并不是业务对象本身,而是与业务对象相关的事实信息。
与业务对象当前状态相关的事实可能会发生改变,但是与之相关的事实历史是不可变的。
账本
账本由“世界状态“和”区块链“这两部分组成,它们彼此不同但却相互关联。
世界状态是一个数据库,它存储了一组账本状态的当前值。
通过世界状态,程序可以直接访问一个账本状态的当前值,不需要遍历整个交易日志来计算当前值。
区块链是交易日志,它记录了促成当前世界状态的所有改变。
世界状态 W 由区块链 B 决定。
Fabric 网络维护着一个账本的多个副本,这些副本通过名为共识的过程来与其他副本保持一致。分布式账本技术(DLT)
世界状态
世界状态将业务对象属性的当前值保存为唯一的账本状态。
世界状态包含两个状态。第一个状态是: key=CAR1 和 value=Audi。第二个状态中有一个更复杂的值:key=CAR2 和 value={model:BMW, color=red, owner=Jane} 。
账本状态记录了一组与特定业务对象有关的事实。我们的示例展示的是 CAR1 和 CAR2 这两辆车的账本状态,二者都各有一个值和一个键。
世界状态被作为数据库来实现。
(所有被提交的交易,无论有效与否,都会被收进区块链)。
关键设计在于,只有那些受到相关背书组织签名的交易才会更新世界状态。
首次创建账本时,世界状态是空的。
个人理解:这个世界状态相当于比特币中的UTXO。
区块链
世界状态存储了与业务对象当前状态相关的事实信息,而区块链是一种历史记录,它记录了这些业务对象是如何到达各自当前状态的相关事实。
区块链记录了每个账本状态之前的所有版本以及状态是如何被更改的。
区块排序以及区块内的交易排序,这一机制是在 Hyperledger Fabric 的排序服务组件首次创建区块时被建立起来的。
区块链总是以文件实现,而与之相反的是,世界状态以数据库实现。
区块链 B 包含了 B0、B1、B2、B3这四个区块。B0 是该区块链的第一个区块,也叫创世区块。
创世区块包含了一个配置交易,该交易含有网络配置(未显示)的初始状态。
区块
区块结构:
区块头
包含三个字段,这些字段是在创建一个区块时候被写入的。
- 区块编号:编号从0(初始区块)开始,每在区块链上增加一个新区块,编号的数字都会加1。
- 当前区块的哈希值:当前区块中包含的所有交易的哈希值。
- 前一个区块头的哈希值:区块链中前一个区块头的哈希值。
区块数据:包含了一个有序的交易列表。区块数据是在排序服务创建区块时被写入的。
区块元数据:包含了区块被写入的时间,还有区块写入者的证书、公钥以及签名。
交易
交易记录了世界状态发生的更新。
T4包括的内容如下:交易头 H4,一个交易签名 S4,一个交易提案 P4,一个交易响应 R4 和一系列背书 E4。
头
这部分用 H4 表示,它记录了关于交易的一些重要元数据,比如,相关链码的名字以及版本。
签名
这部分用 S4 表示,它包含了一个由客户端应用程序创建的加密签名。该字段是用来检查交易细节是否未经篡改,因为交易签名的生成需要用到应用程序的私钥。
提案
这部分用 P4 表示,它负责对应用程序供给智能合约的输入参数进行编码,随后该智能合约生成提案账本更新。在智能合约运行时,这个提案提供了一套输入参数,这些参数同当前的世界状态一起决定了新的账本世界状态。
响应
这部分用 R4 表示,它是以读写集 (RW-set)的形式记录下世界状态之前和之后的值。交易响应是智能合约的输出,如果交易验证成功,那么该交易会被应用到账本上,从而更新世界状态。
背书
就像 E4 显示的那样,它指的是一组签名交易响应,这些签名都来自背书策略规定的相关组织,并且这些组织的数量必须满足背书策略的要求。
世界状态数据库的选择
世界状态是以数据库的形式实现的,旨在提供简单有效的账本状态存储和检索。
世界状态数据库的选项包括 LevelDB 和 CouchDB 。
LevelDB 是世界状态数据库的默认选项,当账本状态是简单的键值对时,使用 LevelDB 非常合适。
当账本状态结构为 JSON 文档时,以 CouchDB 来实现世界状态非常合适,这是因为业务交易涉及的数据类型通常十分丰富,而 CouchDB 可支持对这些数据类型进行各种形式的查询和更新。
在实现方面,CouchDB 是在单独的操作系统进程中运行的,但是节点和 CouchDB 实例之间仍然存在1:1的关系。
命名空间
每个链码都有自己的世界状态,并且与所有其他链码的世界状态分离。
世界状态位于一个命名空间中,因此只有位于同一链码中的智能合约才能访问一个给定的命名空间。
区块链没有命名空间。它包含来自许多不同智能合约命名空间的交易。
通道
每个通道都有一个完全独立的账本。这意味着完全独立的区块链和完全独立的世界状态,包括命名空间。