MerkleTreeWithHistory.sol 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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) public pure returns (uint256 xL, uint256 xR);
  14. }
  15. contract MerkleTreeWithHistory {
  16. uint256 public constant FIELD_SIZE = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
  17. uint256 public constant ZERO_VALUE = 21663839004416932945382355908790599225266501822907911457504978515578255421292; // = keccak256("tornado") % FIELD_SIZE
  18. uint32 public levels;
  19. // the following variables are made public for easier testing and debugging and
  20. // are not supposed to be accessed in regular code
  21. bytes32[] public filledSubtrees;
  22. bytes32[] public zeros;
  23. uint32 public currentRootIndex = 0;
  24. uint32 public nextIndex = 0;
  25. uint32 public constant ROOT_HISTORY_SIZE = 100;
  26. bytes32[ROOT_HISTORY_SIZE] public roots;
  27. constructor(uint32 _treeLevels) public {
  28. require(_treeLevels > 0, "_treeLevels should be greater than zero");
  29. require(_treeLevels < 32, "_treeLevels should be less than 32");
  30. levels = _treeLevels;
  31. bytes32 currentZero = bytes32(ZERO_VALUE);
  32. zeros.push(currentZero);
  33. filledSubtrees.push(currentZero);
  34. for (uint32 i = 1; i < levels; i++) {
  35. currentZero = hashLeftRight(currentZero, currentZero);
  36. zeros.push(currentZero);
  37. filledSubtrees.push(currentZero);
  38. }
  39. roots[0] = hashLeftRight(currentZero, currentZero);
  40. }
  41. /**
  42. @dev Hash 2 tree leaves, returns MiMC(_left, _right)
  43. */
  44. function hashLeftRight(bytes32 _left, bytes32 _right) public pure returns (bytes32) {
  45. require(uint256(_left) < FIELD_SIZE, "_left should be inside the field");
  46. require(uint256(_right) < FIELD_SIZE, "_right should be inside the field");
  47. uint256 R = uint256(_left);
  48. uint256 C = 0;
  49. (R, C) = Hasher.MiMCSponge(R, C);
  50. R = addmod(R, uint256(_right), FIELD_SIZE);
  51. (R, C) = Hasher.MiMCSponge(R, C);
  52. return bytes32(R);
  53. }
  54. function _insert(bytes32 _leaf) internal returns(uint32 index) {
  55. uint32 currentIndex = nextIndex;
  56. require(currentIndex != uint32(2)**levels, "Merkle tree is full. No more leafs can be added");
  57. nextIndex += 1;
  58. bytes32 currentLevelHash = _leaf;
  59. bytes32 left;
  60. bytes32 right;
  61. for (uint32 i = 0; i < levels; i++) {
  62. if (currentIndex % 2 == 0) {
  63. left = currentLevelHash;
  64. right = zeros[i];
  65. filledSubtrees[i] = currentLevelHash;
  66. } else {
  67. left = filledSubtrees[i];
  68. right = currentLevelHash;
  69. }
  70. currentLevelHash = hashLeftRight(left, right);
  71. currentIndex /= 2;
  72. }
  73. currentRootIndex = (currentRootIndex + 1) % ROOT_HISTORY_SIZE;
  74. roots[currentRootIndex] = currentLevelHash;
  75. return nextIndex - 1;
  76. }
  77. /**
  78. @dev Whether the root is present in the root history
  79. */
  80. function isKnownRoot(bytes32 _root) public view returns(bool) {
  81. if (_root == 0) {
  82. return false;
  83. }
  84. uint32 i = currentRootIndex;
  85. do {
  86. if (_root == roots[i]) {
  87. return true;
  88. }
  89. if (i == 0) {
  90. i = ROOT_HISTORY_SIZE;
  91. }
  92. i--;
  93. } while (i != currentRootIndex);
  94. return false;
  95. }
  96. /**
  97. @dev Returns the last root
  98. */
  99. function getLastRoot() public view returns(bytes32) {
  100. return roots[currentRootIndex];
  101. }
  102. }