# ============================================================ # 完整 Merkle 树黄金测试(plan.md §3.6 / 矩阵「全审计」剩余项) # 覆盖:确定性、顺序/数量/内容敏感、成员证明校验、篡改检测、导出携带根。 # ============================================================ from __future__ import annotations import copy import hashlib import json from server.agent_core.audit_export import export_events from server.agent_core.audit_ledger import GENESIS_ROOT from server.agent_core.audit_merkle import ( _leaf_hash, merkle_proof, merkle_root, verify_proof, ) def _events(n: int = 5) -> list[dict]: out: list[dict] = [] prev = "GENESIS" for i in range(n): ev = {"id": i + 1, "action": f"action-{i}", "prevHash": prev} prev = hashlib.sha256((prev + json.dumps(ev, sort_keys=True)).encode()).hexdigest() ev["hash"] = prev out.append(ev) return out def test_merkle_root_deterministic_and_sensitive(): """Merkle 根:同事件同根;空树=创世根;顺序/数量/内容变化均断根。""" evs = _events() assert merkle_root(evs) == merkle_root(evs) assert merkle_root([]) == GENESIS_ROOT assert merkle_root(evs) != merkle_root(list(reversed(evs))) assert merkle_root(evs) != merkle_root(evs[:-1]) tampered = copy.deepcopy(evs) tampered[2]["hash"] = "0" * 64 assert merkle_root(evs) != merkle_root(tampered) def test_merkle_proof_every_index_verifies(): """成员证明:每个事件都能给出 O(log n) proof 且 verify_proof 通过。""" evs = _events(8) root = merkle_root(evs) for i in range(len(evs)): proof = merkle_proof(evs, i) assert proof["root"] == root assert verify_proof(root, _leaf_hash(evs[i]), proof) is True # sibling 数应等于树高(8 叶 → 3 层) assert len(proof["siblings"]) >= 2 def test_merkle_proof_rejects_wrong_leaf(): """错误叶子无法通过证明校验(防伪造成员)。""" evs = _events(6) root = merkle_root(evs) proof = merkle_proof(evs, 1) other_leaf = _leaf_hash(evs[4]) assert verify_proof(root, other_leaf, proof) is False def test_merkle_proof_out_of_range(): """越界索引返回错误,不抛异常。""" evs = _events(3) assert merkle_proof(evs, -1)["error"] assert merkle_proof(evs, 99)["error"] def test_merkle_single_and_empty(): """单事件/空事件边界:根互异且可复算。""" one = _events(1) root1 = merkle_root(one) assert root1 != GENESIS_ROOT assert merkle_root(_events(1)) == root1 proof = merkle_proof(one, 0) assert verify_proof(root1, _leaf_hash(one[0]), proof) is True def test_export_json_carries_merkle_root(): """合规导出 JSON 携带 merkleRoot,且与本地复算一致。""" evs = _events(4) payload = json.loads(export_events(evs, fmt="json")) assert payload["merkleRoot"] == merkle_root(evs)