{"id":22303531,"url":"https://github.com/lovesh/merkle_trees","last_synced_at":"2025-10-12T07:42:22.110Z","repository":{"id":57638068,"uuid":"233851230","full_name":"lovesh/merkle_trees","owner":"lovesh","description":"Various merkle trees ","archived":false,"fork":false,"pushed_at":"2020-01-21T10:57:03.000Z","size":82,"stargazers_count":11,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-14T16:28:59.703Z","etag":null,"topics":["compact-merkle-tree","merkle-tree","patricia-tree","sparse-merkle-tree"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lovesh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-01-14T13:47:12.000Z","updated_at":"2024-06-25T09:59:21.000Z","dependencies_parsed_at":"2022-09-26T20:21:08.981Z","dependency_job_id":null,"html_url":"https://github.com/lovesh/merkle_trees","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lovesh/merkle_trees","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovesh%2Fmerkle_trees","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovesh%2Fmerkle_trees/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovesh%2Fmerkle_trees/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovesh%2Fmerkle_trees/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lovesh","download_url":"https://codeload.github.com/lovesh/merkle_trees/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovesh%2Fmerkle_trees/sbom","scorecard":{"id":600181,"data":{"date":"2025-08-11","repo":{"name":"github.com/lovesh/merkle_trees","commit":"0db6b68bbfb219d584a96d503e2d6e4e4c7147a6"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/5 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-21T00:12:44.726Z","repository_id":57638068,"created_at":"2025-08-21T00:12:44.726Z","updated_at":"2025-08-21T00:12:44.726Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279010671,"owners_count":26084785,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-12T02:00:06.719Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compact-merkle-tree","merkle-tree","patricia-tree","sparse-merkle-tree"],"created_at":"2024-12-03T18:44:07.998Z","updated_at":"2025-10-12T07:42:22.080Z","avatar_url":"https://github.com/lovesh.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Merkle trees in Rust\n\nVarious kinds of merkle trees with hash function and tree storage abstracted.\n\n1. [Vanilla (inefficient) sparse merkle tree](./src/vanilla_sparse_merkle_tree.rs)\n1. [Sparse merkle tree](./src/sparse_merkle_tree.rs) with optimizations from V. Buterin  \n1. [Ethereum's Merkle Patricia trie](./src/merkle_patricia_trie.rs)\n1. [Compact merkle tree](./src/compact_merkle_tree.rs) as described by Google's certificate transparency.\n\n\n## Hashing\n\nThe hash function is abstract such that a hash function like SHA-2, SHA-3 or an algebraic hash function like MiMC can be \nused. For a binary tree, this is the hasher's trait\n\n```rust\n/// To be used with a binary tree\n/// `D` is the type of data the leaf has, like a string or a big number, etc.\n/// `H` is the type for the hash\npub trait Arity2Hasher\u003cD, H\u003e {\n    /// Hash the given leaf data to get the leaf hash\n    fn hash_leaf_data(\u0026self, leaf: D) -\u003e Result\u003cH, MerkleTreeError\u003e;\n    \n    /// Hash 2 adjacent nodes (leaves or inner nodes) to get their root hash\n    fn hash_tree_nodes(\u0026self, left_node: H, right_node: H) -\u003e Result\u003cH, MerkleTreeError\u003e;\n}\n```\n\nFor a 4-ary tree, this is the hasher's trait\n```rust\n/// To be used with a 4-ary tree\n/// `D` is the type of data the leaf has, like a string or a big number, etc.\n/// `H` is the type for the hash\npub trait Arity4Hasher\u003cD, H\u003e {\n    /// Hash the given leaf data to get the leaf hash\n    fn hash_leaf_data(\u0026self, leaf: D) -\u003e Result\u003cH, MerkleTreeError\u003e;\n\n    /// Hash 4 adjacent nodes (leaves or inner nodes) to get their root hash\n    fn hash_tree_nodes(\n        \u0026self,\n        node_0: H,\n        node_1: H,\n        node_2: H,\n        node_3: H,\n    ) -\u003e Result\u003cH, MerkleTreeError\u003e;\n}\n```\n\nSay, i need to use SHA-256 in a binary merkle tree, then such an implementation can be used\n```rust\npub struct Sha256Hasher {\n    .....\n}\n\n/// When SHA-256 is used for hashing in a binary merkle tree\nimpl Arity2Hasher\u003c\u0026str, Vec\u003cu8\u003e\u003e for Sha256Hasher {\n    fn hash_leaf_data(\u0026self, leaf: \u0026str) -\u003e Result\u003cVec\u003cu8\u003e, MerkleTreeError\u003e {\n        ....\n    }\n\n    fn hash_tree_nodes(\n        \u0026self,\n        left_node: Vec\u003cu8\u003e,\n        right_node: Vec\u003cu8\u003e,\n    ) -\u003e Result\u003cVec\u003cu8\u003e, MerkleTreeError\u003e {\n        ....\n    }\n}\n```\n\nWhen using SHA-256 in a 4-ary tree, similar implementation can be used\n```rust\n/// When SHA-256 is used for hashing in a 4-ary merkle tree\nimpl Arity4Hasher\u003c\u0026str, Vec\u003cu8\u003e\u003e for Sha256Hasher {\n    fn hash_leaf_data(\u0026self, leaf: \u0026str) -\u003e Result\u003cVec\u003cu8\u003e, MerkleTreeError\u003e {\n        ....\n    }\n\n    fn hash_tree_nodes(\n        \u0026self,\n        node_0: Vec\u003cu8\u003e,\n        node_1: Vec\u003cu8\u003e,\n        node_2: Vec\u003cu8\u003e,\n        node_3: Vec\u003cu8\u003e,\n    ) -\u003e Result\u003cVec\u003cu8\u003e, MerkleTreeError\u003e {\n        ....\n    }\n}\n```\n\nSimilarly, other hash functions can be used. For demonstration, an implementation of `Arity2Hasher` with algebraic hash function \nMiMC is present as well. MiMC is useful when using merkle trees in various SNARKs constructions where the data to hash and the \nhash output are big numbers.\n```rust\n/// When MiMC is used for hashing in a merkle tree\npub struct MiMCHasher {\n    ...\n}\n\n/// When MiMC is used for hashing in a binary merkle tree\nimpl Arity2Hasher\u003cBigUint, BigUint\u003e for MiMCHasher {\n    fn hash_leaf_data(\u0026self, leaf: BigUint) -\u003e Result\u003cBigUint, MerkleTreeError\u003e {\n        ...\n    }\n\n    fn hash_tree_nodes(\n        \u0026self,\n        left_node: BigUint,\n        right_node: BigUint,\n    ) -\u003e Result\u003cBigUint, MerkleTreeError\u003e {\n        ....\n    }\n}\n```\n\n## Database\nThe database needs to support a key-value style CRU (create, read, update) operations, hence the trait `HashValueDb` is provided.\n```rust\n/// Database to map hashes to values (H -\u003e V)\n/// `H` is the type for the hash\n/// `V` is the type for the value\npub trait HashValueDb\u003cH, V: Clone\u003e {\n    fn put(\u0026mut self, hash: H, value: V) -\u003e Result\u003c(), MerkleTreeError\u003e;\n\n    fn get(\u0026self, hash: \u0026H) -\u003e Result\u003cV, MerkleTreeError\u003e;\n}\n```\n\nFor most of the testing an in-memory implementation is used which keeps a `HashMap`. Since most of the code uses SHA-2 or SHA-3, \nthe hash output can be treated as bytes  \n```rust\n/// Uses an in-memory hashmap and assumes the hash is bytes\n#[derive(Clone, Debug)]\npub struct InMemoryHashValueDb\u003cV: Clone\u003e {\n    db: HashMap\u003cVec\u003cu8\u003e, V\u003e,\n}\n\nimpl\u003cV: Clone\u003e HashValueDb\u003cVec\u003cu8\u003e, V\u003e for InMemoryHashValueDb\u003cV\u003e {\n    fn put(\u0026mut self, hash: Vec\u003cu8\u003e, value: V) -\u003e Result\u003c(), MerkleTreeError\u003e {\n        ...\n    }\n\n    fn get(\u0026self, hash: \u0026Vec\u003cu8\u003e) -\u003e Result\u003cV, MerkleTreeError\u003e {\n        ...\n    }\n}\n```\n\nAn implementation that assumes the hash output to be big numbers (like when MiMC is used) can be supported as well\n```rust\nimpl\u003cV: Clone\u003e HashValueDb\u003cBigUint, V\u003e for InMemoryBigUintHashDb\u003cV\u003e {\n    fn put(\u0026mut self, hash: BigUint, value: V) -\u003e Result\u003c(), MerkleTreeError\u003e {\n        ...\n    }\n\n    fn get(\u0026self, hash: \u0026BigUint) -\u003e Result\u003cV, MerkleTreeError\u003e {\n        ...\n    }\n}\n```\n\nFor demonstration, `HashValueDb` is implemented for persistent some databases as well like sqlite.\n```rust\n/// Testing implementation for sqlite\npub struct RusqliteHashValueDb {\n    ...\n}\n\nimpl HashValueDb\u003cVec\u003cu8\u003e, Vec\u003cu8\u003e\u003e for RusqliteHashValueDb {\n    fn put(\u0026mut self, hash: Vec\u003cu8\u003e, value: Vec\u003cu8\u003e) -\u003e Result\u003c(), MerkleTreeError\u003e {\n        ...\n    }\n\n    fn get(\u0026self, hash: \u0026Vec\u003cu8\u003e) -\u003e Result\u003cVec\u003cu8\u003e, MerkleTreeError\u003e {\n        ...\n    }\n}\n```\n\n## Leaves in sparse merkle tree\nSince sparse merkle trees have huge number of leaves (with most being empty) like 2^32 or 2^64 or 2^256, Rust's native \ndatatypes like u32 or u64 or u128 might not be enough so the leaf index is abstracted as well with a trait `LeafIndex`\n```rust\npub trait LeafIndex {\n    /// Path from root to leaf\n    fn to_leaf_path(\u0026self, arity: u8, tree_depth: usize) -\u003e Vec\u003cu8\u003e;\n}\n```\n\nSay the sparse merkle tree can have at most 2^64 leaves. Then a u64 type is sufficient for being used to index leaves.\n```rust\n/// When sparse merkle tree can have 2^64 leaves at max\nimpl LeafIndex for u64 {\n    /// Returns the representation of the `u64` as a byte array in MSB form\n    fn to_leaf_path(\u0026self, arity: u8, tree_depth: usize) -\u003e Vec\u003cu8\u003e {\n        ....   \n    }\n}\n``` \n\nSay the sparse merkle tree has \u003e 2^128 leaves. The a `BigUint` or another big number type will be required to index leaves\n```rust\n/// When sparse merkle tree can have arbitrary number (usually \u003e 2^128) of leaves\nimpl LeafIndex for BigUint {\n    /// Returns the representation of the `BigUint` as a byte array in MSB form\n    fn to_leaf_path(\u0026self, arity: u8, tree_depth: usize) -\u003e Vec\u003cu8\u003e {\n        ....\n    }\n}\n```\n\n## Trees\n1. Vanilla sparse merkle trees.\nThese sparse merkle trees do not perform any optimizations to use the fact that most leaves are empty. They are useful when using SNARKs. \n2 variations, binary and 4-ary are present. `VanillaBinarySparseMerkleTree\u003cD: Clone, H: Clone, MTH\u003e` and \n`VanillaArity4SparseMerkleTree\u003cD: Clone, H: Clone, MTH\u003e`. The types `D`, `H` and `MTH` correspond to the types of data, hash\nand merkle tree hasher. Have a look at the tests for their usage.\n\n1. Sparse merkle tree\nThe have several optimizations over the vanilla ones. Only a binary sparse merkle tree is present for now `BinarySparseMerkleTree\u003cD: Clone, H: Clone, MTH\u003e`.\nThe types have the same meaning as for the vanilla tree. Look at the tests for usage.\n\n1. Merkle Patricia trie\nEthereum's merkle patricia trie . Apart from the hash function and storage, the node serialization is abstract as well `PatriciaTrieNodeSerializer`.\nThere is only one implementation of the serialization which is RLP (same as Ethereum) as of now. Look at the tests for usage.\n    ```rust\n    /// The type `V` is for the value of the data being stored in the trie.\n    /// The type `H` is for the hash output\n    /// The type `S` is for the serialized (node) output\n    #[derive(Clone, Debug, Serialize, Deserialize)]\n    pub struct MerklePatriciaTrie\u003cV, H, S: Clone + KnownLength, NS, NH\u003e\n    where\n        NS: PatriciaTrieNodeSerializer\u003cH, V, S\u003e,\n        NH: NodeHasher\u003cS, H\u003e,\n    {\n        ....\n    }\n    ```\n1. Compact merkle tree.\nAppend only merkle tree used in Google's certificate transparency and Hyperledger Indy's ledger. \n`CompactMerkleTree\u003cD: Clone, H: Clone, MTH\u003e where MTH: Arity2Hasher\u003cD, H\u003e`\n\n## TODO\n1. Make each tree usable as a feature.\n1. Write the sparse merkle tree as a macro to generate trees of any power of 2 arity.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flovesh%2Fmerkle_trees","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flovesh%2Fmerkle_trees","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flovesh%2Fmerkle_trees/lists"}