可否量化 SOL 网络拥堵的指标区调整优先费提高上链速度呢?判断 SOL 网络拥堵的指标,SOL 域名解析商 sns.id 网页上右上角显示 Congested network, 从区块浏览器上看 TPS 普遍都有 4000+ 但 true TPS 真正属于用户交易的其实就只有几百 TPS,其余的 TPS 都是网络共识层投票等。
网络拥堵时,交易员/开发者/套利者等发出去的交易常常等很久都不上链,也听 space 上开发者抱怨交易很难上链或者优先费用卷的很高,如何利用优先费用 (priority fee)或者jito 小费 (jito tips)机制提高交易成功率和上链速度呢?
优先费用机制
- 交易带 SetComputeUnitPrice 指令才启用 优先费机制
- 交易带 SetComputeUnitPrice 但没 SetComputeUnitLimit 指令 默认按 20 万 ComputeUnitLimit/每条指令
- 交易同时带 CU price/limit 两个指令 (不管指令顺序),不管交易成功或失败都收取 price*limit 的优先费用
ComputeUnit 往后简称为 CU, sol 官方文档 how-to-use-priority-fees 中有个规则 2 的示例交易 (solscan)
文档说
set the Compute Unit Limit to 300 CUs while also adding a priority fee of 20000 micro-lamports
应该是这篇文章里面的 tx 太旧了,是以前验证者节点代码,最新的 agave 源码中如果是内置指令没有加 CUlimit 也会自动设置成 150, 第三方指令就 20 万
实际上这个交易忘了设置 CU limit 变成默认的 20 万 CU limit 每条指令 (最新验证者节点这个交易 CU limit 应该自动是 300 可能过于古老了) 所以收取了每笔交易基本费用,注意 CU price 单位是 micro lamports 要乘以 1e-6 转换成 SOL_lamports per CU 的量纲
5000 + (20000*1e-6 * 200000) = 9000 lamports SOL = 0.000009SOL
交易费用=5000lamports 基础费 + 账户租金费/开户费 + 优先费用,优先费用总值的竞价排名决定了交易在验证者出块的优先级
源码在 agave(solana 2.0 之后改名成 agave 项目继续维护了,原 github 地址不更新) 的 cost-model crate 中可以看到常量 DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT 就是 20 万
fn get_transaction_cost( transaction: &impl TransactionWithMeta, feature_set: &FeatureSet, ) -> (u64, u64, u64) { let mut programs_execution_costs = 0u64; let mut compute_unit_limit_is_set = false; let mut has_user_space_instructions = false; for (program_id, instruction) in transaction.program_instructions_iter() { let ix_execution_cost = if let Some(builtin_cost) = BUILTIN_INSTRUCTION_COSTS.get(program_id) { *builtin_cost } else { has_user_space_instructions = true; u64::from(DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT) }; programs_execution_costs = programs_execution_costs .saturating_add(ix_execution_cost) .min(u64::from(MAX_COMPUTE_UNIT_LIMIT)); if compute_budget::check_id(program_id) { if let Ok(ComputeBudgetInstruction::SetComputeUnitLimit(_)) = try_from_slice_unchecked(instruction.data)
再看一个同时设置了 CU price 和 limit 的例子:https://solscan.io/tx/BcBCS61y3GpYCHVzUZ3KK7v1M7PgYqNM8oyqx3oLq7XcxaYDW5SH1GQqvL5pkR91jypxh9sPDpztMby32oxEnre
agave 源码中 solana_compute_budget_program DEFAULT_COMPUTE_UNITS 是 150, 设置 CU limit/price和转账都是150
上述交易 CU limit 设置了 3000,交易有 2 个设置 CU 的指令和 18 次 SOL 转账的指令,加起来刚好是 (2+18)*150=3000 CU
10000*1e-6 * 3000 = 300 lamports
CU limit 如何设置
即便交易只用了 300CU 但设置了 20 万的 CU limit(如上述例子 1 的 tx), 也是按照 CU limit 20 万收取优先费用
所以交易中尽可能设置更低的 CU Limit,而且根据helius 文档 CULimit 越低的交易上链的优先级更大
常见的交易指令中消耗的 CU
- transfer/SetCU: 150
- 智能合约部署:约 2500-3000
- token transfer: 5000(不需要开户时)
- create ATA account(token 开户): 约 30000
- raydium AMM swap: 约 33000-40000
- jupiter swap: 约 100000-400000
像 jup swap 这样不确定的 CU 消耗 推荐用 simulate rpc 模拟执行获取 CU 消耗
优先费用价格 CU price 设置算法
- 交易预期利润的 60% 除以 CU limit 得到单价的套利贿赂矿工算法
- Helius Priority Fee API 的推荐
- rpc getRecentPrioritizationFees
- triton Improved Priority Fees API
- jupiter,raydium,metaora 这样的产品也内置了优先费用的计算,无需开发者处理
原版 rpc 优先费 API 返回的是某个智能合约地址最近 150 区块交易中的最小值 (at least one successfully landed)
其实更推荐用 triton 增强型优先费 API 能查询到某智能合约最近大伙给的优先费的中位数
一般网络拥堵的时候我个人经验是 jupiter TURBO 等级的优先费用都要给到 0.2u~0.4u 不等
SOL 跟 EVM 不同的是,EVM 如果交易失败了 收取的是 gasPrice * gasUsed(实际消耗的 CU)
那么问题来了,对于一个预期利润是 10SOL 的套利交易,拿出了 80% 预期利润 8SOL 的优先费用贿赂矿工
但是交易因为滑点过大没抢单成功,交易失败了也要支付 8SOL 的优先费用,是非常昂贵的成本了
为套利者而生的 jito
jito 的出现就解决了这个问题,jito 的交易不需要设置优先费用 CU price 的指令 (CU limit 还是建议要)
而是让交易最后加一个给 jito 8 个小费地址随机选一个转账的指令,为什么要随机选一个呢
如果大伙都往第一个小费地址打钱,8 个地址随机选一个可以提高吞吐量同时有 8 个 jito 小费指令可并行执行
所以发送给 jito 的交易失败发生回滚的话,最后一条小费指令不会执行,也就损失 5000lamports 的基础交易费用
bloXroute加速上链服务
很多 bot 的交易不直接发给 jito,而是通过 bloXroute 转发给 jito。因为 bloXroute 有一个 super bundle 的功能,能打包不冲突的交易,bundle 的 tip 也给的高,所以比直接发 jito 速度更快。
bloXroute 也是 jito 最大的合作伙伴之一,在 jito 那里有很高的账户等级;tip 给的高,只是快速上链的条件之一。其实还有其他一些基础设施上的配置,包括全球的节点布置,合作节点,网络拓扑优化等等
据说主要是交易机器人和一些 dex,做市商等采购 bloXroute 服务,我没用过就不评价了
什么时候用 jito 什么时候用优先费
适用于 jito 加速交易的业务
- 套利交易
- 狙击 pump/raydium 等开盘
- 防夹
- 价格波动大的 LP 建仓
- 失败率高允许重试有希望快点上链的业务
笔者有次 LP 建仓发交易就说价格波动导致 tick 滑点变动交易失败,连续失败 4-5 次 每次亏损 0.4$的优先费用 如果用 jito 不断重试交易就不必亏这么多了
适用于优先费用加速交易的业务
- memecoin swap 交易
- 快点转账
既不要 jito 也不要优先费的业务
- 转账 (钱包软件基本不给优先费)
- 智能合约部署
- LP 超出区间了移除流动性等不是很急的业务
智能合约部署我的经验是推荐用 aws 免费节点+helius 免费 rpc 上传/部署智能合约
项目不急着上线失败就重试几次 (急的话 deploy 可加优先费用的命令行参数),失败的话会出现一些 program buffer 占用资金,稍后 solana program close 关掉后就能回收 SOL 了
谁当 leader 就给谁发
由于 SOL 网络中当前 epoch POS 的 leader 顺序是确定的,也可以预测下个 leader 是 jito 的节点就给 jito 发交易,如果是 helius/triton 节点就用优先费给他们发
还有一种思路 nonceAccount 同时签名两个交易一个发 jito 一个发 helius,一个成功另一个自然因为 nonce 无效而失败
swqos 机制加速上链
swqos 简单说就是质押量越大的验证者节点,在下个区块出块中能提交给 leader 节点的交易数更多,所以走质押量更大的节点 rpc 上链更快
听 solayer 在 space 说 要把 swqos 加速上链的机制做成 restaking 奖励,用户质押给项目方更多 SOL,项目的上链速度更快体验更好,项目方应该奖励给质押用户额外奖励这样的经济模型
swqos 节点基本是被 triton,helius 这样的大户厂商垄断了,quicknode 这样的知名厂商也没有,所以 solayer 能否打破这种垄断呢 (支持华语区项目打破垄断)
如何确认交易成功/交易重试
由于 solana 网络拥堵时,发出去的交易可能被 rpc 节点丢弃没有发成功给 leader 节点了,或者等很久很久才上链,因此重试策略推荐阅读 triton 这篇文章 https://docs.triton.one/chains/solana/sending-txs
- 计算下签名交易用的 blockhash 还有多久过期
- ws 订阅交易的 signature
- 发送交易
- 每隔一段时间获取交易状态,定时重发交易
直到 http 轮询交易成功或者 ws 推送交易成功
由于笔者做的是套利业务对时效性要求极高 (行情过几秒后可能滑点巨大),所以我的做法是交易中插入一条超时 5s 指令
ws+http 轮询交易状态超过 5s 就认为是超时了,这样交易很久之后才上链会因为超时而失败