目录
1. 基础算法
Merkle Patricia Trie,简称 MPT,是 Merkle Tree 和 Patricia Trie 的结合。在介绍 MPT 之前,我们先来看看构成它的基础算法。
1.1 Merkle Tree
Merkle Tree,默克尔树,表示将数据块做哈希之后,作为叶子节点,再合并多个节点计算哈希,得到新节点,重复以上步骤直到得到一个根节点,形成一个树状结构,如下图:
可见,默克尔树的树根就相当于对所有的数据做了一个哈希,可以用来校验数据的完整性。但这有什么好处呢?为什么不直接把所有数据合并,直接计算一个哈希呢?既然中间多出了这么多冗余的哈希,那自然会有它的用处。实际上,这常被用来做 默克尔证明(Merkle Proof)。一个默克尔证明包含一个数据块、树根、以及经过这个数据块到树根之间的路径的所有哈希。使用默克尔证明可以快速验证一个数据确实存在树中的某个位置。攻击者无法伪造一个默克尔证明,因为根哈希依赖于其他所有节点的哈希,每一个节点的修改都会导致根哈希不一致。
默克尔证明最初被应用在比特币中,区块链中每个区块的交易计算哈希并形成一棵默克尔树,并将树根存储在区块头中。
这可以应用在“简单支付校验”(simplified payment verification)中:“轻客户端”节点无需下载区块的所有交易数据,只需要下载区块头,当需要获取一个交易的状态时,只需要向全节点请求该交易的一个默克尔证明,以证明该交易确实存在于一棵默克尔树中,并且该树的树根记录在区块头中。
1.2 Trie
Trie 是一种有序的树结构,用于存储和检索键值对(key-value),其中 key 可以映射到有限“字符集”组成的字符串,树的每个节点记录了一个字符,并且指向了下一个字符,每个路径可以组成一个完整的 key,这使得节点可以共享相同的前缀。这种数据结构可以高效地存储和检索有相同前缀的 key 集,实现简单并且占用内存小,常被用于实现路由表以及在路由器等低规格的设备中运行的系统。
“Trie” 一词提取自 “retrieval”(数据检索)的中间部分,根据其特征,也叫前缀树(Prefix Tree)、字典树等。
上图表示了一棵前缀树,存储了 key 值 "A", "to", "tea", "ted", "ten", "i", "in", 和 "inn",每个 key 对应了一个数字作为 value,比如 "A" 对应的值为 15。注意图中的节点标注了完整的单词,但这只是为了演示 Trie 的原理,实际上完整的 key 并不存储在节点中,而是由路径组成的。
在一种具体实现中,Trie 的每个节点存储了一个固定长度的数组,数组的每个元素(除最后一个元素)是指向子节点的指针,数组的最后一个元素存储了 value(若存在),表示根节点到本节点的路径组成的 key 对应的 value。
例如,一种用来存储英文单词(26个字母)的树,每个节点存储的数组长度为 27,下标 0~25 代表 a-z 字符,下标 26 代表 value。如下图所示:
Trie 有一个很大的缺点,即当某个 key 不与其他 key 共享前缀,并且长度很长时,会使得树极为不平衡,即高度不可控,这给攻击者提供了攻击的可能。如下图所示:
为了解决这个问题,有新的数据结构被提出。
1.3 Patricia Trie
Patricia 一名取自论文 PATRICIA - Practical Algorithm to Retrieve Information Coded in Alphanumeric 的首字母缩写