Hyperledger Fabric 文档

2.2 Hyperledger Fabric - 核心概念 -

2019-12-05  本文已影响0人  furnace

核心概念 - 账本 (Ledger)

帐本是 Hyperledger Fabric 中的关键概念。它存储有关业务对象的重要事实信息;对象属性的当前值,以及导致这些当前值的交易历史。

在本主题中,我们将介绍:

1. 什么是帐本?

帐本包含业务的当前状态作为交易日志。最早的欧洲和中国帐本可追溯到大约 1000 年前,而苏美尔人则在 4000 年前就有石头帐本 - 但让我们从一个更新的例子开始吧!

你可能习惯于查看自己的银行帐户。对你而言,最重要的是可用余额 - 它是你当前及时的支出能力。如果要查看余额的产生方式,则可以查看确定余额的交易贷方和借方。这是一个账本的活生生的例子 - 一个状态 (你的银行存款余额),以及一组确定其状态的有序交易 (贷方和借方)。 Hyperledger Fabric 是由这两个相同的组件构成 - 提供一套账本状态的当前值,并捕获确定这些状态的交易历史。

2. 帐本,事实和状态

帐本实际上不存储业务对象,而是存储有关这些对象的事实。当我们说“我们将业务对象存储在帐本中”时,我们的真正意思是我们正在记录有关对象当前状态的事实以及导致当前状态的交易历史的事实。在日益数字化的世界中,感觉就像我们在看一个对象,而不是关于对象的事实。对于数字对象,它可能存在于外部数据存储中;我们存储在帐本中的事实使我们能够识别其位置以及有关他的其他关键信息。

尽管有关业务对象当前状态的事实可能会发生变化,但是有关它的事实历史是不可变的,可以对其进行添加,但不能进行追溯更改。我们将看到如何将区块链视为关于业务对象事实的不变历史,这是一种简单而有效的理解方式。

现在,让我们仔细看一下 Hyperledger Fabric 帐本结构!

3. 帐本

在 Hyperledger Fabric 中,账本由两个不同但相关的部分组成 - 世界状态和区块链。这些中的每一个都代表有关一组业务对象的一组事实。

首先,有一个世界状态 - 一个数据库,其中存储了一组帐本状态的当前值的缓存。世界状态使程序可以轻松地直接访问状态的当前值,而不必通过遍历整个交易日志来计算状态值。默认情况下,帐本状态表示为键值对,稍后我们将看到 Hyperledger Fabric 如何在这方面提供灵活性。世界状态可以频繁更改,因为可以创建,更新和删除状态。

其次,有一个区块链 – 交易日志,记录了导致当前世界状态的所有更改。交易收集在附加到区块链的区块内部,使你能够了解导致当前世界状态变化的历史。区块链数据结构与世界状态非常不同,因为一旦写入,就无法修改;这是一成不变的。

image

账本 L 由区块链 B 和世界状态 W 组成,其中区块链 B 确定世界状态 W。我们也可以说世界状态 W 源自区块链 B。

最好在 Hyperledger Fabric 网络中考虑一个逻辑帐本。实际上,网络维护一个帐本的多个副本 – 通过称为共识的过程,它们与其他所有副本保持一致。术语“分布式账本技术” (Distributed Ledger Technology, DLT) 通常与这种帐本相关联 - 这种帐本在逻辑上是单一的,但是在整个网络中分布有许多一致的副本。

现在,让我们更详细地研究世界状态和区块链数据结构。

4. 世界状态

世界状态将业务对象属性的当前值保留为唯一的帐本状态。这很有用,因为程序通常需要对象的当前值;遍历整个区块链来计算对象的当前值将很麻烦 - 你只需直接从世界状态中获取即可。

image

包含两个状态的帐本世界状态。第一种状态是:key = CAR1 和 value = Audi。第二个状态具有更复杂的值:key = CAR2 和 value = {model:BMW,color = red,owner = Jane}。两种状态的版本均为 0。

帐本状态记录有关特定业务对象的一组事实。我们的示例显示了两个汽车 CAR1 和 CAR2 的帐本状态,每个汽车都有一个键和一个值。应用程序可以调用智能合约,该合约使用简单的帐本 API 来获取,放置和删除状态。注意状态值可以简单 (Audi…) 或复杂 (类型:BMW…)。通常会查询世界状态来检索具有某些属性的对象,例如查找所有红色宝马。

世界状态被实现为数据库。这很有意义,因为数据库为状态的有效存储和检索提供了一组丰富的运算符。稍后我们将看到 Hyperledger Fabric 可以配置为使用不同的世界状态数据库来满足不同类型的状态值和应用程序所需的访问模式的需求,例如在复杂的查询中。

应用程序提交捕获世界状态变化的交易,这些交易最终被提交到账本区块链。 Hyperledger Fabric SDK 将应用程序与该共识机制的细节隔离开来。它们仅调用智能合约,并在交易已包含在区块链中时 (无论有效还是无效) 得到通知。关键设计要点是,只有由所需的一组背书组织签名的交易才会导致对世界状态的更新。如果交易没有得到足够的背书人的签名,则不会导致世界状态的改变。你可以阅读有关应用程序如何使用 智能合约 以及如何 开发应用程序 的更多信息。

你还会注意到,一个状态有一个版本号,在上图中,状态 CAR1 和 CAR2 的起始版本为 0。Hyperledger Fabric 内部使用的版本号,每次状态更改时都会递增。每当状态更新时都会检查版本,以确保当前状态与背书时的版本匹配。这确保了世界状态正在按预期变化;没有并发更新。

最后,当首次创建帐本时,世界状态为空。因为任何代表世界状态有效改变的交易都记录在区块链上,这意味着可以随时从区块链重新生成世界状态。这可能非常方便 – 例如,创建对端节点时会自动生成世界状态。此外,如果对端节点异常失败,则可以在接受交易之前在对端节点重新启动时重新生成世界状态。

5. 区块链

现在,让我们将注意力从世界状态转移到区块链上。世界状态包含与一组业务对象的当前状态有关的一组事实,而区块链是有关这些对象如何到达其当前状态的事实的历史记录。区块链记录了每个帐本状态的每个先前版本以及更改方式。

区块链被构造为互连区块的顺序日志,其中每个区块包含一系列交易,每个交易代表对世界状态的查询或更新。交易排序的确切机制在 其他地方 讨论;重要的是,在首次由称为交易排序服务的 Hyperledger Fabric 组件创建区块时,便要建立区块排序以及区块内的交易排序。

每个区块头均包含该区块交易的哈希值,以及前一个区块头的哈希值。这样,账本上的所有交易都被排序并通过密码链接在一起。这种哈希和链接使帐本数据非常安全。即使托管账本的一个节点被篡改,它也无法说服所有其他节点其具有“正确的”区块链,因为账本分布在整个网络中的独立节点。

与使用数据库的世界状态相反,区块链始终被实现为文件。这是一个明智的设计选择,因为区块链数据结构严重偏向极少量的简单操作。追加到区块链的末尾是主要操作,而查询在当前是相对不频繁的操作。

让我们更详细地了解区块链的结构。

[图片上传失败...(image-5a8c3f-1575546721769)]

包含区块 B0,B1,B2,B3 的区块链 B。B0 是区块链中的第一个区块,即创世区块。

在上图中,我们可以看到区块 B2 的数据 D2 包含其所有交易:T5,T6,T7。

最重要的是,B2 具有一个区块头 H2,它包含 D2 中所有交易的加密哈希以及先前区块 B1 中的等效哈希。通过这种方式,区块彼此之间有着千丝万缕的联系,这就是术语“区块链”如此巧妙地捕捉到的!

最后,如你在图中看到的那样,区块链中的第一个区块称为创世块。尽管它不包含任何用户交易,但它是帐本的起点。相反,它包含一个配置交易,该交易包含网络通道的初始状态 (未显示)。当我们在文档中讨论区块链网络和 通道 时,我们将更详细地讨论创世区块。

6. 区块

让我们仔细看一下区块的结构。它包括三个部分。

6.1 区块头

本节包含三个字段,在创建区块时写入。

这些字段是通过对区块数据进行密码哈希处理而在内部派生的。他们确保每个区块都与其邻居密不可分,从而导致账本不可改变。

image

区块头详细信息。区块 B2 的头部 H2 由区块编号 2,当前区块数据 D2 的哈希 CH2,以及来自前一个区块,区块编号 1 的哈希 PH1 组成。

6.2 区块数据

本节包含按顺序排列的交易列表。在交易排序服务创建区块时写入。这些交易具有丰富但直接的结构,我们将在本主题的后面部分进行介绍。

6.3 区块元数据

此部分包含写入区块的时间,以及区块写入者的证书,公钥和签名。随后,区块提交者还为每个交易添加有效/无效指示符,然而此信息不包括在哈希中,因为创建区块时会创建该信息。

7. 交易

如我们所见,交易捕获了世界状态的变化。让我们看一下详细的阿悄块数据结构,该结构在一个区块中包含交易。

image

交易明细。区块 B1 的区块数据 D1 中的交易 T4 由交易头 H4,交易签名 S4,交易提案 P4,交易提案响应 R4 和背书列表 E4 组成。

在上面的示例中,我们可以看到以下字段:

总结了交易的主要字段 – 还有其他字段,但是你必须了解这些必不可少的字段,才能对账本数据结构有深入的了解。

8. 世界状态数据库选项

世界状态从物理上实现为数据库,以提供简单有效的存储和账本状态检索。如我们所见,帐本状态可以具有简单值或复合值,并且为了适应这种情况,世界状态数据库的实现方式可能会有所不同,从而可以有效地实现这些值。世界状态数据库的选项当前包括 LevelDB 和 CouchDB。

LevelDB 是默认值,当帐本状态是简单的键/值对时尤其适用。 LevelDB 数据库与网络节点紧密位于同一位置 – 嵌入在同一操作系统进程中。

当帐本状态被构造为 JSON 文档时,CouchDB 是一个特别合适的选择,因为 CouchDB 支持丰富的查询和更新业务交易中经常发现的更丰富的数据类型。在实现方面,CouchDB 在单独的操作系统进程中运行,但是对端节点和 CouchDB 实例之间仍然存在 1:1 的关系。所有这些对于智能合约都是看不见的。有关 CouchDB 的更多信息,请参见 CouchDB as the StateDatabase

在 LevelDB 和 CouchDB 中,我们看到了 Hyperledger Fabric 的一个重要方面 – 它是可插入的。世界状态数据库可以是关系数据存储,图形存储或时间数据库。这为可以有效访问的帐本状态类型提供了极大的灵活性,从而使 Hyperledger Fabric 可以解决许多不同类型的问题。

9. 帐本示例:fabcar

当我们结束帐本主题时,让我们看一个示例帐本。如果你运行了 fabcar 示例应用程序,那么你已经创建了此帐本。

fabcar 示例应用程序创建了一组 10 辆汽车,每辆汽车具有唯一的标识;不同的颜色 (color),品牌 (make),型号 (model) 和所有者 (owner)。创建前四辆汽车后,帐本如下所示。

[图片上传失败...(image-2f4c81-1575546721769)]

账本 L 包含一个世界状态 W 和一个区块链 B。W 包含四个具有键的状态:CAR1,CAR2,CAR3 和 CAR4。 B 包含两个区块 0 和 1。区块 1 包含四个交易:T1,T2,T3,T4。

我们可以看到世界状态包含对应于 CAR0,CAR1,CAR2 和 CAR3 的状态。 CAR0 的值表示它是 Tomomo 目前拥有的蓝色 Toyota Prius,我们可以看到其他汽车的相似状态和值。此外,我们可以看到所有汽车状态均为版本号 0,表明这是它们的起始版本号 - 自创建以来尚未对其进行更新。

我们还可以看到,区块链包含两个区块。区块 0 是创世区块,尽管它不包含任何与汽车相关的交易。但是,区块 1 包含交易 T1,T2,T3,T4,这些交易对应于在世界状态下为 CAR0 到 CAR3 创建初始状态的交易。我们可以看到区块 1 链接到区块 0。

我们没有显示区块或交易中的其他字段,特别是区块头和哈希。如果你对这些信息的确切细节感兴趣,可以在文档的其他地方找到专用的参考主题。它为你提供了整个区块的完整可工作的示例,其中包含详细的交易细节 - 但到目前为止,你已经对 Hyperledger Fabric 帐本有了扎实的概念性理解。做得好!

10. 命名空间

即使我们已经将帐本呈现为一个单一的世界状态和单个区块链,但这还是有点过分简化了。实际上,每个链码都有自己的世界状态,该世界状态与所有其他链码是分开的。世界状态位于命名空间中,因此只有相同链码内的智能合约才能访问给定的命名空间。

区块链未命名空间。它包含来自许多不同的智能合约命名空间的交易。你可以在 本主题 中阅读有关链码命名空间的更多信息。

现在让我们看看如何在 Hyperledger Fabric 通道中应用命名空间的概念。

11. 通道

在 Hyperledger Fabric 中,每个 通道 都有一个完全独立的帐本。这意味着完全独立的区块链,以及完全独立的世界状态,包括命名空间。应用程序和智能合约可以在通道之间进行通信,以便可以在它们之间访问帐本信息。

你可以在 本主题 中阅读有关帐本如何与通道一起使用的更多信息。

12. 更多信息

请参阅 交易流读写集语义CouchDB as the StateDatabase 主题,以更深入地了交易务流,并发控制和世界状态数据库。

Reference

项目源代码

项目源代码会逐步上传到 Github,地址为 https://github.com/windstamp

Contributor

  1. Windstamp, https://github.com/windstamp
上一篇下一篇

猜你喜欢

热点阅读