UNPKG

merkle-tree-rollup

Version:
158 lines (127 loc) 4.79 kB
# merkle-tree-rollup This library provides "pure" type roll up functions for merkle tree structure. Implementer can choose or implement own hash function to calculate the branch node. [examples](./contracts/examples) [test codes](./test) ## How to use ### Install ```shell npm install merkle-tree-rollup ``` ### Import and use the roll up tree you want to use ```solidity pragma solidity >= 0.6.0; import { Tree } from "merkle-tree-rollup/contracts/library/Types.sol"; import { MiMCTree } from "merkle-tree-rollup/contracts/trees/MiMCTree.sol"; contract MiMCExample is MiMCTree { Tree public tree; constructor() public { tree = newTree(); } function push( uint[] memory leaves, uint[] memory initialSiblings ) public { uint newRoot = rollUp(tree.root, tree.index, leaves, initialSiblings); tree.root = newRoot; tree.index += leaves.length; } } ``` ### Implement your custom hash function This is an example of roll up contract using keccak256 which depth is 7 ```solidity pragma solidity >= 0.6.0; import { RollUpTree } from "merkle-tree-rollup/contracts/library/RollUpTree.sol"; contract KeccaTree is RollUpTree { function parentOf(uint left, uint right) public override pure returns (uint) { return uint(keccak256(abi.encodePacked(left, right))); } function preHashedZero() public override pure returns (uint[] memory preHashed) { preHashed = new uint[](8); preHashed[0] = 0x0000000000000000000000000000000000000000000000000000000000000000; preHashed[1] = 0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5; preHashed[2] = 0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30; preHashed[3] = 0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85; preHashed[4] = 0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344; preHashed[5] = 0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d; preHashed[6] = 0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968; preHashed[7] = 0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83; //... } } ``` ### APIs #### RollUpTree.sol You can implement a custom hash function by inheriting `RollUpTree` contract. `RollUpTree` has the following interface. ```solidity /** * @param prevRoot The previous root of the merkle tree * @param index The index where new leaves start * @param leaves Items to append to the merkle tree * @param initialSiblings Sibling data for the merkle proof of the prevRoot * @return new root after appending the given leaves */ function rollUp( uint prevRoot, uint index, uint[] memory leaves, uint[] memory initialSiblings ) public pure returns (uint); /** * @param root The roof of a merkle tree * @param leaf The leaf to prove the membership * @param index Where the leaf is located in * @param siblings The sibling data of the given leaf * @return proof result in boolean */ function merkleProof( uint root, uint leaf, uint index, uint[] memory siblings ) public pure returns (bool); /** * @dev You should implement how to calculate the branch node. The implementation * can be differ by which hash function you use. */ function parentOf(uint left, uint right) public virtual pure returns (uint); /** * @dev Merkle tree for roll up consists of empty leaves at first. Therefore you * can reduce the hash cost by using hard-coded pre hashed zero value arrays. * If you want to use a merkle tree which depth is 4, you should return a hard coded * array of uint which length is 5. And the value should be equivalent to the following * [0, hash(0, 0), hash(hash(0,0, hash(0,0)))...] */ function preHashedZero() public virtual pure returns (uint[] memory preHashed); ``` #### RollUpLib.sol Or you can implement your own tree contract using the roll up library. `RollUpLib` provides the following functions. ```solidity function rollUp( Hasher memory self, uint startingRoot, uint index, uint[] memory leaves, uint[] memory initialSiblings ) internal pure returns (uint newRoot); function merkleRoot( Hasher memory self, uint leaf, uint index, uint[] memory siblings ) internal pure returns (uint); function merkleProof( Hasher memory self, uint root, uint leaf, uint index, uint[] memory siblings ) internal pure returns (bool); /** * @dev It returns an initialized merkle tree which leaves are all empty. */ function newTree(Hasher memory hasher) internal pure returns (Tree memory tree) { tree.root = hasher.preHashedZero[hasher.preHashedZero.length - 1]; tree.index = 0; } ```