Skip to content

Instantly share code, notes, and snippets.

@sourcepirate
Created March 3, 2019 14:50
Show Gist options
  • Save sourcepirate/d6579c422bfbf7e2662e1fbfa65c760e to your computer and use it in GitHub Desktop.
Save sourcepirate/d6579c422bfbf7e2662e1fbfa65c760e to your computer and use it in GitHub Desktop.
Simple Merkle tree implementation.
from hashlib import md5
def groupn(lst, n):
return [lst[i:i+n] for i in range(0, len(lst), n)]
class Node(object):
def __init__(self, _hash):
self._hash = _hash
self.childrens = []
def hash(self):
return self._hash
class Leaf(object):
def __init__(self, data):
self.data = data
def hash(self):
_hash = md5()
_hash.update(self.data.encode('utf-8'))
return _hash.hexdigest()
def merge_build(nodes):
if len(nodes) == 1:
return nodes[0]
result_nodes = []
has_even_nodes = len(nodes) % 2 == 0
remaining_nodes = []
if not has_even_nodes:
remaining_nodes.append(nodes.pop())
for n1, n2 in groupn(nodes, 2):
result_hash = md5()
h1 = n1.hash()
h2 = n2.hash()
result_hash.update(h1.encode('utf-8'))
result_hash.update(h2.encode('utf-8'))
hash_str = result_hash.hexdigest()
pnode = Node(hash_str)
pnode.childrens = [n1, n2]
result_nodes.append(pnode)
for n1 in remaining_nodes:
result_hash = md5()
result_hash.update(n1.hash().encode('utf-8'))
hash_str = result_hash.hexdigest()
pnode = Node(hash_str)
pnode.childrens = [n1]
result_nodes.append(pnode)
return merge_build(result_nodes)
class MerkleTree(object):
def __init__(self, tree):
self.tree = tree
@classmethod
def build_from(cls, leafs):
leaf_nodes = []
for leaf in leafs:
leaf_nodes.append(Leaf(leaf))
root = merge_build(leaf_nodes)
return cls(root)
merkle = MerkleTree.build_from(["a", "b", "c", "d", "e"])
print(merkle.tree.hash())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment