当前位置:主页 > 列表页 > 正文

以太坊存储爆炸问题的分析与优化

2021-12-29 03:23 | 出处: odaily

编按:本文为QuarkChain创始人兼CEO周期博士撰写的技术文章,并以此文章为基础,在DApp Learning进行了技术分享讲座。

DeFi、GameFi等去中心化应用的蓬勃发展,极大地增加了对低交易费用的高性能区块链的需求。然而,构建高性能区块链的一个关键挑战是存储爆炸。下图是取自 Etherscan 的图表,它说明了一个以太坊全节点(存档)的区块链数据大小。

从图中我们可以看出,节点的链数据规模稳步增长,现在已经达到~9TB。由于去中心化区块链的一个目标是允许普通配置的计算机运行节点,因此在普通配置的计算机上强制要求 9TB 存储会难以达到。

  • 区块

  • 状态

  • 交易收据

  • 这其中,状态是这 8.7TB 的主要组成部分。所以有时,我们将存储爆炸称为“状态爆炸”。但是为什状态会如此之大?

    什么是以太坊状态?

    以太坊状态是一个Merkle Patrica树(MPT),其中

    • 叶子节点是地址 (0 x...) => 帐户的映射,其中帐户存储与地址关联的余额、nonce等

    • 内部节点维护树结构,以便可以快速计算整个树的哈希根

    由于存档节点将保留所有区块的所有历史状态,这意味着 MPT 中的任何更新都将创建 O(log(N)) 个内部节点,并且不会删除旧的内部节点。

    通过定期存储 MPT,状态的存储大小显著减少。据 Etherscan 数据,目前 Geth 全节点的区块链数据大小约为 1TB。

    在不存储历史 MPT(有时甚至是历史区块主体)的情况下,一个 Geth 节点的存储大小可以进一步减少到 447G(截至 2021/12/06)。通过减去 300GB 的区块数据,我们推断状态大小约为 150GB。

    币安智能链(BSC)。截至 2021 年 12 月 8 日,BSC 已有:

    • 约 984 GB 链上数据,其中区块约占 550 GB,状态约占 400 GB。

    • 20.6623 亿笔交易,100 TPS

    如果我们进一步用交易数量来预测数据大小,我们可以得到:

    如果 TPS 为 100,即 ~3,153 M TPY

    • 1 年后,总 TX ~5,219M,区块 ~ 1.375 TB,状态 ~ 1.085TB

    • 3 年后,总 TX ~11,525M,区块 ~3.025TB,状态 ~2.387 TB

    如果 TPS 为 150(观察到的峰值 TPS),即 ~4,730 M TPY

    • 1 年后,总 TX ~6,796M,区块 ~1.809 TB,状态 ~1.427 TB

    • 3 年后,总 TX ~16,256M,区块 ~4.327 TB,状态 ~3.414TB

    综上所述,对于BSC来说,如果保持目前的速度甚至更高,则很快就会达到以太坊存档节点相同的存储大小,这是普通计算机几乎无法运行的。

    具有极高 TPS 区块链的存储爆炸问题

    如果我们对一个极高 TPS 的区块链(比如像 QuarkChain 能够做到的那样)做一个更大胆的假设,这个数字会变成多少?我们来考虑一个具有 1000 TPS 的区块链并分析其区块和状态大小,将是:

    • 假设 tx 大小约为 100 字节,每年区块所需的存储量为 1000 (TPS) * 100(每 tx 字节数)* 365 * 24 * 3600 = 2.86 TB

    • 假设 MPT 有 100 亿账户(超过世界人口!),我们预计状态大小将为 150G(以太坊状态大小)/0.18B(以太坊唯一地址)* 10B = 8.3 TB

    将这些数字放在一起,我们很容易得出一个结论,这是大多数普通配置计算机将 无法承受的要求!

    优化

    为了优化存储成本,我们必须将限制放宽为兼容 EVM 而不是兼容以太坊。即,我们必须构建/运行另一个支持 EVM 的链,而不是高度优化的以太坊客户端。

  • ~ 10B * 50 100GB(代码)= 600 GB,大约是MPT版本的1/10!

  • 虽然使用普通 KV 会带来巨大的好处,但一个主要问题是我们无法在如此短的区块间隔内计算每个区块的状态后哈希,这意味着我们将失去以太坊的以下好处:

    • 快速同步:下载任何区块的状态并通过重放剩余的区块来快速同步网络

    • 分叉检测(或拜占庭检测):来自对等方新创建的区块是否会导致与本地执行区块的状态不同。

    为了启用快速同步,我们有一个周期性的快照区块(快照间隔 = epoch = 例如,14 周)。一个快照区块包含前状态哈希这一附加信息,即前一个快照区块的后状态哈希(执行交易之后的状态哈希):

    • 非快照区块不维护状态哈希,而是具有增量哈希,其中包含该区块的所有交易事务的原始数据库操作(删除、更新)的哈希。这使得分叉检测成为可能!

    • 我们使用交易前状态哈希来代替以太坊中区块的交易后状态哈希。原因是节点不能立即计算状交易后的状态哈希,但是通过使用交易前状态哈希,节点可以使用整个epoch间隔来计算哈希。例如,假设状态哈希计算每秒处理 10M 的状态数据,那么计算 600 GB 的整个状态将需要 600 GB / 10 M ~ 16.67 小时(vs. epoch = 14 周)

    计算状态前哈希的流程如下:

    1. 当一个快照区块被接收并最终确定时,它的 KV 状态被快照,并创建一个后台线程来迭代所有 KV 条目(地址 => 帐户)并计算哈希。

    2. 当下一个快照区块被创建时,计算出的状态前哈希值将存储在该区块中。同样,节点将创建 KV 的另一个快照并在后台计算其哈希。

    3.当下一个快照区块被创建时,节点除了存储状态前哈希之外,节点现在可以释放快照区块的KV快照,这意味着来自快照区块以来所有被删除/更新的数据将被自动垃圾回收(例如,在 levelDB 中压缩)

    其结果意味着,要存储状态,节点只需要最多两个 KV 快照(很可能是一个带增量和一个 KV 快照)。

  • 最新的快照区块的交易执行前状态快照,即(最新 — 1)快照区块的交易执行后状态

  • (最新 — 1)快照区块之后的完整区块

  • 我们可以对存储成本进行简单的数学计算:假设 epoch 持续时间为 2 周,则区块重放大小为

    • 2 * 14(天)* 24(小时)* 3600(秒)* 100 * 1000(TPS)= 224 GB!

    而且,这里的数字不会随着时间的推移而增长!

  • 不仅是区块,状态存储消耗了很多的空间

  • 当 TPS > 1000 时,存储空间用量高得令人望而却步

  • 我们提出对区块和状态进行优化:

    • 区块大小从每年 2.86 TB 减少到 224 GB

    • 状态大小(~10B 帐户)从 8.3 TB 减少到 600 GB

    • 一台 2TB 的普通配置计算机应该能满足长时间运行节点的条件

    • 缺点:轻节点无法验证状态中的一个数据(必须是全节点)

    致谢

    感谢 dapp-learning 主办此次活动。

    您可能感兴趣的文章:

    相关文章