news 2026/10/12 1:30:27

Cosmos SDK 共识级多档 Gas 价格体系设计:解读 ADR-048(Multi Tier Gas Price System)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Cosmos SDK 共识级多档 Gas 价格体系设计:解读 ADR-048(Multi Tier Gas Price System)
  • 区块链

【免费下载链接】cosmos-sdk

Framework for building performant, customizable blockchains with native interoperability

项目地址:https://gitcode.com/gh_mirrors/co/cosmos-sdk
点击查看免费下载

导读

本文以 Cosmos SDK 架构决策记录 ADR-048 Consensus Fees 为主体,系统讲解一份曾被提出、最终被否决(Status: Rejected)的共识级多档 Gas 价格设计方案:它试图将 Gas 定价从"每个验证人自行配置min-gas-prices"升级为"链上共识统一维护的分层动态价格",并借助 Tendermint mempool 的优先级能力实现交易分层。读完本文,你将理解三档定价的参数模型、EIP-1559 式区块负载调整算法、AuthInfo扩展选项与fee字段语义变更、交易优先级组合规则,以及该提案与当前 Cosmos SDK 实际 fee 检查实现之间的异同。

一、背景与动机:为什么要引入共识级 Gas 价格

在当前的 Cosmos SDK 架构中,Gas 价格保护完全依赖每个验证人节点自身的本地配置。ADR-048 明确指出:

Currently, each validator configures its ownminimal-gas-pricesinapp.yaml. But setting a proper minimal gas price is critical to protect network from DoS attack, and it's hard for all the validators to pick a sensible value, so we propose to maintain a gas price in consensus level.

该机制的现状与源码完全吻合。在当前仓库中,验证人通过app.toml配置minimum-gas-prices(见 server/config/toml.go 中的模板minimum-gas-prices = "{{ .BaseConfig.MinGasPrices }}"),该字段在 server/config/config.go 中定义,其注释写明这是"validator's minimum gas prices";ValidateBasic甚至会强制要求该字段非空(server/config/config.go,否则返回 "set min gas price in app.toml or flag or env variable")。同时 baseapp/config/gas.go 中的GasConfig.MinGasPrices注释也明确:这是"验证人愿意接受处理一笔交易的最低 Gas 价格,主要用于 DoS 与垃圾交易防护"。

问题在于:

  • 设置合理的min-gas-prices对抵御 DoS 攻击至关重要,但全网验证人很难就一个统一的价格达成一致;
  • 验证人之间配置不一致,会导致同一笔交易在不同节点上得到不同待遇,mempool 行为割裂;
  • 静态价格无法随网络负载变化,区块拥堵时缺乏价格信号的自动调节。

因此 ADR-048 提出将 Gas 价格提升到共识层统一维护。此外,该提案还指出自 Tendermint 0.34.20 起 mempool 已支持优先级排序,可以借此实现更精细的 Gas 费用体系。

二、多档价格体系(Multi-Tier Price System):三档设计

ADR-048 的核心设计是在共识层维护一个多档(multi-tier)Gas 价格体系,以提供最大灵活性:

档位价格类型调整方式
Tier 1恒定价格仅能通过治理提案偶尔修改
Tier 2动态价格依据上一区块负载调整
Tier 3动态价格依据上一区块负载调整,但调整速度更快

设计约束:高档位的 Gas 价格必须高于低档位(The gas price of higher tier should be bigger than the lower tier);交易手续费按共识层计算出的精确 Gas 价格收取(The transaction fees are charged with the exact gas price calculated on consensus)。

2.1 参数模型(protobuf Schema)

每档的价格策略通过协议参数表达,ADR-048 给出的参数 schema 如下:

message TierParams { uint32 priority = 1 // priority in tendermint mempool Coin initial_gas_price = 2 // uint32 parent_gas_target = 3 // the target saturation of block uint32 change_denominator = 4 // decides the change speed Coin min_gas_price = 5 // optional lower bound of the price adjustment Coin max_gas_price = 6 // optional upper bound of the price adjustment } message Params { repeated TierParams tiers = 1; }

各字段语义如下:

  • priority:该档交易在 Tendermint mempool 中对应的优先级数值;
  • initial_gas_price:该档 Gas 价格的初始值(首个区块使用);
  • parent_gas_target:区块的目标饱和度(即区块 Gas 用量的期望值,用于负载比较);
  • change_denominator:价格调整速度的分母,数值越大调整越平缓;
  • min_gas_price:可选的价格调整下限,防止价格过低;
  • max_gas_price:可选的价格调整上限,防止价格失控上涨。

2.2 实现层面的字段对齐

在 ADR-048 的"Implementation"一节,TierParams被细化为更贴近实现的形态,其中change_denominator被替换为change_speed(Decimal类型,0 表示不随区块负载调整):

class TierParams: 'gas price strategy parameters of one tier' priority: int # priority in tendermint mempool initial_gas_price: Coin parent_gas_target: int change_speed: Decimal # 0 means don't adjust for block load.

这也解释了三档体系的本质差异:Tier 1 的change_speed为 0(不调整),Tier 2/3 的change_speed非零且不同,从而形成"恒定 / 慢速动态 / 快速动态"的梯度。

三、交易扩展选项与fee字段语义变更

3.1 通过AuthInfo扩展选项指定档位

为了让用户(或钱包/工具)为交易指定服务档位,ADR-048 提出在AuthInfo中增加一个扩展选项:

message ExtensionOptionsTieredTx { uint32 fee_tier = 1 }

其中fee_tier的值就是tiers参数列表的下标索引。这与当前仓库AuthInfo中已经预留的扩展点完全兼容——在 proto/cosmos/tx/v1beta1/tx.proto 中,AuthInfo定义了extension_options(repeated google.protobuf.Any extension_options = 1023;),注释明确说明"arbitrary options that can be added by chains",即各链可以塞入自定义扩展选项而不破坏标准交易结构。ADR-048 正是计划利用这一机制承载ExtensionOptionsTieredTx。

3.2fee从"实收金额"变为"费用上限"

这是本提案对交易语义最重要的变更:

We also change the semantic of existingfeefield ofTx, instead of charging user the exactfeeamount, we treat it as a fee cap, while the actual amount of fee charged is decided dynamically.

变更后的行为:

  • 用户提交的fee不再是实际扣除金额,而是费用上限(fee cap);
  • 实际收费金额由共识层动态决定(即该档位当前 Gas 价格 × 实际 Gas 用量);
  • 若用户给出的fee折算价格低于当前共识价格,交易不会被包含进当前区块,理想情况下应留在 mempool 中,等待共识 Gas 价格下降后被打包;
  • mempool 最终可以清理(prune)这些长期滞留的旧交易。

这一设计相当于把"价格发现"交给了共识层,让低出价交易自动"排队等降价"。

四、交易优先级(Tx Prioritization)

4.1 优先级规则

交易按档位排序,档位越高优先级越高;同一档位内部遵循 Tendermint 默认顺序(当前为 FIFO):

Transactions are prioritized based on the tier, the higher the tier, the higher the priority. Within the same tier, follow the default Tendermint order (currently FIFO).

ADR-048 特别提醒:mempool 的交易排序逻辑不属于共识范畴,恶意验证人可以自行篡改(Be aware of that the mempool tx ordering logic is not part of consensus and can be modified by malicious validator)。因此这套机制只能作为激励性引导,不能作为共识保证。

4.2 与优先级机制的灵活组合

档位机制可以与多种优先级规则自由组合,ADR-048 给出了三类示例:

  • 协议为用户档位追加额外档位:用户可设置 tier 0、10 或 20,但协议内部会创建 tier 0~29 的完整梯度。例如 IBC 交易自动进入user_tier + 5:用户选 tier 1 时,IBC 交易进入 tier 15;
  • 为特殊交易类型保留档位区间:例如 tier 4、5 仅保留给特殊交易类型(如 tier 5 专用于 evidence 交易);普通bank.Send若试图设置 tier 5,会被降级到该普通交易可用的最高档(如 tier 3);
  • 按交易类型强制指定档位:例如 tier 100 专用于 evidence 交易,且所有 evidence 交易无条件进入该档。

这套组合能力使协议可以对"用户自愿选档"之外的交易(跨链消息、作恶举报等)实施协议级强制优先级。

五、min-gas-prices的弃用

若共识级 Gas 价格上线,原有的每验证人min-gas-prices配置将被弃用(deprecate),因为两套机制并存会造成混淆:

Deprecate the current per-validatormin-gas-pricesconfiguration, since it would confusing for it to work together with the consensus gas price.

需要强调的是,这只是一个被否决提案中的设想。当前仓库的实际情况是minimum-gas-prices仍是验证人节点必配项,server/config/config.go 的ValidateBasic要求其非空,且 fee 检查逻辑完全围绕它构建(详见下文第八节)。这也正是"共识级定价"与"本地定价"两条路线在 Cosmos SDK 演进历史中的真实分歧点。

六、区块负载调整算法(Adjust For Block Load)

对于 Tier 2 / Tier 3,Gas 价格依据上一区块 Gas 用量动态调整,算法逻辑与以太坊 EIP-1559 相似:区块用量高于目标时涨价,低于目标时降价,且价格变化量与用量偏差成正比。

ADR-048 给出的 Python 伪代码:

def adjust_gas_price(gas_price, parent_gas_used, tier): if parent_gas_used == tier.parent_gas_target: return gas_price elif parent_gas_used > tier.parent_gas_target: gas_used_delta = parent_gas_used - tier.parent_gas_target gas_price_delta = max(gas_price * gas_used_delta // tier.parent_gas_target // tier.change_speed, 1) return gas_price + gas_price_delta else: gas_used_delta = parent_gas_target - parent_gas_used gas_price_delta = gas_price * gas_used_delta // parent_gas_target // tier.change_speed return gas_price - gas_price_delta

算法要点:

  • 恰好命中目标(parent_gas_used == parent_gas_target):价格保持不变;
  • 超载(用量高于目标):按超量比例涨价,且价格增量至少为 1(max(..., 1)),防止负载很高时价格不涨;
  • 空闲(用量低于目标):按缺量比例降价,降价不设下限(可以降到 0,除非配置了min_gas_price下限);
  • 价格调整步长由gas_price * gas_used_delta // parent_gas_target // change_speed决定,change_speed越大调整越温和——这正是 Tier 2 与 Tier 3"调整速度不同"的实现来源。

七、区块段预留(Block Segment Reservation)

ADR-048 指出一个关键风险:如果高档位交易可以无限挤压低档位交易,用户将被迫全部使用高档位,体系最终退化回单档位(the system degraded to a single tier)。因此理想方案是为每个档位预留区块段(block segment),保证低档位交易不会被完全挤掉:

Ideally we should reserve block segments for each tier, so the lower tiered transactions won't be completely squeezed out by higher tier transactions.

该能力需要 Tendermint 提供支持(We need help from tendermint to implement this),属于依赖外部共识引擎的能力项。

八、整体实现流程(Implementation)

ADR-048 用 Python 风格伪代码勾勒了完整实现,涵盖"档位识别 → 价格调整 → 费用检查 → 优先级回传 → 区块用量记录"的闭环。

8.1 档位识别

interface TieredTx: def tier(self) -> int: pass def tx_tier(tx): if isinstance(tx, TieredTx): return tx.tier() else: # default tier for custom transactions return 0 # NOTE: we can add more rules here per "Tx Prioritization" section

自定义交易默认进入 tier 0;后续可按第四节"Tx Prioritization"的规则在此追加更多判定逻辑(如按交易类型、按 IBC 标记强制提档)。

8.2 共识状态

class State: 'consensus state' # total gas used in last block, None when it's the first block parent_gas_used: Optional[int] # gas prices of last block for all tiers gas_prices: List[Coin]

State记录两个共识状态:上一区块总 Gas 用量(创世后的首个区块为None),以及上一区块各档位的 Gas 价格列表。

8.3 区块生命周期

def begin_block(): 'Adjust gas prices' for i, tier in enumerate(Params.tiers): if State.parent_gas_used is None: # initialized gas price for the first block State.gas_prices[i] = tier.initial_gas_price else: # adjust gas price according to gas used in previous block State.gas_prices[i] = adjust_gas_price(State.gas_prices[i], State.parent_gas_used, tier) def end_block(): 'Update block gas used' State.parent_gas_used = block_gas_meter.consumed()

BeginBlock依据上一区块负载调整各档位价格(首区块用initial_gas_price初始化),EndBlock记录本区块实际 Gas 用量供下一区块使用。

8.4 CheckTx 费用检查与优先级回传

def mempoolFeeTxHandler_checkTx(ctx, tx): # the minimal-gas-price configured by validator, zero in deliver_tx context validator_price = ctx.MinGasPrice() consensus_price = State.gas_prices[tx_tier(tx)] min_price = max(validator_price, consensus_price) # zero means infinity for gas price cap if tx.gas_price() > 0 and tx.gas_price() < min_price: return 'insufficient fees' return next_CheckTx(ctx, tx) def txPriorityHandler_checkTx(ctx, tx): res, err := next_CheckTx(ctx, tx) # pass priority to tendermint res.Priority = Params.tiers[tx_tier(tx)].priority return res, err

这段伪代码体现了提案中CheckTx 阶段的最小价格取max(验证人本地价, 共识价)(在 deliver_tx 上下文下验证人价格为 0,即完全由共识价决定);费用不足直接返回insufficient fees;同时把档位对应的priority写进 ABCI CheckTx 响应,交给 Tendermint mempool 做排序。

九、DoS 攻击防护(DoS Attack Protection)

ADR-048 分析了新体系下的 DoS 防护效果:

  • 高档位饱和攻击成本高昂:攻击者若要占满区块、阻止其他交易执行,必须持续使用最高档位交易,其成本将显著高于默认档位(significantly higher than the default tier),从而形成经济威慑;
  • 低档位垃圾流可被反制:若攻击者用低档位交易刷屏,诚实用户只需发送高档位交易即可在排序上压过攻击者(user can mitigate by sending higher tier transactions)。

十、影响评估(Consequences)

10.1 向后兼容性(Backwards Compatibility)

该提案引入三类不兼容变更:

  • 新的协议参数(Params.tiers);
  • 新的共识状态(parent_gas_used、各档gas_prices);
  • 交易体中新增/变更字段(AuthInfo扩展选项、fee语义)。

10.2 积极影响(Positive)

  • 默认档位维持可预期的 Gas 价格体验:客户端使用 tier 0 即可获得与今天一致的固定价格预期;
  • 高档位价格可自适应区块负载:拥堵时自动涨价、空闲时自动回落;
  • 无优先级冲突:提案仅占用 3 个优先级水平,不会与基于交易类型的自定义优先级规则冲突;
  • 可组合性强:档位可以与其他优先级规则自由叠加。

10.3 负面影响(Negative)

  • 生态需升级:钱包与工具必须适配新的tier参数,且fee字段语义已变更,存量客户端需要重新理解"费用上限"的含义。

十一、与当前仓库实现的对照:一个被否决但影响深远的提案

需要明确:ADR-048 的最终状态是 Rejected(已否决),其"共识级多档 Gas 价格"并未在 Cosmos SDK 主线落地。但将它与当前仓库实现对照,能更清晰地理解其设计的真实价值与取舍:

1. 费用检查:本地定价仍是现状。当前默认费用检查逻辑是 x/auth/ante/validator_tx_fee.go 中的checkTxFeeWithValidatorMinGasPrices:仅在ctx.IsCheckTx()时读取ctx.MinGasPrices(),按fee = ceil(minGasPrice * gasLimit)计算必需费用,不足则返回ErrInsufficientFee("insufficient fees")——这与 ADR-048 伪代码中"低出价返回 insufficient fees"的路径一致,但价格来源仍是各验证人本地配置而非共识状态。

2. 优先级回传:思路已部分落地。该文件中的getTxPriority(x/auth/ante/validator_tx_fee.go)会按交易"最小币种面额的 Gas 价格"计算一个朴素优先级;DeductFeeDecorator(x/auth/ante/fee.go)通过TxFeeChecker接口拿到(fee, priority, error)后调用ctx.WithPriority(priority)(x/auth/ante/fee.go)注入优先级,优先级在 types/context.go 中以int64保存,并最终体现在 ABCI CheckTx 响应中供 Tendermint mempool 排序。而仓库自带的PriorityNonceMempool(types/mempool/priority_nonce.go)正是按"优先级 + 发送者 nonce"二维部分有序存储交易的 mempool 实现——ADR-048 依赖的"mempool 优先级"能力,在现仓库中已有完整落地。

3. 扩展点:机制就绪,但未被用于档位。AuthInfo的extension_options(proto/cosmos/tx/v1beta1/tx.proto)为"链级自定义选项"预留了标准入口,理论上仍可承载类似ExtensionOptionsTieredTx的方案,只是共识级定价本身未获采纳。

综上,ADR-048 是一份"设计了完整参数模型与算法、却因共识复杂度与生态迁移成本被否决"的架构提案;它提出的分层定价、负载自适应、fee 上限语义、优先级组合等思想,与当前仓库"本地最低价 + 优先级 mempool"的实现形成鲜明对照,也为后续链上 Gas 机制设计提供了宝贵参考。

相关资源

  • ADR-048 原文
  • 验证人最低 Gas 价格配置解析
  • app.toml 配置模板(minimum-gas-prices)
  • BaseApp Gas 配置结构
  • 默认费用检查实现 checkTxFeeWithValidatorMinGasPrices
  • DeductFeeDecorator 与 TxFeeChecker 接口
  • Context 的 MinGasPrices 与 Priority
  • PriorityNonceMempool 优先级内存池
  • AuthInfo 扩展选项定义
  • 区块链

【免费下载链接】cosmos-sdk

Framework for building performant, customizable blockchains with native interoperability

项目地址:https://gitcode.com/gh_mirrors/co/cosmos-sdk
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 1:30:15

开源SMU精密测量:从硬件架构到校准实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/12 1:29:21

Tortoise ORM Pydantic 序列化插件:从 Model 到 Schema 的完整实战指南

数据库后端 【免费下载链接】tortoise-orm Familiar asyncio ORM for python, built with relations in mind 项目地址&#xff1a; https://gitcode.com/gh_mirrors/to/tortoise-orm 点击查看 免费下载 本篇技术指南围绕 Tortoise ORM 官方提供的 Pydantic 序列化插件展开&am…

作者头像 李华
网站建设 2026/10/12 1:28:26

SQL Server 2008 R2 CPU与内存调优:从默认配置到手动优化

简介&#xff1a;这份文档面向SQL Server数据库管理员与解决方案供应商&#xff0c;聚焦SQL Server 2008 R2中CPU与内存资源的分配优化问题。相比2005版依赖独立实例与处理器亲和度的做法&#xff0c;2008 R2引入资源控制器&#xff0c;通过资源池与工作负载组实现更灵活的管控…

作者头像 李华
网站建设 2026/10/12 1:28:25

SeetaFace6多功能工具包:离线人脸识别从检测到比对的完整实践

简介&#xff1a;面向人脸识别应用开发者、科研人员与相关专业学生&#xff0c;这份 seetaface6 SDK 多功能开发工具包整合了跨平台人脸识别核心能力&#xff0c;可在 Windows、Linux、macOS 等系统上快速实现人脸检测、特征点定位、人脸比对与活体检测等功能&#xff0c;显著降…

作者头像 李华
网站建设 2026/10/12 1:28:20

UE5延迟渲染管线源码解析:从GBuffer到后处理的数据流与实战

1. 为什么值得花时间啃渲染管线源码很多人第一次打开UE5的渲染模块源码&#xff0c;看到满屏的FSceneRenderer、FDeferredShadingSceneRenderer、FRDGBuilder&#xff0c;第一反应是关掉。我完全理解&#xff0c;因为我自己第一次也是这么干的。但如果你真的想搞清楚"为什…

作者头像 李华