区块链默克尔树
随着区块链技术和加密货币的日益普及,默克尔树或哈希树在验证存储在去中心化账本中的交易的完整性方面发挥着至关重要的作用,而且数据量更少。我们很清楚,区块链是由通过哈希指针连接的“块”形成的,每个块都包含经过大多数矿工验证和批准的交易。 Merkle 树的流行多年来一直在增长,这些树用于比特币和以太坊等加密货币。
在本文中,将介绍 Merkle 树的属性以及这种数据结构如何使区块链不可变和可靠。在进入 Merkle 树之前,必须了解一些定义。
加密哈希
加密哈希是一个函数,它为可变长度输入输出固定大小的摘要。哈希函数是一种重要的密码原语,在区块链中广泛使用。例如,SHA-256 是一个散列函数,其中对于任何可变位长度输入,输出始终是 256 位散列。
从上图中可以清楚地看出,即使是输入句子中字母表的最轻微变化,也可以极大地改变获得的哈希值。因此散列可以用来验证完整性。
考虑有一个包含重要数据的文本文件。将文本文件的内容传递给哈希函数,然后将哈希值存储在手机中。黑客设法打开文本文件并更改数据。现在,当您再次打开文件时,您可以再次计算散列并将此散列与之前存储在手机上的散列进行比较。很明显,这两个哈希不匹配,因此文件已被篡改。
哈希指针
常规指针存储数据的内存地址。使用此指针,可以轻松访问数据。另一方面,散列指针是指向数据存储位置的指针,并且通过该指针,还存储了数据的加密散列。所以哈希指针指向数据,也允许我们验证数据。哈希指针可用于构建各种数据结构,例如区块链和默克尔树。
区块链结构
区块链是两种基于散列的数据结构的熟练组合——
- 链表——这是区块链本身的结构,是哈希指针的链表。常规链表由节点组成。每个节点都有两部分——数据和指针。指针指向下一个节点。在区块链中,只需将常规指针替换为哈希指针即可。
- Merkle 树- Merkle 树是由哈希指针形成的二叉树,并以其创建者 Ralph Merkle 命名。
块结构
- 块头:头数据包含块的元数据,即关于块本身的信息。区块头的内容包括——
- 前一个区块头的哈希
- 当前区块的哈希
- 时间戳
- 密码随机数
- 默克尔根
- Merkle 树: Merkle 树是由哈希指针形成的二叉树,并以其创建者 Ralph Merkle 命名。
- 如前所述,每个块都应该包含一定数量的交易。现在问题来了,如何将这些交易存储在一个区块中?一种方法可以是形成一个基于哈希指针的交易链表,并将这个完整的链表存储在一个块中。但是,当我们考虑这种方法时,存储数百个交易的庞大列表似乎并不实际。如果需要查找特定交易是否属于某个区块怎么办?然后我们将不得不逐个遍历块,并在每个块内遍历交易链表。
- 这是一个巨大的开销,并且会降低区块链的效率。现在,这就是 Merkle 树出现的地方。 Merkle 树是包含在块中的所有交易的每块树。它允许我们对所有交易进行哈希/摘要,并以高效的方式提供成员资格证明。
- 回顾一下,区块链是一个基于哈希的区块链表,其中每个区块都由标头和交易组成。交易以树状方式排列,称为 Merkle 树。
默克尔树结构:
- 一个区块链可能有数千个区块,每个区块中有数千个交易。因此,内存空间和计算能力是两个主要挑战。
- 使用尽可能少的数据来验证交易是最佳选择,这可以减少 CPU 处理并提供更好的安全性,而这正是 Merkle 树所提供的。
- 在 Merkle 树中,交易被分组成对。为每一对计算哈希值,并将其存储在父节点中。现在父节点被分组成对,并且它们的哈希存储在树中的上一层。这一直持续到树的根部。 Merkle 树中不同类型的节点有:
- 根节点:默克尔树的根称为默克尔根,这个默克尔根存储在区块头中。
- 叶节点:叶节点包含交易数据的哈希值。块中的每个事务都对其数据进行哈希处理,然后将该哈希值(也称为事务 ID)存储在叶节点中。
- 非叶节点:非叶节点包含其各自子节点的哈希值。这些也称为中间节点,因为它们包含中间哈希值,并且哈希过程一直持续到树的根。
- 比特币使用 SHA-256 哈希函数对交易数据进行连续哈希处理,直到获得 Merkle 根。
- 此外,Merkle 树本质上是二元的。这意味着叶节点的数量需要均匀才能正确构建 Merkle 树。如果叶节点数为奇数,则树复制最后一个哈希并使叶节点数为偶数。
默克尔树如何工作?
- 通过将节点成对分组并计算该特定级别中每对节点的哈希值,从叶节点级别一直到 Merkle 根级别构建 Merkle 树。这个哈希值被传播到下一个级别。这是一种自下而上的构造,其中哈希值从下向上流动。
- 因此,通过将 Merkle 树结构与常规二叉树数据结构进行比较,可以观察到 Merkle 树实际上是倒置的。
示例:考虑一个有 4 个事务的块 - T1、T2、T3、T4。这四个交易必须存储在 Merkle 树中,这是通过以下步骤完成的 -
第 1 步:计算每笔交易的哈希值。
H1 = Hash(T1).
第 2 步:计算的哈希值存储在 Merkle 树的叶节点中。
第 3 步:现在将形成非叶节点。为了形成这些节点,叶子节点将从左到右配对在一起,并计算这些对的哈希值。首先将计算 H1 和 H2 的哈希以形成 H12。类似地,计算 H34。值 H12 和 H34 分别是 H1、H2 和 H3、H4 的父节点。这些是非叶节点。
H12 = Hash(H1 + H2)
H34 = Hash(H3 + H4)
第 4 步:最后通过配对 H12 和 H34 计算 H1234。 H1234 是唯一剩下的哈希。这意味着我们已经到达根节点,因此 H1234 是 merkle 根。
H1234 = Hash(H12 + H34)
关键点:
- 为了检查交易是否在树内被篡改,只需要记住树的根即可。
- 可以通过遍历哈希指针来访问交易,如果交易中的任何内容发生了变化,这将反映在父节点中存储的哈希上,进而影响上级节点中的哈希等等直到到达根。
- 因此默克尔树的根也发生了变化。因此存储在块头中的默克尔根使交易防篡改并验证数据的完整性。
- 在默克尔根的帮助下,默克尔树有助于消除区块中的重复或虚假交易。
- 它生成一个区块中所有交易的数字指纹,并且区块头中的默克尔根进一步受到存储在下一个区块中的区块头哈希的保护。
为什么默克尔树对区块链很重要?
- 在集中式网络中,可以从一个副本访问数据。这意味着节点不必负责存储自己的数据副本,并且可以快速检索数据。
- 然而,在分布式系统中情况并非如此简单。
- 让我们考虑一个区块链没有默克尔树的场景。在这种情况下,网络中的每个节点都必须记录已发生的每一笔交易,因为没有信息的中央副本。
- 这意味着必须在每个节点上存储大量信息,并且每个节点都将拥有自己的账本副本。如果一个节点想要验证过去的交易,则必须向所有节点发送请求,请求它们的账本副本。然后用户必须将自己的副本与从多个节点获得的副本进行比较。
- 任何不匹配都可能危及区块链的安全性。此外,此类验证请求将需要通过网络发送大量数据,执行此验证的计算机将需要大量处理能力来比较不同版本的分类帐。
- 没有默克尔树, 数据本身必须在整个网络上传输以进行验证。
- Merkle 树允许对具有可行计算能力和带宽的交易进行比较和验证。只需要发送少量信息,因此补偿了之前必须交换的大量分类帐数据。
Merkle trees use a one-way hash function extensively and this hashing separates the proof of data from data itself
会员证明:
Merkle 树的一个非常有趣的特性是它提供了成员资格证明。
示例:矿工想要证明特定交易属于 Merkletree。现在矿工需要展示这个交易以及位于交易和根之间路径上的所有节点。可以忽略树的其余部分,因为存储在中间节点中的哈希足以验证一直到根的哈希。
如果树中有 n 个节点,则只需要检查 log(n) 个节点。因此,即使 Merkle 树中有大量节点,也可以在相对较短的时间内计算出成员资格证明。
默克尔证明:
Merkle 证明用于决定:
- 如果数据属于特定的 Merkle 树。
- 证明数据属于一个集合,而不需要存储整个集合。
- 为了证明某个数据包含在一个更大的数据集中,而不暴露更大的数据集或其子集。
Merkle proofs are established by hashing a hash’s corresponding hash together and climbing up the tree until you obtain the root hash which is or can be publicly known.
考虑下面给出的默克尔树 -
假设我们需要证明交易“a”是这棵 Merkle 树的一部分。网络中的每个人都会知道所有 Merkle 树使用的哈希函数。
- H(a) = Ha,如图所示。
- Ha 和 Hb 的哈希值将是 Hab,它将存储在上层节点中。
- 最后,Hab 和 Hcd 的哈希值将给出 Habcd。这是我们得到的默克尔根。
- 通过比较获得的默克尔根和区块头中已经可用的默克尔根,我们可以验证该区块中是否存在交易“a”。
从上面的例子可以清楚地看出,为了验证 'a' 的存在,'a' 不必被揭示,也不必被揭示 'b'、'c'、'd',只需要它们的哈希值就足够了。因此,默克尔证明提供了一种有效且简单的验证包容性的方法,是“包容性证明”的同义词。
排序的 Merkle 树是一棵树,其中所有数据块都使用排序函数进行排序。这种排序可以是字母、字典、数字等。
非会员证明:
- 也可以使用排序的 Merkle 树在对数时间和空间中测试非成员资格。也就是说,可以证明给定的交易不属于默克尔树。
- 这可以通过显示紧接在相关交易之前的交易路径以及紧随其后的项目的路径来完成。
- 如果树中的这两个元素是连续的,这证明有问题的项目不包括在内,否则它必须在显示的两个事物之间移动,但它们之间没有空间,因为它们是连续的。
Coinbase 交易:
coinbase 交易是一种独特的比特币交易,它包含在区块链中每个区块的 Merkle 树中。它负责创建新硬币,还包含一个 coinbase 参数,矿工可以使用该参数将任意数据插入区块链。
默克尔树的优点:
- 高效验证——默克尔树提供对数据完整性和有效性的有效验证,并显着减少验证所需的内存量。验证证明不需要通过区块链网络传输大量数据。通过快速验证交易,在点对点分布式系统中实现加密货币的无信任传输。
- 无延迟——通过网络传输数据没有延迟。默克尔树广泛用于维持加密货币功能的计算。
- 更少的磁盘空间——与其他数据结构相比,Merkle 树占用的磁盘空间更少。
- 不变的数据传输——默克尔根有助于确保通过网络发送的块是完整的和不变的。
- 篡改检测- Merkle 树为矿工检查是否有任何交易被篡改提供了惊人的优势。
- 由于交易存储在 Merkle 树中,该树将每个节点的哈希存储在上层父节点中,因此交易细节的任何更改,例如要借记的金额或必须付款的地址,然后更改将传播到上层的哈希,最后传播到 Merkle 根。
- 矿工可以将标头中的 Merkle 根与存储在块的数据部分中的 Merkle 根进行比较,并且可以很容易地检测到这种篡改。
- 时间复杂度- 如果在一个块中搜索交易的时间复杂度(如 Merkle 树和另一个块中的交易排列在链表中)进行比较,则默克尔树是最佳解决方案,然后 -
- Merkle 树搜索 - O(logn)
- 链表搜索 - O(n)
- 其中 n 是一个块中的事务数。
简单付款验证(SPV):
- SPV 使客户可以非常轻松地验证特定交易是否存在于区块中并且是否有效,而无需下载整个区块链。用户只需要最长链的块头的副本。
- 此标头副本存储在 SPV 钱包中,此钱包使用 SPV 客户端将交易链接到块中的 Merkle 分支。 SPV 客户端以 Merkle 分支的形式请求包含证明(Merkle 证明) 。交易可以链接到 Merkle 分支的事实证明了交易存在。
- 现在通过评估在交易区块之上开采的区块,客户端还可以得出结论,大多数节点通过使用工作证明等共识机制在这条链上构建了更多区块,因此这是最长的,有效的区块链。