Skip to main content

IndexedMerkleTree

Overview​

License: MIT​

library IndexedMerkleTree

Indexed Merkle Tree Module

Gas usage for adding and updating 100 elements to an IndexedMT with the keccak256 and poseidon hash functions is detailed below:

Keccak256:

  • CMT.add - 249k
  • CMT.update - 250k

Poseidon:

  • CMT.add - 1.13m
  • CMT.update - 1.13m

Custom hashing functions can be provided before initialization to change how nodes and leaves are hashed (useful for e.g. Poseidon-based hashing in zk environments). Default keccak based hashing functions are used when custom hashers are not set.

Usage Example​

using IndexedMerkleTree for IndexedMerkleTree.UintIndexedMT;

IndexedMerkleTree.UintIndexedMT internal tree;

tree.setHashers(hashFunctions);
tree.initialize();

uint256 leafIndex = tree.add(42, 0);

IndexedMerkleTree.Proof memory proof = tree.getProof(leafIndex, 42);

bool ok = tree.verifyProof(proof);

Structs info​

UintIndexedMT​

struct UintIndexedMT {
IndexedMerkleTree.IndexedMT _indexedMT;
}

UintIndexedMT *

Bytes32IndexedMT​

struct Bytes32IndexedMT {
IndexedMerkleTree.IndexedMT _indexedMT;
}

Bytes32IndexedMT *

AddressIndexedMT​

struct AddressIndexedMT {
IndexedMerkleTree.IndexedMT _indexedMT;
}

AddressIndexedMT *

IndexedMT​

struct IndexedMT {
IndexedMerkleTree.LeafData[] leavesData;
mapping(uint256 => bytes32[]) nodes;
uint256 levelsCount;
bool isCustomHasherSet;
function (bytes32,bytes32) view returns (bytes32) hash2;
function (bytes32,bytes32,bytes32,bytes32) view returns (bytes32) hash4;
}

Core storage structure for the Indexed Merkle tree.

Parameters:

NameTypeDescription
leavesDatastruct IndexedMerkleTree.LeafData[]compact storage of leaf metadata (value + pointer to next leaf).
nodesmapping(uint256 => bytes32[])mapping of level => array of node hashes; level 0 is leaves, top index is root.
levelsCountuint256current number of levels present in the tree (>= 1 after init).
isCustomHasherSetbooltrue when caller provided custom hash functions before init.
hash2function (bytes32,bytes32) view returns (bytes32)A two-input hash function used to hash node pairs.
hash4function (bytes32,bytes32,bytes32,bytes32) view returns (bytes32)A four-input hash function used to hash leaf metadata (active flag, idx, value, nextIndex).

HashFunctions​

struct HashFunctions {
function (bytes32,bytes32) view returns (bytes32) hash2;
function (bytes32,bytes32,bytes32,bytes32) view returns (bytes32) hash4;
}

Container type for custom hashing functions.

Proof​

struct Proof {
bytes32 root;
bytes32[] siblings;
bool existence;
uint256 index;
bytes32 value;
uint256 nextLeafIndex;
}

Merkle proof returned by getProof and used by verifyProof.

Parameters:

NameTypeDescription
rootbytes32The root hash for which this proof should verify.
siblingsbytes32[]Array of sibling hashes used to reconstruct the root from the leaf.
existenceboolWhether the supplied index/value exists (true) or this is an exclusion proof (false).
indexuint256The leaf index (position) within the leaves level used to compute the proof.
valuebytes32The stored value for the leaf referenced by index (or candidate value for an exclusion check).
nextLeafIndexuint256For the indexed tree the leaf contains a pointer to the next leaf; used when hashing leaves.

LeafData​

struct LeafData {
bytes32 value;
uint256 nextLeafIndex;
}

The main leaf metadata struct

Parameters:

NameTypeDescription
valuebytes32The stored bytes32 value for the leaf.
nextLeafIndexuint256Index of the next active leaf (ZERO_IDX when none).

Errors info​

ZeroLeafIndex​

error ZeroLeafIndex()

IndexOutOfBounds​

error IndexOutOfBounds(uint256 index, uint256 level)

InvalidLowLeaf​

error InvalidLowLeaf(uint256 lowLeafIndex, bytes32 newValue)

InvalidProofIndex​

error InvalidProofIndex(uint256 index, bytes32 value)

NotANodeLevel​

error NotANodeLevel()

NotALowLeafIndex​

error NotALowLeafIndex(uint256 leafIndex, uint256 lowLeafIndex)

IndexedMerkleTreeNotInitialized​

error IndexedMerkleTreeNotInitialized()

IndexedMerkleTreeAlreadyInitialized​

error IndexedMerkleTreeAlreadyInitialized()

Modifiers info​

onlyInitialized​

modifier onlyInitialized(IndexedMerkleTree.IndexedMT storage tree)

Functions info​

initialize​

function initialize(IndexedMerkleTree.UintIndexedMT storage tree) internal

Initialize the in-storage Indexed Merkle tree wrapper for uint values.

Requirements:

  • The tree must not already be initialized.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.

setHashers​

function setHashers(
IndexedMerkleTree.UintIndexedMT storage tree,
IndexedMerkleTree.HashFunctions memory hashFunctions_
) internal

Set custom hashing functions to be used by the tree.

Requirements:

  • Must be called before the tree is initialized.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.
hashFunctions_struct IndexedMerkleTree.HashFunctionsThe hash function container (hash2 and hash4).

add​

function add(
IndexedMerkleTree.UintIndexedMT storage tree,
uint256 value_,
uint256 lowLeafIndex_
) internal returns (uint256)

Add a new uint value to the Indexed Merkle tree.

Complexity: O(log(levels)) where levels is the current tree height.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.
value_uint256The value to insert.
lowLeafIndex_uint256A known low leaf index indicating insertion position.

Return values:

NameTypeDescription
[0]uint256The new leaf index for the inserted value.

update​

function update(
IndexedMerkleTree.UintIndexedMT storage tree,
uint256 leafIndex_,
uint256 currentLowLeafIndex_,
uint256 newValue_,
uint256 newLowLeafIndex_
) internal

Update an existing leaf in the Indexed Merkle tree.

Requirements:

  • leafIndex_ must be valid and initialized.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.
leafIndex_uint256The index of the leaf to update.
currentLowLeafIndex_uint256The current low-leaf insertion point that precedes the leaf.
newValue_uint256New value to set.
newLowLeafIndex_uint256New low-leaf pointer (may be same as currentLowLeafIndex_).

getProof​

function getProof(
IndexedMerkleTree.UintIndexedMT storage tree,
uint256 index_,
uint256 value_
) internal view returns (IndexedMerkleTree.Proof memory)

Generate an inclusion/exclusion proof for the leaf at index_.

Complexity: O(levels) to build the proof.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.
index_uint256The leaf index to build the proof for.
value_uint256The value expected at the index (used to validate existence vs exclusion).

Return values:

NameTypeDescription
[0]struct IndexedMerkleTree.ProofA merkle Proof structure for index_ and value_.

verifyProof​

function verifyProof(
IndexedMerkleTree.UintIndexedMT storage tree,
IndexedMerkleTree.Proof memory proof_
) internal view returns (bool)

Verify a proof produced by getProof for this tree instance.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.
proof_struct IndexedMerkleTree.ProofThe proof to verify.

Return values:

NameTypeDescription
[0]boolTrue if the proof matches the current root, false otherwise.

processProof​

function processProof(
IndexedMerkleTree.Proof memory proof_
) internal view returns (bytes32)

Convenience helper to process a raw Proof using the default hashers (keccak256).

Parameters:

NameTypeDescription
proof_struct IndexedMerkleTree.ProofA proof as returned by getProof.

Return values:

NameTypeDescription
[0]bytes32The computed root when hashing the proof values using default hash functions.

processProof​

function processProof(
IndexedMerkleTree.Proof memory proof_,
IndexedMerkleTree.HashFunctions memory hashFunctions_
) internal view returns (bytes32)

Process a proof using the provided hash functions.

Parameters:

NameTypeDescription
proof_struct IndexedMerkleTree.ProofA proof as returned by getProof.
hashFunctions_struct IndexedMerkleTree.HashFunctionsCustom hashing functions to use when processing the proof.

Return values:

NameTypeDescription
[0]bytes32The computed root when hashing the proof using the provided functions.

getRoot​

function getRoot(
IndexedMerkleTree.UintIndexedMT storage tree
) internal view returns (bytes32)

Get the current Merkle root for the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.

Return values:

NameTypeDescription
[0]bytes32The bytes32 root hash.

getTreeLevels​

function getTreeLevels(
IndexedMerkleTree.UintIndexedMT storage tree
) internal view returns (uint256)

Get the current number of levels in the Indexed Merkle tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.

Return values:

NameTypeDescription
[0]uint256The number of levels used by the tree (>= 1 when initialized).

getLeafData​

function getLeafData(
IndexedMerkleTree.UintIndexedMT storage tree,
uint256 leafIndex_
) internal view returns (IndexedMerkleTree.LeafData memory)

Read data for a leaf in the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.
leafIndex_uint256The leaf index to query.

Return values:

NameTypeDescription
[0]struct IndexedMerkleTree.LeafDataLeafData struct with value and nextLeafIndex.

getNodeHash​

function getNodeHash(
IndexedMerkleTree.UintIndexedMT storage tree,
uint256 index_,
uint256 level_
) internal view returns (bytes32)

Get the hash of a node at a given index and level.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.
index_uint256Index of the node on the provided level.
level_uint256Level to query (0 == leaves).

Return values:

NameTypeDescription
[0]bytes32The node hash.

getLeavesCount​

function getLeavesCount(
IndexedMerkleTree.UintIndexedMT storage tree
) internal view returns (uint256)

Get the total number of leaves in the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.

Return values:

NameTypeDescription
[0]uint256The number of leaves stored at level 0.

getLevelNodesCount​

function getLevelNodesCount(
IndexedMerkleTree.UintIndexedMT storage tree,
uint256 level_
) internal view returns (uint256)

Get the number of nodes present at a specific level of the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.
level_uint256The level to query.

Return values:

NameTypeDescription
[0]uint256The number of nodes in the specified level.

isCustomHasherSet​

function isCustomHasherSet(
IndexedMerkleTree.UintIndexedMT storage tree
) internal view returns (bool)

Returns true when custom hash functions were provided before initialization.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.UintIndexedMTself.

Return values:

NameTypeDescription
[0]boolTrue if custom hashers are set, false otherwise.

initialize​

function initialize(IndexedMerkleTree.Bytes32IndexedMT storage tree) internal

Initialize the in-storage Indexed Merkle tree wrapper for bytes32 values.

Requirements:

  • The tree must not already be initialized.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.

setHashers​

function setHashers(
IndexedMerkleTree.Bytes32IndexedMT storage tree,
IndexedMerkleTree.HashFunctions memory hashFunctions_
) internal

Set custom hashing functions to be used by the tree.

Requirements:

  • Must be called before the tree is initialized.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.
hashFunctions_struct IndexedMerkleTree.HashFunctionsThe hash function container (hash2 and hash4).

add​

function add(
IndexedMerkleTree.Bytes32IndexedMT storage tree,
bytes32 value_,
uint256 lowLeafIndex_
) internal returns (uint256)

Add a new bytes32 value to the Indexed Merkle tree.

Complexity: O(log(levels)) where levels is the current tree height.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.
value_bytes32The value to insert.
lowLeafIndex_uint256A known low leaf index indicating insertion position.

Return values:

NameTypeDescription
[0]uint256The new leaf index for the inserted value.

update​

function update(
IndexedMerkleTree.Bytes32IndexedMT storage tree,
uint256 leafIndex_,
uint256 currentLowLeafIndex_,
bytes32 newValue_,
uint256 newLowLeafIndex_
) internal

Update an existing leaf in the Indexed Merkle tree.

Requirements:

  • leafIndex_ must be valid and initialized.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.
leafIndex_uint256The index of the leaf to update.
currentLowLeafIndex_uint256The current low-leaf insertion point that precedes the leaf.
newValue_bytes32New value to set.
newLowLeafIndex_uint256New low-leaf pointer (may be same as currentLowLeafIndex_).

getProof​

function getProof(
IndexedMerkleTree.Bytes32IndexedMT storage tree,
uint256 index_,
bytes32 value_
) internal view returns (IndexedMerkleTree.Proof memory)

Generate an inclusion/exclusion proof for the leaf at index_.

Complexity: O(levels) to build the proof.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.
index_uint256The leaf index to build the proof for.
value_bytes32The value expected at the index (used to validate existence vs exclusion).

Return values:

NameTypeDescription
[0]struct IndexedMerkleTree.ProofA merkle Proof structure for index_ and value_.

verifyProof​

function verifyProof(
IndexedMerkleTree.Bytes32IndexedMT storage tree,
IndexedMerkleTree.Proof memory proof_
) internal view returns (bool)

Verify a proof produced by getProof for this tree instance.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.
proof_struct IndexedMerkleTree.ProofThe proof to verify.

Return values:

NameTypeDescription
[0]boolTrue if the proof matches the current root, false otherwise.

getRoot​

function getRoot(
IndexedMerkleTree.Bytes32IndexedMT storage tree
) internal view returns (bytes32)

Get the current Merkle root for the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.

Return values:

NameTypeDescription
[0]bytes32The bytes32 root hash.

getTreeLevels​

function getTreeLevels(
IndexedMerkleTree.Bytes32IndexedMT storage tree
) internal view returns (uint256)

Get the current number of levels in the Indexed Merkle tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.

Return values:

NameTypeDescription
[0]uint256The number of levels used by the tree (>= 1 when initialized).

getLeafData​

function getLeafData(
IndexedMerkleTree.Bytes32IndexedMT storage tree,
uint256 leafIndex_
) internal view returns (IndexedMerkleTree.LeafData memory)

Read data for a leaf in the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.
leafIndex_uint256The leaf index to query.

Return values:

NameTypeDescription
[0]struct IndexedMerkleTree.LeafDataLeafData struct with value and nextLeafIndex.

getNodeHash​

function getNodeHash(
IndexedMerkleTree.Bytes32IndexedMT storage tree,
uint256 index_,
uint256 level_
) internal view returns (bytes32)

Get the hash of a node at a given index and level.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.
index_uint256Index of the node on the provided level.
level_uint256Level to query (0 == leaves).

Return values:

NameTypeDescription
[0]bytes32The node hash.

getLeavesCount​

function getLeavesCount(
IndexedMerkleTree.Bytes32IndexedMT storage tree
) internal view returns (uint256)

Get the total number of leaves in the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.

Return values:

NameTypeDescription
[0]uint256The number of leaves stored at level 0.

getLevelNodesCount​

function getLevelNodesCount(
IndexedMerkleTree.Bytes32IndexedMT storage tree,
uint256 level_
) internal view returns (uint256)

Get the number of nodes present at a specific level of the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.
level_uint256The level to query.

Return values:

NameTypeDescription
[0]uint256The number of nodes in the specified level.

isCustomHasherSet​

function isCustomHasherSet(
IndexedMerkleTree.Bytes32IndexedMT storage tree
) internal view returns (bool)

Returns true when custom hash functions were provided before initialization.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.Bytes32IndexedMTself.

Return values:

NameTypeDescription
[0]boolTrue if custom hashers are set, false otherwise.

initialize​

function initialize(IndexedMerkleTree.AddressIndexedMT storage tree) internal

Initialize the in-storage Indexed Merkle tree wrapper for address values.

Requirements:

  • The tree must not already be initialized.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.

setHashers​

function setHashers(
IndexedMerkleTree.AddressIndexedMT storage tree,
IndexedMerkleTree.HashFunctions memory hashFunctions_
) internal

Set custom hashing functions to be used by the tree.

Requirements:

  • Must be called before the tree is initialized.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.
hashFunctions_struct IndexedMerkleTree.HashFunctionsThe hash function container (hash2 and hash4).

add​

function add(
IndexedMerkleTree.AddressIndexedMT storage tree,
address value_,
uint256 lowLeafIndex_
) internal returns (uint256)

Add a new address value to the Indexed Merkle tree.

Complexity: O(log(levels)) where levels is the current tree height.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.
value_addressThe address value to insert.
lowLeafIndex_uint256A known low leaf index indicating insertion position.

Return values:

NameTypeDescription
[0]uint256The new leaf index for the inserted value.

update​

function update(
IndexedMerkleTree.AddressIndexedMT storage tree,
uint256 leafIndex_,
uint256 currentLowLeafIndex_,
address newValue_,
uint256 newLowLeafIndex_
) internal

Update an existing leaf in the Indexed Merkle tree.

Requirements:

  • leafIndex_ must be valid and initialized.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.
leafIndex_uint256The index of the leaf to update.
currentLowLeafIndex_uint256The current low-leaf insertion point that precedes the leaf.
newValue_addressNew address value to set.
newLowLeafIndex_uint256New low-leaf pointer (may be same as currentLowLeafIndex_).

getProof​

function getProof(
IndexedMerkleTree.AddressIndexedMT storage tree,
uint256 index_,
address value_
) internal view returns (IndexedMerkleTree.Proof memory)

Generate an inclusion/exclusion proof for the leaf at index_.

Complexity: O(levels) to build the proof.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.
index_uint256The leaf index to build the proof for.
value_addressThe value expected at the index (used to validate existence vs exclusion).

Return values:

NameTypeDescription
[0]struct IndexedMerkleTree.ProofA merkle Proof structure for index_ and value_.

verifyProof​

function verifyProof(
IndexedMerkleTree.AddressIndexedMT storage tree,
IndexedMerkleTree.Proof memory proof_
) internal view returns (bool)

Verify a proof produced by getProof for this tree instance.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.
proof_struct IndexedMerkleTree.ProofThe proof to verify.

Return values:

NameTypeDescription
[0]boolTrue if the proof matches the current root, false otherwise.

getRoot​

function getRoot(
IndexedMerkleTree.AddressIndexedMT storage tree
) internal view returns (bytes32)

Get the current Merkle root for the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.

Return values:

NameTypeDescription
[0]bytes32The bytes32 root hash.

getTreeLevels​

function getTreeLevels(
IndexedMerkleTree.AddressIndexedMT storage tree
) internal view returns (uint256)

Get the current number of levels in the Indexed Merkle tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.

Return values:

NameTypeDescription
[0]uint256The number of levels used by the tree (>= 1 when initialized).

getLeafData​

function getLeafData(
IndexedMerkleTree.AddressIndexedMT storage tree,
uint256 leafIndex_
) internal view returns (IndexedMerkleTree.LeafData memory)

Read data for a leaf in the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.
leafIndex_uint256The leaf index to query.

Return values:

NameTypeDescription
[0]struct IndexedMerkleTree.LeafDataLeafData struct with value and nextLeafIndex.

getNodeHash​

function getNodeHash(
IndexedMerkleTree.AddressIndexedMT storage tree,
uint256 index_,
uint256 level_
) internal view returns (bytes32)

Get the hash of a node at a given index and level.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.
index_uint256Index of the node on the provided level.
level_uint256Level to query (0 == leaves).

Return values:

NameTypeDescription
[0]bytes32The node hash.

getLeavesCount​

function getLeavesCount(
IndexedMerkleTree.AddressIndexedMT storage tree
) internal view returns (uint256)

Get the total number of leaves in the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.

Return values:

NameTypeDescription
[0]uint256The number of leaves stored at level 0.

getLevelNodesCount​

function getLevelNodesCount(
IndexedMerkleTree.AddressIndexedMT storage tree,
uint256 level_
) internal view returns (uint256)

Get the number of nodes present at a specific level of the tree.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.
level_uint256The level to query.

Return values:

NameTypeDescription
[0]uint256The number of nodes in the specified level.

isCustomHasherSet​

function isCustomHasherSet(
IndexedMerkleTree.AddressIndexedMT storage tree
) internal view returns (bool)

Returns true when custom hash functions were provided before initialization.

Parameters:

NameTypeDescription
treestruct IndexedMerkleTree.AddressIndexedMTself.

Return values:

NameTypeDescription
[0]boolTrue if custom hashers are set, false otherwise.