Solana交易手续费机制深度分析

Solana交易手续费机制深度分析

背景分析

Solana采用了计算单元(Compute Units)的概念来衡量和控制交易的资源使用。

sequenceDiagram participant Client as 客户端 participant TPU as 交易处理单元(TPU) participant Banking as Banking Stage participant FeeCalc as 费用计算器 participant AccountLoader as 账户加载器 participant Bank as Bank participant Validator as 验证者 Client->>TPU: 提交交易(包含计算预算指令) TPU->>Banking: 转发交易到Banking Stage Banking->>FeeCalc: 解析计算预算指令 Note over FeeCalc: 处理SetComputeUnitLimit
SetComputeUnitPrice等指令 FeeCalc->>FeeCalc: 计算费用组成部分 Note over FeeCalc: 签名费用 = 签名数量 × lamports_per_signature
写锁费用 = 写锁数量 × lamports_per_write_lock
计算费用 = 根据compute_fee_bins确定
优先级费用 = 计算单元限制 × 单元价格 FeeCalc->>Banking: 返回总费用 Banking->>AccountLoader: 加载账户并验证费用支付能力 AccountLoader->>AccountLoader: 验证费用支付者账户 Note over AccountLoader: 检查账户余额是否足够支付费用
从支付者账户扣除费用 alt 费用支付成功 AccountLoader->>Banking: 返回已加载的交易 Banking->>Bank: 执行交易 Bank->>Bank: 处理交易逻辑 Bank->>Banking: 返回执行结果 Banking->>Validator: 收集费用 Note over Validator: 费用分配:
销毁费用 = 总费用 × burn_percent
验证者收益 = 总费用 - 销毁费用 Validator->>Client: 返回交易确认 else 费用支付失败 AccountLoader->>Banking: 返回InsufficientFundsForFee错误 Banking->>Client: 返回交易失败 end
  1. 交易提交阶段:客户端向TPU提交包含计算预算指令的交易
  2. 费用计算阶段:系统解析计算预算指令并计算各项费用
  3. 账户验证阶段:验证费用支付者账户并扣除费用
  4. 交易执行阶段:在Bank中执行交易逻辑
  5. 费用分配阶段:按照burn_percent分配费用给验证者和销毁

Solana手续费模型概述

在Solana中,交易手续费以lamports为单位计算,其中1 SOL = 10^9 lamports。 手续费结构包含多个组成部分:

  1. 基础签名费用 - 每个签名固定收费
  2. 写锁费用 - 对需要写入的账户收费
  3. 计算费用 - 基于计算单元使用量
  4. 优先级费用 - 用户可选的额外费用以提高交易优先级

计算单元(Compute Units)机制

计算预算指令

Solana提供了专门的计算预算指令来管理资源使用:

  • SetComputeUnitLimit - 设置交易允许消耗的最大计算单元数
  • SetComputeUnitPrice - 设置每计算单元的价格(以微lamports为单位)

默认计算单元限制

系统设定了默认的计算单元限制:

  • 单个指令默认限制:200,000 CU
  • 交易最大限制:1,400,000 CU

手续费计算公式

基础费用计算

费用计算包含以下组成部分:

总费用 = 签名费用 + 写锁费用 + 计算费用 + 优先级费用

具体计算公式:

  • 签名费用 = 签名数量 × 每签名lamports费用
  • 写锁费用 = 写锁数量 × 每写锁lamports费用
  • 计算费用 = 根据计算单元区间确定的固定费用
  • 优先级费用 = 计算单元限制 × 计算单元价格(微lamports)

动态费用调整

Solana通过FeeRateGovernor实现动态费用调整:

动态调整公式

  • 最小费用 = 目标费用 ÷ 2
  • 最大费用 = 目标费用 × 10
  • 调整幅度 = 目标费用 ÷ 20(每次调整5%)

根据网络负载自动调整每签名的费用,调整范围为目标费用的50%-1000%。

不同操作的计算单元消耗

基础操作成本

Solana为各种操作预定义了计算单元消耗:

常见操作成本表

  • 日志记录:100 CU
  • 创建程序地址:1,500 CU
  • 程序调用:1,000 CU
  • SHA256基础费用:85 CU
  • secp256k1恢复:25,000 CU

加密操作成本

椭圆曲线操作成本

  • curve25519点验证:159-169 CU
  • 点加法:473-521 CU
  • 点乘法:2,177-2,208 CU
  • MSM基础成本:2,273-2,303 CU

内存使用费用

账户数据加载按32KB页面计费:

内存费用计算公式

复制代码
内存费用 = ⌈加载数据大小 ÷ 32KB⌉ × 堆成本

其中:

  • 页面大小 = 32KB (32,768字节)
  • 默认堆成本 = 8个计算单元每页

计算预算处理实现

指令处理流程

系统在交易处理早期阶段解析计算预算指令:

处理步骤

  1. 解析计算预算指令
  2. 确定计算单元限制(默认或用户设定)
  3. 确定计算单元价格(默认0或用户设定)
  4. 设置堆大小请求
  5. 设置账户数据大小限制

费用销毁机制

与Cosmos不同,Solana采用费用销毁机制:

费用分配公式

复制代码
销毁费用 = 总费用 × 销毁百分比 ÷ 100
未销毁费用 = 总费用 - 销毁费用

默认销毁50%的手续费,剩余部分分配给验证者。

优先级费用机制

用户可以通过设置计算单元价格来提高交易优先级:

优先级费用计算公式

复制代码
优先级费用 = 计算单元限制 × 计算单元价格(微lamports)÷ 1,000,000

实现获取Top90高费用交易的可能流程

基于现有架构,实现此功能需要以下步骤:

sequenceDiagram participant Client as 客户端 participant RPC as RPC服务 participant Bank as Bank participant Blockstore as Blockstore participant FeeAnalyzer as 费用分析器 Client->>RPC: 请求top90高费用交易 RPC->>Bank: 获取最新确认的区块 Bank->>Blockstore: 查询历史交易数据 Blockstore->>FeeAnalyzer: 提供交易列表 FeeAnalyzer->>FeeAnalyzer: 计算每笔交易的总费用 Note over FeeAnalyzer: 总费用 = 基础费用 + 优先级费用
使用FeeStructure.calculate_fee() FeeAnalyzer->>FeeAnalyzer: 按费用降序排序 Note over FeeAnalyzer: 类似cluster_info_metrics中的
select_nth_unstable_by_key逻辑 FeeAnalyzer->>RPC: 返回前90笔高费用交易 RPC->>Client: 返回结果

技术实现要点

  1. 费用计算 :需要使用calculate_fee方法来准确计算每笔交易的总费用。

  2. 数据存储:交易的费用信息可以看到会被记录到rewards中,但需要额外的索引来支持按费用排序。

  3. 排序算法 :可以参考排序逻辑,使用sort_by来实现按费用降序排列。

当前限制

目前Solana的RPC接口主要提供基础的交易查询功能,如供应量查询。要实现top90高费用交易查询,需要:

  1. 扩展RPC接口
  2. 建立费用索引
  3. 实现高效的排序和分页机制

Solana的排序规则

1. 投票统计的Top排序

在gossip网络中,Solana使用排序逻辑来获取投票数最多的slot:

这里使用了select_nth_unstable_by_key方法,按投票数量降序排序,只保留前10个最活跃的slot。

2. 质押权重排序

在修复权重系统中,Solana按质押权重对slot进行排序:

这个排序逻辑优先考虑更高的质押权重,相同权重时按slot编号升序排列。

3. 账户清理中的排序

在账户数据库清理过程中,使用并行排序来处理大量公钥:

根据是否为启动阶段,选择不同的排序策略 - 启动时使用并行排序,运行时使用线程池排序。

4. 存储收缩中的排序

在存储优化过程中,按存活率对存储条目进行排序:

这里按存活率升序排序,优先处理最稀疏的存储条目。

5. 程序缓存排序

在程序缓存管理中,按使用频率排序来决定卸载哪些程序:

使用sort_by_cached_key按事务使用计数器排序,优先卸载使用频率最低的程序。

6. 银行状态排序

在银行状态管理中,对祖先slot进行排序:

这里使用稳定排序来维护祖先关系的一致性。

7. 投票状态排序

在投票状态处理中,对锁定期进行排序:

按slot编号对锁定期进行排序,确保投票状态的正确性。

Solana的排序逻辑主要特点:

  1. 性能优化 - 大量使用unstable_sort和并行排序
  2. 场景特化 - 不同场景使用不同的排序键和策略
  3. 内存效率 - 使用select_nth_unstable等方法避免完整排序
  4. 稳定性考虑 - 在需要保持相对顺序的场景使用稳定排序

总结

Solana的手续费机制在设计上更加精细化,通过计算单元精确衡量各种操作的资源消耗。与Cosmos的gas机制相比,Solana的特点包括:

  1. 预定义成本 - 大多数操作都有预定义的计算单元成本
  2. 分层计费 - 签名、写锁、计算分别计费
  3. 动态调整 - 根据网络负载自动调整基础费用
  4. 优先级机制 - 用户可通过额外费用提高交易优先级
  5. 费用销毁 - 部分费用被永久移除,有助于通胀控制
相关推荐
熟悉的新风景5 小时前
springboot项目或其他项目使用@Test测试项目接口配置-spring-boot-starter-test
java·spring boot·后端
晴空月明7 小时前
分布式系统高可用性设计 - 监控与日志系统
后端
songroom7 小时前
【转】Rust: PhantomData,#may_dangle和Drop Check 真真假假
开发语言·后端·rust
红尘散仙8 小时前
Rust 终端 UI 开发新玩法:用 Ratatui Kit 轻松打造高颜值 CLI
前端·后端·rust
mldong8 小时前
mldong-goframe:基于 GoFrame + Vben5 的全栈快速开发框架正式开源!
vue.js·后端·go
canonical_entropy8 小时前
集成NopReport动态生成复杂Word表格
后端·低代码
come112349 小时前
Go 包管理工具详解:安装与使用指南
开发语言·后端·golang
绝无仅有9 小时前
OSS文件上传解析失败,错误:文件下载失败的排查与解决
后端·面试·架构
LaoZhangAI9 小时前
Kiro vs Cursor:2025年AI编程IDE深度对比
前端·后端