区块链技术博客
www.b2bchain.cn

区块链技术解析 DFINITY 网络架构、原子性与编程范式

第20258篇区块链技术文章区块链技术解析 DFINITY 网络架构、原子性与编程范式

Dfinity已经失去了部分原子性,开发人员在实现defi应用程序时将面临新的挑战原题:讨论Dfinity的网络组成、架构特点和原子问题作者:blockpunk 5月27日,ICP联盟与社区开发者举行了第一次开发者大会,讨论了dfinity的总体架构,并讨论了dfinity最重要的原子问题,本期的亮点是:eth是状态更新机器,dfinity是消息和请求的处理机器

dfinity的底层是actor编程模型。容器之间的调用(即智能合约)是异步操作,需要相互等待。子网之间的调用也是异步的

d单元失去了部分原子性,这对def开发人员来说是一个挑战。借鉴传统的Internet事务处理方法会有所帮助,在我之前的文章“代码即服务:dfinity Internet计算机的体系结构分析”中,我介绍了dfinity的总体体系结构。通过阅读主网上的核心代码,我们可以更详细地了解它的内部结构

这些节点通过NNs随机组合(跨多个数据中心)形成子网。子网的数量不是固定的,而是随着网络资源的使用而动态增加和合并。此子网类似于eth2.0中的碎片或并行链。一个节点组只能形成一个子网,每个子网运行自己的共识。子网的分块速度为每秒一块,不同的子网同步并行分块,不同的子网携带业务逻辑运行的“容器”。该容器可视为智能合约的升级版本。容器也有内存。目前上限为4G,可以存储业务相关数据和前端资源,eth是同步状态更新机,通过事务触发智能合约,达成状态共识;Dfinity是一个异步消息处理器。容器同时接收、计算和返回消息,并对消息的处理顺序达成一致。容器不共享状态,只通过通信处理事务,eth2.0、Boca和layer2都属于分层体系结构,仍然存在瓶颈,不能无限扩展。这不是最终的解决办法。即使我们可以将不同的应用分配给不同的layer2/并行链/片来扩展性能,layer2/片/并行链之间的通信仍然需要通过总线,总线本身的上限决定了系统的性能

  • 在数据单元中有许多对等子网,智能合约将随机部署在这些子网上。对于部署契约的开发人员和用户来说,他们不知道契约在哪个子网中运行,因为芯片间的通信是不敏感的。同一子网中两个容器的交互与不同子网中两个容器的交互在延迟、安全性和复杂度上没有差异,因此无法感知子网之间的差异。这也是异步消息传递系统的好处,通过这种方式,dfinity具有几乎无限的扩展能力,大大提高了一般的计算能力。然而,这也导致了契约间交互中原子性的丧失,以太坊利用原子性实现了许多独特的服务,如def的闪电贷款清算机制在失去原子性后,开发者面临着新的挑战,尤其是在def应用的实现上。如果他们仍然遵循过去以太坊的编程范式,这将导致事务失败后无法恢复状态的问题

  • 例如,如果在dfinity上实现了设计多个容器进行交互的复杂应用程序,例如借出应用程序,它需要与稳定货币、借出代币和流动性凭证三个合约进行交互,并成功调用所有三个合约来完成借出。但是,如果在dfinity中强制实现以太坊范例调用,如果其中两个契约成功,而最后一个调用没有响应,那么贷款事务将失败,前两个契约的状态已经完成,它们将被卡住而不是返回。在用户方面,钱已经被抵押,代币已经被扣除,但是贷款无法完成,退款还没有收到显然,我们需要探索新的模式来确保数据单元中复杂应用的安全,传统Internet分布式体系结构下的一致性和确定性解决方案值得借鉴。数据实体上的智能合约需要关注数据的最终一致性,从写和读开始首先,当我们需要强大的安全保证时,我们可以将所有的逻辑放在一个容器中。主要在一个容器中,所有事务都是原子的,这确保了事务和数据的一致性。但这种方式正面临着扩张的噩梦,这显然是懒惰的

  • 事实上,传统互联网关注的是数据库中数据的一致性,但在数据实体上,它分为两部分:一是业务层面,可以通过更新合同来改变。我们不需要保证这里的原子性;另一部分是数据层,即进入正交持久化的数据和落入磁盘的数据。这就是我们需要保证数据一致性和原子性的地方,在dfinity中,使用一个名为stable的变量类型来定义磁盘丢弃数据,这与传统的数据库类似。目前,有几个团队正在开发dfinity的数据库引擎。由于底层掉盘数据的一致性和原子性,上层业务的安全依赖于数据的一致性来保证

  • 如果借鉴分布式事务的原始概念,我们有四种方法来实现这个功能:

DFINITY 网络如何组成?

TCC两端的事务提交,这是目前银行转账使用的机制。在saga的事务处理机制中,当事务发生时,首先直接更新稳定数据库的最终一致性数据,然后在每个人明确确认后提交,首先建立事务协调器。当容器需要发起交叉合同调用时,它可以向事务协调器申请一个ID,并通过这个ID向事务终止器报告,最后,在每个人提交成功后,它可以提交整个事务

使用事务观察者模式包装稳定状态。每当状态更新时,观察者都会记录更新前后的两个值。如果事务失败,观察者将使用前面的值回滚操作

dfinity的优势在于大规模和高性能的分散式数据库访问。Dfinity的程序在容器中运行,容器中存储与业务相关的数据库,容器之间不共享状态数据。目前,dUnity容器的存储限制为4G。如果服务容器的4G已满,则需要扩展容器。H

解析 DFINITY 网络架构、原子性与编程范式

DFINITY 的最底层是托管专用硬件的独立数据中心,这些数据中心运行在全球各地,目前全球已经有 53 个数据中心,年底将超过 500 个。数据中心对硬件与网络状态的要求较高,硬件也具备特殊要求,需要大量 RAM 而无需硬盘。数据中心想要进入 DFINITY 网络,需要获得去中心化治理系统 NNS 的投票许可,而这种投票往往发生在需要扩容时。

解析 DFINITY 网络架构、原子性与编程范式

数据中心的机器运行 DFINITY 节点程序,这个程序会根据性能虚拟化出一系列计算资源标准化的节点,这些节点会组成 DFINITY 的区块链,处理计算、达成共识、出块并同区块。

这些节点随机地(跨多个数据中心)被 NNS 结合到一起,形成一个个子网。子网数量也不是固定的,而是随着网络的资源使用情况动态地增加、合并。这个子网类似于 ETH2.0 中的分片,或者是平行链,一个节点组只能组成一个子网,每一个子网内部都运行着自己的共识。子网的出块速度为一秒一个区块,且不同的子网同步并行出块。

而在不同的子网上承载着「容器」,容器中运行着业务逻辑。可以把容器看作智能合约的升级版本,容器也具备内存,目前上限为 4G,可以存储业务相关数据,也可以存放前端资源。

与从传统区块链的架构差别

ETH 是一台同步的状态更新机器,由交易触发智能合约,对状态进行共识;而 DFINITY 是一台异步的消息处理机,容器同时进行消息的接收、计算、返回,对消息的处理顺序共识。容器间不会共享状态,只会通过通讯来处理事务。

ETH 2.0、波卡、Layer2 其实都属于分层架构,这种架构依然存在着瓶颈,无法无限扩容,并不是终极方案。即使我们可以把不同的应用分配在不同的 layer2/ 平行链 / 分片上扩展性能,但 layer2 间 / 片间 / 平行链间的通讯依然要通过总线,而总线本身的性能上限决定了系统的性能上线,是确定的。

但与分片 / 多链架构不同的是,DFINITY 没有总线 / 主链 / 中继链 / 信标链的设计,子网之间是完全对等的,任意两个子网都能通过自己的链签名事务,通过事务直接交互,而不需要经过某个上层调度链,因此子网的数量不是固定,可以按需无上限增加,从而最终实现无限扩容。

解析 DFINITY 网络架构、原子性与编程范式

原子性问题

一切即 actor,DFINITY 使用的编程模型与传统区块链有一定差异,反而与传统互联网的 akka 类似。

DFINITY 中的智能合约(即容器)之间的交互也与以太坊不同,DFINITY 的智能合约内部是向存在一个唯一线程,但是容器之间的交互是通过发送异步消息进行,因此容器间可以进行异步操作。如果一个容器向另一个容器发送请求后,需要等待另一个容器的处理结果,才能进行下一步操作。

DFINITY 中存在很多个对等的子网,智能合约会随机的部署上子网。对于部署合约的开发者与使用合约的用户来说,他们并不知道这个合约运行在哪一个子网中,因为片间通讯是无感的。在同一个子网的两个容器的交互,与在不同子网上两个容器的交互,在延迟、安全性、复杂度上都没有差别,因此无法感知到子网之间的差别。这也是异步消息系统的好处。

解析 DFINITY 网络架构、原子性与编程范式

这样 DFINITY 获得了近乎无限的扩容能力,大大提升了通用计算能力。但这也导致了合约间的交互失去了原子性,而在以太坊上利用原子性特点实现了很多独特的服务,比如 DeFi 的闪电贷清算机制。

在失去了原子性后,开发者面临着新的挑战,特别是在实现 DeFi 应用上,如果依然按照过去以太坊上的编程范式,这导致交易失败后状态无法恢复的问题。

比如,如果在 DFINITY 上实现了设计多个容器交互的复杂应用,比如一个借贷应用,需要与稳定币、借出代币、流动性凭证三个合约交互,三个合约都成功调用才能完成借贷。但如果强行在 DFINITY 实现以太坊范式的调用,如果其中两个合约成功,而最后一个调用没有响应,那么借贷交易会失败,并且前两个合约的状态却已经完成,就会卡住,而不会退回去。表现在用户这边,就是钱已经质押上去,代币已经扣走,却没法完成借贷,也没有收到退款。

探索新的编程范式

显然想要在 DFINITY 保证安全性地实现复杂应用,我们需要探索新的范式。

最终一致性与确定性在传统互联网的分布式架构下有一些解决方案,这是值得我们借鉴的。DFINITY 上的智能合约需要关注的是数据的最终一致性,从写入和读取入手。

首先当我们需要很强安全性保证时,可能把整个所有的逻辑放在一个容器里面。主要在一个容器中,所有的交易都是原子性的,这里确保了事务与数据两个层面的一致性。但这种方式面临着扩容的噩梦,显然是偷懒的做法。

传统互联网其实关注的是数据库中数据的一致性,而在 DFINITY 中其实分为两个部分:一个是业务层面的,这部分是可以通过更新合约变化的,我们其实不太需要保证这里的原子性;而还有一部分是数据层面的,也就是进入正交持久性的数据,落盘的数据,这才是我们需要保证一致性与原子性的地方。

在 DFINITY 中有使用了名为 stable 的变量类型来定义落盘的数据,这其实类似于传统的数据库,目前也有多个团队在做 DFINITY 的数据库引擎,有了这个底层落盘数据的一致性与原子性,上层的业务的安全性就依靠数据来保证一致性。

如果是借鉴原来分布式事务的概念,我们有四种方式实现这个能力:

  • tcc 两端事务提交,这是目前银行转账使用的机制,在交易发生时我们先直接更新数据库的 stable 的最终一致数据,等大家都确认清楚后,再去提交。

  • saga 的事务处理机制,首先建立一个事务协调程序,当某个容器需要发起一次跨合约的调用时可以向事务协调程序申请一个 ID,并通过这个 ID 向事务的终结程序汇报,最后大家都提交成功后,再进行整体的提交。

  • 使用事务观察者模式,对 stable 的状态进行包装,每当发生状态的更新操作时,观察者都去记录更新前后的两个值,如果发现某一个事务失败,观察者会就使用之前的值回滚操作。

关于容器数据扩容

DFINITY 的优势在于大规模高性能的去中心化数据库存取,DFINITY 的程序以容器为单位运行,容器中会存储业务相关的数据库,且容器之间不会共享状态数据。而目前 DFINITY 容器存储上限是 4G,如果一个业务容器的 4G 存满之后,容器就需要面临扩容的问题,该如何解决?

目前 DFINITY 能允许容器在存储与带宽等资源即将耗尽时,自动 Fork 出一个新容器进行扩容。新的容器中只保存了最近的状态数据,会丢弃历史。两个容器间依然通过异步调用来实现交互。

同时,在设计容器时,需要把各种级别的数据分开存放。举个例子,如果直接在 DFINITY 上建立一个钱包容器,交易记录的数据量会比用户地址的数据大很多。如果这时候把这两类数据放入一个容器,就会影响后续的扩容能力。

因此我们需要把对最终一致性要求相同的数据放在一起。比如在将钱包的余额与地址放在一起,而交易记录就可以通过分片存放在不同的容器中。从而实现系统的自动弹性扩容。

区块链技术解析 DFINITY 网络架构、原子性与编程范式 由www.b2bchain.cn 提供
文章整理自网络,只为个人学习与分享使用
链接地址https://www.b2bchain.cn/20258.html

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 区块链技术解析 DFINITY 网络架构、原子性与编程范式
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们