The common structure of a Merkle tree is a binary tree, but it can also be a multi-fork tree, which has all the characteristics of a tree structure. The basic data of the Merkle tree is not fixed, and you can store any data you want, because it only needs the hash value obtained by hashing the data. The Merkle tree is calculated layer by layer from bottom to top, each intermediate node is calculated based on the combination of two adjacent leaf nodes, and the root node is calculated based on the combination of two intermediate nodes, so the leaf node is the basis. Therefore, any changes to the underlying data will be propagated to its parent nodes, all the way to the root node of the tree.
The Merkle tree is one of the important security means used in blockchain technology to protect data from tampering, and it plays a very important role. The following example demonstrates the construction of a Merkle tree by traversal, and calculates and displays the hash value of each step.
import hashlib #for hash value calculation #Definition of the Merkle tree node class class MerkleNode(object): def __init__(self,left=None,right=None,data=None): self.left = left self.right = right # The hash value is stored in data self.data = data #Build Merkle tree recursively def createTree(nodes): list_len = len(nodes) if list_len == 0: return 0 else: while list_len %2 != 0: nodes.extend(nodes[-1:]) list_len = len(nodes) secondary = [] #Merge nodes in pairs and calculate their hash value for k in [nodes[x:x+2] for x in range(0,list_len,2)]: d1 = k[0].data.encode() d2 = k[1].data.encode() md5 = hashlib.md5() md5.update(d1+d2) newdata = md5.hexdigest() node = MerkleNode(left=k[0],right=k[1],data=newdata) secondary.append(node) if len(secondary) == 1: return secondary[0] else: return createTree(secondary) #Use the breadth-first search algorithm to traverse the node data def BFS(root): print('Start breadth-first search, build Merkle tree...') i=0 queue = [] queue.append(root) while(len(queue)>0): e = queue.pop(0) i+=1 #print("Hash Value:"+str(i),e.data) if e.left != None: queue.append(e.left) if e.right != None: queue.append(e.right) print("Hash value:"+str(i),e.data) if __name__ == "__main__": blocks = ['node1','node2','node3','node4'] #Sample data, including 4 nodes nodes = [] #node initialization print("node hash:") for element in blocks: #Traverse sample data md5 = hashlib.md5() #Digest algorithm md5.update(element.encode()) d=md5.hexdigest() #Compute the information summary of the node nodes.append(MerkleNode(data=d)) #Add to the Merkle tree node print(element+":",d) root = createTree(nodes) #Create Merkle root node BFS(root) #Construct Merkle tree based on BFS algorithm and output all hashes (summary)
The running screenshot is as follows: