ETH-16状态树

内容整理自 北京大学肖臻老师《区块链技术与应用》公开课 ETH-16-状态树

 

账户地址到账户状态的映射  addr-->state 以太坊中的账户地址是160bits  40个十六进制的数 存储的是key-value pair

1.hash table?提供merkle proof,证明账户余额,把哈希表中的元素组成merkle tree,算出root hash,保存在block header。问题在于有新区块发布,新区块中有新的交易,执行这个交易,必然会使哈希表中的内容发生变化,把哈希表中的内容重新组织成一颗=棵merkle tree,代价大。实际上真正发生变化的账户状态只是一小部分,只是区块中包含的交易所关联的账户发生变化,每次都重构一课merkle tree。
比特币中也是每出一个区块新生成一个merkle tree,但是merkle tree构建完之后是不会再改的,下次再发布一个新的区块就构建一个新的merkle tree。区块中最多4000个交易。以太坊中如果把所有的账户构建成一棵merkle tree,要高出好几个数量级,每次都要遍历所有账户重构。merkle tree另一个作用是维护各个全节点状态的一致性。

2.merkle tree?1.没有提供一个高效的查找和更新的方法。2.不排序产生的问题,查找代价大,叶节点是账户的信息,如果不规定账户在叶节点中的顺序,那么构建的merkle tree不唯一,算出的root hash不一样。
比特币中也是不排序,不唯一,每个全节点收到交易的顺序也不一样,但是是最后获得记账权的节点说的算。每个节点在本地组装一个候选区块,节点自己决定哪些交易被打包到区块以及什么样的顺序打包,然后去争夺记账权,如果没争夺到记账权,什么样的决定别人没必要知道。如果以太坊也这么做,需要把账户的状态发布到区块里,每个全节点自己决定怎么把账户组织成merkle tree,算出root hash,等到挖出矿发布出去。但是发布的是所有账户的状态,不是区块中包含的交易,交易是必须发布的,而账户状态可以维护在本地的。而且大部分账户状态是不变的,还是重复发布,每十几秒打包所有账户状态发布一遍,
不可行。

3.sorted merkle tree?新增一个账户产生的账户地址是随机的,插入数据代价大,重构树。

MPT

trie树   retrieval
好处:
1.每个节点的分支数目(branching factory)取决于key值里每个元素的取值范围。例子中是小写的英文单词,所以每个节点的分叉数目是26个,加上1个结束标志位。以太坊中地址表示成40个16进制的数,所以分叉数目是17(0~f加上结束标志符).
2.查找效率取决于key长度,键值越长,查找需要访问内存的次数就越多。以太坊key值都是一样长的,长度是40.
3.哈希表理论上会出现哈希碰撞,trie不会出现碰撞,只要两个地址不一样,肯定会映射到不同分支。
4.只要输入不变,无论什么顺序插入,最后插入到trie中构成的是同一棵树。
5.每发布一个区块,系统中绝大多数状态是不变的,只有个别受到影响的状态才会变。更新操作的局部性好。如果要修改某个分支key的value,只需要访问特定分支,其他分支无需访问,也无需遍历整棵树。
缺点:
存储浪费。有些节点只有一个子节点,如果这些节点能够合并,能够减少存储的开销,同时也提高查找效率。

Patricia tree(trie):经过路径压缩的前缀树。如果新插入一个分支,原来压缩的路径可能需要扩展开。
树中插入的键值的分布如果是比较稀疏的情况下,做不做路径压缩效果差距比较大。
以太坊中的键值分布是160bits的地址,整个空间是2^160,是非常稀疏的。因为可以减少哈希碰撞的概率,地址足够长,分布足够稀疏,这是一个去中心化的系统防止账户冲突的唯一办法。

MPT(Merkle Patricia tree):
与PT区别(同Merkle tree与binary tree区别、区块链与链表区别):普通指针换成了哈希指针。
所有的账户组织成一个Patricia tree,用路径压缩提高效率,然后把普通指针换成哈希指针,所以可以算出root hash,写在block header中。 
比特币中的block header中只有一个root hash,以太坊中有三个。root hash1.可以防止篡改,每个账户的状态都能保证没有被篡改。2.merkle proof,证明账户余额有多少,证明MPT中某个键值不存在。

以太坊中使用的是Modified MPT。 
以太坊中的结构,是一个大的MPT,包含一个小的MPT,每一个合约账户的存储,都是一棵小的MPT。
系统中每个全节点需要维护的不是一棵MPT,而是每次出现一个区块都要新建一个MPT,只不过这些状态树中大部分的节点是共享的,只有少数发生变化的节点要新建分支。
为什么保留历史状态,不在原地直接修改?
以太坊把出块时间降到几十秒之后,临时性分叉的出现是常态,如果有一个分叉,两个节点同时获得记账权,两个节点最终会有一个胜出,没有胜出的分叉的节点回滚到上一个区块的状态。
要实现回滚,就需要维护历史记录。比特币可以推算出前一个状态,转账交易回滚比较容易。以太坊中有智能合约,如果不保存之前的状态,在智能合约执行完之后,想再推算出之前的状态是不可能的。

value存的是账户状态,是怎么存储在状态树中?经过一个序列化的过程,用RLP(Recursive Length Profix)编码序列化之后再存储.RLP极简主义,仅支持一种类型nested array of bytes,可嵌套字节数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值