区块链入门系列之梅克尔帕特里夏树

区块链入门系列文章

区块链基本概念和名词解释
P2P
共识算法
梅克尔-帕特里夏树
从零开始搭建区块链

这里写自定义目录标题

前言

在讲基本概念那篇文章,提到过区块,如果区块仅仅是一个区块是无法实现那么Web3这么宏伟的蓝图的,还需要区块当中的数据。这些数据在区块中是以什么样的数据结构存储的,以及为什么要使用这样的数据结构,就是本章需要讲到的内容。

Merkle树

Merkle树即梅克尔树,是一种二叉Hash树,其数据全部存储在Leaf节点,Branch节点和Root节点均存储的Hash值。首先Leaf节点计算自身数据的Hash,然后再和Brother节点的Hash组合后再进行Hash即为Parent节点的Hash,就这样一步步向上传导最终生成Root节点的Hash即为Merkle根。形成的Merkle根就可以和区块本身的基础字段一起组合形成区块的Hash,就这样就保证了区块内部的任何东西哪怕1bit都不会被篡改。
在这里插入图片描述

图源自网络侵删

为什么要搞出这样复杂的数据结构,因为这样的数据结构易于实现交易的验证。要具体解释,则不得不提到 Wallet 即钱包的概念,第一章讲过每一个账户实际上就是一个个的私钥,通过该私钥就可以签发独属于你的交易,而钱包就相当于是一个客户端,管理着着一个个的私钥,通过和区块链网络交互实现一些业务需求。区块链网络中当块高很高时其存储的数据动辄几百个GB,普通用户并没有挖矿记账的需求,完全没必要下载完这些数据,那么问题就来了,不下载数据的前提下要如何验证一笔交易的合法性呢?这又引出另外一个概念SPV,Simplified Payment Verification即轻验证,钱包中只需要下载所有区块的区块头即可,区块头中包含了Merkle Root Hash。当用户收到一笔交易,想要验证这笔交易是否合法,只需要向区块链网络中发起Merkle Block Message的查询请求即可,具有完整区块的节点收到后,就将完整的验证路径查询出来并返回。
就拿上图中的交易3来说,如果验证这笔交易是否合法,查询出hash3、hash4、hash12、hash34、hash1234、hash5678、hash12345678返回即可。前面说了,客户端有Root Hash即hash12345678,客户端只需要计算交易3的hash是不是hash3,hash3和hash4组合hash后是不是hash34,hash12和hash34组合后的hash是不是hash1234…如果都是正确的,则返回的Root Hash和本地存储的Root Hash肯定是一样的,那就说明了该笔交易是合法的。这个证明过程就是零知识证明,并没有提供任何交易相关的内容却有力证明了该笔交易的合法性。
不知道大家发现没有,上述验证过程中,完整节点响应的数据中就以及包含了Root Hash,直接比对Root Hash是否一样不就好了吗,为什么还要再做一次Merkle Hash呢?这是为了进一步验证交易的真实性,假设Root Hash是真,交易是假,验证路径是为了构造出这个真Hash计算出来的,这种情况就必须要亲自计算且计算的验证路径完全一致才能确认交易是真。原理是SHA256碰撞概率本来就微乎其微了,经过层层的计算,通过伪造数据来得到一个确定的Hash值几乎是不可能的。
到这里其实都还有一个Bug,那就是返回的Root Hash是真,交易是真,路径也是真,但是这条链不是最长链,就可能导致这笔“真实”的交易还没有被最终确认就被拿出来验证。为了避免这种情况,收到响应时,需要先同步一下最长链的区块头信息,以确保返回的交易信息是否已经经过了6个区块,因为区块链中交易只有在所在的区块被追加上6个区块才算是被最终确认。

MPT

MPT,Merkle Patricia Tree即梅克尔帕特里夏树。顾名思义这种树结合了两种基本树的特征,先简单说下Patricia Tree。如果一个基数树的“基数”(radix)为2或2的整数次幂,就被称为“帕特里夏树”,也可以直接认为帕特里夏树就是基数树。而基数树又是以二进制位串为关键字的trie 树即前缀树(或字典树),是一种多叉树形结构,同时又类似多层索引表,每个中间节点包含指向多个子节点的指针数组。那么先简单看看前缀树的数据结构

root
a
h
n
n
d
a
y
o
e

是不是很像我们的字典,当你要查询牛津字典中Anna的位置,那肯定是先找A的位置,然后再找n的位置…直到找到该单词。前缀树就是这样的原理,可以看到当需要查找字符串“anna”时,只需要从树根开始一个字母一个字母搜索,即可成功遍历出来。其中粉色的节点就是我们的搜索节点,而红色的节点就是搜索到这里就会停止往下搜索的节点,所以这种数据结构的查找复杂度是log级别的。
这里抛出一个问题,就拿图中这个前缀树而言,存储了哪些数据呢?答案是anna、ann、andy、hoe,看到一个“奇怪”的节点了吗(空:那我走?),在前缀树中如果存储的数据刚好Branch节点就能完全覆盖时会多存储一个空节点来表示。
接下来再看看什么是基数树的数据结构

root
00
01
10
11
11
10
10

可以看到这棵树中存储的是二进制数字(或者16进制字符),每个节点存储两个比特位(或者n个比特位)。一般认为帕特里夏树就是在基数树的基础上进一步压缩存储空间,在数据完全存储于Branch节点中且该节点是唯一的儿子的话,就和父节点合并。

root
00
01
10
11
1110
10

铺垫这么久,总算可以开始讲MPT了。前面在讲Merkle树的时候提到了对于钱包的交易验证需求已经完美实现了,而MPT则是进一步优化查询和存储性能。
MPT中节点有如下几种类型:

  • 叶子节点:末端节点,也是存储数据的节点
  • 扩展节点:合并了相同hash的节点(下面一定是分支节点)
  • 分支节点:长度为17的list类型节点(MPT和MerkleTree类似非叶子节点中存储的是hash,和Merkle不同的是MPT存储的是hash片段即前缀,由于MPT中的最小单位是nibble,长度是0.5字节,取值范围刚好是[0,15],在加上一位value,所以长度刚好17)
  • 空节点:顾名思义就是为null的节点

接下来先看一张图,这是MPT中的存储结构示意图
在这里插入图片描述
可以看到存储的四条数据a711355、a77d337、a7f9365、a77d397均存储在叶子节点,大家都复用了a7这个前缀所以有a7这个扩展节点(有两条数据复用了d3所以有这个扩展节点),扩展节点下面紧跟着的就是分支节点。分支节点复用的是索引号,拿a77d337这条数据来举例,在第一个分支节点中索引是7,第二个分支节点索引是3,组合起来刚好构成a7、7、d3、3、7这个key。

每个节点都会有一个固定的前缀,具体的对应关系如下表

类型 路径奇偶 标记符 bits
扩展节点 0 0000
扩展节点 1 0001
叶子节点 2 0010
叶子节点 3 0011

其中节点的类型已经清楚了,这个路径奇偶是什么意思呢? 就是扩展节点或叶子节点中的hash片段个数是奇数还是偶数,比如上面的“1355”、“d3”、“9365”是偶数个,而两个“7”就是奇数个,所以他们前面的prefix分别按照表格中的对照关系填充了标记符。
那这个prefix又是干嘛的呢? 这里就不得不提一下以太坊的为MPT树实现的三种不同编码方式

类型 简述 示例(原始数据cat)
Raw编码 直接是原生字符 [‘c’,‘a’,‘t’]
Hex编码 16进制拆分编码 [3,15,3,13,4,10]
Hex-Prefix编码 16进制前缀编码 [3,15,3,13,4,10,16]

Raw和Hex一目了然,Hex-Prefix最后的那个16是什么玩意。cat一共三个字节,被拆分成6个nibble,分别是3、15、3、13、4、10,即这几个字符ASCII编码的二进制高4位和低4位组成的16进制数,6刚好是偶数,说明prefix是0或者2。本来就偶数个nibble再填充一个不就单上了吗,所以当偶数时后面还会默认填充“0000”,刚好组成“0010 0000”即16。
本来简单的编码干嘛整的这么复杂,好处是什么? 其实就是为了实现前缀压缩树的特性,复用数据的hash路径信息。设计出nibble这个半字节概念,强行把树的度限制为最大16,而Hash值长度是32或64位甚至更高,这就变相增加了树高,可能是ETH团队经过大量测试之后的一个最优取值。有了nibble的概念后,节点的路径信息就可能出现半字节,所以需要补齐,正好又加上一个标记位来存储节点类型,所以最后奇数个直接补上,偶数个再填充上0000。
前面讲的都体现出帕特里夏树的特性,梅克尔树除了Key是Hash外并没有体现出任何特点来呢? 那就先看一张MPT中各节点Value的存储示意图
在这里插入图片描述

图源自网络侵删

如前文所述,叶子节点存储的真实数据,其他节点这是和Merkle一样从叶子节点开始逐步计算Hash值进行填充,就完美实现了和Merkle一样的轻节点效果。其中各个Hash值的计算内容如下表所示
key value
h00(roothash) hash(0+a7+h10)
h10 hash(h20+h21+h22)
h20 hash(0+1355+h30)
h21 hash(0+d3+h31)
h22 hash(0+9365+h32)
h30 45
h31 hash(h40+h41)
h32 1.1
h40 hash(0+7+h50)
h41 hash(0+7+h51)
h50 1.0
h51 0.12

总结

其实区块链当中还有很多新概念,比如

  • Oracle
  • EVM
  • Solidity
  • DApps
  • DAO

  • 只是这些概念是真正从事区块链开发的才更需要关注,我们的目的只是带大家入门,能了解区块链的基本概念,能从零开始搭建一个简易的区块链即可。所以更多区块链相关的概念大家有兴趣可以自行了解,当然后期也可能不定期更新一些。

猜你喜欢

转载自blog.csdn.net/aa54682002/article/details/127426554