以太坊 Trie树

本文介绍了以太坊中使用的Trie树(字典树)和Merkle Patricia Trie(MPT)的概念,强调了它们在存储和检索数据中的作用。Trie树通过字符串公共前缀节省空间,而MPT是Ethereum存储用户账户状态、交易信息的关键数据结构。MPT允许快速验证数据,支持状态回滚和轻节点的简单支付验证。文章还探讨了Trie树的编码格式和节点类型,以及在数据库中的存储方式。
摘要由CSDN通过智能技术生成

Trie树
Trie树,又称字典树,是一种用于快速检索的多叉树结构。
Trie树可以利用字符串的公共前缀来节约存储空间,如果系统中存在大量字符串且这些字符串基本没有公共前缀,则相应的trie树将非常消耗内存,这也是trie树的一个缺点。
Trie树的基本性质可以归纳为:
    根节点不包含字符,除根节点以外每个节点只包含一个字符。
    从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
    每个节点的所有子节点包含的字符串不相同。

如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树。

如下图所示,该trie树用10个节点保存了6个字符串:tea,ten,to,in,inn,int:

Patricia Tries 前缀树
前缀树跟Trie树的不同之处在于Trie树是为每一个字符串分配一个节点,
而前缀树是将那些很长但又没有公共节点的字符串的Trie树退化成数组。

在以太坊里面会由黑客构造很多这种节点造成拒绝服务攻击。
前缀树的不同之处在于如果节点有公共前缀,那么就使用公共前缀,否则就把剩下的所有节点插入同一个节点。

如:


Merkle树
Merkle Tree,通常也被称作Hash Tree,顾名思义,就是存储hash值的一棵树。
Merkle树的叶子是数据块(例如,文件或者文件的集合)的hash值。
非叶节点是其对应子节点串联字符串的hash。

Merkle Tree的主要作用是当我拿到Top Hash的时候,这个hash值代表了整颗树的信息摘要,当树里面任何一个数据发生了变动,都会导致Top Hash的值发生变化。
而Top Hash的值是会存储到区块链的区块头里面去的, 区块头是必须经过工作量证明。
这也就是说我只要拿到一个区块头,就可以对区块信息进行验证。

MPT 以太坊Tries树
Merkle Patricia Trie(MPT) 是 EThereum 中一种非常重要的数据结构,用来存储用户账户的状态及其变更、交易信息、交易的收据信息。
每一个以太坊的区块头包含三颗MPT树,分别是:
1、交易树
2、收据树(交易执行过程中的一些数据)
3、状态树(账号信息,合约账户和用户账户)

MPT树有以下几个作用:
    存储任意长度的key-value键值对数据;
    提供了一种快速计算所维护数据集哈希标识的机制;
    提供了快速状态回滚的机制;
    提供了一种称为默克尔证明的证明方法,进行轻节点的扩展,实现简单支付验证;

下图中是两个区块头,
其中state root,tx root,receipt root分别存储了这三棵树的树根,
第二个区块显示了当账号 175的数据变更(27 -> 45)的时候,只需要存储跟这个账号相关的部分数据,而且老的区块中的数据还是可以正常访问。


key                    value

a711355            45.0 ETH
a77d337            1.00 WEI|
a7f9365             1.1 ETH
a77d397            0.12 ETH

prefix 前缀:
0 - 扩展节点,偶数个半字节
1 - 扩展节点,奇数个半字节
2 - 叶子节点,偶数个半字节
3 - 叶子节点,奇数个半字节


MPT 中对 key 的编码
trie/encoding.go 主要处理trie树中的三种编码格式的相互转换的工作。
三种编码格式分别为:
    KEYBYTES 编码:  这种编码格式是原生的key字节数组
    HEX 编码:             这种编码格式是把一字节拆分成两字节,尾部加一字节编码标记(0x10),
    COMPACT 编码:   这种编码格式是把Hex的两字节合并为一字节,在头部加一字节奇偶数据位(0x20或0x30)
                                         
将 keybytes 编码为 Hex:
编码前: 0x12 0x34 0x56
编码后: 0x01 0x02 0x03 0x04 0x03 0x04 0x05 0x06 0x10
0x10 为标记为 表示是Hex编码

package main

import (
	"fmt"
)

// 将 keybytes 转化成 Hex
// 1. 将 keybytes 中的1byte信息,高4bit和低4bit分别放在2个byte里。
// 2. 最后在尾部加1字节标记当前属于Hex格式。
func keybytesToHex(str []byte) []byte {
	l := len(str)*2 + 1
	var nibbles =
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值