分类 Solana 下的文章

SVM 私有链 Websocket延迟优化


背景

当交易上链后,需要websocket尽快订阅到新发起的交易信息,但已有逻辑有2s左右延迟

目前逻辑

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "blockSubscribe",
  "params": [
    { },
    { "commitment": "finalized" }
  ]
}

当前测试环境为私有网络,且仅有一个Validator

优化延迟

优化链路

  • 原有链路:监听服务 -> WAF -> RPC -> Validator
  • 压缩链路
    • 监听服务 -> RPC -> Validator
      • 去除WAF防护过程造成的延迟
      • 保留RPC对Validator压力防护
    • 监听服务 -> Validator
      • 在1的基础上去除RPC同步Validator区块的时间
      • 在链路路径上,为最短路径,只适合核心私有服务,时间优先

阶段测试结果

结果:链路优化后,延迟优化效果不明显

排除:排除WAF设置或防护逻辑,以及RPC同步相关对websocket的影响

修改参数

修改blockSubscribe.commitment 参数

测试结果

测试参数 最大延迟 概率 备注
blockSubscribe (confirmed) < 1s 95% 满足实时需求
blockSubscribe (finalized) ~ 2s 均值

RPC节点需开启 --rpc-pubsub-enable-block-subscription

总结:当blockSubscribe.commitment 为confirmed时,满足实时性需求

下面继续做具体分析,以及安全性确认

整体分析

commitment

Solana 分别引入了 processedconfirmedfinalized 三种 commitment

Commitment 等级 状态说明 是否可能回滚 用途
processed 当前 leader 节点已执行交易(未确认) 可能被 fork 快速响应
confirmed 超过 1 个 superminority(2/3 vote)节点已投票确认 小概率回滚(如果 fork 被重组) 较安全且快速
finalized 已不可逆地写入链上(root slot) 永不回滚 最终状态

安全分析

confirmed 还可能丢弃?

Solana 是基于 Turbine + Tower BFT 共识 的区块链,允许 fork 存在,直到达成“supermajority lockout”:

举个例子:

  1. Leader A 在 slot 100 产出 block1,包含你的交易 tx1
  2. 多数 validator 已投票确认 → tx1 达到 confirmed
  3. 但 Leader B 在 slot 100 提出了 fork block2(没有 tx1)
  4. 网络切换了分叉,block2 成为主链,block1 被丢弃
  5. 最终你会看到 tx1 消失

这种情况虽然极少发生(除非网络分叉非常激烈),但确实有可能,尤其在以下情况下:

  • 网络波动严重(多个 validator 未及时同步)
  • 特别是在 devnet/testnet 上更常见
  • 冲突交易竞争激烈(如套利机器人密集交易)

单一Validator

结论:如果整个网络只有一个 validator,交易一旦被执行(即 processed),就等同于 finalized,不会被回滚或丢弃

原因:Solana 的分叉和回滚机制依赖于 多个 validator 的投票(tower consensus),但如果你只有一个 validator 节点(如私链或测试环境):

  • 所有交易处理都只走 一个 chain path
  • 没有投票机制(自己 vote 自己)
  • 没有 fork、没有分歧
  • 所有被处理的 block/slot 会直接成为 root → 立即 finalized

延迟分析

问题:在只有一个 Validator 的 Solana 网络中,为什么交易已经 confirmed,但还没有立即 finalized?不是说没有其他节点就没有分叉吗?

原因:因为 finalized 状态取决于 root slot 的推进,而 root slot 的推进有“延迟”或“惰性机制”,即使只有一个 validator。

Solana 的 finalized 并不是单纯根据是否有分叉来判断,而是依赖一个特殊机制:

Tower BFT + Root Slot 推进规则:

  • 每个 validator 会有自己的 "lockout" 投票历史,形成“投票树”
  • 当 validator 在连续的 slot 上投票到一定深度,就能推进 root slot
  • 只有 root 之后的 slot 才会被标记为 finalized

即使只有一个 validator:

  1. 它仍然要投票 → 进入 lockout(自己 vote 自己)
  2. 它仍然需要满足 一定的 slot 深度 才能将旧 slot 设为 root
  3. root slot 推进后,对应的交易和 block 才被认为是 finalized

为什么存在“延迟 finalized”?

机制 描述
lockout period Tower BFT 规定,validator 必须投票到一定深度才可推进 root
skip slot 会阻碍 如果出现 skipped slot(空块),会延迟 root 推进
安全考虑 即使是单节点,仍沿用同样安全逻辑,避免不同部署模式产生不一致行为

举例

假设你只有一个 validator,slot 时间 400ms:

  1. 你在 slot 100 发出一笔交易
  2. 交易执行完成 → processed
  3. 自己投票确认该 block → confirmed
  4. 继续生产 slot 101、102...
  5. 到 slot 104 时,系统满足 root 推进条件,slot 100 被设为 root → 现在它才是 finalized

所以即使没有其他 validator,finalized 仍然比 confirmed 晚 2~4 个 slot(~1.5 秒)

最终总结

  1. 通过blockSubscribe (confirmed) 满足业务实时性要求
  2. 单一Validator,通过订阅confirmed,不存在安全性问题

TokenPocket 如何添加Solana私有网络


安装Chrome扩展

https://chromewebstore.google.com/detail/tokenpocket-web3-crypto-%E9%92%B1/mfgccjchihfkkindfppnaooecgfneiii?utm_source=ext_app_menu

打开资产展示

添加自定义网络

选择SVM


填入私有链对应的RPC,链ID 随意 (对于Solana链没有链ID,这里只是为了与EVM链类型共用布局)

例如

只做演示,BCSkill 技术社区未对外提供私有Solana链支持

添加新增网络

测试

然后回到资产展示,选择新添加的网络即可

注意

不要直接从 系统设置->节点列表->选择Solana->添加自定义节点
这里的添加只能添加Solana官方的节点,添加时会通过RPC 获取getGenesisHash,得到创世hash并与Solana 官方devnet testnet mainnet 进行比对,如果不一致则报错。

应该先添加完自定义网络后,再给自定义网络添加自定义节点


Solana RPC 返回 VersionedTransaction too large


Solana构建发起交易时,返回错误

(*jsonrpc.RPCError)(0xc00739b530)({
 Code: (int) -32602,
 Message: (string) (len=122) "base64 encoded solana_sdk::transaction::versioned::VersionedTransaction too large: 1668 bytes (max: encoded/raw 1644/1232)",
 Data: (interface {}) <nil>
})

错误分析

交易的大小超过1232 字节限制

static_assertions::const_assert_eq!(PACKET_DATA_SIZE, 1232);
/// Maximum over-the-wire size of a Transaction
/// 1280 是 IPv6 最小 MTU
/// 40 字节是 IPv6 报头的大小
/// 8 字节是分片报头的大小
pub const PACKET_DATA_SIZE: usize = 1280 - 40 - 8;

PACKET_DATA_SIZE 硬编码,不可配置,为保障节点间数据传输的稳定和安全性

解决

拆分交易,将多个逻辑拆分到多笔交易

参考

https://github.com/solana-foundation/anchor/issues/2051