aps-agent/tests/golden/test_audit_merkle.py

87 lines
2.9 KiB
Python
Raw 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.

# ============================================================
# 完整 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)