其他
干货 | 了解 Geth 客户端:快照加速机制
以太坊的状态
以太坊的状态存储
并不是所有访问都要一视同仁
在导入一个新区块的时候,EVM 代码的执行会产生或多或少基本平衡的状态读取和写入次数。不过,一个用于拒绝服务式攻击的区块可能会产生远多于写入操作的读取操作次数。 当节点运营者检索状态的时候(例如调用 eth_call
及类似操作),EVM 代码执行仅产生读取操作(当然也可能有写入操作,但这些操作产生的数据最终会丢弃掉,不会持久化到硬盘里面)。当节点在同步区块链的时候,同步者会向远程节点请求状态,被请求者会将数据挖掘出来并通过网络传播给同步者。
请循其本
魔鬼藏在细节中
Self-destruct (合约自毁操作)(以及删除操作)特别难以对付,因为它们需要短路 diff 层的沉降(descent)。 如果出现了比持久硬盘层更深的链重组,那现在的快照就要完全废弃掉、重新生成。整套操作非常昂贵。 在节点关机时,内存内的 diff 层需要持久化到日志并加载备份,不然重启之后快照就没用了。 使用最底层的 diff 层作为一个累加器,仅在其超过一定的内存使用时才刷新到硬盘。这就允许跨区块对同一存储槽执行去重写入操作(deduping write)。 要为硬盘层分配一个读取缓存,这样合约重复访问同一个古老的存储槽时硬盘才不会损坏。 在内存内 diff 层中使用累积的布隆过滤器(bloom filter),以便快速检测出状态物有没有可能存在于 diff 层中,还是应该直接跳到硬盘中查找。 不把原始数据(账户地址、合约存储键)设为键,而是以这些数据的哈希值为键,以保证快照的迭代顺序与默克尔帕特里夏树相同。 生成持久化硬盘层的时间要比剪除状态树窗口的时间多得多,所以即使是生成器,也需要动态地追踪链的运行。
美丑并存
eth_call
调用也快了一个数量级(假设 CPU 不存在瓶颈的话)。snap
同步算法。讲清楚它需要一篇全新的文章,但最近我们在 Rinkeby 测试网上的基准测试很能说明问题:--snapshot
标记来开启,而且还有一些围绕内存使用和崩溃恢复的打磨工作要做。结语
更多推荐阅读