merkle.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. from crypto import get_hasher
  2. import json
  3. from treelib import Node, Tree
  4. class MerkleNode:
  5. """ A hash tree node, pointing to a leaf value or another node. """
  6. def __init__(self, v1, v2):
  7. self.v1 = v1
  8. self.v1_hash = b'' if v1 is None else v1.get_hash()
  9. self.v2 = v2
  10. self.v2_hash = b'' if v2 is None else v2.get_hash()
  11. def get_hash(self):
  12. """ Compute the hash of this node. """
  13. hasher = get_hasher()
  14. hasher.update(self.v1_hash)
  15. hasher.update(self.v2_hash)
  16. return hasher.digest()
  17. def _get_tree(self, tree, parent):
  18. """ Recursively build a treelib tree for nice pretty printing. """
  19. tree.create_node(self.get_hash()[:10], self, parent)
  20. if isinstance(self.v1, MerkleNode):
  21. self.v1._get_tree(tree, self)
  22. elif self.v1 is not None:
  23. tree.create_node(str(self.v1), str(self.v1), self)
  24. if isinstance(self.v2, MerkleNode):
  25. self.v2._get_tree(tree, self)
  26. elif self.v2 is not None:
  27. tree.create_node(str(self.v2), str(self.v2), self)
  28. def __str__(self):
  29. tree = Tree()
  30. self._get_tree(tree, None)
  31. return str(tree)
  32. def merkle_tree(values):
  33. """
  34. Constructs a merkle tree from a list of values.
  35. All values need to support a method get_hash().
  36. """
  37. if not values:
  38. return MerkleNode(None, None)
  39. while len(values) > 1:
  40. nodes = []
  41. for (v1, v2) in zip(values[0::2], values[1::2]):
  42. nodes.append(MerkleNode(v1, v2))
  43. if len(values) % 2:
  44. nodes.append(MerkleNode(values[-1], None))
  45. values = nodes
  46. return values[0]