merkle-tree-lib
Version:
Merkle Tree implementation with BIP340 tagged hash support.
119 lines (118 loc) • 4.89 kB
JavaScript
;
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;