Last active
February 19, 2023 06:40
-
-
Save Iamstanlee/ee7d5b4a0b5de3b9279eb671a8fb2931 to your computer and use it in GitHub Desktop.
Merkle(Hash) Tree Implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MerkleTree { | |
constructor(leaves, concatHash) { | |
this.leaves = leaves; | |
this.concatHash = concatHash; | |
} | |
getRoot() { | |
return this._buildHashRoot(this.leaves); | |
} | |
getProof(leafIndex) { | |
let proof = [] | |
let layer = this.leaves; | |
let index = leafIndex; | |
while(layer.length > 1) { | |
const indexOfPair = this.getIndexOfPairNode(index); | |
if(layer[indexOfPair]) { | |
if(this.isLeftNode(index)) { | |
proof.push({data: layer[indexOfPair], left: false}) | |
}else { | |
proof.push({data: layer[indexOfPair], left: true}) | |
} | |
} | |
// build next layer of merkle tree | |
layer = this._buildLayer(layer); | |
index = Math.floor(index /2); | |
} | |
return proof; | |
} | |
isLeftNode(index) { | |
return index %2 == 0; | |
} | |
getIndexOfPairNode(index) { | |
if(this.isLeftNode(index)) { | |
return index+1; | |
} | |
return index-1; | |
} | |
_buildHashRoot(leaves) { | |
if(leaves.length == 1) return leaves[0]; | |
const layer = this._buildLayer(leaves); | |
return this._buildHashRoot(layer); | |
} | |
_buildLayer(leaves) { | |
let result = []; | |
for(let i = 0;i < leaves.length;i++) { | |
if(i % 2 == 0) { | |
const leftNode = leaves[i]; | |
const rightNode = leaves[i+1]; | |
if(rightNode) { | |
const hash = this.concatHash(leftNode, rightNode); | |
result.push(hash); | |
} else { | |
// move the leaf to the upper layer until we find a pair to combine with | |
result.push(leftNode); | |
} | |
} | |
} | |
return result; | |
} | |
} | |
function verifyProof(node, root, proof, concatHash) { | |
let hash = proof[0].left ? concatHash(proof[0].data, node) : concatHash(node, proof[0].data); | |
for(let i = 1;i< proof.length; i++) { | |
if(proof[i].left) { | |
hash = concatHash(proof[i].data, hash); | |
} else { | |
hash = concatHash(hash, proof[i].data); | |
} | |
} | |
return hash === root | |
} | |
module.exports = MerkleTree; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment