From c9e4192335b67d867a6c0afa956c03cfaf4f91a4 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Mon, 22 Aug 2022 22:26:44 +0200 Subject: [PATCH] Add method to verify merkle proof --- src/BaseTree.ts | 31 +++++++++++++++++++++++++++++++ test/fixedMerkleTree.spec.ts | 31 ++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/BaseTree.ts b/src/BaseTree.ts index c8819ee..732c0cd 100644 --- a/src/BaseTree.ts +++ b/src/BaseTree.ts @@ -179,6 +179,37 @@ export class BaseTree { } } + /** + * Verifies a merkle proof + * @param {Element} root the root of the merkle tree + * @param {number} levels the number of levels of the tree + * @param {HashFunction} hashFn hash function + * @param {Element} leaf the leaf to be verified + * @param {Element[]} pathElements adjacent path elements + * @param {number[]} pathIndices left-right indices + * @returns {Boolean} whether the proof is valid for the given root + */ + static verifyProof( + root: Element, + levels: number, + hashFn: HashFunction, + leaf: Element, + pathElements: Element[], + pathIndices: number[], + ): boolean { + const layerProofs: Element[] = [] + + for (let level = 0; level < levels; level++) { + let elem = level == 0 ? leaf : layerProofs[level - 1] + if (pathIndices[level] == 0) { + layerProofs[level] = hashFn(elem, pathElements[level]) + } else { + layerProofs[level] = hashFn(pathElements[level], elem) + } + } + return root === layerProofs[levels - 1] + } + /** * Verifies a merkle multiproof * @param {Element} root the root of the merkle tree diff --git a/test/fixedMerkleTree.spec.ts b/test/fixedMerkleTree.spec.ts index 150e7db..63706fa 100644 --- a/test/fixedMerkleTree.spec.ts +++ b/test/fixedMerkleTree.spec.ts @@ -1,4 +1,4 @@ -import { MerkleTree, MultiProofPath, PartialMerkleTree, TreeEdge } from '../src' +import { MerkleTree, ProofPath, MultiProofPath, PartialMerkleTree, TreeEdge } from '../src' import { assert, should, expect } from 'chai' import { createHash } from 'crypto' import { it } from 'mocha' @@ -262,6 +262,35 @@ describe('MerkleTree', () => { }) }) + describe('#verifyProof', () => { + it('should verify a merkle-proof', () => { + const leaves = [...Array(16)].map((_, i) => i + 1) + const tree = new MerkleTree(4, leaves) + const proof: ProofPath = { + pathElements: [ + 6, + '1177811302158128621769756786551727063040', + '81822854828781486047086122479545722339328', + '3473994785217814971484840545214368055296' + ], + pathIndices: [ 0, 0, 1, 0 ], + pathPositions: [ 5, 3, 0, 1 ], + pathRoot: '4813607112316126252402222488335589310464' + } + + expect( + BaseTree.verifyProof( + tree.root, + tree.levels, + defaultHash, + 5, + proof.pathElements, + proof.pathIndices, + ), + ).to.be.true + }) + }) + describe('#multiproof', () => { it('should return a merkle-multiproof for a range of leaves in a full tree', () => { const leaves = [...Array(8)].map((_, i) => i + 1)