教程区块链区块链技术ch1313.6 持续集成(CI)与安全扫描流水线

本页目录

"在 CI 中运行模糊测试,比在生产中遇到攻击者便宜无数倍。" 好的合约工程 = 自动化流水线,让每次 git push 都触发编译→测试→安全扫描→部署的完整链路。


13.6.1 GitHub Actions 流水线示例

graph LR
    subgraph Push[git push / PR 触发]
        S1[lint: prettier/solhint]
        S2[compile: solc / foundry build]
        S3[test: unit / integration / fuzz]
        S4[coverage: codecov]
        S5[security: Slither scan]
        S6[gas-snapshot: 对比基线]
    end
    
    S1 --> S2 --> S3 --> S4 --> S5 --> S6
    
    S5 --> |"高危发现"| Block[❌ 阻塞合并]
    S6 --> |"regression > 1%"| Warn[⚠️ 警告]
    
    style Block fill:#ffebee
    style S1 fill:#c8e6c9
    style S2 fill:#c8e6c9
    style S3 fill:#c8e6c9
    style S4 fill:#fff3e0
    style S5 fill:#ffcdD2
    style S6 fill:#fff3e0

基于 TypeScript 的 CI 配置模拟

typescript
/**
 * 模拟 CI 流水线中的质量关卡(gate)检查
 */
interface CIGate {
  name: string;
  check(): { pass: boolean; message: string };
}

class CIPipeline {
  private gates: CIGate[] = [];
  
  addGate(gate: CIGate) { this.gates.push(gate); }
  
  run(): { passed: boolean; results: { name: string; pass: boolean; message: string }[] } {
    const results = this.gates.map(g => ({ name: g.name, ...g.check() }));
    const passed = results.every(r => r.pass);
    return { passed, results };
  }
}

const pipeline = new CIPipeline();

// Step 1: 代码风格
pipeline.addGate({
  name: "lint",
  check() {
    // solhint 检查:无未使用变量、无危险函数
    const issues: string[] = [];
    return {
      pass: issues.length === 0,
      message: issues.length === 0 ? "✅ All clean" : `❌ ${issues.join(", ")}`,
    };
  },
});

// Step 2: 编译
pipeline.addGate({
  name: "compile",
  check() {
    return { pass: true, message: "✅ Foundry build succeeded" };
  },
});

// Step 3: 测试
pipeline.addGate({
  name: "unit-test",
  check() {
    const tests = 150; const failures = 0;
    return {
      pass: failures === 0,
      message: `✅ teststests,{tests} tests,{failures} failed`,
    };
  },
});

// Step 4: 覆盖率
pipeline.addGate({
  name: "coverage",
  check() {
    const line = 92;
    const branch = 84;
    return {
      pass: line >= 90 && branch >= 80,
      message: `📊 Coverage: line line{line}% / branch{branch}%`,
    };
  },
});

// Step 5: 安全扫描(Slither)
pipeline.addGate({
  name: "slither",
  check() {
    const results = {
      critical: 0,
      high: 0,
      medium: 2,
      low: 5,
    };
    const pass = results.critical === 0 && results.high === 0;
    return {
      pass,
      message: pass
        ? `⚠️ Slither: results.mediummedium,{results.medium} medium,{results.low} low`
        : `❌ results.criticalcritical,{results.critical} critical,{results.high} high findings!`,
    };
  },
});

// Step 6: Gas 快照比对
pipeline.addGate({
  name: "gas-snapshot",
  check() {
    const baseline = 1450000n;
    const current = 1462000n;
    const regression = Number((current - baseline) * 10000n / baseline) / 100;
    return {
      pass: regression < 1.0,
      message: `⛽ Gas: current(+{current} (+{regression}%)`,
    };
  },
});

const result = pipeline.run();
console.log(`Pipeline: ${result.passed ? "✅ PASSED" : "❌ BLOCKED"}`);
for (const r of result.results) {
  console.log(`  r.message({r.message} ({r.name})`);
}

13.6.2 覆盖率标准

指标目标值说明
行覆盖率≥ 90%每行代码至少被执行一次
分支覆盖率≥ 80%每个 if/else 两个分支都执行过
函数覆盖率100%所有 public/external 函数都被测试
状态覆盖手动评估关键状态组合(边界、异常路径)

注意:100% 行覆盖率 != 没有漏洞。测试的是"已写代码的行为",但无法测试"遗漏的逻辑"。


13.6.3 Slither CI 集成配置

yaml
# .github/workflows/slither.yml 关键片段模拟
name: Slither
on: [push, pull_request]
jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: crytic/slither-action@v0.3.0
        with:
          node-version: 16
          fail-on: 'high'  # 发现高危则阻断
          slither-args: '--filter-paths "node_modules|test"'

> ← 13.5 合约验证 | 前往 → ch13-summary(本章总结) |*

评论

0

评论加载中…

发表评论

0/2000