实现以太坊的数据结构----状态树

2023-10-30

状态树:实现账户地址(addr)到账户状态(state)的映射。

在以太坊中账户地址用160位(bits)表示,即40个16进制的数。

1、为什么不能使用哈希表实现?

用哈希表实现,就是系统中的全节点维护一个哈希表,在不考虑哈希碰撞的情况下,每次有一个新的账户就插入到哈希表中,查询也是常数级的。

但是这存在一个问题。如果要证明账户余额,需要将哈希表中的内容组织成一个Merkle tree,然后算出根哈希值保存在block header中公布出去,只要保证根哈希值是正确的,就能保证底下的数没有被篡改。除此之外,Merkle tree还可以维护全节点之间状态的一致性。如果不发布Merkle tree的根哈希值,每个节点只在本地维护一个数据结构,这样就无法知道自己数据结构的状态与别人数据结构的状态是否一致。

问题是,当有新的区块需要发布时,因为新区块中包含新的交易,所以要执行交易,这样会使哈希表中的内容发生变化。这样的话,在发布下一个区块的时候,要把哈希表中的内容重新组织成一个Merkle tree,这要付出极大的代价。实际上,真正发生变化的账户状态只有一小部分,因为只有区块中关联的账户交易发生了变化。

这和比特币系统中,每增加一个区块构建一个Merkle tree不同。在比特币系统中,每次发布一个新的区块,就把区块中的交易组织成一个Merkle tree,这棵树是不可更改的。下次发布一个新的区块,会构建一个新的Merkle tree。每个区块中的交易不会超过4000个,所以构建Merkle tree的代价是可以接受的。但是,如果使用哈希表的话,是将以太坊中的所有交易组织成一个Merkle tree。这样每发布一个交易,就要遍历所有的账户构建Merkle tree,这种代价太大了。

2、既然不能使用哈希表,那么可以直接使用一个Merkle tree,把所有账户都放进去吗?

这样的话只需要修改Merkle tree中的一小部分,但是Merkle tree没有提供高效的查找和更新的方法。

如果把所有账户都放在一个Merkle tree中,这个树还需要进行排序成sorted Merkle tree,因为如果不排序,就无法证明一个交易是否不在区块中。

那么如果使用sorted Merkle tree,在新增一个账户的时候,由于产生的账户地址是随机的,那么账户有可能插入到叶节点的中间位置,那么后面的数的结构都要改变。这就变成了每新增一个账户,都要重新生成一个 Merkle tree。

3、trie字典树(前缀树)

优点:

1)分叉数目(braching factor):17个,因为16进制,加一个结束标志位

2)查找效率取决于key的长度

3)不会产生碰撞

4)一些节点按照不同顺序插入,最后得到的结果相同

5)访问一个节点,只需访问其所在分支,具有较好的更新局部性

缺点:存储开销较大

4、Patricia tree(PT)

对trie进行路径压缩。当键值分布比较稀疏的时候,路径压缩效果比较好。

在以太坊中,为了避免碰撞,需要足够长的地址,使得分布足够稀疏。

5、Merkle Patricia tree(MPT)

与PT不同的是,MPT将PT中的普通指针换成了哈希指针。

所有的账户组织成一个PT,用路径压缩提高效率,然后把普通指针换成哈希指针,此时可以计算出一个根哈希值,写入block header中。比特币中只有一个哈希值,即所有交易组成的Merkle tree的根哈希值。以太坊中有3个。

以太坊中根哈希值的作用:

1)防止篡改

2)证明余额:账户所在的分支自底向上作为Merkle Proof发给轻节点,轻节点就可以验证账户有多少钱。

3)证明某个账户不存在(证明MPT中某个键值不存在):将分支作为Merkle Proof发给轻节点,证明该键值是否存在

以太坊的结构是一个大的MPT包含许多小的MPT,每一个合约账户的存储就是一个小的MPT。所以系统每个全节点维护的不是一个MPT,而是每次出现一个区块都要新建一个MPT。

不会原地直接修改,而要保留历史状态。

原因是:系统中有时会发生分叉,其中一条链合法,其余的要回滚(退回到上一个区块的状态)。保留历史记录是为了实现回滚。以太坊中有智能合约,如果不保存历史状态,那么智能合约执行完后就不可能推算出前面的状态。

6、总结

MPT中保存的是(key,value),key是地址,以上介绍的是地址的存储。value是状态,value的存储需要先进行RLP(Recursive Length Prefix)序列化。

 

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

实现以太坊的数据结构----状态树 的相关文章

随机推荐

  • 团队耗时半年,整理两份非常夯实算法工程师基本功。

    这几年来 圈子内越来越卷的话题持续不下 再加上大厂程序员 被毕业 再就业 的新闻层出不穷 贩卖给人们的焦虑也越来越多 2016年 深度学习的春天是不是要来了 2017年 人工智能是不是一个泡沫 2018年 算法岗是否值得进入 2019年 如
  • pandas使用datetime作为索引并用groupby调用tseries.offsets时间位移分组

    import numpy as np import pandas as pd from datetime import datetime from pandas tseries offsets import Day MonthEnd sj
  • 路由控制配置network命令解析

    network命令 1 命令功能 network命令用来配置BGP将IP路由表中的路由以静态方式加入到BGP路由表中并发布给对等体 undo network命令用来删除指定的以静态方式加入到BGP路由表中的路由 缺省情况下 BGP不将IP路
  • C# 获取系统Icon、获取文件相关的Icon

    1 获取系统Icon 工具下载SystemIcon exe using System using System Collections Generic using System ComponentModel using System Dat
  • 什么是DDoS攻击?

    DDoS攻击是目前最常见的网络攻击方式之一 其见效快 成本低的特点 让DDoS这种攻击方式深受不法分子的喜爱 DDoS攻击经过十几年的发展 已经 进化 的越来越复杂 黑客不断升级新的攻击方式以便于绕过各种安全防御措施 一 什么是DDoS攻击
  • QT实例 - 实现http通信

    QT实现通过HTTP与服务器进行交互 原文链接 https blog csdn net hwc3737 article details 108367037 添加依赖 在项目的 pro文件中添加 QT network 引入相关头文件 incl
  • 生命在于学习——指纹混淆技术学习

    一 前言 本篇文章仅为学习笔记记录 不得用于违规用途 本篇文章为安全社公众号的Poker安全所发 本文仅为学习复现 二 介绍 指纹混淆技术 顾名思义 就是迷惑指纹扫描识别技术 三 思路 作者的思路 1 伪装CMS 作者第一个想到的就是wor
  • python的包

    什么是模块 xxx py文件 社么是包 多个模块组成的文件夹 为啥要使用模块 让我下次直接使用 不需要再重写 或者方便多人开发 1 新建一个文件夹testModel 在此文件夹中创建一个名为 init py的文件 此时python解释器就认
  • 第一章:基本概念

    什么是数据结构 其实官方没有统一定义 数据结构是数据对象 以及存在于该对象的实例和组成实例的数据元素之间的各种联系 这种联系可以通过定义相关的函数给出 Sartaj Sahni 数据结构 算法与应用 数据结构是ADT 抽象数据类型 Abst
  • 在服务器上搭建git仓库

    在本地项目中导出裸仓库 git clone bare project name git 上传到服务器上pscp r project name git user name ip or hostname git path 在本地仓库中设置服务端
  • 蓝桥杯 算法训练 印章

    蓝桥杯 算法训练 印章 共有n种图案的印章 每种图案的出现概率相同 小A买了m张印章 求小A集齐n种印章的概率 输入输出 一行两个正整数n和m 一个实数P表示答案 保留4位小数 样例 2 3 0 7500 这是个dp问题 存在两个变量 印章
  • springboot基础篇—SpringBoot 配置

    1 配置文件 SpringBoot 使用一个全局配置文件 application yml application properties 配置文件放在 src main resources 目录或者 类路径 config 下 yml 是 YA
  • 【Spring Boot丨(11 )】json的集成

    集成JSON 概述 Jackson Gson JSON B 主页传送门 传送 概述 Spring boot 提供了三种json库的集成 Gson Jackson JSON B 上述三种库提供了将Java对象转换为JSON字符串以及将JSON
  • c语言全局变量fork,使用fork进行C语言编程()

    好吧我做错了什么 我在Ubuntu上这样做 我想让系统命令 ls 和一个参数如 a 然后让孩子执行它 然后父母只是打印出来 我不明白为什么我一直让 父母 返回两次 有任何想法吗 使用fork进行C语言编程 include include i
  • 内存四区(代码区 静态区 栈区 堆区)

    参考 内存四区 代码区 静态区 栈区 堆区 作者 今天天气眞好 发布时间 2021 04 01 18 09 13 网址 https blog csdn net qq 51118175 article details 115379779 sp
  • C#文件重命名工具

    文章目录 工具背景 4个文件介绍 RenamesSpecificPrefixFile exe config DataSave txt 工具介绍 重命名的存储方式 文件夹介绍 源文件夹 结果 使用 PDF 视频 重名时坚持拷贝 可能的报错 工
  • json数据一次读取多条数据(数组形式,数组前面没有字符和有字符)的操作方法

    适用于读取的数据如图所示的数组格式 public static List
  • 田忌赛马

    题目描述 我国历史上有个著名的故事 那是在2300年以前 齐国的大将军田忌喜欢赛马 他经常和齐王赛马 他和齐王都有三匹马 常规马 上级马 超级马 一共赛三局 每局的胜者可以从负者这里取得200银币 每匹马只能用一次 齐王的马好 同等级的马
  • Linux(CentOS6.5_X86.64)编译libjpeg出现“checking host system type... Invalid configuration `x86_64-unknow...

    本文地址http comexchan cnblogs com 作者Comex Chan 尊重知识产权 转载请注明出处 谢谢 今天在编译libjpeg 的时候 遇到下面的报错 checking host system type Invalid
  • 实现以太坊的数据结构----状态树

    状态树 实现账户地址 addr 到账户状态 state 的映射 在以太坊中账户地址用160位 bits 表示 即40个16进制的数 1 为什么不能使用哈希表实现 用哈希表实现 就是系统中的全节点维护一个哈希表 在不考虑哈希碰撞的情况下 每次