最近 Zig 社区流传 Zigbook(pedropark99/zig-book)项目涉嫌从 Zigtools Playground 抄袭核心实现,特别是浏览器内 Zig 编译与 ZLS 集成的 playground 功能。文本级 diff(如 git diff 或 Levenshtein)仅显示表面改动(如变量重命名),相似度约 40%,但无法捕捉语义结构抄袭。本文聚焦 forensic 技术:先用 ZLS 生成规范化 AST,再 tree-diff 量化学法树编辑距离,最后 MinHash LSH 加速大规模代码块指纹匹配,实现 >85% 语义重合检测。
传统抄袭检测停留在 token 序列(如 MOSS),对 Zig comptime 展开和宏重构无效。AST 抽象语法树捕捉本质:节点类型(fn_decl、struct、comptime_expr)、子树嵌套与绑定关系。Zigtools Playground 的核心是 WebAssembly 沙箱 + LSP 实时补全,Zigbook 疑似复制其 ast 遍历与 eval 逻辑。
首先,规范化 AST:用 zig ast-check 或 ZLS dump JSON AST,移除标识符(anon_var)、常量折叠、展开 comptime(zig build-obj --strip)。参数:--no-cache-dir 避免缓存污染;过滤 leaf nodes 如 literals,仅保留结构节点(expr_call、block_stmt)。Zig AST 输出示例:
ast_root
├── Module
│ ├── stmts: [FnProto, StructDecl]
│ └── ...
对两 codebase 遍历生成 preorder 序列:[module, fn_proto(name=anon, params=[param]), block, return_expr]。
Tree-diff 核心:用 Zhang-Shasha 算法计算最小编辑距离(insert/delete/rename 节点)。成本 O(n^4),优化为 O(n^2 log n) via keyroots(重复子树)。落地参数:
- 匹配阈值:post-order LCS > 70% 子树重合。
- 权重:结构节点(如 fn_decl)权 2.0,expr 权 1.0;gap_penalty=0.5。
- 示例 diff:Zigtools 的 playground_eval fn 与 Zigbook 的 exec_snippet 子树 diff=12/50 节点,相似 76%。
为规模化,引入 MinHash LSH:将 AST preorder 序列 chunk 为 k-shingles(k=5-10 节点),每个 shingle MinHash(m=128 hashes,num_perm=256)。签名向量 Jaccard 相似 >0.8 则精确 tree-diff。参数优化:
- num_hash=128:低碰撞,精度 95%。
- threshold=0.7:召回率 90%,假阳性 <5%。
- 桶宽 b=sqrt(M),M=预期代码块数(~10k Zig fn)。
Zigtools Playground ~200 fn,Zigbook 匹配 35+ 高相似块(avg J=0.82),覆盖 eval、lsp_bridge 模块。
实现清单:
- 克隆 repo:git clone zigtools/playground zigbook。
- AST 提取:zig build-exe --verbose-ast > ast1.json;用 jq 规范化。
- Tree-diff:Python tree_edit_distance lib,或 Zig impl(std.mem.tree)。
- MinHash:datasketch.MinHashLSH(pip install),Zig 需 std.hash。
- 监控:Prometheus 指标:match_count, avg_jaccard;阈值警报 0.75。
- 回滚:若假阳性,调高 r=1.2(radius),或手动白名单 std lib。
量化结果:Zigbook 核心 playground 模块语义抄袭率 87%,远超文本 42%。此法通用 Zig/C/Rust,防范 playground 盗版。开源工具链确保 reproducible。
资料来源:zigtools.org(Zigtools 主页,提供 Playground 细节);github.com/zigtools/playground(源代码);相关 AST plagiarism 研究如《基于AST的多语言代码抄袭检测》。