Merkle Patricia Tree (MPT) 树详解

2023-10-31

转载自:http://www.cnblogs.com/fengzhiwu/p/5584809.html

1.    介绍

  

  Merkle Patricia Tree(简称MPT树,实际上是一种trie前缀树)是以太坊中的一种加密认证的数据结构,可以用来存储所有的(key,value)对。以太坊区块的头部包括一个区块头,一个交易的列表和一个uncle区块的列表。在区块头部包括了交易的hash树根,用来校验交易的列表。在p2p网络上传输的交易是一个简单的列表,它们被组装成一个叫做trie树的特殊数据结构,来计算根hash。值得注意的是,除了校验区块外,这个数据结构并不是必须的,一旦区块被验证正确,那么它在技术上是可以忽略的。但是,这意味着交易列表在本地以trie树的形式存储,发送给客户端的时候序列化成列表。客户端接收到交易列表后重新构建交易列表trie树来验证根hash。RLP(Recursive length prefix encoding,递归长度前缀编码),用来对trie树种所有的条目进行编码(参考:http://www.cnblogs.com/fengzhiwu/p/5565559.html)。

  Trie树也叫作Radix树,为了提高效率,以太坊在实现上对其做了一些改进。在一般的radix树中,key是从树根到对应value得真实的路径。即从根节点开始,key中的每个字符会标识走那个子节点从而到达相应value。Value被存储在叶子节点,是每条路径的终止。假如key来自一个包含N个字符的字母表,那么树中的每个节点都可能会有多达N个孩子,树的最大深度是key的最大长度。

  Radix的好处是具有相同前缀的key所对应的value在树中是非常靠近的,并且trie中不会有像hash-table一样的冲突。但是它也有缺陷,假如有一个很长的key,没有其他的key和它有公共的前缀,那么在遍历或存储它对应的值得时候,你就会遍历或存储相当多的节点,因为这棵树是非常不平衡的。

 

2.    特性

  以太坊对Radix树的实现做了很多改进。

  首先,为了保证树的加密安全,每个节点通过他的hash被引用,而非32bit或64bit的内存地址,即树的Merkle部分是一个节点的确定性加密的hash。一个非叶节点存储在leveldb关系型数据库中,数据库中的key是节点的RLP编码的sha3哈希,value是节点的RLP编码。代码中的实现如图:

  想要获得一个非叶节点的子节点,只需要根据子节点的hash访问数据库获得节点的RLP编码,然后解码就行了。如图所示:

  

  通过这种模式,根节点就成为了整个树的加密签名,如果一颗给定trie的跟hash是公开的,那么所有人都可以提供一种证明,通过提供每步向上的路径证明特定的key是否含有给定的值。

 

  第二,引入了很多节点类型来提高效率。MPT树中的节点包括空节点、叶子节点、扩展节点和分支节点。

  其中有空节点,简单的表示空,在代码中是一个空串。

  标准的叶子节点,表示为[key,value]的一个list,其中key是key的一种特殊十六进制编码,value是value的RLP编码。

  扩展节点,也是[key,value]的列表,但是这里的value是其他节点的hash,这个hash可以被用来查询数据库中的节点。也就是说通过hash链接到其他节点。

  最后分支节点,因为MPT树中的key被编码成一种特殊的16进制的表示,再加上最后的value,所以分支节点是一个长度为17的list,前16个元素对应着key中的16个可能的十六进制字符,如果有一个[key,value]对在这个分支节点终止,最后一个元素代表一个值,即分支节点既可以搜索路径的终止也可以是路径的中间节点。

  除了四种节点,MPT树中另外一个重要的概念是一个特殊的十六进制前缀(hex-prefix, HP)编码,用来对key进行编码。因为字母表是16进制的,所以每个节点可能有16个孩子。因为有两种[key,value]节点(叶节点和扩展节点),引进一种特殊的终止符标识来标识key所对应的是值是真实的值,还是其他节点的hash。如果终止符标记被打开,那么key对应的是叶节点,对应的值是真实的value。如果终止符标记被关闭,那么值就是用于在数据块中查询对应的节点的hash。无论key奇数长度还是偶数长度,HP多可以对其进行编码。最后我们注意到一个单独的hex字符或者4bit二进制数字,即一个nibble。

  HP编码很简单。一个nibble被加到key前,对终止符的状态和奇偶性进行编码。最低位表示奇偶性,第二低位编码终止符状态。如果key是偶数长度,那么加上另外一个nubble,值为0来保持整体的偶特性。

3.  操作

  下面从MPT树的更新,删除和查找过程来说明MPT树的操作。

  • 更新

  函数_update_and_delete_storage(self, node, key, value)

  i. 如果node是空节点,直接返回[pack_nibbles(with_terminator(key)), value],即对key加上终止符,然后进行HP编码。

  ii. 如果node是分支节点,如果key为空,则说明更新的是分支节点的value,直接将node[-1]设置成value就行了。如果key不为空,则递归更新以key[0]位置为根的子树,即沿着key往下找,即调用_update_and_delete_storage(self._decode_to_node(node[key[0]]), key[1:], value)。

  iii. 如果node是kv节点(叶子节点或者扩展节点),调用_update_kv_node(self, node, key, value),见步骤iv

  iv. curr_key是node的key,找到curr_key和key的最长公共前缀,长度为prefix_length。Key剩余的部分为remain_key,curr_key剩余的部分为remain_curr_key。

    a)    如果remain_key==[]== remain_curr_key,即key和curr_key相等,那么如果node是叶子节点,直接返回[node[0], value]。如果node是扩展节点,那么递归更新node所链接的子节点,即调用_update_and_delete_storage(self._decode_to_node(node[1]), remain_key, value)

    b)    如果remain_curr_key == [],即curr_key是key的一部分。如果node是扩展节点,递归更新node所链接的子节点,即调用_update_and_delete_storage(self._decode_to_node(node[1]), remain_key, value);如果node是叶子节点,那么创建一个分支节点,分支节点的value是当前node的value,分支节点的remain_key[0]位置指向一个叶子节点,这个叶子节点是[pack_nibbles(with_terminator(remain_key[1:])), value]

    c)    否则,创建一个分支节点。如果curr_key只剩下了一个字符,并且node是扩展节点,那么这个分支节点的remain_curr_key[0]的分支是node[1],即存储node的value。否则,这个分支节点的remain_curr_key[0]的分支指向一个新的节点,这个新的节点的key是remain_curr_key[1:]的HP编码,value是node[1]。如果remain_key为空,那么新的分支节点的value是要参数中的value,否则,新的分支节点的remain_key[0]的分支指向一个新的节点,这个新的节点是[pack_nibbles(with_terminator(remain_key[1:])), value]

    d)    如果key和curr_key有公共部分,为公共部分创建一个扩展节点,此扩展节点的value链接到上面步骤创建的新节点,返回这个扩展节点;否则直接返回上面步骤创建的新节点

  v. 删除老的node,返回新的node

 

  • 删除

 

  删除的过程和更新的过程类似,而且很简单,函数名:_delete_and_delete_storage(self, key)

  i. 如果node为空节点,直接返回空节点

  ii. 如果node为分支节点。如果key为空,表示删除分支节点的值,直接另node[-1]=‘’, 返回node的正规化的结果。如果key不为空,递归查找node的子节点,然后删除对应的value,即调用self._delete_and_delete_storage(self._decode_to_node(node[key[0]]), key[1:])。返回新节点

  iii. 如果node为kv节点,curr_key是当前node的key。

    a) 如果key不是以curr_key开头,说明key不在node为根的子树内,直接返回node。

    b) 否则,如果node是叶节点,返回BLANK_NODE if key == curr_key else node。

    c)如果node是扩展节点,递归删除node的子节点,即调用_delete_and_delete_storage(self._decode_to_node(node[1]), key[len(curr_key):])。如果新的子节点和node[-1]相等直接返回node。否则,如果新的子节点是kv节点,将curr_key与新子节点的可以串联当做key,新子节点的value当做vlaue,返回。如果新子节点是branch节点,node的value指向这个新子节点,返回。

 

  • 查找

  查找操作更简单,是一个递归查找的过程函数名为:_get(self, node, key)

  i. 如果node是空节点,返回空节点

  ii. 如果node是分支节点,如果key为空,返回分支节点的value;否则递归查找node的子节点,即调用_get(self._decode_to_node(node[key[0]]), key[1:])

  iii. 如果node是叶子节点,返回node[1] if key == curr_key else ‘’

  iv. 如果node是扩展节点,如果key以curr_key开头,递归查找node的子节点,即调用_get(self._decode_to_node(node[1]), key[len(curr_key):]);否则,说明key不在以node为根的子树里,返回空

 

4.    总结

  相对于普通的前缀树,MPT树能有效减少Trie树的深度,增加Trie树的平衡性。而且通过节点的hash值进行树的节点的链接,有助于提高树的安全性和可验证性。所以说MPT树是Trie和Merkle树混合加上平衡操作后的产物。

 

参考: 

https://easythereentropy.wordpress.com/2014/06/04/understanding-the-ethereum-trie/

https://github.com/ethereum/wiki/wiki/Patricia-Tree

https://github.com/ebuchman/understanding_ethereum_trie

https://github.com/ethereum/pyethereum

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

Merkle Patricia Tree (MPT) 树详解 的相关文章

  • GRE隧道协议

    一 GRE协议简介 GRE General Routing Encapsulation 通用路由封装 是对某些网络层协议 如IP和IPX 的数据报文进行封装 使这些被封装的报文能够在另一网络层协议 如IP 中传输 此外 GRE协议也可以作为
  • 区块链中的去中心化

    想知道更多区块链技术知识 请百度 链客区块链技术问答社区 链客 有问必答 去中心化 是加密经济学领域中使用频率最高的词汇之一 同时也是区块链中最为关键的特性 但是其定义一直模糊不清 为了实现去中心化 迄今为止 人们已经花费数千小时的研究 投
  • 以太坊day(4)

    以太坊day 4 一 遇见的错误 1 1 Error Invalid JSON RPC response 二 goland上进行合约的开发 2 1 需要的源 2 2 合约文件 2 3 编译合约 2 4 部署合约 2 5 获取合约实例 2 6
  • 以太坊生产网络/测试网络/私有网络

    要理解以太坊 PrivateNetwork 先要理解以太坊的两种官方网络 目前以太坊官方提供了两种网络 生产环境网络 测试网络 TestNet 下面将分别简单讲解下这两种网络 以太坊生产网络 以太坊的生产网络顾名思义 也就是产生真正有价值的
  • Nethereum:.NET应用和以太坊智能合约的桥梁

    Nethereum基本上是目前唯一可用的 NET平台下的web3 js移植包 在这个教程中 我们将首先编写并部署一个简单的智能合约 然后创建一个简单的 NET应用 并使用Nethereum来访问以太坊上的智能合约 Nethereum是通过以
  • web3.js

    安装 别按照官网上面 npm install web3 下载 我已经吃过一次亏了 npm init npm install ethereum web3 js save 指令 web3 isConnected 检查结点的连接是否存在 web3
  • 以太坊智能合约虚拟机(EVM)原理与实现

    以太坊 EVM原理与实现 以太坊底层通过EVM模块支持合约的执行与调用 调用时根据合约地址获取到代码 生成环境后载入到EVM中运行 通常智能合约的开发流程是用solidlity编写逻辑代码 再通过编译器编译元数据 最后再发布到以太坊上 代码
  • geth web3提供的接口

    admin datadir ethcluster 779977 data 01 nodeInfo enode enode ca624860483a9f749676491bbf5b11cc7ded0a89f5c9f522767ebea0195
  • 笔记:以太坊geth客户端命令及参数

    geth命令的参数 nodiscover 使用此选项可确保未手动添加您的人员无法发现您的节点 否则 如果您的节点具有相同的创世纪文件和网络ID 则可能无意中将您的节点添加到陌生人的区块链中 maxpeers 0 如果您不希望任何其他人连接到
  • 认识一下以太坊、EOS和Hyperledger等不同的区块链

    不同的区块链智能合约和区块链技术现在风靡一时 越来越多的人出于某种原因试图进入这个神奇的世界 如果你是这项技术的新手并正在寻找基于区块链的开发平台的快速入门 那么本指南非常适合你 我们将重点关注和比较的平台是 Ethereum EOS Hy
  • 如何通过Geth、Node.js和UNIX/PHP访问以太坊节点

    本文旨在说明通过Geth Node js如何访问以太坊节点和UNIX下PHP如何访问以太坊节点 说明如何通过RPC使用此 A 以太坊节点 对于以太坊主网络使用RPC url http 85 214 51 53 8545 对于Ropsten测
  • 带你玩转以太坊智能合约的”Hello World“

    学习目标 使用solidity语言撰写智能合约 开发前的准备 Ubuntu环境下Atom编辑器安装及使用 安装所需工具 安装nvm 安装node 安装npm 启动testrpc 建立项目 目录结构 新建HelloWorld合约 代码说明 编
  • 用Go构建一个简单的区块链

    在本教程中 我将尝试通过帮助你在Go中编写简单的区块链来揭开区块链的广义概念 在本教程中 你应该能够 理解区块链术语 创建自己的简单区块链 了解什么是区块以及如何创建块 了解如何维护区块链的完整性 区块链 一种数字分类帐 以较小的集合排列
  • 区块链学习笔记16——以太坊中的交易树和收据树

    十六 以太坊中的交易树和收据树 每次发布一个交易的时候 那些交易会组织成一个交易树 也是一颗Merkle tree跟比特币中的情况是类似的 同时以太坊还增加了一个收据树 每个交易执行完之后会形成一个收据 记录这个交易的相关信息 交易树和收据
  • Remix 以太坊Solidity IDE搭建与初步使用

    以太坊 因为以太坊为开源社区 虽然东西很优秀 但是组件十分的杂乱 因此首先简单介绍下以太坊的一些常用组件 1 Geth Geth是由以太坊基金会提供的官方客户端软件 用Go编程语言编写的 2 Parity Parity 是对以太坊协议的另一
  • 以太坊如何通过构建智能合约来销售商品?

    如何通过构建以太坊智能合约来销售商品 这是个问题 毫无疑问 比特币已经改变了我们看待和理解什么是金钱 价值以及最近由智能合约产生的所有权的方式 这很有趣 因为几乎每个人都听说过它或加密货币 来自许多业务领域的人 不仅仅是我们 IT工作者 在
  • js连接web3,连接小狐狸metamask钱包,实现链不对后切换网络和创建网络

    直接上代码 我这里吧所有配置都改成正式的链56 一旦用户的小狐狸钱包现在的链不一致 就询问切换网络 没有就创建网络 网络切换成功后 收到监听 重新连接一下web3 就是重新调用一些connectWeb3这个方法 再连接合约 connectW
  • 以太坊创世区块源码分析

    genesis 是创世区块的意思 一个区块链就是从同一个创世区块开始 通过规则形成的 不同的网络有不同的创世区块 主网络和测试网路的创世区块是不同的 这个模块根据传入的genesis的初始值和database 来设置genesis的状态 如
  • 以太坊智能合约各方法对应的签名编码

    erc20智能合约常见方法对应的签名编码 常见例如交易 transfer address uint256 编码为 web3 sha3 transfer address uint256 substring 0 10 gt 0xa9059cbb
  • 引介

    转载自 https ethfans org posts rlp encode and decode RLP编码和解码 RLP Recursive Length Prefix 递归的长度前缀 是一种编码规则 可用于编码任意嵌套的二进制数组数据

随机推荐

  • DOM 2 级事件的认识

    DOM中的事件是一个很中要的东西 它可以让用户和浏览器之间进行交互 以此来实现人机交互效果 DOM事件 DOM事件分为DOM0级事件和DOM2级事件 DOM0级其实不存在 我们把DOM最初的版本叫0级 在DOM2级的时候更新了一种新的事件绑
  • 亿级Web系统搭建——单机到分布式集群

    徐汉彬曾在阿里巴巴和腾讯从事4年多的技术研发工作 负责过日请求量过亿的Web系统升级与重构 目前在小满科技创业 从事SaaS服务技术建设 大规模流量的网站架构 从来都是慢慢 成长 而来 而这个过程中 会遇到很多问题 在不断解决问题的过程中
  • 外企程序员常用英语单词

    1 cognitive k n t v adj 认知的 认识的 2 risk r sk n 风险 危险 冒险 vt 冒 的危险 n Risk 人名 英 阿拉伯 里斯克 3 berries beriz 浆果类 4 vegetables ved
  • Mac使用经验分享 - 总览

    Mac本身支持的效率操作 各种快捷键的使用 Mac系统本身支持很多的快捷键 这些快捷键能够很大程度的提升使用效率 在此处简单列出一些我经常使用的快捷键 权作参考 W 关闭当前窗口 M 最小化当前窗口 W 关闭所有finder窗口 有一个fi
  • LLVM介绍

    文章目录 LLVM介绍 一 LLVM三段式架构 1 传统编译器的三段式 2 LLVM的三段式 二 Clang与LLVM的关系 三 LLVM 编译流程 LLVM介绍 在理解LLVM时 我们可以认为它包括了一个狭义的LLVM和一个广义的LLVM
  • mysql实现读写分离自带java驱动

    MySQL 数据库的读写分离和负载均衡一般是通过第三方软件来实现的 也可以通过mysql驱动程序来实现 如com mysql jdbc ReplicationDriver 官网网址 多主机连接配置 1 主备配置 2 负载连接配置 3 主从复
  • arcgis根据矢量范围统计栅格数据众数、最大值、均值、中位数、最小值、少数等

    arcgis根据矢量范围统计栅格数据 数据 表格显示分区统计 分区统计 前面介绍过如何根据面状的矢量数据对 栅格数据进行统计 其主要是统计 每个面内像元值的数量为多少 参考 arcgis统计矢量面内栅格数据像元值个数 注 那么如果我需要统计
  • 惠普笔记本电脑驱动BIOS下载中心,战66驱动下载

    最近发现我战66 g3 2020 fn f3 f4屏幕亮度无法调节 已确定不是键盘的问题 搜索发现可能是驱动问题 惠普产品 https support hp com cn zh drivers laptops 战66驱动程序下载 https
  • Docker 之管理应用数据—数据卷 (二)

    卷是存储Docker容器生成和使用的数据的首选机制 绑定挂载依赖于主机的目录结构 而卷则完全由Docker管理 卷比绑定装载有几个优势 卷比绑定挂载更容易备份或迁移 您可以使用Docker CLI命令或Docker API来管理卷 卷可以在
  • 问题解决:jxls多sheet导出,多余一个空白sheet页

    一 项目需求 1 需求 用户勾选多个业务单 导出Excel 一个业务单占据一个sheet页 2 预期效果 3 实际效果 采用 jxls 2 3 0 jar的导出方法 JxlsHelper getInstance processTemplat
  • Linux设备文件(Device file)

    Linux设备文件 Device file 设备文件概述 在类Unix操作系统中 设备文件或特殊文件是设备驱动程序的接口 出现在文件系统中就好像它是普通文件一样 在MS DOS OS 2和Microsoft Windows中也有特殊文件 这
  • Spark-SQL之DataFrame操作大全

    Spark SQL中的DataFrame类似于一张关系型数据表 在关系型数据库中对单表或进行的查询操作 在DataFrame中都可以通过调用其API接口来实现 可以参考 Scala提供的DataFrame API 本文中的代码基于Spark
  • 使用docker将深度学习模型容器化

    一 使用Docker制作深度学习模型镜像 了解 注 首先 一开始shell中命令行所在位置在root文件下 即root 4210node 其次 整个文件夹目录如下 root model result 存放推理后的图片 val 存在数据集 d
  • 拼音汉字对照表

    啊 a 阿 a e 埃 ai 挨 ai 哎 ai 唉 ai 哀 ai 皑 ai 癌 ai 蔼 ai 矮 ai 艾 ai yi 碍 ai 爱 ai 隘 ai 鞍 an 氨 an 安 an 俺 an 按 an 暗 an 岸 an 胺 an 案
  • ubuntu显示git分支名

    https copyfuture com blogs details 202112180730365938
  • 手机没有root如何抓包,VMOS Pro+小黄鸟HttpCanary(附工具软件)

    2022年7月30日已更新最新版抓包教程 修复了评论中提到的若干问题 请戳下方蓝色链接阅读 2022年8月更新 手机没有root如何抓包 VMOS Pro 小黄鸟HttpCanary 附工具软件 以快手极速版抓包为例 现在手机root越来越
  • 面试复习题--正浩

    1 文件去除重复行 1 大文件分解 每行 2 为什么子线程不能更新UI 3 怎么改造使得子线程可以更新UI 4 子线程的handler 5 Wifi p2p开发 6 蓝牙 7 View post 和handler post区别 在主线程中使
  • CSS3 box-sizing 属性

    CSS3 box sizing 属性 常规盒模型 内容区 padding border margin 如果在页面中设置100100的div 那么padding会撑大div 并且border也是在100100的基础上面进行增加像素的 box
  • 无法找到服务器配置文件,在Linux中PostgreSQL“无法访问服务器配置文件(…)没有这样的文件或目录”干净安装后...

    我刚刚根据官方 documentation安装了postgresql 但由于某种原因 它不起作用 它确实安装使用sudo apt get postgres 等 但服务器的启动似乎不起作用 我尝试按照他们的documentation启动服务器
  • Merkle Patricia Tree (MPT) 树详解

    转载自 http www cnblogs com fengzhiwu p 5584809 html 1 介绍 Merkle Patricia Tree 简称MPT树 实际上是一种trie前缀树 是以太坊中的一种加密认证的数据结构 可以用来存