LOADING...
LOADING...
LOADING...
当前位置: 玩币族首页 > 币圈百科 > 卡尔达诺共识层的抽象性质

卡尔达诺共识层的抽象性质

2020-06-05 wanbizu AI 来源:区块链网络

我想了解更多有关卡尔达诺项目的PoS?我们删除了Joselmo Cabral翻译的文章(最初由Edsko de Vries发表于2020年5月28日,由Joselmo Cabral翻译)。

IOHK工程师的这一系列新技术职位将考虑做出的选择


开发人员深潜

当我们前往Cardano的主要网络上的Shelley时,我们希望为您提供最新消息。我们还想强调幕后工作以及负责工程师的不懈工作。

在Developer Deep Dive偶尔发布的这一系列技术博客中,我们为IOHK工程师腾出了空间。在接下来的几个月中,我们的Haskell开发人员将提供Cardano平台和协议关键要素的开放视图,并分享已做出的选择的见解。

在本系列的第一个文章中,我们考虑在共识层中使用抽象。

介绍

卡尔达诺共识层具有两个重要职责:

它运行区块链共识协议。在区块链的背景下,共识(即“多数意见”)意味着参与区块链执行的每个人都同意唯一的真正链条。这意味着共识层负责采用区块,在竞争链(如果有)之间进行选择,以及决定何时生成自己的区块。 它负责维护做出这些决定的所有必要状态。为了决定是否采用一个块,协议需要根据分类账的状态对其进行验证。如果他决定切换到不同的链(链中不同的叉子),则他必须保留足够的历史记录以能够重建该链中的分类帐状态。为了能够产生区块,他必须维护一组要插入到那些区块中的事务存储器。

共识层在它下面的网络层之间进行中介,该层处理诸如通信协议和对等方选择之类的问题,在它上面的分类帐层之间指定分类帐状态如何以及如何使用每个新块更新该分类帐状态。 。分类帐层是完全无状态的,并且仅由纯功能组成。反过来,共识层不需要知道账本状态的确切性质,甚至不需要知道块的内容(除了执行共识协议所需的一些标头字段之外)。

卡尔达诺共识层的重要细节

在共识层中广泛使用抽象。这很重要,原因如下:

它允许程序员在运行测试时注入故障。例如,我们提取基础文件系统,并用它来测试存储层并模拟各种磁盘故障。同样,我们对时间进行抽象,并使用它来查看当用户的系统时钟向前或向后跳动时节点发生的情况。 这使我们可以使用许多不同类型的分类账实例化共识层。我们当前使用它与Byron分类帐(当前位于Cardano区块链上的分类帐)以及下一个Shelley Haskell测试网络的Shelley分类帐一起运行共识层。另外,我们使用它来运行共识层,其中包含几种专门为测试而设计的分类帐,通常比“真实”分类帐简单得多,因此我们可以将测试重点放在共识层本身上。 它改善了组成,允许从较小的组件构建较大的组件。例如,Shelley的测试分类帐仅包含Shelley的分类帐,但是当Shelley发行时,实际链条将包含直到硬分叉为止的Byron的书和此后Shelley的书。这意味着我们需要一个分类账层,可以在特定点在两个分类账之间进行切换。除了定义新的分类帐,我们可以定义一个硬分叉组合器,该硬分叉组合器仅实现此功能,并且仅实现此功能。这样可以提高代码重用性(下一个硬分叉出现时,我们将无需重新实现硬分叉的功能)以及关注点分离:硬分叉组合器的开发和测试不依赖于它们之间分类账的具体情况。 与最后一点密切相关,使用抽象可以提高可测试性。我们可以定义组合器,这些组合器定义共识协议中的小变化,使我们可以专注于特定方面。例如,我们有一个合并器,它接受现有的共识协议,只替换检查是否应该产生一个块。然后,我们可以使用它来生成测试方案,在该方案中,许多节点在给定的插槽中产生一个块,或者相反,没有节点,并查看共识层在这些情况下是否做正确的事情。如果没有组合器来代替共识层的这一方面,那么在出现这种情况时将碰巧。尽管我们可以控制测试中的“机会”(通过为伪随机数生成器选择特定的初始种子),但无法配置特定的场景,甚至无法将失败的测试用例自动减少到最小测试用例。使用这些测试共识组合器,该测试实际上只能使用编程指定哪些节点应在哪些插槽中产生块。然后,我们可以随机生成这些计划,执行它们,如果有错误,则将它们减少到仍会触发该错误的最小测试用例。这样的最小故障时间表比最初的随机种子选择更容易调试,理解和使用,而最初的随机种子选择会在某时发生某事。

为了实现所有这些,共识层需要利用一些复杂的Haskell类型。在这篇博客中,我们将开发一个“迷你共识协议”,确切说明我们如何抽象各个方面以及如何利用这些抽象定义多个组合器。本博客文章的其余部分假定读者熟悉Haskell。

初步

卡尔达诺共识层旨在支持Ouroboros共识协议系列,所有这些都从根本上假设将时间划分为多个插槽,每个区块链最多可以有一个区块。在本文中,我们将插槽号定义为一个整数:


卡尔达诺共识层演示1

我们还需要一个最小的公钥加密模型,特别是


卡尔达诺2共识层演示

我们在此博客文章中唯一需要的语言扩展是TypeFamilies,尽管实际的实现使用了更多的语言。如果要继续学习,请下载完整的源代码。

共识协议

如本文开头所述,共识协议主要承担三项职责。

领导检查(我们应该出块吗?) 连锁选择 阻止验证

该协议旨在独立于具体的块选择以及分类账的具体选择,因此可以使用不同类型的块和/或寄存器执行单个协议。因此,这三个职责中的每一个都定义了自己对所需数据的“视图”。

领导检查

领导者检查在所有插槽上执行,并且必须确定节点是否应产生块。通常,检查领导者可能需要从分类账状态中提取一些信息:


卡尔达诺3共识层演示

例如,在最初将提供给Shelley的Ouroboros Praos共识协议中,节点将被选为领导者(即,使其产生一个区块)的可能性取决于您的参与;节点的股份当然来自账本状态。

连锁选择

“链选择”是指在两个竞争链之间进行选择的过程。这里的主要标准是链的长度,但是某些协议可能有其他要求。例如,块通常由服务器上的“热”键签名,而服务器上的“热”键又由任何网络设备上都不存在的“冷”键生成。当快捷键被盗用时,节点操作员可以从快捷键中生成一个新密钥,然后“委托”到该新密钥。因此,在长度相等的两个字符串之间进行选择时,它们的结尾均由相同的快捷键签名,但具有不同的快捷键,共识协议将首选最新的快捷键。为了允许特定的共识协议指示这样的要求,我们引入了一个SelectView,用于指定该协议期望在块中提供哪些信息:


卡尔达诺4共识层演示

标头验证

块验证主要是分类帐的关注点;分类账中定义了诸如检查交易中的所有条目是否可用以避免双重费用之类的检查。共识层没有意识到块内部的内容。实际上,它甚至可能不是加密货币,而是不同于区块链技术的应用程序。

块(更确切地说是块头)还包含一些专门用于支持共识层的内容。为了继续使用Praos的示例,Praos希望能够提供一些与区块链的熵推导有关的密码学证据。对这些进行验证是共识的责任,因此,我们定义了共识必须验证的字段的第三个也是最后一个视图:


卡尔达诺5共识层演示

协议定义

我们还需要一个类型族*:每个协议可能都需要执行静态信息;签名块的密钥,用于领导者验证的您自己的身份等。我们称之为“节点配置”,并将其定义为


卡尔达诺6共识层演示

现在,我们可以将所有内容统一到共识协议的抽象定义中。课堂上的三种方法分别对应于我们提到的三种职责。每个方法都接收静态节点配置以及该方法所需的特定视图。请注意,这里的p只是标识特定协议的类型级别标记;它从不存在于价值水平。


卡尔达诺7共识层演示

示例:宽松的BFT(PBFT)

允许的BFT是一种简单的共识协议,其中节点根据轮换时间表生成块:第一个节点A,然后是B,然后是C,然后返回到A。在此编程中,我们将节点的索引称为“ NodeId”。 ‘。这仅是PBFT的概念,并非共识层的其余部分需要注意的概念:


卡尔达诺8共识层演示

PBFT要求的节点配置是节点自身的身份以及日程中可能出现的所有节点的公钥:


卡尔达诺9共识层演示

由于PBFT是一个简单的轮换程序,因此不需要分类账中的任何信息:


卡尔达诺10共识层演示

链选择仅分析链的长度;为了简单起见,我们在这里假设较长的链以大量的插槽**结尾,因此选择链只需要知道尖端的插槽号即可:


卡尔达诺11共识层演示

最后,在验证块时,我们必须验证它们是否被任何有权产生块的节点签名(可以出现在计划中):


卡尔达诺12共识层演示

现在定义协议很简单:


卡尔达诺共识层演示13

链选择仅比较插槽编号;验证将验证密钥是否为允许的插槽前导之一,并且前导选择将执行一些模块化算法以确定是否是该节点的转弯。

请注意,循环时间表仅用于检查我们是否为领导者;对于历史数据块(即在进行验证时),我们仅检查该数据块是否由任何允许的领导者签名,而不检查顺序。这是PBFT的“允许”部分;实际的实现会进行额外的检查(没有一个领导者预订的份额超过您的份额),我们在此博客文章中将其省略。

协议组合器示例:明确的领导者计划

如引言中所述,对于测试,能够显式确定节点签名块的顺序非常有用。为此,我们可以定义一个协议组合器,该组合器接受一个协议,并简单地替换is-leader检查以检查固定时间表:


卡尔达诺共识层演示14

运行该协议所需的配置是调度以及该调度上的节点ID,以及基础协议所需的任何配置:


卡尔达诺共识层演示15

链条的选择保持不变,因此,对于链条选择所需的块也有以下看法:


卡尔达诺共识层演示16

但是,我们需要替换标头验证-实际上完全将其禁用-因为如果基础协议校验由于这些块是由正确的节点签名的,因此显然该验证与此替换不兼容。因此,我们不需要块中的任何东西来验证它(因为我们的确是没有验证):


卡尔达诺共识层演示17

现在定义协议很简单:


卡尔达诺共识第18层示范

链选择仅使用基础协议p的链选择,块验证不执行任何操作,而is-leader验证指的是静态编程。

从块到协议

像共识协议一样,特定的块选择也可以带有其自己必要的配置数据:


卡尔达诺共识层演示19

许多模块可以使用相同的协议,但是特定类型的模块是为特定类型的协议设计的。因此,我们提出了一系列将块类型映射到相关协议的类型:


卡尔达诺20共识层演示

如果我们可以在其特定协议要求的那个块上构建视图,那么我们说一个块支持其协议:


卡尔达诺共识层演示21

示例:拜伦块(简体)

残酷的是,拜伦区块链上的区块看起来像


示范22

上面我们提到,Ouroboros共识协议家族假定时间被划分为多个时隙。另外,他们还假设这些时隙被分组为历元。拜伦的块不包含绝对数字,而是当时的纪元数字和相对插槽号。拜伦链中每个季节的插槽数设置为刚好超过10 k,但是对于测试来说,能够更改k(安全参数)非常有用,因此可以配置;这是使用拜伦模块所需的配置(的一部分):


示范23

给定Byron的配置,可以很容易地将一对纪元号和一个相对时隙转换为绝对时隙号:


示范24

和协议?好吧,拜伦链运行PBFT,所以我们可以定义


示范25

容易证明Byron块支持此协议:


示范26

分类帐的状态

共识层不仅执行共识协议,而且还管理分类账的状态。但是,您不太关心分类帐状态的具体外观;相反,它仅假定某种分类帐状态与块类型相关联:


示范27

我们将需要其他类型的族。当将一个块应用于分类帐状态时,如果该块无效,我们会得到一个错误。分类帐错误的特定类型在分类帐层中定义,并且当然是高度特定的。例如,雪莱的分类帐将有与应用桩有关的错误,而拜伦的分类帐则不会,因为它不支持桩的应用。非加密货币分类帐将具有非常不同的错误类型。


示范28

现在,我们定义两种类型的类型。第一个仅描述分类帐层的接口,说我们应该能够将一个块应用于分类帐状态并获得错误(如果该块无效)或更新的分类帐状态:


示范29

其次,我们将定义一个类型类,该类型类将与一个块关联的分类帐连接到与该块关联的共识协议。正如BlockSupportsProtocol提供从共识协议所需的块派生视图的功能一样,LedgerSupportsProtocol同样提供从共识协议所需的分类账状态派生视图的功能:


示范30

我们将在下一部分中看到为什么将与分类帐(UpdateLedger)的集成与与共识协议(LedgerSupportsProtocol)的连接分开是有用的。

块组合器

作为组合器功能的最后一个示例,我们将展示我们可以定义一个块组合器及其关联的分类帐。作为一个有用的例子,Byron区块链附带了可执行的实现和规范。用这两本书实例化共识层很有用,这样我们就可以在整个过程中验证实现是否与规范一致。这意味着,这种“双分类帐”配置中的区块实际上是一对区块***。

示范31

双重分类帐状态和双重分类帐错误的定义类似:


示范32

要将双重块应用于双重分类帐的状态,我们只需将每个块应用于其关联状态。这个特定的组合器假设两个分类帐必须始终同意特定的块是否有效,这适合于比较实现和规范。其他选项(其他组合器)也是可能的:


示范33

由于双重分类帐的目的是比较分类帐的两种实现,因此,所有共识问题都可以由第一块(“主要”)解决就足够了;我们不需要为helper块使用ProtocolLedgerView的实例,实际上,通常来说,不可能提供一个实例。这意味着双块协议是主要的块协议:


示范34

我们需要的块配置是两个块的块配置:


示范35

现在我们可以轻松地显示出double块也支持其协议:


示范36

卡尔达诺共识结论

Cardano共识层最初是为Cardano区块链设计的,目前运行Byron,并将很快运行Shelley。您可以辩称,这意味着IOHK工程师应首先为该特定区块链设计,然后再将共识层用于其他区块链时再进行概括。但是,这样做将具有严重的缺点:

这会削弱我们执行测试的能力。我们无法替换何时无法生成节点的程序,无法使用双分类账执行等。 我们将涉及逻辑上独立的事物。用抽象的方法,雪莱分类帐由三部分组成:拜伦链,雪莱链和在这两者之间进行调和的叉子组合器。如果没有抽象,则关注点的分离将更难以实现,从而导致代码难以理解和维护。 抽象代码不太容易出错。举一个简单的例子,由于双重分类帐合并器在两个合并分类帐中是多态的,并且它们具有不同的类型,因此我们无法编写正确类型的代码,但是试图将例如主块应用于辅助分类帐。 当时间到了,我们想实例化新区块链的共识层(不可避免地会如此),从一开始就以抽象的方式编写它,这迫使我们仔细考虑设计,避免耦合不应该耦合的事物,或做出对正在考虑的实际区块链合理的假设,但通常可能不正确。在实施设计后纠正这些问题可能很困难。

需要具有良好技能的编程语言

显然,所有这些实际上都需要具有出色抽象技能的编程语言。幸运的是,Haskell非常适合该法案。

这是针对开发人员的一系列“深潜”帖子中的第二篇

与各种视图不同,NodeConfig是一个数据族。由于将节点配置传递给所有功能,因此将NodeConfig用作数据系列有助于确定类型,从而有助于推断。将其余的保留为类型族可以很方便,并避免不必要的包装。

**仅当所有插槽都包含一个块时,插槽号才代表链的长度。 PBFT仅在没有临时网络分区的情况下才是这样,而共识概率算法(例如Praos)则不是这样。换句话说,较低密度的链末端可能比另一个较短但较高密度的链末端具有较高的槽数。

***真正的DualBlock组合器维护与这两个块相关的第三条信息(例如事务ID)。为了简单起见,我们在这篇文章中省略了它。

巴西ADA社区

ADA巴西社区存在于电报此外,我们还有一个博客,其中包含多种可供阅读的材料。本文的翻译者是Joselmo Cabral。

最后,该文本由ADA Cardano-巴西社区的员工推广,该社区是该国官方团队唯一认可的文本。另请访问我们的YouTube频道:

—-

原文链接:https://livecoins.com.br/a-natureza-abstrata-da-camada-de-consenso-da-cardano/

原文作者:marcusoregano

编译者/作者:wanbizu AI

玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。

LOADING...
LOADING...