客官(小姐姐):哎,小二,我看之前有篇文讲到Merkle Tree,听说你要讲Merkle Tree,这Merkle Tree究竟是什么?
小二(我): 嗯,是的,小姐姐今天真幸运,我现在就给你细细讲解。
客官(小姐姐):等等,我先搬好小凳子,好了,你说吧。
小二(我):........
在我说Merkle Tree 之前,我想讲讲另外一个与merkle tree 息息相关的Hash。
1.hash
hash(哈希), 我们通常把哈希函数简称哈希(hash),所以这个hash事实上是一个函数,它也叫做散列函数,在百度百科的定义就是:
把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
使用hash比较突出的特征就是如果输入稍微有不同,那么产生的hash值就有巨大的变化,因为有这个特征,所以可以用来对文件进行完整性校验;由于不同的输入可能会产生相同的输出,所以也很难通过产生的hash值来唯一确定输入,也就是我们很难逆向推算出原来的输入信息,提高了安全性。
我们说验证文件数据的完整性可以通过验证其hash值,那么如果我们验证的这个文件过于庞大呢?按照之前的思路,我们可能就会想着把整个文件生成一个hash来验证不就行了吗?是的,这是可行的,但是我们可以再往更加便利的方向思考,如果经过对比自己所下载的文件与原来文件的hash值不一样,我们就得重新下载一个完整的文件,但问题来了,我们的前提条件已经说了这个文件是大文件下载是需要更多的时间的,然后我们对比过hash值不同后再重新下载文件,等同再花费同样更多的时间,这样的效率十分的低,我们都不想这样浪费时间。
所以,我们都很聪明,想到了把文件分块,分别为这些数据块做hash运算,然后把这一个个hash值串在一起再做hash运算得到一个总hash值来代表这个文件,我们把这些生成的一个个hash值作为这个文件的hash列表(hash list),把总的hash值称为该文件的根hash(root hash),然后当我们下载文件,发现根hash不同,就会往下逐个逐个比较是哪一个hash不同,找到不同的hash就可以只是重新下载不同hash的那个文件小分块,而不用花大时间重新下载大文件了。
客官您可以看看下面的图会更容易理解:
2.merkle tree
有了上面hash的基础,我们就可以进入merkle tree的环节。
为什么提到merkle tree 要提及hash的知识呢,事实上merkle tree(默克尔树) 又叫 hash tree(哈希树)。顾名思义,hash tree 就是由hash值组成的 。我们在上段提到的hash list 其实就是 merkle tree 的特殊形式。而我们说的merkle tree 跟hash list相比起来就是:1、merkle tree一般是二叉树的形式;2、Merkle Tree的叶子节点的value是数据集合的单元数据或者单元数据hash;3、Merke Tree非叶子节点value是其所有子节点value的hash值。
同样的,小二我用一张图来个客官您认识下merkle tree:
根据上面这张图,我们来说说一个文件生成的默尔克根是怎么实现的。
首先还是一个文件把它分块,我们祈祷着这分块的数目最好是偶数,那就可以生成偶数个哈希值,再每相邻两个哈希值串在一起再次做哈希运算,因为上文提到默尔克树一般为二叉树,所以一个节点最大分支数就是2,所以每两个哈希值串起来做哈希运行算就能得到这两个哈希值结合生成的‘子哈希’。
那么如果文件分块出来是奇数的话,对于最后多出来的那一个小数据块的处理就是一直对它进行哈希运算,尽管没有其它哈希跟它匹配(可怜的单身汪),它自身可以自己产生子哈希。不断生成子哈希直到最后只生成两个子哈希节点的时候,当他们再串起来结合生成一个唯一的哈希值,这个值就叫做根哈希,也是默尔克根。
不单单除了文件分块数目是奇数时用上文的规则,只要每一层的子哈希数目是奇数,那多出来的那个子哈希也要自己做哈希运算。
merkle tree 和 hash list 的区别是什么呢?小二我引用某段话来说。
Merkle Tree和Hash List的主要区别是,可以直接下载并立即验证Merkle Tree的一个分支。因为可以将文件切分成小的数据块,这样如果有一块数据损坏,仅仅重新下载这个数据块就行了。如果文件非常大,那么Merkle tree和Hash list都很到,但是Merkle tree可以一次下载一个分支,然后立即验证这个分支,如果分支验证通过,就可以下载数据了。而Hash list只有下载整个hash list才能验证。
简单的说就是merkle tree 比 hash list 更加有效率,并能节省时间。
3.区块链中的merkle tree
刚刚客官您对merkle tree有了一定的概念之后,小二我就可以说说这个merkle tree在区块链上是怎么回事。
我们已经知道了merkle tree 的出现就是为了校验,那么我们可以想到了,merkle tree 可以校验文件是否一致,即一致性校验。那么在区块链中也是一样道理。merkle tree 是校验交易数据的一致性,即可以知道交易数据有没有损坏,或是被攥改。这样就可以保证我们在每一个区块上的交易记录的不可更改性,或是不可重复交易。
客官是否还记得那张区块链merkle tree的 图?若忘记了的话,小二我这下面再放上去给您看看。
从这幅图中我们可以知道一个区块中记录了数笔的交易,而至于这具体的数目是多少,是说不准的,因为一个区块的容量为1M,每一笔的交易大小都不同,平均可能是250字节,那么一个区块算下来就可容纳2500笔交易左右。然后把这么多的交易数据不断进行哈希运算,形成merkle tree,最终生成一个默尔克根放在每一个的区块头上。可以进行校验。
merkle tree 能进行一致性校验,同时也可以进行数据校验,验证某一条数据是否存在,检验到与默尔克根值不同,那就证明某一条数据并不存在。至于具体的的内容小二我给客官您一张推荐劵——理解区块链背后的Merkle Tree
文章写得很详细,小二我强烈推荐。
客官(小姐姐):小二,可以了,我现在脑胀了,我得好好消化才继续听你讲吧
小二(我):好的,欢迎再来,我在这里再给您一张推荐劵——MerkleTree概念,相信客官拥有了这两张推荐劵,能够对merkle tree豁然开朗(微笑)。