diff --git a/src/data-structures/tree/merkle-tree/MerkleTree.js b/src/data-structures/tree/merkle-tree/MerkleTree.js index 358cff65..f673ab38 100644 --- a/src/data-structures/tree/merkle-tree/MerkleTree.js +++ b/src/data-structures/tree/merkle-tree/MerkleTree.js @@ -146,6 +146,57 @@ class MerkleTree { return result } + /** + * verify + * @desc verify a proof generated by getProof() + * @param {Proof} proof - proof object generated by getProof() + * { + * node, index, path + * } + * @return {Boolean} - If true, the correct merkle root can be calculated through the path provided by input proof, false other wise. + *@example + * ```js + *const tree = new MerkleTree(['a', 'b', 'c', 'd', 'e']); + *const proof = tree.getProof('b')) // {node: 'b', index: 1, path: [[3,0],[2,1],[1,1]]} + *console.log(tree.verify(proof)) //true + *``` + */ + verify(proof) { + const node = proof.node + const index = proof.index + const path = proof.path + + if (node === undefined || node === null) return false + if (index >= this.originalArray.length ) return false + let hashed = this.hash(this.inputHash(node)) + // If path is [] and index == 0 means the input array contains only one node. Just compare the hash of itself with root + if (path === []) { + if(index === 0) return hashed === this.root + return false + } + + // Rebuild hashes bottem up by only calculating the necessary nodes, compare the final hash with root + while(path.length > 0) { + const current = path.shift() + const row = current[0] + const index = current[1] + + try { + const sibling = this.fullPath[row][index] + // If the coordinate indicates the sibling is a left node, do H(sibling + current) + // H(current + sibling) otherwise* + if ((index%2) == 0) { + hashed = this.hash(sibling + hashed) + } else { + hashed = this.hash(hashed + sibling) + } + } catch (err) { + return false + } + } + + return hashed === this.root + } }