Download tests/test_hash_engine.py from JakCwi/HDK-audit: direct link, hf CLI and curl.
- Browser
- Download file 4.4 kB
-
https://huggingface.co/JakCwi/HDK-audit/resolve/main/tests/test_hash_engine.py
- Command line
-
hf download hf://JakCwi/HDK-audit/tests/test_hash_engine.py
-
curl -L -o test_hash_engine.py https://huggingface.co/JakCwi/HDK-audit/resolve/main/tests/test_hash_engine.py
4.4 kB
| import hashlib | |
| from hdk.core.hash_engine import HashEngine | |
| from hdk.models import HDKNode, NodeLevel, EventType | |
| def test_content_hash_deterministic(): | |
| engine = HashEngine() | |
| h1 = engine.hash_content("hello world") | |
| h2 = engine.hash_content("hello world") | |
| assert h1 == h2 | |
| assert len(h1) == 64 # SHA-256 hex | |
| def test_content_hash_different_input(): | |
| engine = HashEngine() | |
| h1 = engine.hash_content("hello") | |
| h2 = engine.hash_content("hello!") | |
| assert h1 != h2 | |
| def test_hierarchical_hash_includes_parents(): | |
| engine = HashEngine() | |
| content = engine.hash_content("my query") | |
| h_no_parent = engine.hash_with_parents(content, []) | |
| h_with_parent = engine.hash_with_parents(content, ["aaa111"]) | |
| assert h_no_parent != h_with_parent | |
| def test_changing_ancestor_breaks_hash(): | |
| """Core HDK property: modifying any ancestor invalidates descendants.""" | |
| engine = HashEngine() | |
| root = engine.hash_content("project_1") | |
| tab = engine.hash_with_parents(engine.hash_content("tab_1"), [root]) | |
| conv = engine.hash_with_parents(engine.hash_content("conv_1"), [tab, root]) | |
| query = engine.hash_with_parents(engine.hash_content("prompt"), [conv, tab, root]) | |
| # Now change root | |
| root_tampered = engine.hash_content("project_1_MODIFIED") | |
| query_with_tampered = engine.hash_with_parents( | |
| engine.hash_content("prompt"), [conv, tab, root_tampered] | |
| ) | |
| assert query != query_with_tampered | |
| def _leaf(x: str) -> bytes: | |
| return hashlib.sha256(b"\x00" + x.encode()).digest() | |
| def _node(left: bytes, right: bytes) -> bytes: | |
| return hashlib.sha256(b"\x01" + left + right).digest() | |
| def test_merkle_root_single(): | |
| """A single leaf is hashed with the leaf prefix, never returned bare.""" | |
| engine = HashEngine() | |
| root = engine.compute_merkle_root(["aaa"]) | |
| assert root != "aaa" | |
| assert root == _leaf("aaa").hex() | |
| def test_merkle_root_pair(): | |
| engine = HashEngine() | |
| root = engine.compute_merkle_root(["aaa", "bbb"]) | |
| assert root == _node(_leaf("aaa"), _leaf("bbb")).hex() | |
| def test_merkle_root_odd_count(): | |
| """RFC 6962 shape for 3 leaves: H(0x01 || H(0x01||La||Lb) || Lc).""" | |
| engine = HashEngine() | |
| a, b, c = "a" * 64, "b" * 64, "c" * 64 | |
| root3 = engine.compute_merkle_root([a, b, c]) | |
| assert root3 == _node(_node(_leaf(a), _leaf(b)), _leaf(c)).hex() | |
| # no duplication of the odd leaf | |
| assert root3 != engine.compute_merkle_root([a, b, c, c]) | |
| def test_merkle_root_matches_rfc6962_split(): | |
| """Bottom-up result equals RFC 6962's recursive split at the largest power of two.""" | |
| def mth(d): | |
| if len(d) == 1: | |
| return _leaf(d[0]) | |
| k = 1 | |
| while k * 2 < len(d): | |
| k *= 2 | |
| return _node(mth(d[:k]), mth(d[k:])) | |
| engine = HashEngine() | |
| for n in range(1, 18): | |
| data = [f"leaf{i}" for i in range(n)] | |
| assert engine.compute_merkle_root(data) == mth(data).hex(), n | |
| def _chain(engine): | |
| root = HDKNode(id="r", content_hash=engine.hash_content("project"), parent_chain=[]) | |
| root.self_hash = engine.hash_with_parents(root.content_hash, []) | |
| root.node_hash = engine.create_node_hash(root) | |
| child = HDKNode(id="c", content_hash=engine.hash_content("query"), | |
| parent_chain=[root.node_hash]) | |
| child.self_hash = engine.hash_with_parents(child.content_hash, child.parent_chain) | |
| child.node_hash = engine.create_node_hash(child) | |
| return root, child | |
| def test_verify_chain_valid(): | |
| """parent_chain holds the parent's node_hash, and verify_chain accepts that.""" | |
| engine = HashEngine() | |
| root_node, child_node = _chain(engine) | |
| assert engine.verify_chain(child_node, [root_node]) is True | |
| def test_verify_chain_tampered(): | |
| engine = HashEngine() | |
| root_node, child_node = _chain(engine) | |
| # wrong parent hash in the chain | |
| child_node.parent_chain = ["TAMPERED_HASH"] | |
| assert engine.verify_chain(child_node, [root_node]) is False | |
| def test_verify_chain_tampered_parent(): | |
| engine = HashEngine() | |
| root_node, child_node = _chain(engine) | |
| root_node.model = "forged" # parent's fields no longer match its node_hash | |
| assert engine.verify_chain(child_node, [root_node]) is False | |
| def test_verify_chain_missing_parent(): | |
| engine = HashEngine() | |
| root_node, child_node = _chain(engine) | |
| assert engine.verify_chain(child_node, []) is False | |