MerkleTreeWithHistory.sol 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // https://tornado.cash
  2. /*
  3. * d888888P dP a88888b. dP
  4. * 88 88 d8' `88 88
  5. * 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b.
  6. * 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88
  7. * 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88
  8. * dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP
  9. * ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
  10. */
  11. pragma solidity ^0.5.8;
  12. library Hasher {
  13. function MiMCSponge(uint256 in_xL, uint256 in_xR, uint256 in_k) public pure returns (uint256 xL, uint256 xR);
  14. }
  15. contract MerkleTreeWithHistory {
  16. uint256 public levels;
  17. uint8 constant ROOT_HISTORY_SIZE = 100;
  18. uint256[] private _roots;
  19. uint256 public current_root = 0;
  20. uint256[] private _filled_subtrees;
  21. uint256[] private _zeros;
  22. uint32 public next_index = 0;
  23. constructor(uint256 tree_levels, uint256 zero_value) public {
  24. levels = tree_levels;
  25. _zeros.push(zero_value);
  26. _filled_subtrees.push(_zeros[0]);
  27. for (uint8 i = 1; i < levels; i++) {
  28. _zeros.push(hashLeftRight(_zeros[i-1], _zeros[i-1]));
  29. _filled_subtrees.push(_zeros[i]);
  30. }
  31. _roots = new uint256[](ROOT_HISTORY_SIZE);
  32. _roots[0] = hashLeftRight(_zeros[levels - 1], _zeros[levels - 1]);
  33. }
  34. function hashLeftRight(uint256 left, uint256 right) public pure returns (uint256 hash) {
  35. uint256 k = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
  36. uint256 R = 0;
  37. uint256 C = 0;
  38. R = addmod(R, left, k);
  39. (R, C) = Hasher.MiMCSponge(R, C, 0);
  40. R = addmod(R, right, k);
  41. (R, C) = Hasher.MiMCSponge(R, C, 0);
  42. hash = R;
  43. }
  44. function _insert(uint256 leaf) internal {
  45. uint32 current_index = next_index;
  46. require(current_index != 2**levels, "Merkle tree is full. No more leafs can be added");
  47. next_index += 1;
  48. uint256 current_level_hash = leaf;
  49. uint256 left;
  50. uint256 right;
  51. for (uint256 i = 0; i < levels; i++) {
  52. if (current_index % 2 == 0) {
  53. left = current_level_hash;
  54. right = _zeros[i];
  55. _filled_subtrees[i] = current_level_hash;
  56. } else {
  57. left = _filled_subtrees[i];
  58. right = current_level_hash;
  59. }
  60. current_level_hash = hashLeftRight(left, right);
  61. current_index /= 2;
  62. }
  63. current_root = (current_root + 1) % ROOT_HISTORY_SIZE;
  64. _roots[current_root] = current_level_hash;
  65. }
  66. function isKnownRoot(uint256 root) public view returns(bool) {
  67. if (root == 0) {
  68. return false;
  69. }
  70. // search most recent first
  71. uint256 i;
  72. for(i = current_root; i < 2**256 - 1; i--) {
  73. if (root == _roots[i]) {
  74. return true;
  75. }
  76. }
  77. // process the rest of roots
  78. for(i = ROOT_HISTORY_SIZE - 1; i > current_root; i--) {
  79. if (root == _roots[i]) {
  80. return true;
  81. }
  82. }
  83. return false;
  84. // or we can do that in other way
  85. // uint256 i = _current_root;
  86. // do {
  87. // if (root == _roots[i]) {
  88. // return true;
  89. // }
  90. // if (i == 0) {
  91. // i = ROOT_HISTORY_SIZE;
  92. // }
  93. // i--;
  94. // } while (i != _current_root);
  95. }
  96. function getLastRoot() public view returns(uint256) {
  97. return _roots[current_root];
  98. }
  99. function roots() public view returns(uint256[] memory) {
  100. return _roots;
  101. }
  102. function filled_subtrees() public view returns(uint256[] memory) {
  103. return _filled_subtrees;
  104. }
  105. function zeros() public view returns(uint256[] memory) {
  106. return _zeros;
  107. }
  108. }