区块链杂谈---浅谈我所理解的Merkle树(默克尔树)与hash list


前言

文章标题中提到的其实是两种数据结构-Merkle树hash list,前者俗称默克尔树。有些小伙伴可能会说,这两种数据结构以前怎么没有听说过呢?

其实这两种数据结构就根本不是为了我们所熟知的http/https协议所设计的。相反,他们是为了p2p网络或者说是区块链网络而设计运用的。接下来我们慢慢进入正题。


Merkle树

有关上文提到的http/https协议和p2p网络的区别,这里不做多介绍。可以参考我上两篇博客,这里直接介绍数据结构。

首先Merkle树本质上就是一个树,而且还是一个二叉树,直接上图:

在这里插入图片描述

可以看到叶子结点下面居然还有一层数据块,按理说叶子结点应该就是结束了,下面没东西了。那么数据块又是啥呢?

这里是这样的,叶子结点存储的是数据块内的数据根据哈希算法计算出来的哈希值(hash)。 说白了就是存储着哈希值。得到哈希值之后,在将相邻的两个结点合起来再计算一次哈希值,存储在它们的父结点中。像上图中的结点A存储着叶子结点A与叶子结点B的哈希值结合。同理,结点A与结点B在结合进行一次哈希计算,得到根节点的哈希值。

在这里需要注意一下,如果叶子结点的个数是奇数怎么办,那么就不能两两配对,进行结合哈希计算了。答案是也可以的,与自己配对进行结合哈希计算即可。

数据结构大致就是这个流程,不难理解。那么问题又来了,这样子设计有什么好处呢?

在前言中就介绍到了,Merkle树是运用在p2p或者区块链网络中的。而IPFS就是里面的代表,有关这方面可以参考之前的博客《区块链杂谈—谈谈我所理解的IPFS》《区块链杂谈—简单记录Fil是个啥?》

我们知道在Fil网络中,主网会要求矿工提交复制证明,即证明矿工是真实且正确存储了客户所要的数据。而怎么验证这个数据的正确性呢?就要用到我们所介绍的MerKle树了。

我们知道哈希算法,只要有一个字节不一样,那么最终计算出来的哈希值就会不相同。那么就可以直接比对根节点的哈希值,如果不一样,那就说明没有存储到正确的数据。从而比对出了数据的完整性。

这里打个比方,简单说明比对过程。还是上面那张图:

在这里插入图片描述

  1. 首先比对根节点的哈希值,发现不一样。
  2. 接着往下走先比较结点A是否一致,发现不一致,再往下走。
  3. 叶子结点A一致,比较叶子结点B的哈希,发现不一致。找到数据块B不一致。

这里就定位出了具体哪一个数据块受损或者被攥改。由于每次比对它的规模都减半,所以在Merkle树中,它的比对时间复杂度为O(logn)。可以看到,效率还是很快的。

Merkle树还被用于在分布式的数据库中,一个文件在分布式数据库中可能会有多个备份,要确保备份之间的一致性,就可以用到默克尔树了。


hash list(哈希列表)

接下来记录一下另外一种数据结构—hash list(哈希列表)。它和Merkle树很像,可是又不一样。先上图:

在这里插入图片描述

大家可以看一下,它比Merkle树少了什么?没错,哈希列表根节点下面就直接一层叶子节点,而叶子结点存储的是数据块数据进行哈希运算得到的值。

这一段是我在网上看到的:

在点对点网络中数据传输的时候,为了提高效率往往会同时从多个机器下载数据的不同部分。
即,不是从一台机器下载整个数据,而是将完整数据分成不同的部分,
分别同时从不同的机器获取完整数据的不同组成部分。
这样分块传输不但可以同时从多台机器下载数据,另一个好处是如果这一小块数据传输过程中损坏了,
只要重新下载这一小数据块就可以了,不用重新下载整个数据。

在这种环境下,怎么确保数据的完整性呢?

我们可以在下载前,对每一个数据块进行一次哈希运算,然后在对这些数据块哈希进行一次结合哈希运算,得到根哈希,从而得到一个哈希列表。这个列表我们自己存着。

之后就可以下载数据了。下载完成后,直接比对根哈希,如果一致,则说明没有损坏。如果不一致,像上面Merkle树一样,去比对那个数据块受损或者被攥改。


两者区别

大家发现,两个数据结构都有相似的功能,那么怎么选呢?

哈希列表比对数据时,是直接进入叶子节点来比较,而不像Merkle树那样,有个二叉树分出去。所以它的时间复杂度为O(n)

因此,在数据量大,数据块多的时候,Merkle树的效率会更高。


感谢您的观看🙏

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页