Files
sol-trade-sdk/docs/CODE_REVIEW_REPORT.md
2026-03-07 11:45:33 +08:00

8.9 KiB
Raw Permalink Blame History

sol-trade-sdk 代码审查报告

审查维度:逻辑准确性可读性模块化超低延迟代码质量安全性


1. 代码逻辑准确性

1.1 Instruction 与 IDL / 官方行为

模块 结论 说明
PumpFun buy/sell 一致 账户顺序、discriminator、track_volume 与 idl/pump.json 一致;cashback 时 remainingAccounts 顺序正确
PumpSwap buy/sell 一致 idl/pump_amm.json 一致;sell cashback 使用 quote_mint ATA
PDA 推导 一致 bonding_curve_v2、pool_v2、user_volume_accumulator、creator_vault 等 seeds 与官方一致

1.2 需修正的逻辑/风格

  • src/instruction/utils/pumpswap.rs 约 258、291 行let program_id: &Pubkey = &&accounts::AMM_PROGRAM 为双重引用,易误导且多余。建议改为 &accounts::AMM_PROGRAM

2. 代码可读性

2.1 命名与注释

  • 多数模块有中英文注释,instruction 与 IDL 的对应关系有标注。
  • 建议src/instruction/pumpfun.rs 约 259 行 sell 的 discriminator 使用魔法数组 [51, 230, 133, ...],建议改为 SELL_DISCRIMINATOR 常量(与 buy 路径一致)。

2.2 错误信息与文案

  • 建议src/lib.rs 中 “Current version only support” 应为 “only supports”;类似拼写/语法可统一检查。

2.3 过长函数

  • 建议src/lib.rsensure_wsol_ata 可拆为「入口 + 重试循环」与「单次尝试 + 结果判断」,便于单测和阅读。

3. 模块化

3.1 职责与分层

  • instruction:按协议分(pumpfun / pumpswap / bonk / raydium_* 等),实现 InstructionBuilder,边界清晰。
  • instruction/utils:PDA、常量、类型、池子解析与上层「组指令」分工明确。
  • swqos:按提供商分模块,common 放序列化、确认轮询、HTTP 客户端,无循环依赖。
  • 结论:分层合理,模块化良好。

4. 超低延迟

4.1 必须改:避免多余 clone

位置 问题 建议
src/instruction/pumpswap.rs 约 232、429 行 Instruction { accounts: accounts.clone(), data } 对已拥有的 Vec<AccountMeta> 做完整 clone 改为直接移动:Instruction { program_id, accounts, data },不再 clone

4.2 建议

  • 若多路 SWQOS 并发发同一笔交易,可在调用方序列化一次,再传 &[u8] 给各 client,减少重复 bincode 序列化。
  • 热点路径未见不必要的 Mutex/RwLock 竞争,当前设计可接受。

5. 代码质量

5.1 必须改:避免 panic 的 unwrap

以下 PDA 或关键 Option 使用 .unwrap(),在异常输入下会直接 panic,建议改为 Result 并向上传播错误:

文件 行号(约) 说明
src/instruction/pumpfun.rs 67, 101, 149, 221, 291, 295 get_bonding_curve_pdaget_user_volume_accumulator_pdaget_bonding_curve_v2_pda
src/instruction/pumpswap.rs 184, 198, 385, 407 get_user_volume_accumulator_pdaget_pool_v2_pda
src/instruction/utils/pumpfun.rs 229 DEFAULT_CREATOR_VAULT.unwrap()LazyLock 未初始化时可能 panic
src/instruction/bonk.rs 多处 get_pool_pdaget_vault_pdaparams.rpc.as_ref().unwrap()
src/instruction/utils/bonk.rs 110116, 148152 checked_* 链后 .unwrap(),数学假设不成立会 panic
src/instruction/raydium_cpmm.rs 46, 106, 189, 250 PDA / 状态相关 unwrap
src/instruction/utils/raydium_cpmm.rs 83, 85, 141 get_vault_pda(...).unwrap()

建议:统一改为 .ok_or_else(|| anyhow!("..."))? 或返回 Result,在调用链顶层处理错误,避免进程退出。

5.2 建议

  • 测试:为 instruction 构建(或至少 PDA + discriminator/data 布局)增加单元测试,固定输入与预期 bytes/accounts 比对,便于 IDL 升级时回归。
  • 错误类型claim_cashback_* 等返回 Option<Instruction>;可考虑统一为 Result<Instruction> 并带“无法构建”原因,或在文档中明确 None 的语义。

6. 安全性

6.1 必须改:API key 不得写入日志

位置 问题 建议
src/swqos/astralane_quic.rs 约 61 行 info!(..., "api_key as CN: {}", api_key) 移除 api_key 或改为占位(如 *** / 仅长度)
src/swqos/astralane_quic.rs 约 74 行 info!(..., "Connected at {} (api_key: {})", addr, api_key) 同上

6.2 必须改:SkipServerVerification 风险

位置 问题 建议
src/swqos/astralane_quic.rs 约 179181 行 with_custom_certificate_verifier(SkipServerVerification) 完全跳过服务端证书校验 1)若服务端提供证书:用 RootCertStore 或固定证书做校验;2)若仅 dev/内网:用 feature 或配置限制,并在文档/日志中明确“仅受控环境使用”;3)默认/生产构建建议不跳过校验

6.3 建议

  • 敏感配置:确保生产环境从环境变量或安全配置读取 API key,并在文档中说明。
  • 依赖:定期执行 cargo audit 与依赖升级。
  • unsafeperf/hardware_optimizations.rsrealtime_tuning.rs 中的 unsafe 使用范围可控,需保持注释中的安全约定。

7. 三库联动与超低延迟检查(sol-trade-sdk / sol-parser-sdk / solana-streamer

7.1 逻辑一致性(已确认)

检查项 sol-parser-sdk solana-streamer 说明
Pump buy 账户数 16fill 用 get(9) 填 creator_vault 16accounts[9]=creator_vault 与 idl/pumpfun.json 一致
Pump sell 账户数 14get(8)=creator_vault 14accounts[8]=creator_vault 一致
PumpSwap buy 17/18 指令解析 + fill_buy_accounts get(17)/get(18) 指令解析 accounts.get(17)/get(18) coin_creator_vault_ata/authority 正确
PumpSwap sell 17/18 fill_sell_accounts 同左 同左 一致
填充顺序 先 parselog 或 instruction)→ fill_accounts → push 指令解析直接写 17/18;无单独 fill 步骤 两者均保证事件带齐 creator_vault / coin_creator_vault
find_instruction_invoke 选「账户数最多」的 invoke,保证取到 outer buy/sell N/A(按当前 instruction 解析) 正确

7.2 版本化交易账户解析

  • sol-parser-sdkget_instruction_account_getter 正确支持 versioned tx:先 account_keys,再 loaded_writable_addresses,再 loaded_readonly_addresses,与 Solana 约定一致。
  • solana-streamer:指令的 accounts 为索引,通过 accounts.get(idx as usize).copied() 从完整 accounts: &[Pubkey] 解析;调用方需传入已包含 loaded 的完整账户列表,否则高索引会得到 default()

7.3 超低延迟相关

项目 状态 / 建议
solana-streamer 热路径 已改为顺序执行 inner 解析与 swap_data 提取,去掉 thread::scope + 双 spawn/join,减少 μs 级开销。
sol-parser-sdk log 与 instruction 并行(rayon::join);fill 仅在有 invoke 时做;find_instruction_invoke 为 O(invokes),单程序单 tx 下可接受。
sol-trade-sdk 见上文第 4 节;PumpSwap instruction 构建避免 accounts.clone() 已列为必须改。

7.4 建议

  • solana-streamer:若 gRPC 上游已提供完整 accounts(含 loaded),可避免对每笔 tx 做 accounts.to_vec(),仅在需要 resize 时克隆,进一步降低分配。
  • 三库:保持 IDL 与账户索引注释同步(pumpfun.json / pump_amm.json),避免后续扩展时索引错位。

8. 汇总:必须改 vs 建议改

必须改(优先处理)

序号 位置
1 移除 astralane_quic 中 API key 的日志输出 src/swqos/astralane_quic.rs 61、74 行
2 SkipServerVerification:改为证书校验或仅限 dev 并文档化 src/swqos/astralane_quic.rs 179181 行
3 instruction 中 PDA 等 .unwrap() 改为 Result 并传播错误 pumpfun.rs、pumpswap.rs、pumpfun/utils、bonk、raydium_cpmm 等
4 PumpSwap 构建 instruction 时避免 accounts.clone(),改为移动 src/instruction/pumpswap.rs 232、429 行

建议改(可分批)

序号 位置
5 PDA 的 program_id&&AMM_PROGRAM 改为 &AMM_PROGRAM src/instruction/utils/pumpswap.rs 258、291 行
6 PumpFun sell discriminator 改为命名常量 src/instruction/pumpfun.rs 约 259 行
7 ensure_wsol_ata 拆分;修正 “only support” 等文案 src/lib.rs
8 为 instruction 构建与 PDA 增加单元测试 新建 tests 或模块下
9 生产日志用 tracing 替代 println!/eprintln! src/swqos/astralane.rs

报告基于当前仓库与 IDL 的静态阅读;若官方 SDK 或链上程序有未公开变更,建议再与官方实现或链上行为做一次对照验证。