等离子现金区块链状态数据结构

您好,亲爱的哈布拉斯(Habrausers)! 本文是关于Web 3.0(分散式Internet)的。 Web 3.0引入了分散化的概念,将其作为现代Internet的基础;许多计算机系统和网络都需要安全性和分散性来满足其需求。 去中心化解决方案称为分布式注册表技术或区块链。



区块链是一个分布式注册表。 它可以被认为是一个巨大的数据库,可以永久存在并且不会改变历史,区块链被用作去中心化Web应用程序或服务的基础。

从本质上讲,区块链不仅是数据库,而且是在网络参与者之间执行业务逻辑的能力,从而增加了网络参与者之间的信任的机会。

拜占庭共识提高了网络可靠性,解决了一致性问题
DLT带来的可伸缩性正在改变现有的业务网络。

区块链具有新的非常重要的优势:

  1. 预防代价高昂的错误。
  2. 透明的交易。
  3. 实物数字化。
  4. 智能合约。
  5. 付款速度和安全性。

Opporty PoE是一个旨在研究密码协议并改善现有DLT和区块链解决方案的项目。

大多数公共分布式注册表系统不具有可伸缩性属性-它们的吞吐量相当低。 例如,以太坊仅处理〜20 tx / s。
创建了许多解决方案来增加可伸缩性,而又不会失去分散性(如您所知,只有三分之二可以被知道:可伸缩性,安全性,分散性)。

最有效的方法之一是使用侧链的解决方案。

等离子概念


这个概念是,根链处理来自子链的少量提交,因此根链充当存储所有中间状态的最安全和最后一层。 每个子链都有其自己的共识算法,作为自己的区块链运行,但是有一些重要的警告。

  • 智能合约在根链中创建,并充当根链中子链的检查点。
  • 创建一个子链,并以自己的共识充当其自己的区块链。 子流程链中的所有状态均受欺诈证明的保护,这可确保状态之间的所有转换均有效并应用撤回协议。
  • 然后,可以将特定于dapp或子链(应用程序逻辑)的智能合约部署到子链。
  • 必要的工具可以从根链转移到子链。

验证者有经济动机去诚实行事,并将评论发送到根链-交易的最终结算层。

结果,在子链中工作的dapp用户完全不应与根链进行交互。 此外,即使子链遭到黑客入侵,他们也可以随时将其资金提取到根链上。 这些来自子链的出口使用户可以使用Merkle证明安全地存储他们的资金,从而确认一定数量的资金的所有权。

Plasma的主要优势在于其能够显着促进当前使主链超载的计算的能力。 此外,以太坊区块链可以处理更广泛,更并行的数据集。 根链所花费的时间也转移到以太坊节点,以降低对处理和存储的需求。

Plasma Cash是一种设计,可为网络令牌提供唯一的序列号,从而将其转换为唯一的令牌。 这样做的优点包括无需确认,对所有类型的令牌(包括不可替代令牌)的更简单支持以及减轻子链中大量退出的缓解。

等离子问题与子链的“大量出口”的概念有关。 在这种情况下,子链的同时协调退出可能会导致缺乏提取所有资金的计算能力。 结果,用户可能会赔钱。

血浆实施方案




基本血浆有许多实施方案。

主要区别在于:

  • 存储有关存储和显示状态的方法的信息,
  • 令牌类型(可分割不可分割),
  • 交易安全
  • 共识算法的类型等

血浆的主要变化:

  • 基于UTXO-每笔交易都由输入和输出组成:可以进行和花费一笔交易,未花费的交易清单是子链本身的状态。
  • 基于帐户-仅包含每个帐户及其余额的反映,在以太坊中使用此类型,因为每个帐户可以有两种类型-用户帐户和智能合约帐户。 这种状态存储的优点是操作简便,其缺点是该选项不可扩展(特殊的nonce属性用于防止事务执行两次)。

本文的目的是解释Plasma Cash区块链中使用的数据结构。

为了准确了解承诺的工作原理,您需要阐明Merkle树的概念。

默克尔树在等离子中的用途


Merkle树是区块链世界中极其重要的数据结构。 本质上,默克尔树使我们能够以隐藏数据的方式捕获某些数据集,但允许用户证明某些信息在该数据集中。 例如,如果我有十个数字,则可以为这些数字创建证明,然后证明这组数字中有一个特定的数字。 这些证明的常量大小很小,因此可以便宜地发布到以太坊。

您可以将其用于一组事务。 您还可以证明该组交易中包含特定交易。 这正是操作员要做的。 每个块均包含一组交易,这些交易会变成Merkle树。 这棵树的根是证明,它与每块血浆一起发布在以太坊中。

用户应该能够从等离子链中提取资金,当用户想退出等离子链时,他们会将“退出”交易发送给以太坊。

Plasma Cash使用特殊的Merkle树,这使得不验证整个区块而是仅验证与用户令牌相对应的那些分支成为可能。

也就是说,要传输令牌,您需要浏览历史记录并仅扫描特定用户需要的那些令牌,在传输令牌时,用户只需将整个历史记录传递给另一个用户,他就可以对整个历史记录进行身份验证-而且最重要的是,可以非常快速地进行身份验证。



等离子现金数据结构,用于存储状态和历史记录


尽管如此,仅需使用一些Merkle树,因为有必要获得该区块中交易的包含证明和不包含交易的证明,例如-

  • 稀疏的默克尔树
  • 帕特里夏·特里

Opporty完成了稀疏Merkle树和Patricia Trie的实施

稀疏的Merkle树类似于标准的Merkle树,不同之处在于它包含的数据已建立索引并且每个数据点都放在与该数据点的索引匹配的工作表上

假设我们有一棵有四片叶子的Merkle树。 我们将在这棵树上填充几个字母(A,D)以进行演示。 字母A是字母表的第一个字母,因此我们必须将其放在第一页上。 同样,我们可以将D放在第四张纸上。

那么第二和第三片叶子会发生什么呢? 我们只是把它们留空。 更准确地说,将放置一个特殊值(例如零)而不是放置字母。

该树最终看起来像这样:



包含证明的工作原理就像在普通的Merkle树中一样,如果我们想证明C不属于此Merkle树,会发生什么? 很简单! 我们知道,如果C是树的一部分,它将在第三页上。 如果C不是树的一部分,则第三片叶子必须为零。

所需要的只是包含Merkle的标准证明,表明第三张纸为零。

稀疏的Merkle树的最好之处在于它们实际上表示Merkle树内的键值存储!

这是实现稀疏Merkle树构建的PoE协议代码的一部分。

class SparseTree { //... buildTree() { if (Object.keys(this.leaves).length > 0) { this.levels = [] this.levels.unshift(this.leaves) for (let level = 0; level < this.depth; level++) { let currentLevel = this.levels[0] let nextLevel = {} Object.keys(currentLevel).forEach((leafKey) => { let leafHash = currentLevel[leafKey] let isEvenLeaf = this.isEvenLeaf(leafKey) let parentLeafKey = leafKey.slice(0, -1) let neighborLeafKey = parentLeafKey + (isEvenLeaf ? '1' : '0') let neighborLeafHash = currentLevel[neighborLeafKey] if (!neighborLeafHash) { neighborLeafHash = this.defaultHashes[level] } if (!nextLevel[parentLeafKey]) { let parentLeafHash = isEvenLeaf ? ethUtil.sha3(Buffer.concat([leafHash, neighborLeafHash])) : ethUtil.sha3(Buffer.concat([neighborLeafHash, leafHash])) if (level == this.depth - 1) { nextLevel['merkleRoot'] = parentLeafHash } else { nextLevel[parentLeafKey] = parentLeafHash } } }) this.levels.unshift(nextLevel) } } } } 

这段代码非常简单。 我们有一个键值存储,其中包含/不包含证明。

在每次迭代中,将从最后一棵树开始,填充特定级别的最终树。 根据当前工作表的哪个键是偶数还是奇数,我们取两个相邻的工作表并考虑当前级别的哈希值。 如果到达最后,我们将编写一个merkleRoot-普通哈希。

您必须了解,该树已经开始填充了空值! 如果我们存储了大量的IDS令牌。 我们的树很大,生成时间很长!

有许多解决方案可以解决这种未优化问题,但是Opporty决定将其更改为Patricia Trie。

Patricia Trie是Radix Trie和Merkle Trie的混合体。

Radix Trie数据键将自身存储数据路径! 这使您可以为内存创建优化的数据结构!



机会实施


 buildNode(childNodes, key = '', level = 0) { let node = {key} this.iterations++ if (childNodes.length == 1) { let nodeKey = level == 0 ? childNodes[0].key : childNodes[0].key.slice(level - 1) node.key = nodeKey let nodeHashes = Buffer.concat([Buffer.from(ethUtil.sha3(nodeKey)), childNodes[0].hash]) node.hash = ethUtil.sha3(nodeHashes) return node } let leftChilds = [] let rightChilds = [] childNodes.forEach((node) => { if (node.key[level] == '1') { rightChilds.push(node) } else { leftChilds.push(node) } }) if (leftChilds.length && rightChilds.length) { node.leftChild = this.buildNode(leftChilds, '0', level + 1) node.rightChild = this.buildNode(rightChilds, '1', level + 1) let nodeHashes = Buffer.concat([Buffer.from(ethUtil.sha3(node.key)), node.leftChild.hash, node.rightChild.hash]) node.hash = ethUtil.sha3(nodeHashes) } else if (leftChilds.length && !rightChilds.length) { node = this.buildNode(leftChilds, key + '0', level + 1) } else if (!leftChilds.length && rightChilds.length) { node = this.buildNode(rightChilds, key + '1', level + 1) } else if (!leftChilds.length && !rightChilds.length) { throw new Error('invalid tree') } return node } 

也就是说,我们递归地进行遍历并分别构建左右子树。 同时,构建密钥就像这棵树中的一条路径!

该解决方案更加简单,并且在进行了相当优化的同时,运行速度更快! 实际上,Patricia树可以通过引入新的节点类型(扩展节点,分支节点等)来进一步优化,就像以太坊协议中所做的那样,但是此实现满足了我们所有的条件-我们获得了快速且内存优化的数据结构。

通过实现这些数据结构,Opporty使得扩展Plasma Cash成为可能,因为它可以检查令牌的历史记录,并且可以在树中包括不包括令牌的内容! 这使您可以极大地加快对块和Plasma Child Chain本身的验证。

有用的链接:


  1. 白皮书等离子
  2. Git中心
  3. 用例和架构描述
  4. 闪电网纸

Source: https://habr.com/ru/post/zh-CN456374/


All Articles