smt.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import hashlib
  2. # SMT non-membership check
  3. # https://hackmd.io/@aztec-network/ryJ8wxfKK
  4. NULL = bytearray(32)
  5. def from_value(value):
  6. return value.to_bytes(32, 'little')
  7. def hash_node(left, right):
  8. return hashlib.sha256(left + right).digest()
  9. # R
  10. # / \
  11. # o o
  12. # / \ / \
  13. # o o o o
  14. # / \ / \ / \ / \
  15. # 110 4 77 5 - - 6 -
  16. # 0 1 2 3 4 5 6 7
  17. pos = {
  18. 110: 0,
  19. 4: 1,
  20. 77: 2,
  21. 5: 3,
  22. 6: 6
  23. }
  24. empties = [
  25. NULL,
  26. hash_node(NULL, NULL),
  27. ]
  28. empties.append(hash_node(empties[-1], empties[-1]))
  29. # root for an empty tree
  30. empties.append(hash_node(empties[-1], empties[-1]))
  31. # Positions 4, 5 and 7 are empty
  32. layer_0 = [
  33. from_value(110),
  34. from_value(4),
  35. from_value(77),
  36. from_value(5),
  37. NULL,
  38. NULL,
  39. from_value(6),
  40. NULL,
  41. ]
  42. layer_1 = [
  43. hash_node(layer_0[0], layer_0[1]),
  44. hash_node(layer_0[2], layer_0[3]),
  45. # Subtree has empty leaves so just use NULL instead
  46. hash_node(layer_0[4], layer_0[5]),
  47. hash_node(layer_0[6], layer_0[7]),
  48. ]
  49. layer_2 = [
  50. hash_node(layer_1[0], layer_1[1]),
  51. hash_node(layer_1[2], layer_1[3]),
  52. ]
  53. root = hash_node(layer_2[0], layer_2[1])
  54. table = {
  55. # root
  56. 0: (layer_2[0], layer_2[1]),
  57. # [1, 0]
  58. 1: (layer_1[0], layer_1[1]),
  59. # This subtree contains a single value so just store that
  60. # [1, 1]
  61. 2: (layer_1[2], 2, True),
  62. # [2, 0]
  63. layer_1[0]: (layer_0[0], layer_0[1]),
  64. # [2, 1]
  65. layer_1[1]: (layer_0[2], layer_0[3]),
  66. # ... [2, 2] and [2, 3] are not needed
  67. }
  68. # Prove that leaf 5 is set to None
  69. leaf = NULL
  70. path = [
  71. NULL,
  72. layer_1[3],
  73. layer_2[0]
  74. ]
  75. assert hash_node(path[2], hash_node(hash_node(path[0], leaf), path[1])) == root
  76. # Starting from the bottom here
  77. pos = 0b101
  78. # Now do verification
  79. bits = [bool(pos & (1<<n)) for n in range(3)]
  80. node = leaf
  81. for bit, other_node in zip(bits, path):
  82. nodes = (other_node, node) if bit else (node, other_node)
  83. node = hash_node(*nodes)
  84. assert root == node
  85. print("Passed")