Fuel Core 存储费用定价机制解析:63 gas/字节如何推导并落地到链配置
【免费下载链接】fuel-coreRust full node implementation of the Fuel v2 protocol.项目地址: https://gitcode.com/GitHub_Trending/fu/fuel-core
导读
存储成本与执行成本如何处理,是 Fuel v2 这类模块化区块链的 Gas 经济核心问题之一。Fuel Core 当前在协议层面不区分「执行费」与「存储费」,因此采用了一种过渡方案:对写入新数据的操作码、以及向链上新增合约的交易,按「gas/字节」额外计费。本文完整还原 fee_calculations.md 中关于存储费的两套估算方法(保守 500 GB/年、宽松 5 TB/年)与推导过程,并结合仓库内的真实链配置(ignition、v44 等)验证「初始 63 gas/字节」这一结论在 Genesis 配置中的实际落地。
背景:为什么需要单独的存储费用
Fuel 目前并不像部分区块链那样分别对执行成本与存储成本收取两笔独立费用,这一能力被规划为未来特性。但与此同时,网络必须有一个机制来补偿「为网络存储合约数据」所付出的成本。Fuel 采取的临时方案是:
- 对写入新数据到存储的操作码增加额外成本;
- 对向链上添加新合约的交易增加额外成本。
这套做法的目的,是让每个字节的持久化状态增长都有对应的 Gas 开销,从而防止状态无限膨胀。而具体的费率(多少 gas/字节)并不由代码硬编码死,而是以「共识参数」形式出现在链配置(chain_config.json)中,因此可以在每次网络版本/分叉时调整。
从设计路径上看,文档采用了「反向推算」的方法:先设定一个目标存储增长率,再反推每个字节应当收取多少 gas。下文两套估算即为此方法的两个版本。
保守估算(Pessimistic Estimate):假设用户把每个区块的 Gas 上限都「写满存储」
第一个问题是:如果把存储目标增长率任意设定为500 GB/年,并且假设用户在每个区块内,把区块 Gas 上限(此处假设为 10,000,000 gas/块)全部用于写存储,那么每字节应该收多少 gas?
计算所需的中间量:
- 每年秒数 = 365 × 24 × 60 × 60 =31,536,000(隐含假设约每秒一个区块);
- 每块可容纳的存储字节 = 500,000,000,000 / 31,536,000 ≈15,855 字节/块;
- gas/字节 = 10,000,000 / 15,855 ≈630.72 gas/字节。
文档给出的完整表格如下:
| bytes per year | block gas limit | blocks per year | bytes per block | gas per bytes |
|---|---|---|---|---|
| 500,000,000,000 | 10,000,000 | 31536000 | 15,855 | 630.72 |
这是一个非常苛刻(harsh)的估计,文档明确指出了其缺陷:
- 没有把交易执行的基础成本、其他操作码的成本考虑进来;
- 假设所有区块都会把存储写满上限(现实中不可能发生)。
换句话说,630 gas/字节 是「最坏情况下防止状态增长失控」的上限价格,而非贴近实际用途的定价。
宽松估算(Generous Estimate):把年存储上限放宽到 5 TB
保守估算过于严苛,但存储费本身只会作用于早期网络,而这些网络的生命周期并不长。这给了协议侧一个「冒更大风险定价」的空间:先以较低的单价放行早期生态增长,未来若用户大量写入数据,再随时间上调价格予以补偿。
基于以上考量,将年存储上限重新估算为5 TB/年后:
| bytes per year | block gas limit | blocks per year | bytes per block | gas per bytes |
|---|---|---|---|---|
| 5,000,000,000,000 | 10,000,000 | 31536000 | 158,549 | 63.07 |
计算过程与上一张表完全同构:
- 每块可容纳的存储字节 = 5,000,000,000,000 / 31,536,000 ≈158,549 字节/块;
- gas/字节 = 10,000,000 / 158,549 ≈63.07。
由此得到初始存储费率的建议值:每字节 63 gas。
横向对照:为什么这个数字与以太坊量级一致
为了确认 63 gas/字节 的合理性,文档将上述数字与以太坊的收费水平做了对比。核心假设是:如果对以太坊做同样的保守估算——即每个以太坊区块都塞满「新建合约」交易:
- 单个合约最大字节数
max_contract_size = 24,000字节; - 单个最大合约所需 gas =
32,000 + max_contract_size × 200 = 4,832,000(其中 32,000 可理解为合约创建的基础 gas,200 gas/字节 为按字节计费部分); - 以太坊区块 gas 上限取
gas_per_block = 30,000,000; - 每块可容纳的合约数 =
30,000,000 / 4,832,000 ≈ 6个; - 每年区块数 =
365 × 24 × 60 × ~5 ≈ 2,628,000(对应约 12 秒一个区块); - 每年新增合约字节 =
2,628,000 × 6 × 24,000 = 378,432,000,000,即约378 GB/年。
这个约 378 GB/年的「以太坊存储写入上限」与 Fuel 前述保守估算中 500 GB/年的量级基本吻合,说明 63 gas/字节 落在行业可比的合理区间内,不存在数量级上的偏差。
结论与上线策略
综合两套估算与以太坊对照,文档给出的最终建议是:以 63 gas/字节 作为存储费的初始价格。
与此同时,文档对低估风险的处理方式是「在测试网上先验证」:
如果该价格被低估(即过于便宜),这一现象会在正式发布前的测试网络中暴露出来,从而为收集更多数据、更新价格留出充足时间。
即:初始费率不需要一次性定准,重点是先在可丢弃的早期网络上运行,用真实数据校准后再进入长期网络。
从设计文档到链配置:63 gas/字节的源码级落地
上述设计并非停留在纸面。在仓库的版本兼容测试配置中,可以找到该参数的真实取值。
ignition 网络配置:gas_per_byte = 63
在 ignition/chain_config.json 中,consensus_parameters.fee_params.V1明确写有:
"fee_params": { "V1": { "gas_price_factor": 92, "gas_per_byte": 63 } }同时,该配置中的相关约束与文档假设也相互印证:
block_gas_limit: 30000000(区块总 Gas 上限 3,000 万,与文档以太坊对照中使用的gas_per_block数量级一致);contract_params.V1.contract_max_size: 102400、max_storage_slots: 1760(合约体积与存储槽位上限);chain_id: 0。
也就是说,设计文档推导出的初始值63正是 ignition 链配置中实际写入的gas_per_byte取值。
v44 升级配置:参数依旧延续
在 v44/chain_config.json 中,gas_per_byte仍为63,但同一位置的gas_price_factor已由 ignition 的 92 调整为 92000(该字段属于另一套独立的 Gas 价格换算逻辑,不影响按字节存储费),contract_max_size与max_storage_slots则保持一致:
"fee_params": { "V1": { "gas_price_factor": 92000, "gas_per_byte": 63 } }可以看到,存储费率作为共识参数,在网络升级时被显式保留,体现了文档「早期网络逐步按数据量调价」的意图。
费率可随网络配置调整:ignition-v21 的反例
若将视角扩展到 ignition-v21/chain_config.json,可发现该网络版本中gas_per_byte被设为1,block_gas_limit为 42000000。这组配置属于 forkless 升级兼容性测试所使用的历史网络快照,恰好说明同一字段在不同的链/网络版本中可以承载完全不同的取值——存储费率并非协议常量,而是每个网络的 Genesis/共识配置参数,这也正是文档选择「先定值、后调价」策略的前提。
参数如何进入链状态
从配置装载的源码结构看,fee_params并不由 Fuel Core 单独定义,而是嵌套在fuel_tx的ConsensusParameters中:链配置的顶层结构体ChainConfig(定义于 crates/chain-config/src/config/chain.rs)持有pub consensus_parameters: ConsensusParameters字段,连同chain_name、consensus(共识配置)等一起被序列化为chain_config.json;而state_transition_bytecode则按约定存放在同目录下的state_transition_bytecode.wasm文件中,二者共同构成网络的创世定义。
从 chain.rs 的ChainConfig::load实现可以看到,fuel-core启动时通过读取 JSON 反序列化出完整配置,因此gas_per_byte这类取值对每个网络都是开箱即用的配置化输入,修改后即可生成不同的创世配置。
补充说明与限制
需要强调的是,本文与原始设计文档讨论的都是存储费率的推导与参数值本身:
- 推导基于「1 秒一个区块 × 全年运行」的隐含假设(
blocks per year = 31,536,000),与真实网络出块节奏未必一致; - 630.72 gas/字节 的保守估算只用于界定理论上限,不作为实际费率;
- 63 gas/字节 针对的是「早期、非长期存续的网络」;上线后在测试网中收集实际存储增长数据并据此调价,是设计内的一环;
- 该文档为设计阶段的说明,具体的字节计费实现细节(写存储操作码如何累加 gas)位于执行层(fuel-vm)而非本仓库内,本文不做超出证据的推断。
若需在本地查看当前链配置参数的全貌(含fee_params、gas_costs等),可直接阅读上述 ignition/v44 的chain_config.json,或在 fuel-core 中通过ChainConfig序列化相关代码进一步追查配置结构。
【免费下载链接】fuel-coreRust full node implementation of the Fuel v2 protocol.项目地址: https://gitcode.com/GitHub_Trending/fu/fuel-core
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考