init partial tree

This commit is contained in:
Sergei SMART 2022-02-26 19:01:46 +10:00
parent 5f036748a9
commit e6a1ce979c
2 changed files with 58 additions and 6 deletions

@ -13,7 +13,7 @@ export default class MerkleTree {
levels: number levels: number
capacity: number capacity: number
private _hash: HashFunction private _hashFn: HashFunction
private zeroElement: Element private zeroElement: Element
private _zeros: Element[] private _zeros: Element[]
private _layers: Array<Element[]> private _layers: Array<Element[]>
@ -27,12 +27,12 @@ export default class MerkleTree {
if (elements.length > this.capacity) { if (elements.length > this.capacity) {
throw new Error('Tree is full') throw new Error('Tree is full')
} }
this._hash = hashFunction this._hashFn = hashFunction
this.zeroElement = zeroElement this.zeroElement = zeroElement
this._zeros = [] this._zeros = []
this._zeros[0] = zeroElement this._zeros[0] = zeroElement
for (let i = 1; i <= levels; i++) { 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 = []
this._layers[0] = elements.slice() this._layers[0] = elements.slice()
@ -43,7 +43,7 @@ export default class MerkleTree {
for (let level = 1; level <= this.levels; level++) { for (let level = 1; level <= this.levels; level++) {
this._layers[level] = [] this._layers[level] = []
for (let i = 0; i < Math.ceil(this._layers[level - 1].length / 2); i++) { 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], this._layers[level - 1][i * 2],
i * 2 + 1 < this._layers[level - 1].length i * 2 + 1 < this._layers[level - 1].length
? this._layers[level - 1][i * 2 + 1] ? this._layers[level - 1][i * 2 + 1]
@ -93,7 +93,7 @@ export default class MerkleTree {
while (index % 2 === 1) { while (index % 2 === 1) {
level++ level++
index >>= 1 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],
this._layers[level - 1][index * 2 + 1], this._layers[level - 1][index * 2 + 1],
) )
@ -114,7 +114,7 @@ export default class MerkleTree {
this._layers[0][index] = element this._layers[0][index] = element
for (let level = 1; level <= this.levels; level++) { for (let level = 1; level <= this.levels; level++) {
index >>= 1 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],
index * 2 + 1 < this._layers[level - 1].length index * 2 + 1 < this._layers[level - 1].length
? this._layers[level - 1][index * 2 + 1] ? this._layers[level - 1][index * 2 + 1]

52
src/partialMerkleTree.ts Normal file

@ -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<Element[]>
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],
)
}
}
}
}