UNPKG

merkle-tree-lib

Version:

Merkle Tree implementation with BIP340 tagged hash support.

119 lines (118 loc) 4.89 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MerkleProofVerifier = void 0; const MerkleProof_1 = require("./MerkleProof"); const TaggedSha256Strategy_1 = require("../hash/strategies/TaggedSha256Strategy"); const MerkleTree_1 = require("../tree/MerkleTree"); /** * MerkleProofVerifier - Class responsible for verifying Merkle proofs */ class MerkleProofVerifier { /** * Initialize a verifier with the hash strategies * * @param leafHashStrategy - Strategy for hashing leaves (default: TaggedSha256 with 'MERKLE_LEAF' tag) * @param branchHashStrategy - Strategy for hashing branches (default: TaggedSha256 with 'MERKLE_BRANCH' tag) */ constructor(leafHashStrategy = new TaggedSha256Strategy_1.TaggedSha256Strategy(MerkleTree_1.DEFAULT_TAGS.LEAF), branchHashStrategy = new TaggedSha256Strategy_1.TaggedSha256Strategy(MerkleTree_1.DEFAULT_TAGS.BRANCH)) { this.leafHashStrategy = leafHashStrategy; this.branchHashStrategy = branchHashStrategy; } /** * Verify a Merkle proof * * @param proof - The proof to verify * @returns True if the proof is valid, false otherwise */ verify(proof) { const elements = proof.getElements(); const leafData = proof.getLeafData(); const expectedRoot = proof.getRootHash(); // Calculate the leaf hash let currentHash = this.leafHashStrategy.hash(leafData); // Apply each proof element to compute the potential root for (const element of elements) { currentHash = this.applyProofElement(currentHash, element); } // Check if the computed root matches the expected root return currentHash.equals(expectedRoot); } /** * @deprecated Use verify() with MerkleProof objects instead * Legacy verification method for backward compatibility * * @param leafData - The original leaf data * @param proofPath - Array of {sibling, position} objects * @param expectedRoot - The expected Merkle root as hex string * @returns True if the proof is valid, false otherwise */ legacyVerify(leafData, proofPath, expectedRoot) { // Calculate the leaf hash let currentHash = this.leafHashStrategy.hash(leafData); // Apply each proof element from the legacy format for (const { sibling, position } of proofPath) { const siblingHash = Buffer.from(sibling, 'hex'); const direction = position === 'left' ? MerkleProof_1.ProofDirection.LEFT : MerkleProof_1.ProofDirection.RIGHT; // Convert to the new element format and apply const element = { siblingHash, direction }; currentHash = this.applyProofElement(currentHash, element); } // Compare with expected root const rootBuffer = Buffer.from(expectedRoot, 'hex'); return currentHash.equals(rootBuffer); } /** * Apply a single proof element to calculate the next hash * * @param currentHash - The current hash * @param element - The proof element to apply * @returns The next hash in the path */ applyProofElement(currentHash, element) { // Concatenate the hashes in the correct order based on direction const combinedData = element.direction === MerkleProof_1.ProofDirection.LEFT ? Buffer.concat([element.siblingHash, currentHash]) : Buffer.concat([currentHash, element.siblingHash]); // Apply the branch hash function return this.branchHashStrategy.hash(combinedData); } /** * Verify a proof with simplified inputs * * @param leafData - The original leaf data * @param proof - Array of proof elements * @param merkleRoot - The expected Merkle root * @returns True if valid, false otherwise */ verifySimple(leafData, proof, merkleRoot) { // Convert string hashes to Buffer const elements = proof.map(([hash, direction]) => ({ siblingHash: Buffer.from(hash, 'hex'), direction })); // Create a MerkleProof and verify it const merkleProof = new MerkleProof_1.MerkleProof(leafData, 0, // Index doesn't matter for verification elements, Buffer.from(merkleRoot, 'hex')); return this.verify(merkleProof); } /** * Set the leaf hash strategy * * @param strategy - The hash strategy to use for leaf nodes */ setLeafHashStrategy(strategy) { this.leafHashStrategy = strategy; } /** * Set the branch hash strategy * * @param strategy - The hash strategy to use for branch nodes */ setBranchHashStrategy(strategy) { this.branchHashStrategy = strategy; } } exports.MerkleProofVerifier = MerkleProofVerifier;