卡尔达诺结算层更新器概览

更新系统的实现可以从 Pos.Update 系列模块中找到。实现的方法与 CSL 的其他子系统相同,比如 Txp, Ssc 和委派。更新系统有一个全局状态,存储在数据库中。全局状态可以从区块链中明确导出。本地状态,有时候也被称为『内存池』,被存储在内存中。内存池用于数据传输,将传输的数据保存到区块中。在二进制文档中描述的二进制协议在应用级文档中描述了网络协议(使用标准的 Inv/Req/Data pattern 模式构建)。

目前,通过软件更新,执行研究部分所述的硬分叉来增加硬分叉的功能已经准备好了;软分叉(或者说软件更新)已经完全实现。

软分叉可更新字段

一个 UpdateProposal 包含用于修改由卡尔达诺结算层使用的一些参数(例如 slot 持续时间)的字段。具体来说,upBlockVersion 用于提议协议有了一些修改;如果 upBlockVersion 比上一次使用的区块还新,upBlockVersionData 的修改就会被采用。

upBlockVersionData 具有 BlockVersionData 的类型。

这些字段如下所述:

  • bvdScriptVersion - 用于验证脚本转账的脚本语言版本,如果协议中 upBlockVersion 增加了,它必须也给增加 upBlockVersion 1(不能保持不变)。
  • bvdSlotDuration - slot 持续时间(以毫秒为单位)。
  • bvdMaxBlockSize - 区块大小限制(以字节为单位)。与上一个限制相比而言,协议不能将区块的大小限制增加两倍以上。
  • bvdMaxHeaderSize - 区块大小限制(以字节为单位)。
  • bvdMaxTxSize - 转账大小限制(以字节为单位,当前为4096字节),限制 TxAux 的大小。

这些检查在 verifyNextBVData 中进行。

此外,有一些现在未被使用,但将来会被使用的字段。以下是它们的简要说明:

  • bvdMpcThd MPC 的资格临界值。
  • bvdHeavyDelThd 重量级委派的临界值。
  • bvdUpdateVoteThd 投赞成票和反对更新所需的股份份额。
  • bvdUpdateProposalThd 所有股份的一个份额,要让区块拥有 UpdateProposal,权益所有人的投票份额必须大于这一份额。
  • bvdUpdateImplicit 静默更新之后的 slot 数(除非它有更多的否定票数)。
  • bvdUpdateSoftforkThd 所有股份的一个份额,如果某些区块权益所有人的总持股比例比该数值大,则采用该区块版本。

内存池结构

内存池 由投票和提案组成。除此以外,内存池 还包含 tip,slot 以及 MemPool 对应的 PollModifier(当前 GState,即应用的 MemPool 对应 GState)。无论是来自网络/内存池提案状态改变,还是来自区块链加载的提案状态改变,PollModifier 都表示全局状态的改变,会被应用到内存池。

更新内存池

随着节点反序列化更新系统消息的数据,内存池会被更新,实现在这里

MemPool 在三种情况下会被更新:

  1. 当收到新的提案/表决时。在这种情况下,调用一个处理函数,然后调用 verifyAndApplyUSPayload 并更新当前 PollModifierMemPool

  2. 当一个新 slot 开始时。在这种情况下,一些内存池的数据可能会失效。事实上,只有 epoch 发生变化时才会发生这种情况。这种情况可能会发生是因为稳定的股份分配发生了变化,有些投票可能没有足够的股份。这是 processNewSlot 方法实现的。

  3. GState 更新时。它被称为 usNormalize。有些数据可能由于区块应用程序或回滚而变得无效。例如,我们在内存中有个提案,将这个提案应用于区块,然后它变无效了(因为它已经在区块中)。我们应该放弃这个提案。或者我们从某个区块对提案进行投票,然后回滚这个区块,然后投票变得无效。它通过将所有本地数据应用于空状态来实现的,忽略所有不再有效的数据。

提案和投票累计

要为提案投票,节点应该发送它们的投票。提案和投票存储在内存池(即使没有足够的选票加入区块,这种方式也可以自动收集投票),或者从区块链收集,以确定哪个方案通过。

与数据库的交互

为了验证更新系统数据,我们必须从全局状态(数据库)获取这些数据。有一个文档详实的类型类 MonadPollRead 提供这样的接口。这种类型不但用于数据库交互,还用于在处理从网络接收到的数据时将内存池写入账户。非常重要的一点是,它的实现依赖于 Pos.Update.DB 模块中的函数。

核心类型

核心类型在二进制协议文档中提到。这些类型直接反映了研究章节的概念,有关更多信息,请参阅核心类型模块

更新提案批准

更新机制实现的一个很重要的部分是创始块的部分。这个逻辑在 processGenesisBlock 中。下面将解释与该过程有关的术语。

阈值

假设有一个区块版本 X。以及在 slots S 中创建的版本为 X 的区块(其中 S 是一组 slots)。如果所有 slot 的领导者的总相对资产 SsoftforkResolutionThreshold (在代码中被称为阈值),则 X 被采纳。请参阅研究概述获取更详细说明。

提案状态

更新的提案状态可处于下面的状态之一。

未定

这意味着更新提案被包含在其中一个区块中,但是它没有 50% 的赞成/反对票(这里的 50% 的意义是赞成/反对提案选民总数相对于系统所有权益相关者的总股权),默认赞同规则还没有触发。

批准

这意味着这个提案有超过 50% 的投票或很久之前加入了区块(根据默认批准规则),赞同的票数比反对的票数更多(与股权比较)。

拒绝

如果反对该提案的投票超过 50%,或很久之前加入了区块(根据默认批准规则),反对的票数比赞同的票数更多(再次与股权比较)。

确认

如果至少 k 个区块提案通过,那么这个批准的提案被称为确认。这时候我们可以确定该提案不会被拒绝。因为深度超过 k 的回滚是不可能的。

废弃

如果至少 k 个区块提案未通过,那么这个拒绝的提案被废弃。这时候我们可以确定该提案不会被通过。因为深度超过 k 的回滚是不可能的。

下载新版本

Pos.Update.Download 模块中,实现了以下算法。已下载的更新通过一个叫做 cardano-launcher 的工具操作。

下载更新的版本

要下载更新的版本,我们从 ConfirmedProposalState 提取更新的哈希值。如果更新哈希值成功提取了,则调用『下载更新哈希值』算法以下载保存更新的版本,这取决于我们是否在给定的平台使用安装程序。

通过哈希值下载更新

为了通过哈希值下载更新,我们会使用 HTTP 中的 httpLBS,遍历已知的更新服务器,用给定的哈希值下载更新。很简单:最后,我们要么完成了更新的下载,要么遍历完服务器清单,上报错误信息。已知更新服务器的 URI 使用 cardano-node 可执行文件的 --update-server 参数定义。