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

171 lines
8.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.rs``ensure_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_pda``get_user_volume_accumulator_pda``get_bonding_curve_v2_pda` |
| `src/instruction/pumpswap.rs` | 184, 198, 385, 407 | `get_user_volume_accumulator_pda``get_pool_v2_pda` |
| `src/instruction/utils/pumpfun.rs` | 229 | `DEFAULT_CREATOR_VAULT.unwrap()`LazyLock 未初始化时可能 panic |
| `src/instruction/bonk.rs` | 多处 | `get_pool_pda``get_vault_pda``params.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` 与依赖升级。
- **unsafe**`perf/hardware_optimizations.rs``realtime_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-sdk**`get_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 或链上程序有未公开变更,建议再与官方实现或链上行为做一次对照验证。*