From f6f94f60cff409915f6e443d6c822edc5e61c4ab Mon Sep 17 00:00:00 2001 From: theSatvik Date: Mon, 30 Aug 2021 16:04:18 +0530 Subject: [PATCH 01/10] Defined and declared class MerkleTree with constructor --- .../tree/merkle-tree/MerkleTree.js | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/data-structures/tree/merkle-tree/MerkleTree.js diff --git a/src/data-structures/tree/merkle-tree/MerkleTree.js b/src/data-structures/tree/merkle-tree/MerkleTree.js new file mode 100644 index 00000000..4b72e4b7 --- /dev/null +++ b/src/data-structures/tree/merkle-tree/MerkleTree.js @@ -0,0 +1,49 @@ +var crypto = require('crypto'); + +class MerkleTree { + /** + * @desc Constructs a Merkle Tree. + * If the number of nodes is odd, last node is duplicated while calculating next level up: + * Hash(LN) = Hash(LN+LN) + * @param {[]} array - Array of inputs. Each value must be a string/number/object. + * @param {Object} options - Additional options: {inputHash, hash} + * inputHash: - string + * ex: 'sha256' | 'md5' + * (*listOfSupportedHashes = crypto.getHashes()) + * + * - function + * ex: + * function sha256(data) { + * return crypto.createHash('sha256').update(data).digest('hex') + * } + * + * @example + * ```js + * const tree = new MerkleTree([1,2,3,4,5,6], {hash: 'md5'}) + * ``` + */ + + constructor (array, option = {}) { + if (!array) { + array = [] + } else { + if (!Array.isArray(array)) { + throw new Error('Input has to be an array') + } + } + + if (option.constructor !== Object) { + throw new Error('Invalid option object: has to be {hash, inputHash}') + } + + this.option = { + hash: option.hash || 'sha256', + inputHash: option.inputHash || 'sha256' + } + this.originalArray = array + this.buildTree() + } + +} + +module.exports = MerkleTree \ No newline at end of file From 2992aafcc8dc013f2c6cc2942251aeba13a63264 Mon Sep 17 00:00:00 2001 From: theSatvik Date: Mon, 30 Aug 2021 16:05:14 +0530 Subject: [PATCH 02/10] added buildTree method --- .../tree/merkle-tree/MerkleTree.js | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/data-structures/tree/merkle-tree/MerkleTree.js b/src/data-structures/tree/merkle-tree/MerkleTree.js index 4b72e4b7..ce4efba3 100644 --- a/src/data-structures/tree/merkle-tree/MerkleTree.js +++ b/src/data-structures/tree/merkle-tree/MerkleTree.js @@ -43,6 +43,33 @@ class MerkleTree { this.originalArray = array this.buildTree() } + buildTree() { + // Hash all the inputs with inputHash() + this.hashedArray = this.originalArray.map(item => { + return this.inputHash(item) + }) + // Initiate a 2D map to store all the hash values + this.fullPath = [] + // Hash first row + let currentRow = this.hashedArray.map(item => { + return this.hash(item) + }) + while (currentRow.length > 1) { + let nextRow = [] + if ((currentRow.length % 2) !== 0) { + // Duplicate last node in the row if the node is alone + currentRow.push(currentRow[currentRow.length-1]) + } + for (let i = 0; i < currentRow.length; i += 2) { + nextRow.push(this.hash(currentRow[i]+currentRow[i+1])) + } + this.fullPath.unshift(currentRow) + currentRow = nextRow + } + this.fullPath.unshift(currentRow) + // Set the final hash as root + this.root = currentRow[0] + } } From 1bb83c68662383499502679c8711019339816ada Mon Sep 17 00:00:00 2001 From: theSatvik Date: Mon, 30 Aug 2021 16:05:57 +0530 Subject: [PATCH 03/10] added hash based methods --- .../tree/merkle-tree/MerkleTree.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/data-structures/tree/merkle-tree/MerkleTree.js b/src/data-structures/tree/merkle-tree/MerkleTree.js index ce4efba3..e504b763 100644 --- a/src/data-structures/tree/merkle-tree/MerkleTree.js +++ b/src/data-structures/tree/merkle-tree/MerkleTree.js @@ -70,6 +70,23 @@ class MerkleTree { // Set the final hash as root this.root = currentRow[0] } + inputHash(node) { + return this.hashBase(node, this.option.inputHash) + } + + hash(node) { + return this.hashBase(node, this.option.hash) + } + + hashBase(node, method = this.option.hash) { + node = this._toString(node) + if (method && (typeof method === 'function')) { + return method(node) + } + const hash = crypto.createHash(method) + return hash.update(node, 'utf8').digest('hex') + } + } From 8a88cbc4559fd7360e7081f7d8c6eb94d78730e3 Mon Sep 17 00:00:00 2001 From: theSatvik Date: Mon, 30 Aug 2021 16:06:59 +0530 Subject: [PATCH 04/10] added _toString method --- src/data-structures/tree/merkle-tree/MerkleTree.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/data-structures/tree/merkle-tree/MerkleTree.js b/src/data-structures/tree/merkle-tree/MerkleTree.js index e504b763..765557e6 100644 --- a/src/data-structures/tree/merkle-tree/MerkleTree.js +++ b/src/data-structures/tree/merkle-tree/MerkleTree.js @@ -86,6 +86,12 @@ class MerkleTree { const hash = crypto.createHash(method) return hash.update(node, 'utf8').digest('hex') } + _toString(node) { + if (node.constructor === String) return node + if (node.constructor === Number) return node.toString() + if (node.constructor === Object) return JSON.stringify(node) + throw new Error('Input object only takes string, number, object') + } } From 64ac0fd259094242f44e482d156f01a956df2caf Mon Sep 17 00:00:00 2001 From: theSatvik Date: Mon, 30 Aug 2021 16:09:28 +0530 Subject: [PATCH 05/10] added proof method with commented explanation --- .../tree/merkle-tree/MerkleTree.js | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/data-structures/tree/merkle-tree/MerkleTree.js b/src/data-structures/tree/merkle-tree/MerkleTree.js index 765557e6..358cff65 100644 --- a/src/data-structures/tree/merkle-tree/MerkleTree.js +++ b/src/data-structures/tree/merkle-tree/MerkleTree.js @@ -92,6 +92,59 @@ class MerkleTree { if (node.constructor === Object) return JSON.stringify(node) throw new Error('Input object only takes string, number, object') } + + addNode(node) { + this.originalArray.push(node) + // Rebuild tree + this.buildTree() + } + + getRoot() { + return this.root + } + + /** + * getProof + * @desc Returns the proof for a node. + * @param {} node + * @param {Number} [index] - claimed node index of the input array. + * If not provided, getProof will set it default to first found index in the input array + * @return {Object} - An object provides the claim of the proof including: + * { + * node - the original input node, + * index - the original input index(if valid/applicable for the current tree), -1 otherwise, + * path - an array contains the coordinates of a bottom-up merkle path + * } + *@example + * ```js + *const tree = new MerkleTree(['a', 'b', 'c', 'd', 'e']); + *console.log(tree.getProof('b')) + * // {node: 'b', index: 1, path: [[3,0],[2,1],[1,1]]} + *``` + */ + + getProof(node, index) { + const result = {node, index: -1, path: []} + // Filter out invalid inputs + if (node === undefined || node === null) return result + if (index && (!Number.isInteger(index) || index < 0) || index >= this.originalArray.length) return result + // Set the index to real index if not provided + if (index === undefined || index === null) index = this.hashedArray.indexOf(this.inputHash(node)) + if (index === -1) return result + result.index = index + + // Build a path array bottom up based on the current full hash map by calculating indexes + for (let j=this.fullPath.length - 1; j>0;j--) { + // If the index indicates it is a left node, push right sibling to the path array, left otherwise. + if ((index % 2) == 0) { + result.path.push([j, index + 1]) + } else { + result.path.push([j, index - 1]) + } + index = Math.floor(index/2) + } + return result + } } From dbadfe72416a6aa93525afe8eb24289990f53cfd Mon Sep 17 00:00:00 2001 From: theSatvik Date: Mon, 30 Aug 2021 16:10:34 +0530 Subject: [PATCH 06/10] added proof validation method --- .../tree/merkle-tree/MerkleTree.js | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/data-structures/tree/merkle-tree/MerkleTree.js b/src/data-structures/tree/merkle-tree/MerkleTree.js index 358cff65..f673ab38 100644 --- a/src/data-structures/tree/merkle-tree/MerkleTree.js +++ b/src/data-structures/tree/merkle-tree/MerkleTree.js @@ -146,6 +146,57 @@ class MerkleTree { return result } + /** + * verify + * @desc verify a proof generated by getProof() + * @param {Proof} proof - proof object generated by getProof() + * { + * node, index, path + * } + * @return {Boolean} - If true, the correct merkle root can be calculated through the path provided by input proof, false other wise. + *@example + * ```js + *const tree = new MerkleTree(['a', 'b', 'c', 'd', 'e']); + *const proof = tree.getProof('b')) // {node: 'b', index: 1, path: [[3,0],[2,1],[1,1]]} + *console.log(tree.verify(proof)) //true + *``` + */ + verify(proof) { + const node = proof.node + const index = proof.index + const path = proof.path + + if (node === undefined || node === null) return false + if (index >= this.originalArray.length ) return false + let hashed = this.hash(this.inputHash(node)) + // If path is [] and index == 0 means the input array contains only one node. Just compare the hash of itself with root + if (path === []) { + if(index === 0) return hashed === this.root + return false + } + + // Rebuild hashes bottem up by only calculating the necessary nodes, compare the final hash with root + while(path.length > 0) { + const current = path.shift() + const row = current[0] + const index = current[1] + + try { + const sibling = this.fullPath[row][index] + // If the coordinate indicates the sibling is a left node, do H(sibling + current) + // H(current + sibling) otherwise* + if ((index%2) == 0) { + hashed = this.hash(sibling + hashed) + } else { + hashed = this.hash(hashed + sibling) + } + } catch (err) { + return false + } + } + + return hashed === this.root + } } From 5958bcfa1a17df7fc9f404913c4df8961c16ff64 Mon Sep 17 00:00:00 2001 From: theSatvik Date: Mon, 30 Aug 2021 17:56:42 +0530 Subject: [PATCH 07/10] Added Documentation --- .../tree/merkle-tree/README.md | 35 ++++++++++++++++++ .../merkle-tree/complexity-merkle-tree.jpg | Bin 0 -> 34718 bytes 2 files changed, 35 insertions(+) create mode 100644 src/data-structures/tree/merkle-tree/README.md create mode 100644 src/data-structures/tree/merkle-tree/complexity-merkle-tree.jpg diff --git a/src/data-structures/tree/merkle-tree/README.md b/src/data-structures/tree/merkle-tree/README.md new file mode 100644 index 00000000..a59ca5aa --- /dev/null +++ b/src/data-structures/tree/merkle-tree/README.md @@ -0,0 +1,35 @@ +# Merkle - Tree + +_Read this in other languages:_ + +## What Is a Merkle Tree? +A Merkle tree is a data structure that is used in computer science applications. In bitcoin and other cryptocurrencies​, Merkle trees serve to encode blockchain data more efficiently and securely. + +Ralph C. Merkle (born February 2, 1952) is a computer scientist. He is one of the inventors of public key cryptography, the inventor of hashing. He is also the inventor of MERKEL tree. + +A Merkle tree is a hash-based data structure that is a generalization of the hash list. It is a tree structure in which each leaf node is a hash of a block of data, and each non-leaf node is a hash of its children. Typically, Merkle trees have a branching factor of 2, meaning that each node has up to 2 children. + +Merkle trees are used in distributed systems for efficient data verification. They are efficient because they use hashes instead of full files. Hashes are ways of encoding files that are much smaller than the actual file itself. Currently, their main uses are in peer-to-peer networks such as Tor, Bitcoin, and Git. + +![MerkleTree](https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Hash_Tree.svg/1920px-Hash_Tree.svg.png) + +## Usage +Merkle tree(Hash tree) is used to verify any kind of data stored, handled and transferred in and between computers. + +Currently, the main use of Merkle tree is to make sure that data blocks received from other peers in a peer-to-peer network are received undamaged and unaltered, and even to check that the other peers do not lie and send fake blocks. + +Merkle tree is used in git, Amazon's Dynamo, Cassandra as well as BitCoin. + +## Role of Merkle Tree in Block Chain: + +Merkle Tree is one of the core data structures which is used in the Bitcoin blockchain to verify the existence of a transaction in a way that conserves both space and time quite effectively + +Merkle trees produce an overall digital fingerprint of the entire set of transactions, providing a very efficient process to verify whether a transaction is included in a block. + +## Complexity + Merkle trees have very little overhead when compared with hash lists. Binary Merkle trees, like the one pictured above, operate similarly to binary search trees in that their depth is bounded by their branching factor, 2. Included below is worst-case analysis for a Merkle tree with a branching factor of kk. +![MerkleTree](https://www.google.com/url?sa=i&url=https%3A%2F%2Fmedium.com%2F%40skj48817%2Fmerkle-trees-introduction-to-blockchain-c80c0247046&psig=AOvVaw3kakSbcvZ_Np71aiixWGfK&ust=1630408818280000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCKi2p5nd2PICFQAAAAAdAAAAABAD) + +## References + +- [Wikipedia](https://en.wikipedia.org/wiki/Merkle_tree) \ No newline at end of file diff --git a/src/data-structures/tree/merkle-tree/complexity-merkle-tree.jpg b/src/data-structures/tree/merkle-tree/complexity-merkle-tree.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d1534a920aef4cf86fe066ffa08e7149abc97360 GIT binary patch literal 34718 zcmeFZ2Ut_lx-A-t0@9>6Ar_icX`-}dm2nZ-uI)V_95_+Ty zi1ZdpAoLOlJwQla+&H)MT$Su9rO{O4R_&N2QmCuxi{130Uv zrK<&?pr8Oi$v*(n1V95oMM?SVO@2|6-=}C#ouZ~bb%uuKG%dp!1_t^w^z@8OtY;aS zSeWSP&vKq+VPogu;9y|p;^t)MW@YDK|8)}zD)RqOpQ1Z;ijJL;o{|0k_lxumz(Px5 zL=i+qaS=etLP5nsL23m60RW0q?r5Vcd@slzZY9NOy*li<^g6NLWPl zvY5QWRmE%9l{9W?YH91}>fO8lz{J$d+``88shz!pqm%nf4^J13@QC})r$f^_19|sx0?M{FBWpWD5A>Wl{L{_k~79}JaOwk!zm~~E41~iYJaKOKUcB9|EZe&w~GD0^+Ev{ zs3^#dN5ujF0Z#5^N9-WaLU-CSabGH#>G9weC8^?*%)IecQ!b0f8ii1TUyldxMM2Mm zjgE2dc)b&x%ngBXO>gx6Qd{N`YdsGM@a7Gg1Q1&$PU6c+fSaa4Al#Qa5@5j!;3LGb z1e?g@ge~jg?1`LQFhX(8u{);sgwC3Q1ZZyFBmoj%QY^nSO(y|d{LD#!Eb*pHyqOgV zuw5F9?TrNO3PI&a0D5{P@j)L=wvn~hNzIl$F&KUtHv8C%1n8;-A=D&DfWE|;UV?-a z32;0@uc7{r?^^#ZQT^kQTt$4#jN*cE%aZ_H4a88UAlNLD)f(!8;e+gWvwyV=JJ5^g z&Q{iS1Bfwksp0^tS0h9}Qr2&3kN^oGTkw+z6f-e#jbk}+$p=VCQ;deKoAkkU;btG1 zZ)Hb_0)9W>%J?l3;G)(C62QhV6tsKr)H>YSYio{pD_V}&p2-AT+30$u%KGa&{yz?8 z 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 Date: Mon, 30 Aug 2021 18:06:35 +0530 Subject: [PATCH 08/10] Added Visuals and Usage --- src/data-structures/tree/merkle-tree/README.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/data-structures/tree/merkle-tree/README.md b/src/data-structures/tree/merkle-tree/README.md index a59ca5aa..fa2a5a68 100644 --- a/src/data-structures/tree/merkle-tree/README.md +++ b/src/data-structures/tree/merkle-tree/README.md @@ -1,6 +1,5 @@ # Merkle - Tree - -_Read this in other languages:_ +- [Role](https://media-exp1.licdn.com/dms/image/C5112AQHbQzs-tGzrsQ/article-cover_image-shrink_720_1280/0/1537618109250?e=1635984000&v=beta&t=cATJRvRamNOSOdEFDi9EyH1ls3aQ1r_FHD9RXJIPmKY) ## What Is a Merkle Tree? A Merkle tree is a data structure that is used in computer science applications. In bitcoin and other cryptocurrencies​, Merkle trees serve to encode blockchain data more efficiently and securely. @@ -26,9 +25,22 @@ Merkle Tree is one of the core data structures which is used in the Bitcoin bloc Merkle trees produce an overall digital fingerprint of the entire set of transactions, providing a very efficient process to verify whether a transaction is included in a block. +## Algorithm and Implementation + +- [Role](https://media-exp1.licdn.com/dms/image/C5112AQEehgC6XD-20Q/article-inline_image-shrink_1000_1488/0/1537618459684?e=1635984000&v=beta&t=jRQinfqEPZvstqnlzklZvUXwyLIjWy6uFkCK3TsMcKQ) +A Merkle tree is constructed by recursively hashing pairs of nodes until there is only one hash. + +a, b, c, and d are some data elements (files, JSON, etc) and H is a hash function. + +a hash function acts as a “digital fingerprint” of some piece of data by mapping it to a simple string with a low probability that any other piece of data will map to the same string. + +Each node is created by hashing the concatenation of its “parents” in the tree. + +Note: Merkle tree are mostly a binary tree but there are also Trees. Platforms like Ethereum use non binary tree. + ## Complexity Merkle trees have very little overhead when compared with hash lists. Binary Merkle trees, like the one pictured above, operate similarly to binary search trees in that their depth is bounded by their branching factor, 2. Included below is worst-case analysis for a Merkle tree with a branching factor of kk. -![MerkleTree](https://www.google.com/url?sa=i&url=https%3A%2F%2Fmedium.com%2F%40skj48817%2Fmerkle-trees-introduction-to-blockchain-c80c0247046&psig=AOvVaw3kakSbcvZ_Np71aiixWGfK&ust=1630408818280000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCKi2p5nd2PICFQAAAAAdAAAAABAD) +- [Complexity](https://www.google.com/url?sa=i&url=https%3A%2F%2Fmedium.com%2F%40skj48817%2Fmerkle-trees-introduction-to-blockchain-c80c0247046&psig=AOvVaw3kakSbcvZ_Np71aiixWGfK&ust=1630408818280000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCKi2p5nd2PICFQAAAAAdAAAAABAD) ## References From 9917dcfa3ca948ffe5137a3dd1b36857f3de8fe8 Mon Sep 17 00:00:00 2001 From: theSatvik Date: Mon, 30 Aug 2021 18:09:53 +0530 Subject: [PATCH 09/10] Added links --- src/data-structures/tree/merkle-tree/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data-structures/tree/merkle-tree/README.md b/src/data-structures/tree/merkle-tree/README.md index fa2a5a68..49c27a78 100644 --- a/src/data-structures/tree/merkle-tree/README.md +++ b/src/data-structures/tree/merkle-tree/README.md @@ -1,5 +1,5 @@ # Merkle - Tree -- [Role](https://media-exp1.licdn.com/dms/image/C5112AQHbQzs-tGzrsQ/article-cover_image-shrink_720_1280/0/1537618109250?e=1635984000&v=beta&t=cATJRvRamNOSOdEFDi9EyH1ls3aQ1r_FHD9RXJIPmKY) +![MerkleVisual](https://media-exp1.licdn.com/dms/image/C5112AQHbQzs-tGzrsQ/article-cover_image-shrink_720_1280/0/1537618109250?e=1635984000&v=beta&t=cATJRvRamNOSOdEFDi9EyH1ls3aQ1r_FHD9RXJIPmKY) ## What Is a Merkle Tree? A Merkle tree is a data structure that is used in computer science applications. In bitcoin and other cryptocurrencies​, Merkle trees serve to encode blockchain data more efficiently and securely. @@ -27,7 +27,7 @@ Merkle trees produce an overall digital fingerprint of the entire set of transac ## Algorithm and Implementation -- [Role](https://media-exp1.licdn.com/dms/image/C5112AQEehgC6XD-20Q/article-inline_image-shrink_1000_1488/0/1537618459684?e=1635984000&v=beta&t=jRQinfqEPZvstqnlzklZvUXwyLIjWy6uFkCK3TsMcKQ) +![Algorithm](https://media-exp1.licdn.com/dms/image/C5112AQEehgC6XD-20Q/article-inline_image-shrink_1000_1488/0/1537618459684?e=1635984000&v=beta&t=jRQinfqEPZvstqnlzklZvUXwyLIjWy6uFkCK3TsMcKQ) A Merkle tree is constructed by recursively hashing pairs of nodes until there is only one hash. a, b, c, and d are some data elements (files, JSON, etc) and H is a hash function. @@ -40,7 +40,7 @@ Note: Merkle tree are mostly a binary tree but there are also Trees. Platforms l ## Complexity Merkle trees have very little overhead when compared with hash lists. Binary Merkle trees, like the one pictured above, operate similarly to binary search trees in that their depth is bounded by their branching factor, 2. Included below is worst-case analysis for a Merkle tree with a branching factor of kk. -- [Complexity](https://www.google.com/url?sa=i&url=https%3A%2F%2Fmedium.com%2F%40skj48817%2Fmerkle-trees-introduction-to-blockchain-c80c0247046&psig=AOvVaw3kakSbcvZ_Np71aiixWGfK&ust=1630408818280000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCKi2p5nd2PICFQAAAAAdAAAAABAD) +![Complexity](https://www.google.com/url?sa=i&url=https%3A%2F%2Fmedium.com%2F%40skj48817%2Fmerkle-trees-introduction-to-blockchain-c80c0247046&psig=AOvVaw3kakSbcvZ_Np71aiixWGfK&ust=1630408818280000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCKi2p5nd2PICFQAAAAAdAAAAABAD) ## References From a0600f308e8685f5e9a74bf1e1be298d5dcf17c4 Mon Sep 17 00:00:00 2001 From: theSatvik Date: Mon, 30 Aug 2021 18:11:57 +0530 Subject: [PATCH 10/10] done --- src/data-structures/tree/merkle-tree/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/data-structures/tree/merkle-tree/README.md b/src/data-structures/tree/merkle-tree/README.md index 49c27a78..6d6183b9 100644 --- a/src/data-structures/tree/merkle-tree/README.md +++ b/src/data-structures/tree/merkle-tree/README.md @@ -28,6 +28,7 @@ Merkle trees produce an overall digital fingerprint of the entire set of transac ## Algorithm and Implementation ![Algorithm](https://media-exp1.licdn.com/dms/image/C5112AQEehgC6XD-20Q/article-inline_image-shrink_1000_1488/0/1537618459684?e=1635984000&v=beta&t=jRQinfqEPZvstqnlzklZvUXwyLIjWy6uFkCK3TsMcKQ) + A Merkle tree is constructed by recursively hashing pairs of nodes until there is only one hash. a, b, c, and d are some data elements (files, JSON, etc) and H is a hash function. @@ -40,7 +41,7 @@ Note: Merkle tree are mostly a binary tree but there are also Trees. Platforms l ## Complexity Merkle trees have very little overhead when compared with hash lists. Binary Merkle trees, like the one pictured above, operate similarly to binary search trees in that their depth is bounded by their branching factor, 2. Included below is worst-case analysis for a Merkle tree with a branching factor of kk. -![Complexity](https://www.google.com/url?sa=i&url=https%3A%2F%2Fmedium.com%2F%40skj48817%2Fmerkle-trees-introduction-to-blockchain-c80c0247046&psig=AOvVaw3kakSbcvZ_Np71aiixWGfK&ust=1630408818280000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCKi2p5nd2PICFQAAAAAdAAAAABAD) +![Complexity](https://miro.medium.com/max/875/1*AghVi4KgVsnxjXNKZBJu9Q.png) ## References