MerkleTreeWithHistory.test.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /* global artifacts, web3, contract */
  2. require('chai').use(require('bn-chai')(web3.utils.BN)).use(require('chai-as-promised')).should()
  3. const { takeSnapshot, revertSnapshot } = require('../scripts/ganacheHelper')
  4. const MerkleTreeWithHistory = artifacts.require('./MerkleTreeWithHistoryMock.sol')
  5. const hasherContract = artifacts.require('./Hasher.sol')
  6. const MerkleTree = require('fixed-merkle-tree')
  7. const snarkjs = require('snarkjs')
  8. const bigInt = snarkjs.bigInt
  9. const { ETH_AMOUNT, MERKLE_TREE_HEIGHT } = process.env
  10. // eslint-disable-next-line no-unused-vars
  11. function BNArrayToStringArray(array) {
  12. const arrayToPrint = []
  13. array.forEach((item) => {
  14. arrayToPrint.push(item.toString())
  15. })
  16. return arrayToPrint
  17. }
  18. function toFixedHex(number, length = 32) {
  19. let str = bigInt(number).toString(16)
  20. while (str.length < length * 2) str = '0' + str
  21. str = '0x' + str
  22. return str
  23. }
  24. contract('MerkleTreeWithHistory', (accounts) => {
  25. let merkleTreeWithHistory
  26. let hasherInstance
  27. let levels = MERKLE_TREE_HEIGHT || 16
  28. const sender = accounts[0]
  29. // eslint-disable-next-line no-unused-vars
  30. const value = ETH_AMOUNT || '1000000000000000000'
  31. let snapshotId
  32. let tree
  33. before(async () => {
  34. tree = new MerkleTree(levels)
  35. hasherInstance = await hasherContract.deployed()
  36. merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels, hasherInstance.address)
  37. snapshotId = await takeSnapshot()
  38. })
  39. describe('#constructor', () => {
  40. it('should initialize', async () => {
  41. const zeroValue = await merkleTreeWithHistory.ZERO_VALUE()
  42. const firstSubtree = await merkleTreeWithHistory.filledSubtrees(0)
  43. firstSubtree.should.be.equal(toFixedHex(zeroValue))
  44. const firstZero = await merkleTreeWithHistory.zeros(0)
  45. firstZero.should.be.equal(toFixedHex(zeroValue))
  46. })
  47. })
  48. describe('#insert', () => {
  49. it('should insert', async () => {
  50. let rootFromContract
  51. for (let i = 1; i < 11; i++) {
  52. await merkleTreeWithHistory.insert(toFixedHex(i), { from: sender })
  53. tree.insert(i)
  54. rootFromContract = await merkleTreeWithHistory.getLastRoot()
  55. toFixedHex(tree.root()).should.be.equal(rootFromContract.toString())
  56. }
  57. })
  58. it('should reject if tree is full', async () => {
  59. const levels = 6
  60. const merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels, hasherInstance.address)
  61. for (let i = 0; i < 2 ** levels; i++) {
  62. await merkleTreeWithHistory.insert(toFixedHex(i + 42)).should.be.fulfilled
  63. }
  64. let error = await merkleTreeWithHistory.insert(toFixedHex(1337)).should.be.rejected
  65. error.reason.should.be.equal('Merkle tree is full. No more leaves can be added')
  66. error = await merkleTreeWithHistory.insert(toFixedHex(1)).should.be.rejected
  67. error.reason.should.be.equal('Merkle tree is full. No more leaves can be added')
  68. })
  69. it.skip('hasher gas', async () => {
  70. const levels = 6
  71. const merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels)
  72. const zeroValue = await merkleTreeWithHistory.zeroValue()
  73. const gas = await merkleTreeWithHistory.hashLeftRight.estimateGas(zeroValue, zeroValue)
  74. console.log('gas', gas - 21000)
  75. })
  76. })
  77. describe('#isKnownRoot', () => {
  78. it('should work', async () => {
  79. for (let i = 1; i < 5; i++) {
  80. await merkleTreeWithHistory.insert(toFixedHex(i), { from: sender }).should.be.fulfilled
  81. await tree.insert(i)
  82. let isKnown = await merkleTreeWithHistory.isKnownRoot(toFixedHex(tree.root()))
  83. isKnown.should.be.equal(true)
  84. }
  85. await merkleTreeWithHistory.insert(toFixedHex(42), { from: sender }).should.be.fulfilled
  86. // check outdated root
  87. let isKnown = await merkleTreeWithHistory.isKnownRoot(toFixedHex(tree.root()))
  88. isKnown.should.be.equal(true)
  89. })
  90. it('should not return uninitialized roots', async () => {
  91. await merkleTreeWithHistory.insert(toFixedHex(42), { from: sender }).should.be.fulfilled
  92. let isKnown = await merkleTreeWithHistory.isKnownRoot(toFixedHex(0))
  93. isKnown.should.be.equal(false)
  94. })
  95. })
  96. afterEach(async () => {
  97. await revertSnapshot(snapshotId.result)
  98. // eslint-disable-next-line require-atomic-updates
  99. snapshotId = await takeSnapshot()
  100. tree = new MerkleTree(levels)
  101. })
  102. })