git / moonbite-network / tests/test_merkle.py · raw
"""Tests for Milestone 2/7 — Merkle tree and inclusion proofs."""import hashlibimport sysfrom pathlib import Pathimport pytestsys.path.insert(0, str(Path(__file__).resolve().parent.parent))from merkle import merkle_proof, merkle_root, verify_merkle_proof # noqa: E402def _txid(s: str) -> str: return hashlib.sha256(s.encode()).hexdigest()def test_single_leaf_root_is_itself(): leaf = _txid("only") assert merkle_root([leaf]) == leafdef test_root_is_deterministic(): ids = [_txid(str(i)) for i in range(4)] assert merkle_root(ids) == merkle_root(list(ids))def test_root_changes_with_any_leaf(): ids = [_txid(str(i)) for i in range(4)] r1 = merkle_root(ids) ids2 = list(ids) ids2[2] = _txid("tampered") assert merkle_root(ids2) != r1def test_odd_count_duplicates_last_node(): # With 3 leaves the last is duplicated; root must be stable/deterministic. ids = [_txid(str(i)) for i in range(3)] assert merkle_root(ids) == merkle_root(ids)@pytest.mark.parametrize("n", [1, 2, 3, 4, 5, 6, 7, 8, 9])def test_proofs_for_every_index(n): ids = [_txid(str(i)) for i in range(n)] root = merkle_root(ids) for i in range(n): proof = merkle_proof(ids, i) assert verify_merkle_proof(ids[i], proof, root) is Truedef test_tampered_proof_fails(): ids = [_txid(str(i)) for i in range(6)] root = merkle_root(ids) proof = merkle_proof(ids, 2) bad = list(proof) sibling, side = bad[0] bad[0] = (_txid("evil"), side) assert verify_merkle_proof(ids[2], bad, root) is Falsedef test_wrong_leaf_fails(): ids = [_txid(str(i)) for i in range(4)] root = merkle_root(ids) proof = merkle_proof(ids, 1) assert verify_merkle_proof(_txid("not-in-tree"), proof, root) is Falsedef test_empty_raises(): with pytest.raises(ValueError): merkle_root([]) with pytest.raises(ValueError): merkle_proof([], 0)