区块链数据结构概述(MT、MPT)

  • Ethereum Foundation Blog
  • MT
    • Hash List
    • Merkle Tree
    • Merkle Tree的主要特点
    • Merkle Tree的相关操作
  • MPT(Merkle Patricia Tree)
    • Tire
    • Patricia Trie
    • MPT
    • MPT的相关操作
    • MPT的主要特点

Ethereum Foundation Blog

https://blog.ethereum.org/2015/11/15/merkling-in-ethereum/

以太坊的一篇博客对MT做了一个简单的描述:
Merkle trees是区块链的基本组成部分。虽然理论上完全可以不使用Merkle trees来构建区块链,直接通过创建巨大头部来处理每一笔交易,但这样做会带来巨大的可扩展性挑战,从长远来看,除了最强大的计算机之外,其他所有计算机都无法可靠地使用区块链。
由于有了Merkle trees,我们就有可能在所有大大小小的电脑和笔记本电脑、智能手机、甚至物联网设备上构建以太节点。
最简单的Merkle Tree的形式是下图展示的这种二叉树。每个节点有两个孩子, 叶子节点是数据的哈希值。

Merkle Proofs
这种结构可以提供一种叫Merkle Proofs的机制。使用默克尔证明能够实现轻节点的扩展。
默克尔证明指的是一个轻节点向一个全节点发起一次证明请求,询问全节点完整的默克尔树中,是否存在某个指定的节点;全节点向轻节点返回一个默克尔证明路径,由轻节点进行计算,验证存在性。
首先Merkle树的根是公开的、受信任的。Merkle Proofs包含三部分: 一个待验证的块数据的哈希(如图中的9Dog:64), 一个根哈希(如图中的6c0a)以及验证路径(图中黄色部分: 1FXq:18, ec20, 8f74)。
具体的验证过程如图所示:一颗 merkle tree,如果某个轻节点想要验证图中绿色的这个节点是否存在,只需要向全节点发送该请求,全节点会返回一个如图中黄色块显示的路径。得到路径之后,轻节点依次求哈希,最后将得到的结果与本地维护的根哈希相比,判断其是否相等。

Merkle Proofs in Bitcoin
Merkle Proofs最早应用在比特币中, 如图所示比特币用所有交易的哈希构造了一颗Merkle Tree, 而Merkle Tree的根哈希写在区块头中:

这种设计可以支持SPV(简单支付验证): 当验证一笔交易的时候,它不需要下载所有区块和交易信息, 只需下载80字节左右的区块头就可以了。区块头包含:前一个区块头的哈希值、工作量证明nonce以及 该区块中所有交易组成的Merkle Tree的根哈希和一个时间戳。
如果客户端想验证一笔交易的可靠性, 只需要按照前面说的Merkle Proofs过程提供交易哈希和路径, 再经过一系列哈希运算后比对根哈希就可以了。
这样客户端避免了下载所有区块数据进行交易验证的噩梦, 我们称这种客户端为轻客户端。

Merkle Proofs in Ethereum

以太坊中的区块头包含三颗Merkle Tree, 分别是: 交易树, 单据树, 状态树。
这种设计使得它能处理一些比特币不能处理的问题 。比如:可以查看账户信息等等。
它的Merkle Proofs证明过程和比特币是一样的。也是提供路径,经过哈希计算,比对跟哈希值是否相同。

MT

区块链中的一个比较重要的概念就是hash指针。
Hash Pointers:与普通的指针不同的是它不仅要保存结构体的地址还要保存结构体的hash值。然后从这个Hash指针不仅能找到这个结构体的位置还能检测这个结构体是否被篡改。区块链就是使用Hash指针代替普通指针。

用hash指针来实现链表就是区块链;用hash指针来实现二叉树就是默克尔树。MT是Hash List的一个泛化。

Hash List


Hash List:当传输一个大的数据时可以将其分成多个小的数据块,为了判断每一个小的数据块在传输过程中没有损坏。在得到真正的数据之前,会得到一个哈希列表。
把每个小块数据的Hash值拼到一起,然后对这个长字符串在作一次Hash运算,这样就得到Hash列表的根Hash。传输数据的时候,首先从可信的数据源得到正确的根Hash,就可以用它来校验Hash列表了,然后通过校验Hash列表来校验数据块是否被篡改。

Merkle Tree


Merkle Tree就是在Hash List上作了相应的改进。他的最下面一层是也是数据块或者是交易,内部节点还是Hash指针 。但是不同的是它不是直接将所有的hash值拼到一起去运算根哈希,而是把相邻的两个哈希合并成一个字符串,然后运算这个字符串的哈希,得到一个“子哈希”。如果最底层的哈希总数是单数,就会有一个哈希值不用合并直接进行哈希运算。依次往上推,最终能得到一棵Merkle tree,树根处只有一个根哈希,记为Merkle Root。
在P2P网络下传输文件之前,先从可信的源获得文件的Merkle Root,就可以从其他不可信的源获取Merkle tree。通过可信的Merkle Root来验证Merkle tree是否损坏或者是虚假的。
Merkle Tree和Hash List的主要区别是,可以直接下载并立即验证Merkle Tree的一个分支。因此merkle tree可以一次下载一个分支,然后立即验证这个分支,如果验证通过,就可以下载这个分支。而Hash List是只有下载整个Hash List才能验证。MT与binary tree的区别就是使用Hash指针代替了普通指针。

Merkle Tree的主要特点

快速重哈希
就是当树节点内容发生变化时,能够在前一次哈希计算的基础上,仅仅将被修改的树节点进行哈希重计算,便能得到一个新的根哈希用来代表整棵树的状态。

轻节点扩展
采用默克尔树,可以在公链环境下扩展一种“轻节点”。轻节点的特点是对于每个区块,仅仅需要存储约80个字节大小的区块头数据,而不存储交易列表,回执列表等数据。然而通过轻节点,可以实现在非信任的公链环境中验证某一笔交易是否被收录在区块链账本的功能。这使得像比特币,以太坊这样的区块链能够运行在个人PC,智能手机等小存储容量的终端上。

Merkle Tree的相关操作

Merkle Tree创建:

step1:(红色线)对数据块做hash运算,Node0i = hash(Data0i), i=1,2,…,9
step2: (橙色线)相邻两个hash块串联,然后做hash运算,Node1((i+1)/2) = hash(Node0i+Node0(i+1)), i=1,3,5,7;对于i=9, Node1((i+1)/2) = hash(Node0i)
step3: (黄色线)重复step2
step4:(绿色线)重复step2
step5:(蓝色线)重复step2,生成Merkle Tree Root

检索
检索错误节点的过程如图所示:

Step1. 首先比较v0是否相同,如果不同,检索其孩子node1和node2.
Step2. v1 相同,v2不同。检索node2的孩子node5 node6;
Step3. v5不同,v6相同,检索比较node5的孩子node 11 和node 12
Step4. v11不同,v12相同。node 11为叶子节点,获取其目录信息。
Step5. 检索比较完毕

MPT(Merkle Patricia Tree)

Tire


Trie是一种字典树,用于存储文本字符,并利用了单词之间共享前缀的特点,所以叫做前缀树。如左图所示,Trie的高度只与最长的文本串的长度s有关系,而与单词的数量n无关。Trie的节点分两种:内部结点和叶子结点,内部结点用来存储单词的共享前缀字母,叶子结点存储该单词的数据内容(data)。但内部内部结点和叶子结点并不是互斥的,一个内部结点本身可以有叶子结点,同时它也可以是一个叶子结点。
3个基本性质:
1、根节点不包含字符,除根节点外每个节点都只含一个字符
2、从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3、每个节点的所有子节点包含的字符都不相同。

Patricia Trie


压缩前缀树:是一种更节省空间的Trie。对于树的每个节点,如果该节点是唯一的儿子的话,就和父节点合并。

MPT

Merkle Patricia Tree(又称为Merkle Patricia Trie)是一种经过改良的、融合了默克尔树和前缀树两种树结构优点的数据结构,是以太坊中用来组织管理账户数据、生成交易集合哈希的重要数据结构。
MPT树中的节点包括空节点、叶子节点、扩展结点和分支节点。
1、空节点(NULL):简单的表示为空,在代码中就是一个空串。
2、叶子节点(leaf):2元组[key,value]。第一个字段是剩下的Key的RLP编码。第二个字段是value值。
3、拓展节点(extension):也是[key,value],但是这里的value是其他节点的hash,通过这个hash链接到其他节点。
4、分支节点(branch):MPT中的key被序列化成一种特殊的16进制编码,在加上最后的value,所以分支节点是一个长度为17的list,前16个元素对应着key中的16个可能的十六进制字符,如果有一个[key,value]对在这个分支节点终止,最后一个元素代表一个值(例如,有三个key,分别是(abc,abd,ab)第17个字段存储了ab节点的值)即分支节点既可以搜索路径的终止也可以是路径的中间节点。
MPT树中另外一个重要的概念是一个特殊的十六进制前缀(hex-prefix, HP)编码,用来对key进行编码。因为字母表是16进制的,所以每个节点可能有16个孩子。因为有两种[key,value]节点(叶节点和扩展节点),它们的存储结构是完全相同的,所以引进一种特殊的终止符标识来标识key所对应的是值是真实的值,还是其他节点的hash。如果终止符标记被打开,那么key对应的是标准叶子节点,它的值是真实的value。如果终止符标记被关闭,那么值就是用于在数据块中查询对应的节点的hash。

如图所示是以太坊中的一个世界状态,假定有四个账户,那么他就对应了如图所示的一棵MPT。首先依据压缩前缀树的特性,判断的key的公共前缀,就是图中的第一个拓展节点a7,然后依据HP编码规则,给拓展节点加一个标记符。图中对标记符做了相应的定义,一个半字节nibble被加到key前(上图中的prefix),对终止符的状态和奇偶性进行编码。最低位表示奇偶性,第二低位编码终止符状态。可以看到如果key长度是偶数,就会再加上另外一个值为0的半字节,保持整体的偶特性。拓展节点下面接的是一个分支节点,如果某个账户的key刚好到分支节点结束,那么它的值就直接存储到分支节点的value域中,如果没有就继续向下寻找公共前缀。可以看到1355这个账户和其他账户没有公共前缀,所以它直接被定义为一个叶子节点。有公共前缀就继续之前的过程,直到所有的账户都被写入MPT中。这样一颗MPT就被构造完了。

MPT的相关操作

检索
首先将需要查找的key转换为十六进制拓展编码,得到的内容就是搜索路径。从根节点开始搜索与搜索路径内容一致的路径:然后分几种情况
1)若当前节点为叶子节点,存储的内容是数据项的内容,且搜索路径的内容与叶子节点的key一致,则表示找到该节点;反之则表示该节点在树中不存在。
2)若当前节点为扩展节点,存储的内容是另外一个节点的引用,且当前节点的key是搜索路径的前缀,那么就将将搜索路径减去当前节点的key,将剩余的搜索路径作为参数,对其子节点递归地调用查找函数;若当前节点的key不是搜索路径的前缀,表示该节点在树中不存在。
3)若当前节点为分支节点,若搜索路径为空,则返回分支节点的存储内容;反之利用搜索路径的第一个字节选择分支节点的孩子节点,将剩余的搜索路径作为参数递归地调用查找函数。

上图是一次查找key为”cat“节点的过程。
将key"cat"转换成16进制前缀编码[3,15,3,13,4,10,T] (在末尾添加了也该终止符T,来判断终止);
当前节点是根节点,且是扩展节点,其key为3,15,则递归地对其子节点进行查找调用,剩余的搜索路径为[3,13,4,10,T];
当前节点是分支节点,以搜索路径的第一个字节内容3选择第4个孩子节点递归进行查找,剩余的搜索路径为[13,4,10,T];
当前节点是叶子节点,且key与剩余的搜索路径一致,表示找到了该节点,返回Val为“dog”;

插入
插入操作是基于查找操作完成的,插入过程如图所示:
1、首先找到与新插入节点拥有最长相同路径前缀的节点
2、若该节点是分支节点:
1)剩余的搜索路径不为空,那么就将新节点作为一个叶子节点插入到对应的孩子列表中;
2)如果剩余的搜索路径为空(完全匹配),则将新节点的内容存储在分支节点的Value中;
3、若该节点为叶子/扩展节点:
1)剩余的搜索路径与当前节点的key一致,则把当前节点的更新即可;
2)剩余的搜索路径与当前节点的key不完全一致,则将叶子/扩展节点的孩子节点替换成分支节点,将新节点与当前节点key的共同前缀作为当前节点的key,将新节点与当前节点的孩子节点作为两个孩子插入到分支节点的孩子列表中,同时当前节点转换成了一个扩展节点(若新节点与当前节点没有共同前缀,则直接用生成的分支节点替换当前节点);

删除
删除操作与插入操作类似,都需要借助查找过程完成,删除过程:
1、若节点不存在则删除失败。
2、若节点是叶子节点则删除该节点,并判断删除后该分支是否只剩一个叶子节点,若是,则将该节点的值给分支节点的value。
3、若与扩展节点的值完全相同,且分支节点的value存在,则删除分支节点的value。

MPT的主要特点

MPT的主要特点就是能够实现快速状态回滚
区块链公链的环境下,可能会造成分叉而导致区块链状态需要进行回滚的。在以太坊中,由于出块时间短,这种分叉的几率很大,区块链状态回滚的现象很频繁。
所谓的状态回滚指的是:(1)区块链内容发生了重组织,链头发生切换(2)区块链的世界状态(账户信息)需要进行回滚,即对之前的操作进行撤销。
MPT树就提供了一种机制,当区块发生了碰撞,零延迟地完成世界状态的回滚。这种优势的代价就是需要浪费存储空间去冗余地存储每个节点的历史状态。(虽然每生成一个新的区块就会有一棵状态树,但它与前一区块的大部分节点是共享的)
每个节点在数据库中的存储都是值驱动的。当一个节点的内容发生了变化,其哈希相应改变,而MPT将哈希作为数据库中的索引,也就实现了对于每一个值,在数据库中都有一条确定的记录。而MPT是根据节点哈希来关联父子节点的,因此每当一个节点的内容发生变化,最终对于父节点来说,改变的只是一个哈希索引值;父节点的内容也由此改变,产生了一个新的父节点,递归地将这种影响传递到根节点。最终,一次改变对应创建了一条从被改节点到根节点的新路径,而旧节点依然可以根据旧根节点通过旧路径访问得到。


如图所示,当MPT中一个节点的内容由27变为45,就对应成创建了一条的新路径,通过复用前一个中的未修改节点信息,构造一棵新树,但是它的旧路径依旧保留。因此通过旧stateRoot,依旧能够查询到该节点的值为27。
所以,在以太坊中,发生分叉而进行世界状态回滚时,只需要用旧的MPT根节点作为入口,就能完成一次“状态回滚”。

区块链数据结构概述(MT、MPT)相关推荐

  1. 如何用 Python 快速开发一个区块链数据结构?

    作者 | arjuna sky kok 整理 | Aholiab 出品 | 区块链大本营(blockchain_camp) 根据IEEE此前的一项调查,Python已成为最受开发者欢迎的语言之一.由于 ...

  2. (三) 区块链数据结构 – 交易

    区块由交易组成.区块体中包含若干项交易数据. 交易 交易主要包含两类数据:交易输入和交易输出. - 交易输入用来指明钱的来源 - 交易输出用来指明钱的去向 除了交易输入和交易输出外,交易中还包含版本号 ...

  3. 国外大牛教你,如何用Python开发一个简单的区块链数据结构| 建议收藏

    来源 | Medium 作者 | arjuna sky kok 整理 / Aholiab 出品 | 区块链大本营(blockchain_camp) 根据IEEE此前的一项调查,Python已成为最受开 ...

  4. 区块链存储优化——从MPT树到KV存储

    MPT树存储的优缺点 区块链如果采用MPT树存储,大概会有以下优点: 可用全局数据的根哈希做共识,数据篡改会被立即发现: 可以查询任意历史区块对应时刻的所有数据: 方便从指定区块开始同步数据,因为正如 ...

  5. Hyperledger Fabric 超级账本 区块链技术 概述 优点

    超级账本概述 区块链的第一个也是最被广泛认可的应用是比特币,另一种加密货币以太坊采取了不同的方法,它集成了许多与比特币相同的特征,添加了智能合约来创建分布式应用程序的平台.比特币和以太坊属于区块链,我 ...

  6. 都2021年了,还不知道什么是区块链就out了 | 从区块链数据结构到应用

    序言 在现阶段及后10年都是发展主流的数字化经济的催动下,区块链技术越来越火爆.那么比特币的区块数据结构是如何构成的,区块链有什么特性,我们用区块链能用来做什么?我们一起来探讨下. 区块链诞生背景 2 ...

  7. 去中心化应用:区块链技术概述

    内容简介 在这本实用指南中,作者解释了为什么去中心化应用(dapp)将比现在最流行的 Web 应用得到更广泛的使用以及实现更多盈利,展示了如何使用现有工具来创建可用的 dapp 及其市场,并研究了目前 ...

  8. 数据结构课程设计之区块链工作原理模拟设计

    数据结构与算法课程设计课程之区块链客户端设计 本文章是基于C/C++进行模拟区块链主要工作原理的代码模拟设计,主要是对数据结构与算法的实践. 一. 设计要求 1. 基本算法设计 a) 创建交易单和区块 ...

  9. 区块链在数据流通中的应用

    区块链在数据流通中的应用 闫树,卿苏德,魏凯 中国信息通信研究院,北京 100191 摘要:大数据的流通是创造数据价值的关键一环,然而目前数据流通面临着诸多问题.区块链是一种分布式账本技术,具有去中心 ...

最新文章

  1. 在ubuntu16.0403X64上安装海思交叉编译工具链
  2. linux内核 DebugFS
  3. Android libcore添加JNI调用Hal层接口问题
  4. sqlite 模糊匹配日期_sql模糊查询和根据日期筛选
  5. 组策略配置客户端计算机使用WSUS服务器进行更新
  6. java ejb jsp 架构_JavaEE架构
  7. clocks_per_sec 时间不正确_你该拥有的不只是护肤品,还有正确护肤时间表
  8. 业务编排可视化_微服务设计-服务组合和可视化编排思考
  9. 网络中的那些事儿(五)之校园网规划综述
  10. osqa mysql_osqa安装出现的问题解决办法 | 学步园
  11. mysql在安全模式下备份_win10安全模式下怎么备份数据?
  12. MySQL数据库备份的三种方式
  13. vue+element实现天翼云oos上传文件
  14. zxing二维码的使用
  15. 配置阿里云镜像源失败
  16. 易乐游装在云服务器_五大网吧无盘系统环境下绝地求生吃鸡卡运行出错
  17. describe函数的参数举例详解
  18. 用函数求斐波那契数列前n项和
  19. 发光二极管和光敏二极管
  20. 哄女朋友开心的html源码,很好玩的代码,哄女票开心用

热门文章

  1. Python3 获取CSDN博客文章的阅读数和评论量
  2. Natas 幽灵王病毒分析
  3. 学习会计实操真的有用吗?
  4. 机器人上使用超声波传感器的原理
  5. WampServer 搭建本地服务器及 XSS 基本原理和初步实践(一)
  6. 太阳系发现的外星文明
  7. QT编程从入门到精通之十一:“第三章:Qt Creator”之“3.5 构建与运行程序”
  8. Rhythmbox等音乐播放器歌名乱码的解决方法
  9. python3.7魔塔游戏_基于pygame的开发:魔塔小游戏开发
  10. 电脑经常弹出“不支持的硬件”解决办法