Skip to content

Commit 244d2de

Browse files
committed
Add Merkle Tree construction and verification algorithm
1 parent e2a78d4 commit 244d2de

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

blockchain/merkle_tree.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
"""
2+
Merkle Tree Construction and Verification
3+
4+
This module implements the construction of a Merkle Tree and
5+
verification of inclusion proofs for blockchain data integrity.
6+
7+
Each leaf is a SHA-256 hash of a transaction, and internal nodes are
8+
computed by hashing the concatenation of their child nodes.
9+
10+
References:
11+
https://en.wikipedia.org/wiki/Merkle_tree
12+
"""
13+
14+
import hashlib
15+
16+
17+
def sha256(data: str) -> str:
18+
"""Compute SHA-256 hash of a string."""
19+
return hashlib.sha256(data.encode()).hexdigest()
20+
21+
22+
def build_merkle_tree(leaves: list[str]) -> list[list[str]]:
23+
"""
24+
Build a Merkle Tree from the given leaf nodes.
25+
26+
Args:
27+
leaves: List of data strings (transactions).
28+
29+
Returns:
30+
A list of lists representing tree levels,
31+
with the last level containing the Merkle root.
32+
33+
>>> len(build_merkle_tree(["a", "b", "c", "d"])[-1][0])
34+
64
35+
"""
36+
if not leaves:
37+
raise ValueError("Leaf list cannot be empty.")
38+
39+
current_level = [sha256(x) for x in leaves]
40+
tree = [current_level]
41+
42+
while len(current_level) > 1:
43+
next_level = []
44+
for i in range(0, len(current_level), 2):
45+
left = current_level[i]
46+
right = current_level[i + 1] if i + 1 < len(current_level) else left
47+
next_level.append(sha256(left + right))
48+
current_level = next_level
49+
tree.append(current_level)
50+
51+
return tree
52+
53+
54+
def merkle_root(leaves: list[str]) -> str:
55+
"""
56+
Return the Merkle root hash for a given list of data.
57+
58+
>>> r = merkle_root(["tx1", "tx2", "tx3"])
59+
>>> isinstance(r, str)
60+
True
61+
"""
62+
return build_merkle_tree(leaves)[-1][0]
63+
64+
65+
def verify_proof(leaf: str, proof: list[str], root: str) -> bool:
66+
"""
67+
Verify inclusion of a leaf using a Merkle proof.
68+
69+
Args:
70+
leaf: Original data string.
71+
proof: List of sibling hashes up the path.
72+
root: Expected Merkle root hash.
73+
74+
Returns:
75+
True if proof is valid, else False.
76+
77+
>>> data = ["a", "b", "c", "d"]
78+
>>> tree = build_merkle_tree(data)
79+
>>> root = tree[-1][0]
80+
>>> leaf = "a"
81+
>>> proof = [sha256("b"), sha256(sha256("c") + sha256("d"))]
82+
>>> verify_proof(leaf, proof, root)
83+
True
84+
"""
85+
computed_hash = sha256(leaf)
86+
for sibling in proof:
87+
combined = sha256(computed_hash + sibling)
88+
computed_hash = combined
89+
return computed_hash == root
90+
91+
92+
if __name__ == "__main__":
93+
import doctest
94+
doctest.testmod()

0 commit comments

Comments
 (0)