ConvergeLedger.Integrity.MerkleTree (Converge Ledger v0.1.2)
View SourceMerkle tree implementation for cryptographic integrity verification.
A Merkle tree is a binary tree of hashes where:
- Leaf nodes contain hashes of data items
- Internal nodes contain hashes of their children
- The root hash represents the integrity of all data
Use Cases
- Snapshot verification: Detect corruption before loading
- Efficient sync: Identify which entries differ between replicas
- Audit proofs: Prove an entry exists without revealing all entries
- Tamper detection: Any change to data changes the root hash
Usage
iex> entries = [entry1, entry2, entry3]
iex> hashes = Enum.map(entries, &MerkleTree.hash_entry/1)
iex> root = MerkleTree.compute_root(hashes)
iex> MerkleTree.to_hex(root)
"a1b2c3d4..."Properties
- Deterministic: Same inputs → same root hash
- Collision-resistant: Different inputs → different root hash (with high probability)
- Single-element trees: Hash is combined with itself (Bitcoin-style)
Summary
Functions
Combines two hashes into a parent hash (for internal tree nodes).
Computes the Merkle root from a list of leaf hashes.
Computes the Merkle root from a list of entries.
Converts a hexadecimal string to a hash.
Generates a Merkle proof for a leaf at the given index.
Computes the SHA-256 hash of binary content.
Computes the hash of an Entry.
Converts a hash to a hexadecimal string.
Returns a short form of the hash for display (first 16 hex chars).
Verifies entries against an expected Merkle root.
Verifies a Merkle proof for a leaf hash.
Verifies that a computed root matches an expected root.
Types
Functions
Combines two hashes into a parent hash (for internal tree nodes).
Computes the Merkle root from a list of leaf hashes.
Uses standard binary Merkle tree construction:
- Empty list: returns hash of empty binary
- Single element: combined with itself (Bitcoin-style)
- Multiple elements: build tree bottom-up
Examples
iex> MerkleTree.compute_root([])
<<227, 176, 196, ...>> # hash of ""
iex> h = MerkleTree.hash("data")
iex> MerkleTree.compute_root([h])
MerkleTree.combine(h, h) # single element duplicated
@spec compute_root_from_entries([ConvergeLedger.Entry.t()]) :: hash()
Computes the Merkle root from a list of entries.
Entries are hashed and then combined into a tree.
Converts a hexadecimal string to a hash.
@spec generate_proof([hash()], non_neg_integer()) :: {:ok, proof()} | {:error, :invalid_index}
Generates a Merkle proof for a leaf at the given index.
The proof contains the sibling hashes needed to recompute the root.
Returns {:ok, proof} or {:error, :invalid_index}.
Computes the SHA-256 hash of binary content.
@spec hash_entry(ConvergeLedger.Entry.t()) :: hash()
Computes the hash of an Entry.
Combines context_id, key, payload, sequence, and appended_at_ns into a deterministic hash.
Converts a hash to a hexadecimal string.
Returns a short form of the hash for display (first 16 hex chars).
@spec verify_entries([ConvergeLedger.Entry.t()], hash()) :: boolean()
Verifies entries against an expected Merkle root.
Verifies a Merkle proof for a leaf hash.
Given a leaf hash, its proof (sibling hashes), and the expected root, verifies that the leaf is indeed part of the tree.
Verifies that a computed root matches an expected root.