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

2023-10-30

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根节点作为入口,就能完成一次“状态回滚”。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

区块链数据结构概述(MT、MPT) 的相关文章

随机推荐

  • Grub2启动项启动顺序修改

    关键点即 修改grub cfg 终端命令 sudo i 获取权限 chmod w boot grub grub cfg 给文件添加写入权限 gedit boot grub grub cfg 编辑文件内容 BEGIN etc grub d 3
  • 渗透测试-地基钓鱼篇-Cobalt Strike钓鱼(二十五)

    渗透测试 地基钓鱼篇 Cobalt Strike钓鱼 二十五 作者 大余 时间 2020 12 17 简介 渗透测试 地基篇 该篇章目的是重新牢固地基 加强每日训练操作的笔记 在记录地基笔记中会有很多跳跃性思维的操作和方式方法 望大家能共同
  • MTCNN实现流程

    MTCNN实现流程 文章 https arxiv org pdf 1604 02878 pdf code 1 mxnet上的实现 https github com Seanlinx mtcnn 2 tensorflow上的实现 https
  • linux 安装python3(亲测可用)

    首先安装python3所需的基础库 yum y install openssl devel bzip2 devel expat devel gdbm devel yum y install readline devel zlib devel
  • uniapp uni.requet()二次封装ts版

    uni app网络请求 uni app题拱了uni requet 方法 发起网络请求 uni request url https wwww xxxx cn api home list 仅为示例 并非真实接口地址 data text uni
  • 96-97-----JS基础-----DOM查询(二、三)

    一 代码 不难 用到时看一下DOM查询的相关方法即可
  • [零基础学C#] C#从小白到菜鸟 第5期 - 判断

    前言 上一期我们学习了常量和运算符 这一期我们就要开始学习语句块了 简单啊 本来这一期想讲判断和循环的 但是一起讲的话太多了 所以本期就只讲判断吧 学习编程一定要多学多练 多敲出来才能记得更牢 同样 本期的资源下载在底部 大家在学习过程中有
  • 解决Linux,Ubuntu下使用python包管理工具pip命令安装和下载包速度很慢、失败或者connection timeout等问题

    pip 是 Python 包管理工具 该工具提供了对Python 包的查找 下载 安装 卸载的功能 1 原因 pip命令在Linux系统下使用频率非常高 但是国内使用时常常会下载很慢 或者经常提醒连接超时 其主要问题就是它的默认服务器在国外
  • Beyond Compare 4 密钥解决办法

    修改注册表 1 在搜索栏中输入 regedit 打开注册表 2 Ctrl F搜索CacheId 3 删除项目CacheId 路径 HKEY CURRENT USER Software Scooter Software Beyond Comp
  • HCIP笔记

    HCIA复习 抽象语言 编码编码 二进制 二进制 电信号处理电信号 OSI参考模型 OSI RM 应用层 表示层 会话层 传输层 端口号 0 65535 1 1023是注明端口网络层 IP地址 数据链路层 物理层 ARP协议 正向ARP 通
  • 手把手教你写垃圾分类系统

    垃圾分类是目前社会的一个热点 制作垃圾分类只要找到合适的数据集 垃圾分类的模型构建并不难 这里收集了一份关于垃圾分类的数据集 一共有四个大类和245个小类 大类分别是厨余垃圾 可回收物 其他垃圾和有害垃圾 小类主要是垃圾的具体类别 果皮 纸
  • 2021-10-24

    2021 10 24
  • Linux系统常用命令

    文章目录 一 Linux目录介绍 二 Linux命令 三 Linux常用系统工作命令 1 输出字符串或者环境变量取值后的值 echo 2 显示或者设置系统时间与日期 date 3 设置系统时间 timedatectl 4 系统重启 rebo
  • C++模板-泛型函数与泛型类

    泛型 在调用函数或使用该类时才指定特定的类型 可以避免重复写类似功能代码 那C 语言如何定义泛型呢 Author W 泛型 模板 只有在调用或使用该函数或类时 才确定类型 1 泛型函数 2 泛型类 引入标准输入输出流 include
  • C++异常详细介绍

    目录 前言 一 C 异常概念 二 异常的抛出和匹配规则 三 异常的重新抛出 四 异常安全问题 五 异常规范说明 六 自定义异常体系 七 C 标准库的异常体系 八 异常优缺点 前言 在C语言中处理错误的方式和缺陷有 返回错误码 缺陷 1 错误
  • 硬件系统工程师宝典(22)-----电容、电感的特性,你都知道吗?

    各位同学大家好 欢迎继续做客电子工程学习圈 今天我们继续来讲这本书 硬件系统工程师宝典 上篇我们说到做电阻选型时要考虑阻值 功率 精度和封装大小 上下拉电阻除了给引脚一个稳定的电平 可以提高电压准位 增加输出功率以及满足阻抗匹配的要求 今天
  • buuctf(入门) Have Fun

    首先我们打开题目链接 我们看到一只猫 什么也没有 直接F12查看原代码 发现中间绿色代码的意思大概是定义一个数cat赋予它值cat值cat使用get函数请求的 如果数cat dog的话 则输出syc cat cat cat 所以我们只需要在
  • 867. 转置矩阵

    class Solution public vector
  • 安装postgresql以及乱码问题

    一 进入官网 按照自己的电脑型号选择合适的安装包 点下载那个图标的时候没有反应就多点几次 就可以弹出下载窗口了 二 打开下载好的安装包进行安装 可能出现乱码问题 一般出现这个问题大部分是因为你的系统用户名有中文字符 你需要把它改掉才行 之前
  • 区块链数据结构概述(MT、MPT)

    区块链数据结构概述 MT MPT Ethereum Foundation Blog MT Hash List Merkle Tree Merkle Tree的主要特点 Merkle Tree的相关操作 MPT Merkle Patricia