词条 · 加密与分布式 · 核心
状态膨胀 / State Growth
链上每记住一件事都要全世界所有节点一起永久记住,而这笔账没有还款日。
也称:状态膨胀、state growth、状态增长、状态膨胀问题、state bloat、状态爆炸
一句话
区块链上有些数据是永久的:写进去一次,之后全世界每一个全节点都要一直存着它,直到这条链死掉。这些数据的总量只会涨,不会跌。
一个麻烦
假设你要自己跑一个以太坊全节点。你租了台机器,装好客户端,同步完成,一切正常。
半年后它开始变慢。一年后磁盘满了,你加了块盘。两年后同步一个新节点要花好几天。
你没做错任何事。你的节点也没有处理更多的交易——每秒的吞吐量和第一天一样。变大的是它必须随时能回答问题的那堆数据。
这里要区分两样很容易混淆的东西:
- 历史:过去发生过什么。区块、交易、收据。这部分也在涨,但它是只增不减的日志——你可以把老的扔掉,让别人存,需要的时候再去取。
- 状态:现在是什么样。谁有多少钱,每个合约的每个存储槽里放着什么。这部分是验证下一个区块所必需的。你扔不掉。
状态膨胀说的是第二样。
这个区别有多重要,看一个数就知道:历史可以被剪掉(以太坊的 EIP-4444 就是在做这件事,让客户端不再无限期保留老的区块体和收据),但状态不能。要验证下一笔交易合法,你必须知道付款人现在有多少钱。
几个朴素猜测
猜测一:涨就涨吧,磁盘越来越便宜。
问题不在磁盘的价格,在于谁还愿意跑节点。一条链的抗审查能力来自有多少互不相干的人各自独立地验证它。当跑一个节点需要企业级硬件时,节点数量会掉,而且会集中到少数几家托管商手里——那正是这套系统本来要避免的形状。状态大小不是一个存储账单问题,是一个去中心化程度问题。
猜测二:那就收费,谁写状态谁付钱。
已经在收了。这恰恰是问题的形状所在:你付一次,全世界存永远。
写入的人付的是一次性的 gas 费,按当时的价格。节点承担的是无限期的存储。这两边的期限根本不对齐——经济学上这叫成本外部化,代价被转嫁给了不参与那笔交易的第三方。
更糟的是,费用只在写入那一刻收。一个地址收了 1 wei 就再也不动,它的账户叶子会永久留在状态里,而没有任何人在为此持续付费。
猜测三:那把不用的东西删掉——余额为零就清理。
删除比看起来危险得多。假设某个账户被清理了,然后有人重新用同一个地址、把它重新创建出来——那么它的 nonce(防重放的计数器)回到零,历史上那笔已经花掉的交易可以被重新提交一次。这不是假想,以太坊在 EIP-161 里真实处理过一个相关形态。
问题的根子是:状态里的条目往往同时在承载两个不同的事实——“这东西存在”和”这东西的当前值是多少”。你想删的是第二个,但删掉之后第一个也没了,而第一个正是防重放所依赖的。
猜测四:租金。存着就一直交钱,不交就清掉。
这是被讨论最久的一个方向,也确实能对齐激励。它撞的墙是用户体验和合约的组合性:一个多年没动过的钱包会因为欠租被清空吗?一个所有用户共用的合约,谁来续租?一个依赖另一个合约状态的合约,会不会因为对方被清掉而在半路崩掉?没有一个干净的答案,所以它一直没落地。
机制
看清这件事的最好方式,是问每个模型把永久成本放在了哪一刻。
一笔交易要合法,验证方必须回答两个问题:
- 存在性:这个东西存在过吗?
- 消费性:它已经被用掉了吗?
不同的设计把这两个答案放在不同的地方,而永久成本就跟着答案走:
存在性放哪 消费性放哪 创建时的永久写入
比特币 状态(UTXO集合) 历史(已花费) 每个输出 50~100+ 字节
以太坊 状态(账户/存储) 状态(同一条目) 账户或槽 100~150+ 字节
比特币和以太坊的差别常被说成”UTXO 对账户”,但从状态膨胀的角度看,它们犯的是同一个错:永久成本都落在创建那一刻。
比特币至少有一条回收路径——花掉一个 UTXO 就把它从集合里删了,空间还回来。所以它的状态大小跟的是未花费输出的数量,会上下波动。
以太坊没有这条路径。账户叶子和存储槽创建之后就留着,余额归零也留着。所以它的曲线是单调上升的。
第三种排法是把两个问题拆开:存在性从只增不减的历史里证明(历史反正是要留的,而且可以剪、可以让别人存),状态里只留一个比特——“用过了吗”。这样永久成本从创建搬到了消费:一个创建了但从没被用掉的对象,永久状态写入是零。
这个排法的代价很实在,而且方向正好相反:取回存在性变得又慢又不可靠。它现在藏在几年前的某个区块的日志里,而如果历史已经被剪掉、没人替你留着,那条退路就断了。状态膨胀的每一种解法都是在做同一笔交换——把常驻的成本换成取回时的麻烦。
为什么值得知道
这不是区块链独有的问题。凡是”写一次、之后每次都要带着它”的系统,都在付同一笔账:
- 一个每轮都注入完整上下文的 AI 智能体,它的持久记忆就是热状态。写入时付一次,之后每一轮都在付。等它满了,你就得开始做删除决策。
- 一张只加索引不删索引的数据库表。每个索引都在为每次写入抽税。
- 一个从不过期的缓存键空间。
判断这类方案好不好,有一个比”压缩率多少”更有用的问题:它的永久成本落在写入时还是消费时?
落在写入时的,会随使用量线性膨胀,最终逼你做不可逆的删除决策。落在消费时的,膨胀得慢得多,代价是你需要一条可靠的取回路径——而这条路径的可靠性,往往比设计者预想的更难保证。
收束
回到那台磁盘满了的机器。它变慢不是因为处理的交易变多了,是因为它必须随时记住的东西变多了,而当初写进那些东西的人只付了一次钱。
真正的问题从来不是”数据太多”,而是”记住的期限和付费的期限不一致”。任何一个不去改这条不一致的方案,都只是在推迟那一天。
提到这个词条的文章
- 原生 UTXO:把永久状态成本从「创建」搬到「消费」,只留 0.125 字节 2026-08-05