快捷搜索:

ETH核心开发者:MPT十六叉树将被替换

致谢

这项建议得益于Alexey Akhuno,Vitalik Buterin,Anna George,Sina Mahmoop,Tomasz Stanczak与Martin H. Swende提供的宝贵建议。

有关讨论:https://ethresear.ch/t/oerlay-method-for-hex-bin-tree-conersion/7104

覆盖转化法

不幸的是,要将ETH从十六叉树切换到二叉树,并非一件容易的事。有不少数据需要转换,并且实行更改需要花费超越15秒的区块时间。

此外,想象一下,你正在翻译一本5000页的书本,作者一直打电话对你说他对故事做了调整,这会干扰到你已经翻译过的页面……而这可能会一直持续下去。

这就是现在ETH遇见的问题,由于用户可以更新已转换的地址,这意味着你需要重新开始转换过程。

解决此问题的建议是设一个过渡期,在此期间,在十六叉树的顶部放置一棵覆盖二叉树,它有哪些用途是保存状况发生的所有更改,直到基树转换为二叉树。

背景

现在,ETH的竞价推广账户是被存储到一棵十六叉树当中的。所谓十六叉,就表示一个节点有16个子节点,理论上这是非常不错的,由于这意味着你需要更少的”阶段”来存储你所有些数据。

比如,这就是以十六叉树的形式表示键与值对(170,)的过程。在十六进制中,170表示为0xaa,因此你仅需两层:其中之一用于第一个a,另一层则用于第二个a

图1: 这是一棵十六叉trie树示例,显示了值“”怎么样存储在键0xaa处。此树只有2字节长的键,并且只沿0xaa键的子树被展开。为了简单起见,不有关的子树被替换为“…”

注意,这棵树非常浅,也非常宽。然后将其与以下相同键与值对的二叉树表示法进行比较。在二进制中,170表示为10101010

图2: 和图1中相同的键值对,以二叉树形式进行存储。为了简单起见,不有关的子树被表示为“…”

你可以看到,这棵树要深得多,也窄得多。

在ETH中,每一个区块都包含一个stateRoot字段,它是MPT根的哈希值。总而言之,这个哈希,是通过对根的16个子项的哈希列表进行哈希运算而获得的。这部分子哈希列中的每个,又依次是其子哈希列表的哈希,依此类推。

每次生成一个新区块时,矿工都会更新帐户树并重新计算其根哈希值。哈希存储在新区块的stateRoot字段中,然后新区块被密封。

图3 区块头的state root字段指向十六叉树的根。

问题就出目前这里了:通过对所有节点进行哈希运算来重新计算哈希根花费的时间太长,因此,为了计算根节点,矿工将从数据库中检索同级哈希(sibling hash)。尽管从数据库中获得所有子叶并对整棵树进行哈希运算所需的时间不多,但此操作仍然需要很多时间。这是由于需要要从数据库中获得每一个哈希。

在十六叉树中,一般每一个阶段要获得15个同级哈希。在上面的示例中,这就是30个哈希。

即便更深入,二叉树每一个阶段也仅需一个同级哈希。在上面的示例中,就只有8个哈希!这就是为何在实践当中,二叉树事实上要更好是什么原因。

下一步

大家已经创建了一个初步的原,以便估计完成转换所需的时间。大家相信,整个过程可以在适当的时间内(大约几天)完成。伴随算法的改进,我将发布更多的细则。

写在前面:

想象一下,你正在翻译一本5000页的书本,作者一直打电话对你说他对故事做了调整,这会干扰到你已经翻译过的页面……而这可能会一直持续下去,这就是ETH从目前用的MPT十六叉树转变为二叉树结构中遇见的一个类似困境。对此,ETH核心开发者Guillaume Ballet提出了一种策略,可以在大约几天的时间内,通过3个步骤完成这一转换手术。

对于该提案,ETH联合开创者italik评论称:

“来自Ballet的要紧研究基础,它会使ETH无状况变得友好,同时创造了一个机会,以大大简化该协议。期待在将来的几个月中,来自ETH1.x开发职员愈加出色的工作及成就。”

以下是译文:

影响ETH的海量问题之一是竞价推广账户和合约数据的存储方法,ETH现在选择的结构称为默克尔帕特里夏树(Merkle Patricia Tree,或简称MPT)。尽管从理论上讲,它是非常有意义的,但在实践中,它带来的问题要比其解决的问题要更多。多年来,核心开发职员一直在讨论向二叉树(binary tree)的转换,在本文中,我将阐明我对这一问题的怎么看,然后给出一个解决它的办法。

建议的过程引入了一个过渡期,在此期间,两种树结构都会存在。如此做有哪些好处是,在转换树结构时,主链可以维持运行,并且还可以确保将所有帐户转换为二叉树格式。

这种过渡会分成三步进行:

在这种办法中,确定在区块高度H1处,区块具备两个stateRoots:一个用于“基础”十六叉树,一个用于“覆盖”二叉树。

图4: 在转换过程中,区块具备2个状况根(state Root):一个是传统十六叉树的只读根,第二个是“覆盖”二叉树的根。

十六叉树被觉得是只读的,因此对状况的任何更新都将是对覆盖树的更新。

当一笔买卖读取或更新一个帐户时,系统第一搜索覆盖树。假如在那里找不到帐户,系统将在旧的十六叉树中搜索该值。

而在同时,十六叉树正在后台转换。目前可以不需要担忧插入,由于所有更改都存储在顶部树中。

后台转换过程完成后,矿工将通过转换结果替换只读的十六叉树基础根来宣布他们已筹备好进行切换。对状况的读写操作与步骤1相同。

图5:转换的第二个阶段,区块头将十六叉树基础根替换为其二叉树转换基础根,以向互联网发送信号,告知它们已筹备就绪。

当一个足够大的序列区块对转换后的基础根具备相同的值时,这意味着大部分矿工都完成了转换,并对转换后的树的外观达成了共识。接下开,就进入到合并过程。

合并过程会渐渐进行:每次生成新区块时,都会从叠加层中删除n个键,然后将其重新插入到基础树中。该过程将持续进行,直到从叠加层中删除所有键为止。在此阶段,覆盖状况根将从区块头中删除。

此外,假如买卖实行写入覆盖树中找到的键,则该键将从覆盖树中删除,并直接写入到基础树。

您可能还会对下面的文章感兴趣: