Skip to content

Instantly share code, notes, and snippets.

@ryzokuken
Last active July 30, 2022 15:57
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ryzokuken/4b2e34c79eb00327402079af884027c4 to your computer and use it in GitHub Desktop.
Save ryzokuken/4b2e34c79eb00327402079af884027c4 to your computer and use it in GitHub Desktop.
TypeScript Merkle Tree Implementation
const hash = require('easy-crypto/hash');
class MerkleTreeNodeGeneric {
compare(node) {
return this.hash === node.hash;
}
}
class MerkleTreeChildNode extends MerkleTreeNodeGeneric {
constructor(data) {
super();
this.data = data;
this.hash = hash.hash('sha256', JSON.stringify(data), 'utf-8', 'hex');
}
}
class MerkleTreeNode extends MerkleTreeNodeGeneric {
constructor(leftChild, rightChild) {
super();
this.leftChild = leftChild;
this.rightChild = rightChild;
this.hash = hash.hash('sha256', leftChild.hash + rightChild.hash, 'hex', 'hex');
}
}
function generateLevel(nodes) {
const result = [];
while (nodes.length > 1) {
const first = nodes.shift();
const second = nodes.shift();
result.push(new MerkleTreeNode(first, second));
}
if (nodes.length == 1) {
const last = nodes.shift();
result.push(new MerkleTreeNode(last, undefined));
}
return result;
}
class MerkleTree {
constructor(documents) {
let nodes = documents.map(data => new MerkleTreeChildNode(data));
while (nodes.length > 1) {
nodes = generateLevel(nodes);
}
this.root = nodes[0];
}
compare(tree) {
return this.root.compare(tree.root);
}
}
const first = new MerkleTree(['one', 'two', 'three', 'four']);
const second = new MerkleTree(['one', 'two', 'three', 'four']);
const third = new MerkleTree(['one', 'two', 'five', 'four']);
console.log(first.compare(second));
console.log(first.compare(third));
import * as hash from 'easy-crypto/hash';
class MerkleTreeNodeGeneric<T> {
hash: string;
compare(node: MerkleTreeNodeGeneric<T>) {
return this.hash === node.hash;
}
}
class MerkleTreeChildNode<T> extends MerkleTreeNodeGeneric<T> {
hash: string;
constructor(public data: T) {
super();
this.hash = hash.hash('sha256', JSON.stringify(data), 'utf-8', 'hex');
}
}
class MerkleTreeNode<T> extends MerkleTreeNodeGeneric<T> {
hash: string;
constructor(public leftChild: MerkleTreeNodeGeneric<T>, public rightChild: MerkleTreeNodeGeneric<T>) {
super();
this.hash = hash.hash('sha256', leftChild.hash + rightChild.hash, 'hex', 'hex');
}
}
function generateLevel<T>(nodes: MerkleTreeNodeGeneric<T>[]) {
const result: MerkleTreeNodeGeneric<T>[] = [];
while (nodes.length > 1) {
const first = nodes.shift();
const second = nodes.shift();
result.push(new MerkleTreeNode<T>(first, second));
}
if (nodes.length == 1) {
const last = nodes.shift();
result.push(new MerkleTreeNode<T>(last, undefined));
}
return result;
}
class MerkleTree<T> {
root: MerkleTreeNodeGeneric<T>;
constructor(documents: T[]) {
let nodes: MerkleTreeNodeGeneric<T>[] = documents.map(data => new MerkleTreeChildNode<T>(data));
while (nodes.length > 1) {
nodes = generateLevel(nodes);
}
this.root = nodes[0];
}
compare(tree: MerkleTree<T>) {
return this.root.compare(tree.root);
}
}
const first = new MerkleTree<string>(['one', 'two', 'three', 'four']);
const second = new MerkleTree<string>(['one', 'two', 'three', 'four']);
const third = new MerkleTree<string>(['one', 'two', 'five', 'four']);
console.log(first.compare(second));
console.log(first.compare(third));
@AtHeartEngineer
Copy link

Whats the license on this? Can I use it in an LGPLv3 project?

@ryzokuken
Copy link
Author

@AtHeartEngineer

Whats the license on this? Can I use it in an LGPLv3 project?

Please feel free. Let me know if you'd like me to release this as a LGPLv3 licensed npm module.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment