diff --git a/src/index.ts b/src/index.ts index d0711a5..3a7c7f1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,7 @@ export default class MerkleTree { levels: number capacity: number - private _hash: HashFunction + private _hashFn: HashFunction private zeroElement: Element private _zeros: Element[] private _layers: Array @@ -27,12 +27,12 @@ export default class MerkleTree { if (elements.length > this.capacity) { throw new Error('Tree is full') } - this._hash = hashFunction + this._hashFn = hashFunction this.zeroElement = zeroElement this._zeros = [] this._zeros[0] = zeroElement for (let i = 1; i <= levels; i++) { - this._zeros[i] = this._hash(this._zeros[i - 1], this._zeros[i - 1]) + this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1]) } this._layers = [] this._layers[0] = elements.slice() @@ -43,7 +43,7 @@ export default class MerkleTree { for (let level = 1; level <= this.levels; level++) { this._layers[level] = [] for (let i = 0; i < Math.ceil(this._layers[level - 1].length / 2); i++) { - this._layers[level][i] = this._hash( + this._layers[level][i] = this._hashFn( this._layers[level - 1][i * 2], i * 2 + 1 < this._layers[level - 1].length ? this._layers[level - 1][i * 2 + 1] @@ -93,7 +93,7 @@ export default class MerkleTree { while (index % 2 === 1) { level++ index >>= 1 - this._layers[level][index] = this._hash( + this._layers[level][index] = this._hashFn( this._layers[level - 1][index * 2], this._layers[level - 1][index * 2 + 1], ) @@ -114,7 +114,7 @@ export default class MerkleTree { this._layers[0][index] = element for (let level = 1; level <= this.levels; level++) { index >>= 1 - this._layers[level][index] = this._hash( + this._layers[level][index] = this._hashFn( this._layers[level - 1][index * 2], index * 2 + 1 < this._layers[level - 1].length ? this._layers[level - 1][index * 2 + 1] diff --git a/src/partialMerkleTree.ts b/src/partialMerkleTree.ts new file mode 100644 index 0000000..4050b20 --- /dev/null +++ b/src/partialMerkleTree.ts @@ -0,0 +1,52 @@ +import { Element, HashFunction, ProofPath } from './index' + +type LeafWithIndex = { index: number, data: Element } + +export class PartialMerkleTree { + levels: number + private _hash: HashFunction + private zeroElement: Element + private _zeros: Element[] + private _layers: Array + private _leaves: Element[] + private _leavesAfterEdge: Element[] + private _edgeLeaf: LeafWithIndex + private _root: string + private _hashFn: HashFunction + private _edgeLeafProof: ProofPath + + constructor(edgeLeafProof: ProofPath, edgeLeaf: LeafWithIndex, leaves: Element[], root: string, hashFn: HashFunction) { + this._edgeLeafProof = edgeLeafProof + this._edgeLeaf = edgeLeaf + this._leavesAfterEdge = leaves + this._root = root + this._hashFn = hashFn + + } + + get capacity() { + return this.levels ** 2 + } + + private _buildTree(): void { + const edgeLeafIndex = this._edgeLeaf.index + this._leaves = [...Array.from({ length: edgeLeafIndex - 1 }, () => null), ...this._leavesAfterEdge] + this._layers = [this._leaves] + this._rebuild() + + } + + _rebuild() { + for (let level = 1; level <= this.levels; level++) { + this._layers[level] = [] + for (let i = 0; i < Math.ceil(this._layers[level - 1].length / 2); i++) { + this._layers[level][i] = this._hash( + this._layers[level - 1][i * 2], + i * 2 + 1 < this._layers[level - 1].length + ? this._layers[level - 1][i * 2 + 1] + : this._zeros[level - 1], + ) + } + } + } +}