A library to construct Merkle Trees and verify proofs in JavaScript
View on Github ›

Documentation

MerkleTree Class Documentation

A comprehensive implementation of a Merkle Tree data structure for creating tamper-proof data structures and generating cryptographic proofs. This is the core class of the merkletreejs library.

Features

Standard Merkle Tree: Classic binary tree implementation
Multiple Hash Functions: Support for SHA256, keccak256, and custom hash functions
Proof Generation: Generate and verify inclusion proofs
Multi-Proofs: Generate and verify proofs for multiple leaves simultaneously
Bitcoin Compatibility: Support for Bitcoin-style Merkle trees
Serialization: Marshal/unmarshal trees and proofs to/from JSON
Flexible Options: Configurable sorting, duplicate handling, and tree completion
Type Safety: Full TypeScript support with proper type definitions

Installation

npm install merkletreejs

Quick Start

import { MerkleTree } from 'merkletreejs'
import SHA256 from 'crypto-js/sha256'

// Create leaves (typically hashed data)
const leaves = ['a', 'b', 'c', 'd'].map(x => SHA256(x))

// Create tree
const tree = new MerkleTree(leaves, SHA256)

// Get root
const root = tree.getRoot()
const hexRoot = tree.getHexRoot()

// Generate proof
const leaf = SHA256('b')
const proof = tree.getProof(leaf)

// Verify proof
const verified = tree.verify(proof, leaf, root)
console.log('Proof verified:', verified) // true

Constructor

new MerkleTree(leaves, hashFunction?, options?)

Creates a new Merkle tree instance.

Parameters:

const tree = new MerkleTree(leaves, SHA256, {
  sortPairs: true,
  duplicateOdd: false
})

Options

interface Options {
  duplicateOdd?: boolean        // Duplicate odd nodes (default: false)
  hashLeaves?: boolean          // Hash leaves before adding (default: false)
  isBitcoinTree?: boolean       // Use Bitcoin-style tree (default: false)
  sortLeaves?: boolean          // Sort leaves (default: false)
  sortPairs?: boolean           // Sort pairs (default: false)
  sort?: boolean                // Sort leaves and pairs (default: false)
  fillDefaultHash?: Function    // Fill function for odd layers
  complete?: boolean            // Create complete tree (default: false)
  concatenator?: Function       // Custom concatenation function
}

Core Methods

Tree Information

getRoot()

Returns the Merkle root as a Buffer.

const root = tree.getRoot()

getHexRoot()

Returns the Merkle root as a hex string with '0x' prefix.

const hexRoot = tree.getHexRoot()

getLeaves(values?)

Returns array of leaves. Optionally filter by specific values.

const allLeaves = tree.getLeaves()
const filteredLeaves = tree.getLeaves([specificHash1, specificHash2])

getHexLeaves()

Returns array of leaves as hex strings.

const hexLeaves = tree.getHexLeaves()

getLeafCount()

Returns the total number of leaves.

const count = tree.getLeafCount()

getDepth()

Returns the tree depth (number of layers).

const depth = tree.getDepth()

Leaf Operations

getLeaf(index)

Gets a leaf by index.

const leaf = tree.getLeaf(0)

getHexLeaf(index)

Gets a leaf by index as hex string.

const hexLeaf = tree.getHexLeaf(0)

getLeafIndex(leaf)

Gets the index of a leaf (-1 if not found).

const index = tree.getLeafIndex(leafHash)

addLeaf(leaf, shouldHash?)

Adds a single leaf to the tree.

tree.addLeaf(newLeafHash)
tree.addLeaf('raw data', true) // Hash before adding

updateLeaf(index, value, shouldHash?)

Updates a leaf at specific index.

tree.updateLeaf(1, newHash)
tree.updateLeaf(1, 'new data', true) // Hash before updating

addLeaves(leaves, shouldHash?)

Adds multiple leaves to the tree.

tree.addLeaves([hash1, hash2, hash3])
tree.addLeaves(['data1', 'data2'], true) // Hash before adding

removeLeaf(index)

Removes a leaf by index.

const removedLeaf = tree.removeLeaf(2)

Proof Operations

getProof(leaf, index?)

Generates a proof for a leaf.

const proof = tree.getProof(leafHash)
// For duplicate leaves, specify index
const proof = tree.getProof(leafHash, 2)

verify(proof, targetNode, root)

Verifies a proof against a root.

const isValid = tree.verify(proof, leafHash, root)

getHexProof(leaf, index?)

Generates a proof as hex strings.

const hexProof = tree.getHexProof(leafHash)

getPositionalHexProof(leaf, index?)

Generates a proof with positional information.

const positionalProof = tree.getPositionalHexProof(leafHash)
// Returns: [[position, hash], [position, hash], ...]

getProofs()

Gets proofs for all leaves.

const allProofs = tree.getProofs()

getHexProofs()

Gets proofs for all leaves as hex strings.

const allHexProofs = tree.getHexProofs()

getMultiProof(indices)

Generates a multi-proof for multiple leaves.

const multiProof = tree.getMultiProof([0, 2, 4])

getHexMultiProof(tree, indices)

Generates a multi-proof as hex strings.

const hexMultiProof = tree.getHexMultiProof(flatTree, [0, 2, 4])

verifyMultiProof(root, proofIndices, proofLeaves, leavesCount, proof)

Verifies a multi-proof.

const isValid = tree.verifyMultiProof(
  root, 
  [0, 2, 4], 
  [leaf0, leaf2, leaf4], 
  totalLeaves, 
  multiProof
)

verifyMultiProofWithFlags(root, leaves, proofs, proofFlag)

Verifies a multi-proof using boolean flags.

const isValid = tree.verifyMultiProofWithFlags(root, leaves, proofs, flags)

getProofFlags(leaves, proofs)

Gets boolean flags for multi-proof verification.

const flags = tree.getProofFlags([leaf0, leaf2], multiProof)

Layer Operations

getLayers()

Gets all tree layers as 2D array of Buffers.

const layers = tree.getLayers()

getHexLayers()

Gets all tree layers as 2D array of hex strings.

const hexLayers = tree.getHexLayers()

getLayersFlat()

Gets all tree layers as flat array.

const flatLayers = tree.getLayersFlat()

getHexLayersFlat()

Gets all tree layers as flat array of hex strings.

const hexFlatLayers = tree.getHexLayersFlat()

getLayerCount()

Returns the total number of layers.

const layerCount = tree.getLayerCount()

getLayersAsObject()

Returns layers as nested objects for visualization.

const layersObj = tree.getLayersAsObject()

Serialization

static marshalLeaves(leaves)

Converts leaves to JSON string.

const jsonLeaves = MerkleTree.marshalLeaves(leaves)

static unmarshalLeaves(jsonStr)

Converts JSON string back to leaves.

const leaves = MerkleTree.unmarshalLeaves(jsonLeaves)

static marshalProof(proof)

Converts proof to JSON string.

const jsonProof = MerkleTree.marshalProof(proof)

static unmarshalProof(jsonStr)

Converts JSON string back to proof.

const proof = MerkleTree.unmarshalProof(jsonProof)

static marshalTree(tree)

Converts entire tree to JSON string.

const jsonTree = MerkleTree.marshalTree(tree)

static unmarshalTree(jsonStr, hashFn?, options?)

Recreates tree from JSON string.

const tree = MerkleTree.unmarshalTree(jsonTree, SHA256)

Utility Methods

resetTree()

Clears all leaves and layers.

tree.resetTree()

toString()

Returns visual representation of the tree.

console.log(tree.toString())

getOptions()

Returns current tree options.

const options = tree.getOptions()

Advanced Methods

getProofIndices(treeIndices, depth)

Returns the proof indices for given tree indices.

const proofIndices = tree.getProofIndices([2,5,6], 4)

Static Methods

MerkleTree.verify(proof, targetNode, root, hashFn?, options?)

Static method to verify a proof without tree instance.

const isValid = MerkleTree.verify(proof, leaf, root, SHA256)

MerkleTree.getMultiProof(tree, indices)

Static method to generate multi-proof from flat tree.

const multiProof = MerkleTree.getMultiProof(flatTree, [0, 2, 4])

Examples

Basic Usage

import { MerkleTree } from 'merkletreejs'
import SHA256 from 'crypto-js/sha256'

// Prepare data
const leaves = ['alice', 'bob', 'charlie', 'dave'].map(x => SHA256(x))

// Create tree
const tree = new MerkleTree(leaves, SHA256)

// Get root
const root = tree.getHexRoot()
console.log('Root:', root)

// Generate and verify proof
const leaf = SHA256('bob')
const proof = tree.getProof(leaf)
const verified = tree.verify(proof, leaf, tree.getRoot())
console.log('Proof verified:', verified)

Bitcoin-Style Tree

const tree = new MerkleTree(leaves, SHA256, {
  isBitcoinTree: true
})

Multi-Proof Example

const tree = new MerkleTree(leaves, SHA256, { complete: true })
const indices = [0, 2, 4]
const multiProof = tree.getMultiProof(indices)
const proofLeaves = indices.map(i => leaves[i])

const verified = tree.verifyMultiProof(
  tree.getRoot(),
  indices,
  proofLeaves,
  leaves.length,
  multiProof
)

Functional API for MerkleTreeJS

A functional programming interface for merkletreejs that provides an intuitive, viem-inspired API for working with Merkle trees. This wrapper makes it easy to create, manipulate, and verify Merkle trees with a clean, functional interface.

Features

Functional API: Intuitive, functional interface inspired by viem
Type Safety: Full TypeScript support with proper type definitions
Flexible Input: Accepts strings, buffers, objects, and numbers as leaves
Multiple Hash Functions: Built-in support for SHA256 (default), keccak256, and custom hash functions
Proof Generation: Easy proof creation and verification
Tree Manipulation: Add, remove, and update leaves
Serialization: Marshal/unmarshal trees and proofs to JSON
Advanced Options: Support for Bitcoin-style trees, sorted trees, and complete trees

Quick Start

import { createMerkleTree, getHexRoot, getProof, verifyProof } from 'merkletreejs'

// Create a simple Merkle tree
const leaves = ['a', 'b', 'c', 'd']
const tree = createMerkleTree(leaves)
const root = getHexRoot(tree)

// Generate and verify a proof
const proof = getProof(tree, 'b')
const isValid = verifyProof(proof, 'b', root)
console.log('Proof valid:', isValid) // true

API Reference

Core Functions

createMerkleTree(leaves, hashFn?, options?)

Creates a Merkle tree from an array of leaves. Uses SHA256 as the default hash function.

const tree = createMerkleTree(['a', 'b', 'c'])
// Using custom hash function
const customHashFn = (data) => {
  const crypto = require('crypto')
  return crypto.createHash('sha256').update(data).digest()
}
const treeWithOptions = createMerkleTree(leaves, customHashFn, { sort: true })

getHexRoot(tree)

Gets the root hash as a hex string.

const root = getHexRoot(tree)

getProof(tree, leaf, index?)

Gets a proof for a specific leaf.

const proof = getProof(tree, 'targetLeaf')

verifyProof(proof, leaf, root, hashFn?, options?)

Verifies a proof against a root and target leaf.

const isValid = verifyProof(proof, 'targetLeaf', root)

getHexProof(tree, leaf, index?)

Gets a proof as hex strings.

const hexProof = getHexProof(tree, 'targetLeaf')

getMultiProof(tree, indices)

Gets a multiproof for multiple indices.

const multiProof = getMultiProof(tree, [0, 2, 4])

getHexMultiProof(tree, indices)

Gets a multiproof as hex strings.

const hexMultiProof = getHexMultiProof(tree, [0, 2, 4])

verifyMultiProof(root, proofIndices, proofLeaves, leavesCount, proof, hashFn?, options?)

Verifies a multiproof.

const isValid = verifyMultiProof(root, [0, 2], [leaf0, leaf2], 5, proof)

getProofs(tree)

Gets proofs for all leaves.

const allProofs = getProofs(tree)

getHexProofs(tree)

Gets proofs for all leaves as hex strings.

const allHexProofs = getHexProofs(tree)

Tree Manipulation

addLeaf(tree, leaf, options?)

Adds a single leaf to the tree.

const updatedTree = addLeaf(tree, 'newLeaf')
const updatedTreeWithHash = addLeaf(tree, 'newLeaf', { shouldHash: true })

updateLeaf(tree, index, value, options?)

Updates a leaf at a specific index.

updateLeaf(tree, 0, 'newValue')
updateLeaf(tree, 0, 'newValue', { shouldHash: true })

addLeaves(tree, leaves, options?)

Adds multiple leaves to the tree.

const updatedTree = addLeaves(tree, ['leaf1', 'leaf2'])
const updatedTreeWithHash = addLeaves(tree, ['leaf1', 'leaf2'], { shouldHash: true })

removeLeaf(tree, index)

Removes a leaf by index.

const removedLeaf = removeLeaf(tree, 0)

Tree Information

getRoot(tree)

Gets the root hash as a Buffer.

const rootBuffer = getRoot(tree)

getLeaves(tree)

Gets all leaves as Buffers.

const leaves = getLeaves(tree)

getHexLeaves(tree)

Gets all leaves as hex strings.

const hexLeaves = getHexLeaves(tree)

getLeafCount(tree)

Gets the number of leaves.

const count = getLeafCount(tree)

getLeaf(tree, index)

Gets a specific leaf by index.

const leaf = getLeaf(tree, 0)

getHexLeaf(tree, index)

Gets a specific leaf by index as a hex string.

const hexLeaf = getHexLeaf(tree, 0)

getLeafIndex(tree, leaf)

Gets the index of a specific leaf.

const index = getLeafIndex(tree, 'targetLeaf')

getDepth(tree)

Gets the tree depth (number of layers).

const depth = getDepth(tree)

getLayers(tree)

Gets all tree layers as 2D array of Buffers.

const layers = getLayers(tree)

getHexLayers(tree)

Gets all tree layers as 2D array of hex strings.

const hexLayers = getHexLayers(tree)

getLayersFlat(tree)

Gets all tree layers as flat array.

const flatLayers = getLayersFlat(tree)

getHexLayersFlat(tree)

Gets all tree layers as flat array of hex strings.

const hexFlatLayers = getHexLayersFlat(tree)

Serialization

marshalTree(tree)

Converts a tree to JSON string.

const json = marshalTree(tree)

unmarshalTree(jsonStr, hashFn?, options?)

Creates a tree from JSON string.

const tree = unmarshalTree(jsonStr)

marshalProof(proof)

Converts a proof to JSON string.

const proofJson = marshalProof(proof)

unmarshalProof(jsonStr)

Creates a proof from JSON string.

const proof = unmarshalProof(proofJson)

marshalLeaves(leaves)

Converts leaves to JSON string.

const jsonLeaves = marshalLeaves(leaves)

unmarshalLeaves(jsonStr)

Creates leaves from JSON string.

const leaves = unmarshalLeaves(jsonLeaves)

Utility Methods

resetTree(tree)

Clears all leaves and layers from the tree.

resetTree(tree)

getOptions(tree)

Gets the current tree options.

const options = getOptions(tree)

treeToString(tree)

Returns visual representation of the tree.

const treeString = treeToString(tree)
console.log(treeString)

Hash Functions

The functional API uses SHA256 as the default hash function. You can specify a custom hash function as the second parameter:

import { createMerkleTree } from 'merkletreejs'

// Default SHA256
const tree = createMerkleTree(['a', 'b', 'c'])

// Custom keccak256
const keccakTree = createMerkleTree(['a', 'b', 'c'], (data) => {
  const keccak256 = require('keccak256')
  return keccak256(Buffer.from(String(data)))
})

// Custom SHA1
const sha1Tree = createMerkleTree(['a', 'b', 'c'], (data) => {
  const crypto = require('crypto')
  return crypto.createHash('sha1').update(data).digest()
})

Examples

Basic Usage

import { createMerkleTree, getHexRoot, getProof, verifyProof } from 'merkletreejs'

// Create tree
const leaves = ['a', 'b', 'c', 'd']
const tree = createMerkleTree(leaves)
const root = getHexRoot(tree)

// Generate proof
const proof = getProof(tree, 'b')

// Verify proof
const isValid = verifyProof(proof, 'b', root)
console.log('Valid:', isValid) // true

Comparison with Original API

Original MerkleTreeJS

const tree = new MerkleTree(leaves, hashFn, options)
const root = tree.getHexRoot()
const proof = tree.getProof(leaf)
const isValid = tree.verify(proof, leaf, root)

Functional API

const tree = createMerkleTree(leaves, hashFn, options)
const root = getHexRoot(tree)
const proof = getProof(tree, leaf)
const isValid = verifyProof(proof, leaf, root)

Additional Merkle Tree Implementations

Besides the standard MerkleTree, there are specialized implementation classes available:

Browser Support

The MerkleTree library works in both Node.js and browser environments. For browser usage, ensure you have appropriate polyfills for Buffer operations.

TypeScript Support

Full TypeScript support with comprehensive type definitions for all methods and options.

Contributing

This library is designed to provide comprehensive Merkle tree functionality for JavaScript applications. Feel free to contribute improvements or additional features!