Forráskód Böngészése

MerkleProof library and initial stubbed out tests

Yondon Fu 8 éve
szülő
commit
3c4d0d0a77
3 módosított fájl, 104 hozzáadás és 0 törlés
  1. 38 0
      contracts/MerkleProof.sol
  2. 54 0
      test/MerkleProof.js
  3. 12 0
      test/helpers/MerkleProofMock.sol

+ 38 - 0
contracts/MerkleProof.sol

@@ -0,0 +1,38 @@
+pragma solidity ^0.4.11;
+
+/*
+ * @title MerkleProof
+ * @dev Merkle proof verification
+ * @note Based on https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
+ */
+library MerkleProof {
+    /*
+     * @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
+     * and each pair of pre-images is sorted.
+     * @param _proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree
+     * @param _root Merkle root
+     * @param _leaf Leaf of Merkle tree
+     */
+    function verifyProof(bytes _proof, bytes32 _root, bytes32 _leaf) constant returns (bool) {
+        bytes32 proofElement;
+        bytes32 computedHash = _leaf;
+
+        for (uint256 i = 32; i <= _proof.length; i += 32) {
+            assembly {
+                // Load the current element of the proof
+                proofElement := mload(add(_proof, i))
+            }
+
+            if (computedHash < proofElement) {
+                // Hash(current computed hash + current element of the proof)
+                computedHash = sha3(computedHash, proofElement);
+            } else {
+                // Hash(current element of the proof + current computed hash)
+                computedHash = sha3(proofElement, computedHash);
+            }
+        }
+
+        // Check if the computed hash (root) is equal to the provided root
+        return computedHash == _root;
+    }
+}

+ 54 - 0
test/MerkleProof.js

@@ -0,0 +1,54 @@
+var MerkleProofMock = artifacts.require("./helpers/MerkleProofMock.sol");
+
+contract('MerkleProof', function(accounts) {
+    let merkleProof;
+
+    before(async function() {
+        merkleProof = await MerkleProofMock.new();
+    });
+
+    describe("verifyProof", function() {
+        it("should return true for a valid Merkle proof given even number of leaves", async function() {
+            // const elements = ["a", "b", "c", "d"].map(el => sha3(el));
+            // const merkleTree = new MerkleTree(elements);
+
+            // const root = merkleTree.getHexRoot();
+
+            // const proof = merkleTree.getHexProof(elements[0]);
+
+            // const leaf = merkleTree.bufToHex(elements[0]);
+
+            // const validProof = await merkleProof.verifyProof(proof, root, leaf);
+            // assert.isOk(validProof, "verifyProof did not return true for a valid proof given even number of leaves");
+        });
+
+        it("should return true for a valid Merkle proof given odd number of leaves", async function () {
+            // const elements = ["a", "b", "c"].map(el => sha3(el));
+            // const merkleTree = new MerkleTree(elements);
+
+            // const root = merkleTree.getHexRoot();
+
+            // const proof = merkleTree.getHexProof(elements[0]);
+
+            // const leaf = merkleTree.bufToHex(elements[0]);
+
+            // const validProof = await merkleProof.verifyProof(proof, root, leaf);
+            // assert.isOk(validProof, "verifyProof did not return true for a valid proof given odd number of leaves");
+        });
+
+        it("should return false for an invalid Merkle proof", async function() {
+            // const elements = ["a", "b", "c"].map(el => sha3(el));
+            // const merkleTree = new MerkleTree(elements);
+
+            // const root = merkleTree.getHexRoot();
+
+            // const proof = merkleTree.getHexProof(elements[0]);
+            // const badProof = proof.slice(0, proof.length - 32);
+
+            // const leaf = merkleTree.bufToHex(elements[0]);
+
+            // const validProof = await merkleProof.verifyProof(badProof, root, leaf);
+            // assert.isNotOk(validProof, "verifyProof did not return false for an invalid proof");
+        });
+    });
+});

+ 12 - 0
test/helpers/MerkleProofMock.sol

@@ -0,0 +1,12 @@
+pragma solidity ^0.4.11;
+
+import '../../contracts/MerkleProof.sol';
+
+contract MerkleProofMock {
+
+  bool public result;
+
+  function verifyProof(bytes _proof, bytes32 _root, bytes32 _leaf) {
+    result = MerkleProof.verifyProof(_proof, _root, _leaf);
+  }
+}