• 区块链100篇之第九篇--默克尔树(Merkle Tree)


    中本聪在他的创世论文中一个概念,就是SPV,中文意思是简单支付验证,从这里我们可以看出SPV指的是“支付验证”而不是“交易验证”,那这两者有什么区别吗?简单的说就是支付验证只需验证该笔交易是否被确认过了,而交易验证是需要验证该笔交易是否满足一些条件如“余额”是否足够,还有该笔交易有没有存在双花等等一些问题,只有一切都没什么问题后该笔交易才算验证通过,可以看出交易验证要比支付验证更加复杂,所以它一般是由挖矿节点来完成的,而支付验证只要普通的轻钱包就可以完成。那现在有一个问题了,SPV是如何实现的?答案就是默克尔树,也就是今天要讲的主题,理解了默克尔树之后在回过头来就能理解SPV了。

    什么是Merkle Tree?

    默克尔树是一种二叉树,由一组叶节点、一组中间节点和一个根节点构成,看下图: 
    consensus-png 
    来简单讲一下这幅图,我们从最底部开始看,D0、D1、D2和D3是叶子节点包含的数据,也就是叶子节点的value,继续往上看,N0、N1、N2和N3是就是叶子节点,它是将数据(也就是D0、D1、D2和D3)进行hash运算后得到的hash值;继续往上看,N4和N5是中间节点,它们各是N0和N1经过hash运算得到的哈希值以及N2和N3经过hash运算得到的哈希值,注意,它们是把相邻的两个叶子结点合并成一个字符串,然后运算这个字符串的哈希;接着往上,Root节点是N4和N5经过hash运算后得到的哈希值,这就是这颗默克尔树的根哈希。

    分析到这里我们大概可以知道在默克尔树中最下面的大量的叶节点包含基础数据;每个中间节点是它的两个叶子节点的哈希,根节点也是由它的两个子节点的哈希,代表了默克尔树的顶部。

    还有从默克尔树的结构可以看出,任意一个叶子节点的交易被修改,叶子节点hash值就会变更,最终根节点的hash值就会改变。所以确定的根节点的hash值可以准确的作为一组交易的唯一摘要。

    现在可以总结一下默克尔树的特点: 
    1.首先是它的树的结构,默克尔树常见的结构是二叉树,但它也可以是多叉树,它具有树结构的全部特点。

    2.默克尔树的基础数据不是固定的,想存什么数据由你说了算,因为它只要数据经过哈希运算得到的hash值。

    3.默克尔树是从下往上逐层计算的,就是说每个中间节点是根据相邻的两个叶子节点组合计算得出的,而根节点是根据两个中间节点组合计算得出的,所以叶子节点是基础。

    如何通过Merkle树验证一笔交易?

    大概了解了什么是默克尔树后,可能会有一个疑问,就是默克尔树是如何验证一笔交易的?也就是我们上文提到的SPV(支付验证)。看下面一幅图:

    consensus-png 
    假设我们要验证区块中存在Hash值为9Dog:64(绿色框)的交易,我们仅需要知道1FXq:18、ec20、8f74(黄色框)即可计算出781a、5c71与Root节点(藕粉色框)的哈希,如果最终计算得到的Root节点哈希与区块头中记录的哈希(6c0a)一致,即代表该交易在区块中存在。这是因为我上文提到的两个点,一个是默克尔树是从下往上逐层计算的,所以只要知道相邻的另一个节点的hash值就可以一直往上计算直到根节点,另一个是根节点的hash值可以准确的作为一组交易的唯一摘要,依据这两点就可以来验证一笔交易是否存在。

    比特币中的默克尔树

    介绍完默克尔树的基本知识,我们来看一下比特币中的默克尔树长什么样,看下面一幅图: 
    consensus-png
    可以看到区块头包含了根节点的hash值,而中间节点、叶子节点还有基础数据在放在了区块体中。

    这里有一点需要提的就是在比特网络中的Merkle树是二叉树,所以它需要偶数个叶子节点。如果仅有奇数个交易需要归纳,那最后的交易就会被复制一份以构成偶数个叶子节点,这种偶数个叶子节点的树也被称为平衡树。

    默克尔树的典型应用场景

    默克尔树的应用场景其实很广泛,比较典型的就是P2P下载。在点对点网络中作数据传输的时候,会同时从多个机器上下载数据,而且很多机器可以认为是不稳定或者不可信的。为了校验数据的完整性,更好的办法是把大的文件分割成小的数据块(例如,把分割成2K为单位的数据块)。这样的好处是,如果小块数据在传输过程中损坏了,那么只要重新下载这一快数据就行了,不用重新下载整个文件。

    怎么确定小的数据块没有损坏哪?只需要为每个数据块做Hash。BT下载的时候,在下载到真正数据之前,我们会先下载一个Hash列表。那么问题又来了,怎么确定这个Hash列表本事是正确的哪?答案是把每个小块数据的Hash值拼到一起,然后对这个长字符串在作一次Hash运算,这样就得到Hash列表的根Hash。下载数据的时候,首先从可信的数据源得到正确的根Hash,就可以用它来校验Hash列表了,然后通过校验后的Hash列表校验数据块。

    除了P2P下载外,默克尔树还可以被用来快速比较大量的数据,因为当两个默克尔树根相同时,则意味着所代表的数据必然相同。还有就是可以用来实现零知识证明(零知识证明指的是证明者能够在不向验证者提供任何有用的信息的情况下,使验证者相信某个论断是正确的。举个例子,你要我向你证明我拥有某一把钥匙,这个时候我不需要直接拿钥匙给你看,而是用这个钥匙开锁拿出所在柜子中的某一样东西给你看以此来证明我拥有这把钥匙),关于零知识证明以后有时间再讲,ZCash就是采用零知识证明来达到交易匿名的目的,有兴趣可以去查找资料。

  • 相关阅读:
    深入理解系统调用
    基于mykernel 2.0编写一个操作系统内核
    交互式多媒体图书平台的设计与实现
    Ubuntu下VSCode调试环境搭建指南-C语言篇
    码农的自我修养之必备技能 学习笔记
    工程化编程实战callback接口学习笔记
    CentOS7.4网络配置
    R-CNN
    CUDA整理
    CUDA by Example 第四章 julia集
  • 原文地址:https://www.cnblogs.com/wangsea/p/9429898.html
Copyright © 2020-2023  润新知